Compare commits

...

714 Commits

Author SHA1 Message Date
Maarten L. Hekkelman
50df250415 Merge branch 'develop' into trunk 2023-06-08 10:12:03 +02:00
Maarten L. Hekkelman
2409fc5b7b update changelog, version bump 2023-06-08 10:10:49 +02:00
Maarten L. Hekkelman
8a1184a24c Fix cif_id_for_number 2023-06-07 19:11:20 +02:00
Maarten L. Hekkelman
d2fbc54765 New cache location 2023-06-07 14:07:27 +02:00
Maarten L. Hekkelman
1bcb26ba75 extend validator
faster unique_id
2023-06-07 13:08:36 +02:00
Maarten L. Hekkelman
32f4749d84 faster cif parser 2023-06-07 11:19:35 +02:00
Maarten L. Hekkelman
da12be879a progress_bar consuming too much time 2023-06-07 09:15:17 +02:00
Maarten L. Hekkelman
94a38ad4e8 Merge branch 'develop' of github.com:PDB-REDO/libcifpp into develop 2023-06-06 14:31:26 +02:00
Maarten L. Hekkelman
20ef79a172 for c++17, limited version of std::string_view 2023-06-06 14:30:11 +02:00
Maarten L. Hekkelman
92bf25476e Speed improvements 2023-06-06 14:12:21 +02:00
Maarten L. Hekkelman
b55e074dd7 reserve some token buffer space 2023-06-06 09:33:31 +02:00
Maarten L. Hekkelman
7b654a837d with reserved words automaton 2023-06-06 09:22:55 +02:00
Maarten L. Hekkelman
ae9d247d22 optimised the parser a bit 2023-06-05 13:43:31 +02:00
Maarten L. Hekkelman
16b7deafe8 Better is_unquoted_string test 2023-06-02 17:09:57 +02:00
Maarten L. Hekkelman
f2cfe28458 Update README 2023-05-31 15:56:50 +02:00
Maarten L. Hekkelman
2e8a52949e Update example and README 2023-05-31 15:54:53 +02:00
Maarten L. Hekkelman
441e142767 Update readme 2023-05-31 15:42:54 +02:00
Maarten L. Hekkelman
bf9bdd2aae Merge branch 'trunk' of github.com:PDB-REDO/libcifpp into trunk 2023-05-31 15:17:00 +02:00
Maarten L. Hekkelman
ce14593f0b improved loading resources from absolute path
better error reporting when loading dictionary
2023-05-31 15:16:10 +02:00
Maarten L. Hekkelman
1c02a451e1 improved has_atom_id
added couple of comparison operators to sym_op class
2023-05-16 13:55:07 +02:00
Maarten L. Hekkelman
448855a2d3 catch error in create entity for branch 2023-05-09 11:46:37 +02:00
Maarten L. Hekkelman
8ac8e89f2b Fix progress bar by removing conditional variable 2023-05-02 13:45:02 +02:00
Maarten L. Hekkelman
2281f59401 Remove struct_conn records as well in remove_branch 2023-05-02 13:44:36 +02:00
Maarten L. Hekkelman
4cb0673370 small change to matrix 2023-04-25 10:13:30 +02:00
Maarten L. Hekkelman
76c5706f7c moving to eigen3 eigensolver, fixing include and dependencies 2023-04-22 14:14:48 +02:00
Maarten L. Hekkelman
2bf4284ff4 cleanup 2023-04-21 14:52:12 +02:00
Maarten L. Hekkelman
d9e2fc97f3 Added missing spinner test 2023-04-21 14:50:22 +02:00
Maarten L. Hekkelman
85dfdf4174 Better progress bar 2023-04-21 14:49:54 +02:00
Martin Salinas
1bede3efda Removed unused argument warning (#36)
As argument rhs is not being used in that equals (should the equals function always return false), I added that flag so the compiler skips that warning.
2023-04-21 09:18:47 +02:00
Maarten L. Hekkelman
505f0fdd31 oops 2023-04-20 16:33:24 +02:00
Maarten L. Hekkelman
eed7ec3a4a Merge branch 'develop' of github.com:PDB-REDO/libcifpp into develop 2023-04-20 13:38:48 +02:00
Maarten L. Hekkelman
fdb057e0e2 for now, require eigen3
add inverse_symmetry_copy to crystal
2023-04-20 13:14:52 +02:00
Maarten L. Hekkelman
3fddd1a628 Using quaternions, when possible 2023-04-20 11:37:36 +02:00
Maarten L. Hekkelman
2440706b87 backup 2023-04-19 18:51:41 +02:00
Maarten L. Hekkelman
cf628fa95c backup 2023-04-19 18:36:33 +02:00
Maarten L. Hekkelman
2b0b47d20d Fix special case 2023-04-19 16:04:59 +02:00
Maarten L. Hekkelman
a8abf2804f attempt to use quaternions 2023-04-19 16:01:52 +02:00
Maarten L. Hekkelman
22d7757949 Introduced cif::crystal 2023-04-19 10:17:38 +02:00
Maarten L. Hekkelman
0b0d170c96 a bit of documentation 2023-04-19 09:57:49 +02:00
Maarten L. Hekkelman
1e8e9adf62 Merge branch 'trunk' into develop 2023-04-19 09:22:49 +02:00
Maarten L. Hekkelman
0f03fc31e0 added required include 2023-04-19 09:22:32 +02:00
Maarten L. Hekkelman
518432e0fb test data 2023-04-17 20:54:57 +02:00
Maarten L. Hekkelman
10ef3464ef Fix symmetry issue 2023-04-17 20:52:10 +02:00
Maarten L. Hekkelman
226abbd577 Merge branch 'develop' of s4.hekkelman.net:git-repo/libcifpp into develop 2023-04-17 18:56:46 +02:00
Maarten L. Hekkelman
8d66f42ab1 more test cases 2023-04-17 18:56:02 +02:00
Maarten L. Hekkelman
0f14d06f9a Added inverse symmetry operation 2023-04-14 19:38:39 +02:00
Maarten L. Hekkelman
c53be78496 symmetry fixes 2023-04-14 19:04:16 +02:00
Maarten L. Hekkelman
a38f31ce48 fix closest_symmetry_copy 2023-04-14 17:56:59 +02:00
Maarten L. Hekkelman
1258bd5047 eigen, fixed 2023-04-14 14:08:52 +02:00
Maarten L. Hekkelman
d25cbeb14c matrix eigen value work 2023-04-14 11:47:18 +02:00
Maarten L. Hekkelman
9b60a07fb6 calculating eigen values 2023-04-13 19:55:32 +02:00
Maarten L. Hekkelman
c0dd41ce50 added inverse symmetry operation 2023-04-13 15:49:15 +02:00
Maarten L. Hekkelman
4cff92bbcc symmetry operations now working correctly 2023-04-13 11:42:59 +02:00
Maarten L. Hekkelman
9aa8a223c7 symmetry work 2023-04-12 17:00:09 +02:00
Maarten L. Hekkelman
fb59adcfdd Fix symmetry rotational numbers 2023-04-12 10:59:23 +02:00
Maarten L. Hekkelman
4acca8a3e3 Merge branch 'trunk' into develop 2023-04-07 09:31:11 +02:00
Maarten L. Hekkelman
c1030d2b08 Merge branch 'MartinSalinas98-trunk' into trunk 2023-04-07 09:26:00 +02:00
Maarten L. Hekkelman
16a185c6c0 More include changes 2023-04-07 09:16:38 +02:00
Maarten L. Hekkelman
174e818bd0 Merge branch 'trunk' of github.com:MartinSalinas98/libcifpp into MartinSalinas98-trunk 2023-04-07 08:43:44 +02:00
Maarten L. Hekkelman
7f829bf5df Merge branch 'trunk' of github.com:PDB-REDO/libcifpp into trunk 2023-04-07 08:43:01 +02:00
Maarten L. Hekkelman
71908282bb merged from trunk 2023-04-07 08:42:46 +02:00
MartinSalinas98
db3ae446af Imported local files with relative path 2023-04-07 03:39:02 +02:00
Martin Salinas
bc7d291307 Merge branch 'PDB-REDO:trunk' into trunk 2023-04-07 03:33:57 +02:00
Maarten L. Hekkelman
cfd4702279 Fix memory leak 2023-04-05 20:46:18 +02:00
Maarten L. Hekkelman
54eefb546d Fix memory leak 2023-04-05 20:44:47 +02:00
Maarten L. Hekkelman
6af0d96a4e Fix memory leak in category 2023-04-05 20:28:47 +02:00
Maarten L. Hekkelman
eb50bee4a3 atom_type_traits changes 2023-04-04 19:19:30 +02:00
Maarten L. Hekkelman
b6143f3652 optimise load atom data 2023-03-30 20:49:03 +02:00
Maarten L. Hekkelman
348aa7afb6 fix test (use gTestDir) 2023-03-30 20:48:41 +02:00
Martin Salinas
66912b68cc Commented unused variable
```
/home/msalinas/Documents/standalone-installations/cifParsers/libcifpp/src/pdb/cif2pdb.cpp: In function ‘std::tuple<int, int> cif::pdb::WriteCoordinatesForModel(std::ostream&, const cif::datablock&, const std::map<std::__cxx11::basic_string<char>, std::tuple<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >&, std::set<std::__cxx11::basic_string<char> >&, int)’:
/home/msalinas/Documents/standalone-installations/cifParsers/libcifpp/src/pdb/cif2pdb.cpp:3362:15: warning: unused variable ‘pdbx_nonpoly_scheme’ [-Wunused-variable]
 3362 |         auto &pdbx_nonpoly_scheme = db["pdbx_nonpoly_scheme"];
      |         
```
This warning appeared while compiling the library. The use of that variable below has been commented, so I think it's appropiate to do the same thing with the unused variable.
2023-03-28 13:54:45 +02:00
Maarten L. Hekkelman
84dd218758 Merge branch 'MartinSalinas98-patch-1' into trunk 2023-03-28 11:33:05 +02:00
Maarten L. Hekkelman
106ae38976 Update readme 2023-03-28 11:32:11 +02:00
Maarten L. Hekkelman
f1a52245ea Merge branch 'patch-1' of github.com:MartinSalinas98/libcifpp into MartinSalinas98-patch-1 2023-03-28 11:27:48 +02:00
Maarten L. Hekkelman
cea38e5bb2 Merge branch 'trunk' into develop 2023-03-28 10:31:24 +02:00
Maarten L. Hekkelman
ed5aac358c libcifpp really requires zlib, not only private. 2023-03-28 10:27:58 +02:00
Maarten L. Hekkelman
5eb128251e Added category::find1<std::optional> 2023-03-27 10:36:47 +02:00
Maarten L. Hekkelman
cfa46ec954 Added model::has_atom_id 2023-03-23 14:32:21 +01:00
Martin Salinas
07cc60e264 Fixed installation commands
Installation commands in the readme cause an error when running last command `cmake --install .` because of the lack of sudo privileges.
The following commands don't require sudo to run successfully and install the library.
2023-03-23 11:42:10 +01:00
Maarten L. Hekkelman
90973dc547 version bump, update changelog 2023-03-22 12:39:16 +01:00
Maarten L. Hekkelman
12e3d71b00 fix construct_from_angle_axis 2023-03-21 19:49:21 +01:00
Maarten L. Hekkelman
9addc8f873 fix remove_atom
add create_water
2023-03-21 19:49:11 +01:00
Maarten L. Hekkelman
343465cef0 Added test for create_non_poly with initializers 2023-03-08 16:00:40 +01:00
Maarten L. Hekkelman
bec5159415 residue numbering in pdb, again... 2023-02-14 08:28:40 +01:00
Maarten L. Hekkelman
f8da8360e6 write twin info in pdb format 2023-02-14 08:27:13 +01:00
Maarten L. Hekkelman
fb2ad7b75d Fix in REMARK3 parser for more strict mmcif_pdbx dictionary 2023-02-10 16:24:53 +01:00
Maarten L. Hekkelman
24aa7a70e5 Fix writing pdbx_ens_id 2023-02-07 11:38:15 +01:00
Maarten L. Hekkelman
5ade3d6cdd Fixes in update data script 2023-02-06 16:10:41 +01:00
Maarten L. Hekkelman
0d8e548ffc pdb2cif and vv 2023-02-06 14:19:56 +01:00
Maarten L. Hekkelman
b09650812f oops 2023-02-06 06:48:57 +01:00
Maarten L. Hekkelman
acc9ad5c08 Merge branch 'develop' of github.com:PDB-REDO/libcifpp into develop 2023-02-05 11:28:03 +01:00
Maarten L. Hekkelman
67b6c4bd27 update downloaded files only when needed and clean up afterwards 2023-02-05 11:27:54 +01:00
Maarten L. Hekkelman
7a1d3dbdfa Merge branch 'develop' of github.com:PDB-REDO/libcifpp into develop 2023-02-03 19:21:08 +01:00
Maarten L. Hekkelman
4bf10df0c5 include <array> 2023-02-03 19:20:40 +01:00
Maarten L. Hekkelman
d84faad109 Accept X as alias for atom symbol Nn 2023-02-02 11:23:40 +01:00
Maarten L. Hekkelman
e01ace7ea4 write auth_seq_num as well as pdb_seq_num for nonpolies 2023-02-02 09:49:21 +01:00
Maarten L. Hekkelman
e004e1591e fix cron script 2023-02-02 09:35:44 +01:00
Maarten L. Hekkelman
4613084e1b find_first, find_min, find_max, count added
PDB writing changed for auth_seq_num
version bump
2023-02-01 13:46:08 +01:00
Maarten L. Hekkelman
637b795a8f Merge branch 'develop' of github.com:PDB-REDO/libcifpp into develop 2023-02-01 09:00:51 +01:00
Maarten L. Hekkelman
4de981a3c0 better handling of missing residues in pdb2cif 2023-01-31 20:32:57 +01:00
Maarten L. Hekkelman
15db026e27 Merge branch 'develop' of github.com:PDB-REDO/libcifpp into develop 2023-01-31 19:10:44 +01:00
Maarten L. Hekkelman
d88d520553 Use std::experimental::is_detected from libzeep, if needed
version bump
2023-01-25 17:06:47 +01:00
Maarten L. Hekkelman
46cd98ea1d Dependencies and share location in Win 2023-01-25 17:01:39 +01:00
Maarten L. Hekkelman
d10328d891 Use the zeep implementation of std::experimental::is_detected 2023-01-25 16:31:13 +01:00
Maarten L. Hekkelman
e418a17256 Version bump 2023-01-25 15:01:28 +01:00
Maarten L. Hekkelman
627d3b9df2 export by default, fixes for MSVC 2023-01-25 11:23:08 +01:00
Maarten L. Hekkelman
ba28ade414 clean up 2023-01-25 10:45:08 +01:00
Maarten L. Hekkelman
7c11130357 explicitly export what needs to be exported 2023-01-25 10:07:54 +01:00
Maarten L. Hekkelman
151915beea Merge branch 'exports' into develop 2023-01-25 09:44:04 +01:00
Maarten L. Hekkelman
4f9aacb338 Merge branch 'trunk' into develop 2023-01-25 09:41:59 +01:00
Maarten L. Hekkelman
1f8e491ddc generate exports header 2023-01-25 09:41:43 +01:00
Maarten L. Hekkelman
05cfa92182 revert version number 2023-01-17 14:16:36 +01:00
Maarten L. Hekkelman
e8031aeb49 Fix is_cis 2023-01-17 14:12:33 +01:00
Maarten L. Hekkelman
85885406aa Fix sugar test 2023-01-17 14:10:50 +01:00
Maarten L. Hekkelman
636f17d78d Update changelog 2023-01-17 14:10:38 +01:00
Maarten L. Hekkelman
29559a5339 Fix is_cis 2023-01-17 13:51:46 +01:00
Maarten L. Hekkelman
19f2fd75c9 Merge branch 'develop' of github.com:PDB-REDO/libcifpp into develop 2023-01-04 17:14:33 +01:00
Maarten L. Hekkelman
8a60bae335 non-throwing remove_residue
add chem_comp for sugars
2023-01-04 17:05:48 +01:00
Maarten L. Hekkelman
fa5ff60550 Merge branch 'develop' of github.com:PDB-REDO/libcifpp into develop 2023-01-03 21:31:09 +01:00
Maarten L. Hekkelman
f6e0568964 start reconstructing 2023-01-03 21:30:17 +01:00
Maarten L. Hekkelman
fa27a11fea some quaternion additions 2023-01-03 16:45:53 +01:00
Maarten L. Hekkelman
19706559cb Merge branch 'trunk' of github.com:PDB-REDO/libcifpp into trunk 2023-01-02 14:06:16 +01:00
Maarten L. Hekkelman
0a06a0a51d Fix cron script 2023-01-02 14:06:09 +01:00
Maarten L. Hekkelman
b045177734 less nervous progress bar 2023-01-02 14:05:47 +01:00
Maarten L. Hekkelman
7ee5fa8765 some quaternion tests added 2023-01-02 14:05:31 +01:00
Maarten L. Hekkelman
3e690048a6 sugar work 2023-01-02 14:04:56 +01:00
Maarten L. Hekkelman
7ec3bfea9f 3d work 2023-01-02 14:04:41 +01:00
Maarten L. Hekkelman
098f3fd496 FIx compound factory stacking 2022-12-21 21:14:41 +01:00
Maarten L. Hekkelman
5476eef049 some extensions for sugar tree building 2022-12-21 16:33:33 +01:00
Maarten L. Hekkelman
33c1eea9a1 Fix copy construction, do not copy the links 2022-12-19 17:40:43 +01:00
Maarten L. Hekkelman
d3432ed87c merging in fixes from develop branch 2022-12-15 09:05:51 +01:00
Maarten L. Hekkelman
f05363ea93 duh 2022-12-15 08:51:05 +01:00
Maarten L. Hekkelman
77389c20a4 Fix equals in condition_impl, columns might be unknown 2022-12-15 08:49:49 +01:00
Maarten L. Hekkelman
7c5f1ba85e Merge branch 'trunk' into develop 2022-12-14 10:49:56 +01:00
Maarten L. Hekkelman
e7c34cc15c Merge changes 2022-12-14 10:47:20 +01:00
Maarten L. Hekkelman
72fd03a6b2 formatting, fix in is_unquoted test 2022-12-13 16:48:09 +01:00
Maarten L. Hekkelman
61f464ae4d Merge branch 'trunk' of github.com:PDB-REDO/libcifpp into trunk 2022-12-13 16:08:16 +01:00
Maarten L. Hekkelman
19cdf66f10 fix operator or for conditions (equals or empty) 2022-12-13 16:05:23 +01:00
Maarten L. Hekkelman
0c036df6a8 fix operator or for conditions (equals or empty) 2022-12-13 16:02:55 +01:00
Maarten L. Hekkelman
4c1b9d83d1 Fix memory leak 2022-12-13 15:49:11 +01:00
Maarten L. Hekkelman
b976b4657b Optimised erase III 2022-12-13 15:41:57 +01:00
Maarten L. Hekkelman
eba04950d5 Optimised erase II 2022-12-13 11:31:56 +01:00
Maarten L. Hekkelman
0c70df27ec Optimised erase 2022-12-13 10:38:33 +01:00
Maarten L. Hekkelman
d83f34722b Accept and fix incorrect SEQRES 2022-12-13 09:50:40 +01:00
Maarten L. Hekkelman
652b6021d3 improved parser. is_non_quoted string 2022-12-07 16:58:54 +01:00
Maarten L. Hekkelman
7fe9c87b6e Some small fixes for windows 2022-12-07 15:39:26 +01:00
Maarten L. Hekkelman
9b2ae6d7fd Fix update script, order is important 2022-11-28 08:48:13 +01:00
Maarten L. Hekkelman
8fd5b9a34b Remove PATH_MAX to enable compilation on Debian/hurd 2022-11-20 13:30:44 +01:00
Maarten L. Hekkelman
dffbf52d04 removed erronous static-assert 2022-11-19 11:17:50 +01:00
Maarten L. Hekkelman
57ac5f0112 Fix for 32bit, version bump 2022-11-19 10:21:36 +01:00
Maarten L. Hekkelman
d5a71b0b24 Fix verbose checking
faster aniso_row retrieval
report missing header line for pdb
2022-11-16 17:07:28 +01:00
Maarten L. Hekkelman
d95b7be2e4 removed remaining lzma references 2022-11-15 12:11:41 +01:00
Maarten L. Hekkelman
2f0a23f56a debian dislikes tweaks 2022-11-14 09:28:19 +01:00
Maarten L. Hekkelman
13b218f643 revert export of CIFPP_SHARE_DIR variable 2022-11-14 08:53:52 +01:00
Maarten L. Hekkelman
92a836ecdc More location fixes 2022-11-13 11:43:35 +01:00
Maarten L. Hekkelman
c88a46f155 Fix installation issues, version bump 2022-11-13 11:16:51 +01:00
Maarten L. Hekkelman
8882a34984 installation dirs cleanup 2022-11-11 20:40:42 +01:00
Maarten L. Hekkelman
2d4a1731d9 Merge branch 'develop' into trunk 2022-11-11 09:04:30 +01:00
Maarten L. Hekkelman
be1e3073f1 Fixes based on upstream changes 2022-11-10 17:06:59 +01:00
Maarten L. Hekkelman
6fe5a04cc0 static zlib on windows 2022-11-09 19:52:54 +01:00
Maarten L. Hekkelman
426432885e back on linux 2022-11-09 18:57:32 +01:00
Maarten L. Hekkelman
9bc3381814 First steps to compile libcifpp 5 in Windows 2022-11-09 17:23:47 +01:00
Maarten L. Hekkelman
f3a492fd67 Fix regex include 2022-11-09 15:07:04 +01:00
Maarten L. Hekkelman
8cd2aa46b6 simply include boost-regex 2022-11-09 14:58:25 +01:00
Maarten L. Hekkelman
d638d634ba Remove gxrio and replace it with stripped down version 2022-11-09 14:23:51 +01:00
Maarten L. Hekkelman
35196789e0 updated makefile, use system regex if good enough 2022-11-09 10:33:44 +01:00
Maarten L. Hekkelman
e907ce6c29 exclude regex from tar 2022-11-09 09:19:39 +01:00
Maarten L. Hekkelman
b80bc20d17 Use system installed boost headers for regex, when available 2022-11-09 08:54:56 +01:00
Maarten L. Hekkelman
3a87eaa435 include utility
exclude from all for gxrio
2022-11-08 15:46:03 +01:00
Maarten L. Hekkelman
143eb57f04 Removed remaining mrc_add_resources call 2022-11-08 15:38:06 +01:00
Maarten L. Hekkelman
6cc550bf18 oops 2022-11-08 15:20:29 +01:00
Maarten L. Hekkelman
7f5336661b Error reporting 2022-11-08 14:53:15 +01:00
Maarten L. Hekkelman
e44539ef2c Checks before building indices. Better error reporting 2022-11-08 13:45:06 +01:00
Maarten L. Hekkelman
a2f5850173 avoid crash on empty branches 2022-11-08 09:29:15 +01:00
Maarten L. Hekkelman
283f4883f7 Fix makefile 2022-11-08 08:43:49 +01:00
Maarten L. Hekkelman
ce9842f671 Fix in PDB export
Better add_git_submodule
2022-11-08 08:28:02 +01:00
Maarten L. Hekkelman
b784433fd7 less verbose parser 2022-11-07 17:00:49 +01:00
Maarten L. Hekkelman
8c064e7c0a version bump 2022-11-07 12:37:01 +01:00
Maarten L. Hekkelman
c15a8bd127 export source tarballs 2022-11-07 12:32:14 +01:00
Maarten L. Hekkelman
64e40e7b31 Fix writing PDB CISPEP records
Better checking for open files
More verbose parser
2022-11-07 11:06:06 +01:00
Maarten L. Hekkelman
06d254e0de Revert "Use system version of boost regex, when available"
This reverts commit eaa342ca32.
2022-11-03 16:52:09 +01:00
Maarten L. Hekkelman
eaa342ca32 Use system version of boost regex, when available 2022-11-03 16:36:14 +01:00
Maarten L. Hekkelman
782f7c467b Support for cifv1.0 (empty category names) 2022-11-03 15:48:58 +01:00
Maarten L. Hekkelman
c45d02cb70 sigh 2022-11-03 13:09:04 +01:00
Maarten L. Hekkelman
5b4c131eea More verbose 2022-11-03 13:00:11 +01:00
Maarten L. Hekkelman
bbe71af99e Accept invalid CCD component files, for now 2022-11-03 12:18:26 +01:00
Maarten L. Hekkelman
49912d019f Better error reporting 2022-11-03 11:43:57 +01:00
Maarten L. Hekkelman
d4758e09d7 Merge branch 'trunk' of github.com:PDB-REDO/libcifpp into trunk 2022-11-03 09:37:38 +01:00
Maarten L. Hekkelman
f0a913cc07 Fixes for deuterium...
Fixes for sugar branches
2022-11-03 09:37:31 +01:00
Maarten L. Hekkelman
8b0b8e3688 removed submodule 2022-11-01 16:52:42 +01:00
Maarten L. Hekkelman
de4fc8a015 Added necessary include 2022-11-01 16:50:54 +01:00
Maarten L. Hekkelman
bf1e56ec53 Another attempt 2022-11-01 16:29:59 +01:00
Maarten L. Hekkelman
040b4e4ff9 clean up 2022-11-01 14:54:26 +01:00
Maarten L. Hekkelman
4666ee3145 Merge branch 'trunk' of github.com:PDB-REDO/libcifpp into trunk 2022-11-01 14:54:10 +01:00
Maarten L. Hekkelman
2958c56a92 change parser to use streambuf directly 2022-11-01 14:53:17 +01:00
Maarten L. Hekkelman
9cff8768ab Merge branch 'potential-performance-gain' into trunk 2022-11-01 13:41:06 +01:00
Maarten L. Hekkelman
cc671b8006 fixes in numeric conversions 2022-11-01 13:41:01 +01:00
Maarten L. Hekkelman
728abe6d0e less verbose pdb2cif 2022-11-01 12:11:04 +01:00
Maarten L. Hekkelman
7b8f3f2538 optimise retract buffer 2022-11-01 11:56:18 +01:00
Maarten L. Hekkelman
98db98f916 Merge branch 'trunk' of github.com:PDB-REDO/libcifpp into trunk 2022-11-01 09:54:20 +01:00
Maarten L. Hekkelman
96a67b23ca Fix loading dictionaries 2022-11-01 09:53:36 +01:00
Maarten L. Hekkelman
2c3d7542e5 no submodule for gxrio 2022-11-01 08:45:52 +01:00
Maarten L. Hekkelman
f84d83b723 Add gxrio dependency again 2022-10-31 10:50:53 +01:00
Maarten L. Hekkelman
b1837ba029 for freebsd 2022-10-31 10:35:28 +01:00
Maarten L. Hekkelman
260438fa44 fix for meta project 2022-10-30 19:51:29 +01:00
Maarten L. Hekkelman
23d82beb04 Fix version string 2022-10-30 13:02:53 +01:00
Maarten L. Hekkelman
19db5d736b Merge branch 'trunk' of github.com:PDB-REDO/libcifpp into trunk 2022-10-30 11:14:16 +01:00
Maarten L. Hekkelman
6946c40657 Merge branch 'trunk' of github.com:PDB-REDO/libcifpp into trunk 2022-10-30 11:12:30 +01:00
Maarten L. Hekkelman
bd3723ee20 Do not crash on empty rows (find result) 2022-10-30 11:12:19 +01:00
Maarten L. Hekkelman
1f078d4827 update for meta project 2022-10-30 10:28:01 +01:00
Maarten L. Hekkelman
3c62a38667 write out PDB files 2022-10-28 16:13:33 +02:00
Maarten L. Hekkelman
7ffda74e3d pdb2cif, avoid duplicate key violation on REMARK 350 2022-10-26 16:43:21 +02:00
Maarten L. Hekkelman
560f6debc6 updating dictionaries and default to downloading components.cif 2022-10-26 15:46:50 +02:00
Maarten L. Hekkelman
ea1ac33de8 Update README.md
No more boost requirement
2022-10-26 15:30:56 +02:00
Maarten L. Hekkelman
7ea30237ae Merge branch 'trunk' into new-develop 2022-10-26 15:23:35 +02:00
Maarten L. Hekkelman
bc668487e2 Fix installation of dictionary files 2022-10-26 14:29:40 +02:00
Maarten L. Hekkelman
1769f9864b Fixed TLS parser, and more 2022-10-26 13:23:23 +02:00
Maarten L. Hekkelman
75ffd97802 use gxrio internally for reading pdb files 2022-10-25 12:41:14 +02:00
Maarten L. Hekkelman
cfd5b7da0f Reintroduce more atom members 2022-10-25 11:51:35 +02:00
Maarten L. Hekkelman
26b7d1df26 Write chem_comp for polymer residues in pdb2cif 2022-10-21 16:01:12 +02:00
Maarten L. Hekkelman
0747929cd6 Allow missing CRYST1 record in PDB files... finally 2022-10-21 15:42:19 +02:00
Maarten L. Hekkelman
5bcfb102f4 change_residue fix 2022-10-20 19:48:26 +02:00
Maarten L. Hekkelman
908fb1ccea gxrio dependency 2022-10-20 13:36:18 +02:00
Maarten L. Hekkelman
af8389baa4 fix dependencies 2022-10-11 15:36:53 +02:00
Maarten L. Hekkelman
24ca1017cd Fix mm::polymer to have its own auth_asym_id 2022-10-11 12:17:42 +02:00
Maarten L. Hekkelman
85c21aeb01 row as vector 2022-10-11 09:05:03 +02:00
Maarten L. Hekkelman
2f249048d9 Merge branch 'develop' of github.com:PDB-REDO/libcifpp into develop 2022-10-10 09:03:34 +02:00
Maarten L. Hekkelman
974cb40ab3 for gcc 9.4 2022-10-10 09:01:40 +02:00
Maarten L. Hekkelman
c01c16ea60 more accessors in cif::mm::atom 2022-10-05 17:04:39 +02:00
Maarten L. Hekkelman
bd157c249c Reintroduced PDB conversion code 2022-10-05 14:18:08 +02:00
Maarten L. Hekkelman
b0ac33c1b1 optimisation in query
fix memory problem in cif::item, making it safer
2022-10-05 13:21:57 +02:00
Maarten L. Hekkelman
82e73a9525 All tests pass 2022-10-05 10:13:53 +02:00
Maarten L. Hekkelman
adc316d671 Use index in lookup, when available
start branch code in model::structure (not done yet)
2022-10-04 13:57:38 +02:00
Maarten L. Hekkelman
6a0b6b99ac using index in category 2022-10-03 16:22:32 +02:00
Maarten L. Hekkelman
08dd9dd5b4 missing methods 2022-10-03 10:01:42 +02:00
Maarten L. Hekkelman
557a1c2d00 Reactivated several structure methods 2022-10-03 09:32:20 +02:00
Maarten L. Hekkelman
f77bbfedda updates 2022-10-03 08:41:50 +02:00
Maarten L. Hekkelman
3aa3fe19e2 Better validate diagnostic output 2022-09-30 10:25:55 +02:00
Maarten L. Hekkelman
35fcc0493e Moving cif::Structure back in as model 2022-09-28 17:11:04 +02:00
Maarten L. Hekkelman
9485bec2fa Moved symmetry back into libcifpp 2022-09-27 16:09:24 +02:00
Maarten L. Hekkelman
4b759e731c Moved code back into libcifpp, 3d stuff mainly 2022-09-27 14:34:31 +02:00
Maarten L. Hekkelman
7dd6a8a1aa fixes and updated submodules 2022-08-24 16:20:16 +02:00
Maarten L. Hekkelman
96725ae8b9 Clean up makefile 2022-08-19 13:55:35 +02:00
Maarten L. Hekkelman
b3a0ded9a8 add git submodule 2022-08-19 13:38:59 +02:00
Maarten L. Hekkelman
184c491803 changed find1 a bit more
reverted to returning empty results in case nothing is found
2022-08-18 17:20:41 +02:00
Maarten L. Hekkelman
f944b3ce00 changed find1 logic for only row_handles, now returns empty row_handle instead of throwing when not found
various condition fixes
2022-08-18 11:16:28 +02:00
Maarten L. Hekkelman
2557f41863 some documentation and cleanup of cif::item 2022-08-17 20:40:31 +02:00
Maarten L. Hekkelman
2b92cee3f7 some documentation and cleanup of cif::item 2022-08-17 20:14:48 +02:00
Maarten L. Hekkelman
8071768579 better row_handle::get 2022-08-17 19:39:14 +02:00
Maarten L. Hekkelman
71c8541b68 validate links
fix get_parents_condition
2022-08-17 17:08:38 +02:00
Maarten L. Hekkelman
3d66c77188 writing order 2022-08-17 16:02:57 +02:00
Maarten L. Hekkelman
8701512961 Remove cif++/Cif++.hpp
Implemented reorder by index
2022-08-17 15:29:14 +02:00
Maarten L. Hekkelman
b317c780ba Fixes for pre c++20
file constructor from raw data
2022-08-17 15:02:56 +02:00
Maarten L. Hekkelman
681aa3bf8b clean up 2022-08-17 11:24:29 +02:00
Maarten L. Hekkelman
a68e053471 Remove tests 2022-08-17 11:17:09 +02:00
Maarten L. Hekkelman
25a90e3b32 split out pdbx code
fix dangling memory reference
2022-08-17 11:14:06 +02:00
Maarten L. Hekkelman
2f62759dfe Before split-out of libpdbxpp 2022-08-17 08:50:56 +02:00
Maarten L. Hekkelman
cf9ec46ab8 Removed DSSP code, moved to dssp project 2022-08-16 16:57:25 +02:00
Maarten L. Hekkelman
ecbef51b10 - fix category::clear
- fix dssp TCO value
2022-08-16 16:34:15 +02:00
Maarten L. Hekkelman
dfff8c9587 condition work (children, parents) 2022-08-16 16:18:11 +02:00
Maarten L. Hekkelman
cc5d52bbf9 boost::regex usage 2022-08-16 16:17:56 +02:00
Maarten L. Hekkelman
a9e9f86c93 Renaming internal use of mmcif_pdbx dictionary. It was wrong to use the name mmcif_pdbx_v50 2022-08-16 16:17:30 +02:00
Maarten L. Hekkelman
a2c52713b2 Refactored dssp to be standalone 2022-08-16 11:50:43 +02:00
Maarten L. Hekkelman
545aca88d8 More info 2022-08-15 17:17:56 +02:00
Maarten L. Hekkelman
ac27248784 Started moving DSSP code 2022-08-15 15:37:07 +02:00
Maarten L. Hekkelman
5758bfbaea Required changes for FreeBSD 2022-08-15 10:11:11 +02:00
Maarten L. Hekkelman
8d3a079774 Fix regex for item_validator 2022-08-15 10:09:18 +02:00
Maarten L. Hekkelman
718c138510 Fix constructor for item 2022-08-15 09:49:23 +02:00
Maarten L. Hekkelman
29aac70e67 Changed boost::regex dependency to git submodule, in case it is needed 2022-08-15 08:59:47 +02:00
Maarten L. Hekkelman
700575adfe Merged 2022-08-15 07:42:51 +02:00
Maarten L. Hekkelman
9fe6e5df85 remove dependency on boost::program_options 2022-08-14 20:08:36 +02:00
Maarten L. Hekkelman
ce7434a463 Make boost::regex optional 2022-08-14 19:31:31 +02:00
Maarten L. Hekkelman
ad7d876d07 new dependency 2022-08-13 21:55:19 +02:00
Maarten L. Hekkelman
0dc19e86fa fixed example 2022-08-11 20:53:54 +02:00
Maarten L. Hekkelman
a12acaa5c7 moving from namespace cif::v2 to cif 2022-08-11 20:39:34 +02:00
Maarten L. Hekkelman
ff62efe720 More tests 2022-08-11 16:49:59 +02:00
Maarten L. Hekkelman
2407877184 Reordering all files 2022-08-11 15:44:59 +02:00
Maarten L. Hekkelman
5fde050738 debugging 2022-08-10 17:09:53 +02:00
Maarten L. Hekkelman
a855f88073 Getting rid of boost/algorithm/string 2022-08-10 16:46:48 +02:00
Maarten L. Hekkelman
cfa2acd61d backup 2022-08-08 08:10:22 +02:00
Maarten L. Hekkelman
d9db2fe2e7 insert 2022-08-07 20:48:59 +02:00
Maarten L. Hekkelman
15d62cd3b6 Fix mapping between pdbx_poly_seq_scheme and atom_site while reading an mmcif::Structure 2022-08-07 12:51:16 +02:00
Maarten L. Hekkelman
19a89aeb7e - start row_initializer 2022-08-07 11:49:09 +02:00
Maarten L. Hekkelman
677c61c32f moving insert_impl, index work 2022-08-06 16:08:34 +02:00
Maarten L. Hekkelman
4dd4f66397 backup 2022-08-04 16:29:55 +02:00
Maarten L. Hekkelman
04b7828abc validator work 2022-08-04 13:57:12 +02:00
Maarten L. Hekkelman
9c621ecab8 more condition work 2022-08-03 16:40:48 +02:00
Maarten L. Hekkelman
ab9c4d9416 compiling again 2022-08-03 16:09:27 +02:00
Maarten L. Hekkelman
e5eb62255a started with validator, running into the ground 2022-08-03 12:44:58 +02:00
Maarten L. Hekkelman
98ff79432b backup 2022-08-02 16:56:55 +02:00
Maarten L. Hekkelman
24fa80ba2a parser just started working again, a bit 2022-08-02 16:42:52 +02:00
Maarten L. Hekkelman
3999d792ef const iterator construction from non-const iterator 2022-08-02 11:59:29 +02:00
Maarten L. Hekkelman
4db3732749 move construction and operators = 2022-08-02 11:42:11 +02:00
Maarten L. Hekkelman
07131e8b40 copy constructor for category 2022-08-02 11:24:14 +02:00
Maarten L. Hekkelman
39b91e74c9 - new item storage
- formatting of numbers using to_chars
2022-08-02 10:35:14 +02:00
Maarten L. Hekkelman
d4bb7ec3bc Fixed includes based on feedback from Patricia Herrera. 2022-08-01 19:00:42 +02:00
Maarten L. Hekkelman
6175b7e359 backup 2022-08-01 16:58:52 +02:00
Maarten L. Hekkelman
10442d506a structured binding, start 2022-08-01 15:08:42 +02:00
Maarten L. Hekkelman
573a695c3d small steps 2022-08-01 12:57:00 +02:00
Maarten L. Hekkelman
a76bef0d01 backup 2022-08-01 08:33:49 +02:00
Maarten L. Hekkelman
e20111b566 small optimization 2022-07-31 16:19:24 +02:00
Maarten L. Hekkelman
4a1d9c8f75 New storage layout for item_value 2022-07-31 15:53:18 +02:00
Maarten L. Hekkelman
26c86282e3 before refactoring item_value based on statistics 2022-07-27 16:46:33 +02:00
Maarten L. Hekkelman
0eaeb1650d split out item 2022-07-27 12:41:25 +02:00
Maarten L. Hekkelman
f4a6533f6b eerste fröbelwerk 2022-07-26 17:00:14 +02:00
Maarten L. Hekkelman
df1b6a13e1 updated git ignore 2022-07-25 16:21:55 +02:00
Maarten L. Hekkelman
e8f24f617c - Fixed copy/paste error in Category interface
- message in progress finished
2022-07-25 10:40:03 +02:00
Maarten L. Hekkelman
9454fdc217 Fix for parsing empty quoted strings. 2022-07-21 13:03:23 +02:00
Maarten L. Hekkelman
22543d8fe5 Update changelog 2022-07-12 16:55:55 +02:00
Maarten L. Hekkelman
60d1dc82e6 Improved remark 3 parser for large molecules 2022-07-12 16:54:38 +02:00
Maarten L. Hekkelman
87486f87ef revert loading compressed dictionaries 2022-07-12 14:20:01 +02:00
Maarten L. Hekkelman
80e7da0f13 Locating dictionaries updated 2022-07-12 14:13:59 +02:00
Maarten L. Hekkelman
3745beae66 Fix search order for resources 2022-07-12 13:55:19 +02:00
Maarten L. Hekkelman
3965840bfa New way of locating resources 2022-07-12 13:49:02 +02:00
Maarten L. Hekkelman
a88c6f3d32 Fix for older clang (on MacOS?). 2022-07-05 11:07:12 +02:00
Maarten L. Hekkelman
ed6c6f0026 Move assignment of Structure is not possible due to reference to datablock 2022-07-05 09:46:59 +02:00
Maarten L. Hekkelman
bdda9d72b5 Merge branch 'trunk' of github.com:PDB-REDO/libcifpp into trunk 2022-07-05 09:36:36 +02:00
Maarten L. Hekkelman
fd080e778e Changes for MacOS/MSVC 2022-07-05 09:36:26 +02:00
Maarten L. Hekkelman
9f72df2ecd Update LICENSE
Format changed, now recognized
2022-07-01 08:21:22 +02:00
ojcharles
617db012f0 Update Cif++.cpp (#15)
add mutex library for std::unique_lock, not included in std lib
2022-07-01 08:07:24 +02:00
Maarten L. Hekkelman
9d15541237 include cstring for gnu c++ 12 2022-06-22 08:53:05 +02:00
Maarten L. Hekkelman
35c99564c6 Fix importing sugars from PDB files 2022-06-01 15:17:54 +02:00
Maarten L. Hekkelman
1d8fe334d6 Fix writing sugar branches 2022-06-01 13:22:34 +02:00
Maarten L. Hekkelman
d86bb314ac Better handling of missing residues/mismatch seqres 2022-06-01 11:27:41 +02:00
Maarten L. Hekkelman
0ef8eb59f8 Fix scattering factors error 2022-05-18 13:04:42 +02:00
Maarten L. Hekkelman
b5fe4a9a87 locating resources that might be protected 2022-05-18 11:53:13 +02:00
Maarten L. Hekkelman
11fea31b98 more loading resources 2022-05-18 11:37:26 +02:00
Maarten L. Hekkelman
f629275ed5 locating resources that might be protected 2022-05-18 11:25:47 +02:00
Maarten L. Hekkelman
a5f6166469 locating resources that might be protected 2022-05-18 11:14:14 +02:00
Maarten L. Hekkelman
501050e591 Add move constructor to mmcif::Structure 2022-05-10 17:11:04 +02:00
Maarten L. Hekkelman
e1b240b2b2 sugar work 2022-05-04 16:48:28 +02:00
Maarten L. Hekkelman
3d79278ed7 Merge branch 'trunk' into develop 2022-05-04 09:51:15 +02:00
Maarten L. Hekkelman
5e0b197a43 mmcif::Atom::compound() revision 2022-05-04 09:50:24 +02:00
Maarten L. Hekkelman
9c4170d9e2 - Added more const members
- change PDB writing interface
2022-05-03 11:52:15 +02:00
Maarten L. Hekkelman
af721eb196 Make having no compound less fatal 2022-05-02 14:40:22 +02:00
Maarten L. Hekkelman
788e315f5e Fix entity_branch_link entry 2022-05-02 12:24:35 +02:00
Maarten L. Hekkelman
4a82a8d5a8 Fixed all tests 2022-05-02 11:09:36 +02:00
Maarten L. Hekkelman
11019a26f8 Merge branch 'sugar-tests' into develop 2022-05-02 10:03:44 +02:00
Maarten L. Hekkelman
6f8909dce9 Fixed tests 2022-05-02 10:01:10 +02:00
Maarten L. Hekkelman
5525103aaf backup 2022-05-02 09:26:59 +02:00
Maarten L. Hekkelman
291ef737b1 - Fix removing atoms
- Optimize isUnquotedString
2022-05-01 14:09:06 +02:00
Maarten L. Hekkelman
af125bdd57 backup 2022-04-26 16:04:13 +02:00
Maarten L. Hekkelman
79089bbb8c removed incorrect assert 2022-04-20 16:32:47 +02:00
Maarten L. Hekkelman
1f08498d00 Merge branch 'develop' of github.com:PDB-REDO/libcifpp into develop 2022-04-20 11:18:50 +02:00
Maarten L. Hekkelman
49ba714a03 - structure id stuff
- added cif::null
- more tests
2022-04-20 11:17:11 +02:00
Maarten L. Hekkelman
85fd9296b2 Add test for loading 2022-04-19 17:03:09 +02:00
Maarten L. Hekkelman
1cda14867f More interface changes in mmcif::Structure 2022-04-19 13:40:38 +02:00
Maarten L. Hekkelman
2d2b26f7dc Fix regression in bondmap calculation 2022-04-19 09:10:54 +02:00
Maarten L. Hekkelman
93b33af44a oops, wrong field name 2022-04-13 10:57:50 +02:00
Maarten L. Hekkelman
eb80490bcd getPolymerByAsymID 2022-04-13 09:47:18 +02:00
Maarten L. Hekkelman
ba2b06f5af reduce complexity 2022-04-13 09:39:43 +02:00
Maarten L. Hekkelman
fecc762db1 - better link validation
- better output (quote reserved strings)
2022-04-12 17:00:47 +02:00
Maarten L. Hekkelman
1e406253ab loading unknown atoms 2022-04-12 12:41:25 +02:00
Maarten L. Hekkelman
6e3b85f43d getResidue, again 2022-04-11 16:36:40 +02:00
Maarten L. Hekkelman
58f1b626e2 change getResidue 2022-04-06 12:49:03 +02:00
Maarten L. Hekkelman
c104a08e16 fixed Atom::charge to pick more sensible default 2022-03-30 11:14:11 +02:00
Maarten L. Hekkelman
dd0f6ca1e6 accept more invalid characters, sigh 2022-03-29 11:45:33 +02:00
Maarten L. Hekkelman
f02ea91b51 label and auth seq id, some improvements 2022-03-28 09:50:37 +02:00
Maarten L. Hekkelman
6768a501a3 access to atoms 2022-03-21 09:58:16 +01:00
Maarten L. Hekkelman
879e15c759 Merge branch 'develop' of github.com:PDB-REDO/libcifpp into develop 2022-03-14 16:28:55 +01:00
Maarten L. Hekkelman
89285b4abc construct quaternion from angle/axis 2022-03-14 16:28:41 +01:00
Maarten L. Hekkelman
c584714f91 ion radii 2022-03-09 15:40:32 +01:00
Maarten L. Hekkelman
f5016403b7 refactored mmcif::File 2022-03-02 15:26:29 +01:00
Maarten L. Hekkelman
c8f66ae6bb start remove residue 2022-02-23 08:24:26 +01:00
Maarten L. Hekkelman
858c967e71 Locate mmcif dictionary in CCP4 space 2022-02-15 08:08:01 +01:00
Maarten L. Hekkelman
f9ca5de5bf Add missing include for gcc 8.2 2022-02-09 16:04:24 +01:00
Maarten L. Hekkelman
252c3476a1 Slightly better handling of hetero residues 2022-02-09 14:53:05 +01:00
Maarten L. Hekkelman
19210df6db Fix parsing mmCIF files with an unquoted string ?? 2022-02-08 11:22:10 +01:00
Maarten L. Hekkelman
15c5730749 Remove redundant FindFilesystem include 2022-02-03 10:35:34 +01:00
Maarten L. Hekkelman
3764adb7ef update changelog 2022-02-02 13:44:32 +01:00
Maarten L. Hekkelman
9160adb1cf Merge branch 'develop' into trunk 2022-02-02 13:40:47 +01:00
Maarten L. Hekkelman
3ebf4338ab Do not crash on uninitialized Atoms 2022-02-02 12:41:32 +01:00
Maarten L. Hekkelman
2eb4b7b39b Fix building in Windows 2022-01-25 15:27:15 +01:00
Maarten L. Hekkelman
c241e49b48 fix makefile 2022-01-25 15:13:15 +01:00
Maarten L. Hekkelman
238c881132 Update dependencies, version string 2022-01-25 13:27:58 +01:00
Maarten L. Hekkelman
49dc733536 Create non poly from described atoms 2022-01-25 13:27:19 +01:00
Maarten L. Hekkelman
755bd78f60 Fix declaration for mmcif::Nudge 2022-01-19 13:21:29 +01:00
Maarten L. Hekkelman
77f80cd51f Fix atomic test (apparently, libatomic is only needed for std::atomic<long long>) 2022-01-19 08:25:25 +01:00
Maarten L. Hekkelman
3df6000635 cleaning up code 2022-01-18 16:06:28 +01:00
Maarten L. Hekkelman
5efee2b40d comment adjusted 2022-01-18 13:28:42 +01:00
Maarten L. Hekkelman
f3c2e59184 Merge branch 'develop' of github.com:PDB-REDO/libcifpp into develop 2022-01-18 11:26:23 +01:00
Maarten L. Hekkelman
24ab660e6e Change logic for testing std::filesystem and libatomic 2022-01-18 11:24:31 +01:00
Maarten L. Hekkelman
6c0a418068 Revert "Check atomic"
This reverts commit 07a180991e.
2022-01-18 11:12:56 +01:00
Maarten L. Hekkelman
07a180991e Check atomic 2022-01-17 11:40:46 +01:00
Maarten L. Hekkelman
4732004b67 Merge branch 'develop' into trunk 2022-01-12 16:41:18 +01:00
Maarten L. Hekkelman
faa9cd0431 Added another rotate/translate method to mmcif::Structure 2022-01-12 14:06:32 +01:00
Maarten L. Hekkelman
e0c3c2394d Fix Structure::createNonPoly to add atoms... 2022-01-11 11:21:56 +01:00
Maarten L. Hekkelman
2dec584f54 clean up code 2022-01-05 15:54:23 +01:00
Maarten L. Hekkelman
5ab2ccae40 avoid calling cif::Category::size() too often 2022-01-05 15:45:27 +01:00
Maarten L. Hekkelman
1017d08626 skip updating links when changing atom location 2022-01-05 15:24:22 +01:00
Maarten L. Hekkelman
32b1bbd943 combine translate and rotate in a single call 2022-01-05 14:27:16 +01:00
Maarten L. Hekkelman
1abf31ffa5 no-validate option in cif::Row::assign 2022-01-05 14:04:28 +01:00
Maarten L. Hekkelman
aec60829d2 more quiet code 2022-01-05 11:29:10 +01:00
Maarten L. Hekkelman
888c3c38c2 Add a 'quiet' mode (cif::VERBOSE < 0) 2022-01-05 10:36:39 +01:00
Maarten L. Hekkelman
e2c4648037 clean up 2022-01-05 10:24:37 +01:00
Maarten L. Hekkelman
f7b98c0530 refactored AtomImpl 2022-01-05 10:23:15 +01:00
Maarten L. Hekkelman
d4bd3faa16 Merge branch 'profiling-structure' into trunk 2022-01-04 10:29:23 +01:00
Maarten L. Hekkelman
c4f3b1cd7b delay loading atoms in residues 2022-01-04 09:48:41 +01:00
Maarten L. Hekkelman
74add69a83 Finish removing bzip2 support 2022-01-03 15:51:01 +01:00
Maarten L. Hekkelman
a490b19d24 version bump 2022-01-03 15:45:48 +01:00
Maarten L. Hekkelman
44cfa2c1a2 further optimisation 2022-01-03 15:19:50 +01:00
Maarten L. Hekkelman
6dd9522b3f optimized mmcif::Atom 2022-01-03 14:32:42 +01:00
Maarten L. Hekkelman
5e352cb8e4 Removed erronous dependency in config.cmake.in 2021-12-20 13:33:06 +01:00
Maarten L. Hekkelman
2fad7315b8 make DSSP::iterator bidirectional 2021-12-15 15:12:23 +01:00
Maarten L. Hekkelman
520759dfe8 update changelog 2021-12-14 15:17:50 +01:00
Maarten L. Hekkelman
577b44ae11 Fix in processing CCP4 monomers, proline is a peptide 2021-12-14 15:16:23 +01:00
Maarten L. Hekkelman
66f742d6c0 code to facilitate DSSP 2021-12-14 15:14:45 +01:00
Maarten L. Hekkelman
7ba9f688c7 Merge branch 'develop' into trunk 2021-12-10 10:39:34 +01:00
Maarten L. Hekkelman
883f0307a2 Merge branch 'develop' of github.com:PDB-REDO/libcifpp into develop 2021-12-10 10:38:43 +01:00
Maarten L. Hekkelman
c9719f873f Merge branch 'develop' into trunk 2021-12-10 10:37:04 +01:00
Maarten L. Hekkelman
123d25f853 formatting of floating points in cif files
better verbose info for differences
2021-12-10 10:35:02 +01:00
Maarten L. Hekkelman
56da42db84 formatting of floating points in cif files
better verbose info for differences
2021-12-10 10:32:21 +01:00
Maarten L. Hekkelman
7f820449ca formatting 2021-12-08 09:06:09 +01:00
Maarten L. Hekkelman
ecb2cf5f11 Fix for compiling with gcc 11.2 2021-12-08 09:03:21 +01:00
Maarten L. Hekkelman
7f27da9b3b Fixed rename-compound-test to work when not using resources 2021-11-25 16:27:45 +01:00
Maarten L. Hekkelman
01eb499c69 attempt to fix running tests in different directory 2021-11-25 16:27:42 +01:00
Maarten L. Hekkelman
1ff6f70682 changelog update 2021-11-25 16:25:53 +01:00
Maarten L. Hekkelman
ddde996e10 strip newlines from compound names read from CCD 2021-11-25 16:24:55 +01:00
Maarten L. Hekkelman
1c9212c7e0 Fixed rename-compound-test to work when not using resources 2021-11-25 16:09:15 +01:00
Maarten L. Hekkelman
a568143991 unneeded loading of resource removed from test 2021-11-24 13:52:23 +01:00
Maarten L. Hekkelman
2b6f1bd9ee attempt to fix running tests in different directory 2021-11-23 10:51:22 +01:00
Maarten L. Hekkelman
2527aa5ea6 correct version in cmakefile, fix structure-test to no longer load resource 2021-11-24 13:57:36 +01:00
Maarten L. Hekkelman
4c28091ecd Merge branch 'develop' of github.com:PDB-REDO/libcifpp into develop 2021-11-18 09:56:11 +01:00
Maarten L. Hekkelman
d49725423e re-added group to Compound. Seems to be important 2021-11-18 09:56:01 +01:00
Maarten L. Hekkelman
fcb4dc61b5 fixed writing PDB files (= remove to_upper for all header lines...) 2021-11-17 08:01:24 +01:00
Maarten L. Hekkelman
b7330c074f Fixed Structure::changeResidue to actually change the residue itself as well. 2021-11-16 08:38:14 +01:00
Maarten L. Hekkelman
e8f4123030 strip newlines from names in Compound 2021-11-15 12:37:45 +01:00
Maarten L. Hekkelman
975057c4c4 Fixed bug in structure::changeresidue when removing atoms 2021-11-15 11:32:50 +01:00
Maarten L. Hekkelman
a0e01668d1 take largest in value for best quaternion 2021-11-15 10:22:56 +01:00
Maarten L. Hekkelman
2c77491416 cleaner implementation of matrices 2021-11-12 10:36:38 +01:00
Maarten L. Hekkelman
be19e4a9cb Merge branch 'develop' of github.com:PDB-REDO/libcifpp into develop 2021-11-12 09:20:01 +01:00
Maarten L. Hekkelman
61ce91a9d7 using expression templates for matrices 2021-11-12 09:17:21 +01:00
Maarten L. Hekkelman
18f1d07e85 clean up code 2021-11-12 08:28:10 +01:00
Maarten L. Hekkelman
b596976194 correct implementation of alignpoints 2021-11-12 08:15:33 +01:00
Maarten L. Hekkelman
1f6b86d516 Merge branch 'develop' of github.com:PDB-REDO/libcifpp into develop 2021-11-11 21:41:05 +01:00
Maarten L. Hekkelman
31499b977d Fix the 3d alignment code 2021-11-11 21:39:52 +01:00
Maarten L. Hekkelman
f83850e380 git and revisions 2021-11-11 09:42:22 +01:00
Maarten L. Hekkelman
1a4ccd86fe changelog update 2021-11-03 09:28:14 +01:00
Maarten L. Hekkelman
5c3c6fec09 strip newlines from compound names read from CCD 2021-10-29 10:48:09 +02:00
Maarten L. Hekkelman
f97e742daa removed a too strict test in loading structures 2021-10-21 08:42:42 +02:00
Maarten L. Hekkelman
7f39d401e2 Optimised assigning data 2021-10-20 14:55:30 +02:00
Maarten L. Hekkelman
af412c284d clean up 2021-10-20 12:27:27 +02:00
Maarten L. Hekkelman
874cd3bae5 Fix symmetry lookup 2021-10-20 11:36:31 +02:00
Maarten L. Hekkelman
ea28ebdd13 optimized caching of items in mmcif::Atom 2021-10-19 16:10:59 +02:00
Maarten L. Hekkelman
3ba468933f Merge branch 'develop' of github.com:PDB-REDO/libcifpp into develop 2021-10-18 17:17:20 +02:00
Maarten L. Hekkelman
45f33e4bea Merge branch 'trunk' into develop 2021-10-18 11:12:56 +02:00
Maarten L. Hekkelman
021487ed16 Fix reading mmCIF file where model is defined but model 1 is missing. Version bump. 2021-10-18 11:11:03 +02:00
Maarten L. Hekkelman
cb3443ffb1 Merge branch 'develop' of github.com:PDB-REDO/libcifpp into develop 2021-10-18 09:42:30 +02:00
Maarten L. Hekkelman
6b2c9dc3e3 order of compound info, load CCD first 2021-10-18 09:40:33 +02:00
Maarten L. Hekkelman
7513cc1947 Merge branch 'trunk' into develop 2021-10-14 09:30:19 +02:00
Maarten L. Hekkelman
c98b8ae5c9 fix pkgconfig file
fix example for new interface
2021-10-13 14:25:19 +02:00
Maarten L. Hekkelman
ab2dd4b75f Merge branch 'trunk' into develop 2021-10-13 14:03:29 +02:00
Maarten L. Hekkelman
be77316545 Rename options to make them all start with CIFPP_
Add cmake options for CACHE_DIR and DATA_DIR
2021-10-13 14:01:42 +02:00
Maarten L. Hekkelman
cdfb0d9497 remove unused files 2021-10-13 12:30:44 +02:00
Maarten L. Hekkelman
71f7e7c741 Version bump, changelog updated 2021-10-13 11:51:12 +02:00
Maarten L. Hekkelman
cff099596e Fix installation rules for CCD data 2021-10-13 11:32:10 +02:00
Maarten L. Hekkelman
e182604455 Fix all tests to work with embedded data, no CCD, part 4 2021-10-13 11:23:17 +02:00
Maarten L. Hekkelman
45a7defb7e Fix all tests to work with embedded data, no CCD, part 3 2021-10-13 10:55:25 +02:00
Maarten L. Hekkelman
906f6ac1ea Fix all tests to work with embedded data, no CCD 2021-10-13 10:31:57 +02:00
Maarten L. Hekkelman
8d96e513bd rename update script 2021-10-13 09:55:02 +02:00
Maarten L. Hekkelman
cdefd063e2 Added small ccd subset for testing in absense of full CCD 2021-10-13 09:34:58 +02:00
Maarten L. Hekkelman
8bbcba76cf Performance increase by using std::string_view
Updated Structure::changeResidue
2021-10-12 16:04:27 +02:00
Maarten L. Hekkelman
c767e89a5d Fixed symmetry operator table generator 2021-10-06 12:57:18 +02:00
Maarten L. Hekkelman
b78a603dca run tests before installation 2021-10-05 11:49:54 +02:00
Maarten L. Hekkelman
18088457d3 last updates in develop 2021-09-29 14:21:41 +02:00
Maarten L. Hekkelman
056697d901 imported libname for stdc++fs 2021-09-29 13:24:16 +02:00
Maarten L. Hekkelman
2681cfad50 Merge branch 'develop' of github.com:PDB-REDO/libcifpp into develop 2021-09-29 13:21:45 +02:00
Maarten L. Hekkelman
8aaa7925a3 fix lib name 2021-09-29 13:21:37 +02:00
Maarten L. Hekkelman
d4f73e471b No need to search zlib/bzip2 in Windows 2021-09-29 11:08:05 +02:00
Maarten L. Hekkelman
750be0c4a4 for 18.04 2021-09-28 15:26:15 +02:00
Maarten L. Hekkelman
0f4a2a26fc dependencies
check compiler version
2021-09-28 14:15:17 +02:00
Maarten L. Hekkelman
6adb56341d remove boost::date_time dependency 2021-09-28 12:48:15 +02:00
Maarten L. Hekkelman
4524357cd3 zlib, again (use the zlib from boost in Windows) 2021-09-28 11:20:02 +02:00
Maarten L. Hekkelman
0b05b6f6e3 run tests in build dir 2021-09-28 10:40:40 +02:00
Maarten L. Hekkelman
6382170157 zlib 2021-09-28 09:39:15 +02:00
Maarten L. Hekkelman
c2eeb69dcc optional static libs boost 2021-09-28 09:38:35 +02:00
Maarten L. Hekkelman
f32261fc59 revert zlib in boost 2021-09-28 09:37:42 +02:00
Maarten L. Hekkelman
90c967c8c6 Merge branch 'develop' of github.com:PDB-REDO/libcifpp into develop 2021-09-28 09:30:56 +02:00
Maarten L. Hekkelman
4ac90128db zlib in boost 2021-09-28 09:30:43 +02:00
Maarten L. Hekkelman
3d71db1bb7 less stringent test for compiler version 2021-09-28 09:30:22 +02:00
Maarten L. Hekkelman
5e35ea5168 warnings and compiler detection 2021-09-28 09:17:28 +02:00
Maarten L. Hekkelman
2fc88d52eb Updating cmake file to install correct update mechanism 2021-09-28 08:50:28 +02:00
Maarten L. Hekkelman
567b0f3b57 Merge branch 'develop' of github.com:PDB-REDO/libcifpp into develop 2021-09-28 07:57:05 +02:00
Maarten L. Hekkelman
8f29386998 fix file read test 2021-09-26 14:52:34 +02:00
Maarten L. Hekkelman
d2427d57d9 unit test for reading files 2021-09-27 11:36:24 +02:00
Maarten L. Hekkelman
14a9499962 fix cmake files, pkg-config file 2021-09-27 09:36:33 +02:00
Maarten L. Hekkelman
0fafb80d44 Remove bzip2 support 2021-09-27 08:40:05 +02:00
Maarten L. Hekkelman
b5454f0943 Merge branch 'develop' of github.com:PDB-REDO/libcifpp into develop 2021-09-26 13:41:21 +02:00
Maarten L. Hekkelman
b698260d73 Merge branch 'trunk' of github.com:PDB-REDO/libcifpp into develop 2021-09-26 13:40:39 +02:00
Maarten L. Hekkelman
ccdd1b74a0 required 2021-09-26 13:39:49 +02:00
Maarten L. Hekkelman
298fe20a1b improve cmake files? 2021-09-25 12:05:42 +02:00
Maarten L. Hekkelman
12a7c45452 Merge branch 'develop' of github.com:PDB-REDO/libcifpp into develop 2021-09-24 16:02:22 +02:00
Maarten L. Hekkelman
02a28c2fd6 clean up makefile 2021-09-24 16:01:48 +02:00
Maarten L. Hekkelman
68e182b0bd Merge branch 'develop' of github.com:PDB-REDO/libcifpp into develop 2021-09-24 15:31:31 +02:00
Maarten L. Hekkelman
b0ec88f469 link compression libs 2021-09-24 15:30:34 +02:00
Maarten L. Hekkelman
4feee6ac22 Merge branch 'develop' of github.com:PDB-REDO/libcifpp into develop 2021-09-24 15:27:48 +02:00
Maarten L. Hekkelman
ee8a85ec2f static boost libs 2021-09-24 15:27:13 +02:00
Maarten L. Hekkelman
0245d4a881 Merge branch 'develop' of github.com:PDB-REDO/libcifpp into develop 2021-09-24 15:24:42 +02:00
Maarten L. Hekkelman
e8f0058956 add link of stdc++fs 2021-09-24 15:24:30 +02:00
Maarten L. Hekkelman
9c75dbaae0 Merge branch 'develop' of github.com:PDB-REDO/libcifpp into develop 2021-09-24 15:22:15 +02:00
Maarten L. Hekkelman
5bd39b598e Add filesystem check, with libstdc++fs test 2021-09-24 15:21:12 +02:00
Maarten L. Hekkelman
25a43abffd update version number, fix revision file 2021-09-24 14:06:47 +02:00
Maarten L. Hekkelman
9a7ca022e2 check for existence of run-parts to be more compatible 2021-09-21 08:56:22 +02:00
Maarten L. Hekkelman
46fe0d7caf fixed cmake file
reduced verbosity for missing atoms
update script, more cross platform
2021-09-21 08:52:48 +02:00
Maarten L. Hekkelman
0371cec415 Merge branch 'develop' of github.com:PDB-REDO/libcifpp into develop 2021-09-21 08:40:25 +02:00
Maarten L. Hekkelman
2b1020cbb9 Merge branch 'trunk' into develop 2021-09-21 08:16:57 +02:00
Andrius Merkys
8c3ce2a87d Update OpenStructure compounds.chemlib if OpenStructure is found (#8)
* Update OpenStructure compounds.chemlib if OpenStructure is found.

* Replacing the code to update OpenStructure compounds.chemlib with a call to its internal script.

* Implementing more flexible approach allowing notifying all dependent software.
2021-09-20 12:39:15 +02:00
Maarten L. Hekkelman
d633622e27 Creating new nonpoly compounds 2021-09-20 11:34:07 +02:00
Maarten L. Hekkelman
19b652f615 Merge commit '37f7dd0' into develop 2021-09-15 16:06:43 +02:00
Maarten L. Hekkelman
37f7dd0631 load compound if needed 2021-09-15 16:04:49 +02:00
Maarten L. Hekkelman
4c99710fb3 Refactored iterators (Category, Row)
const versions of find
2021-09-15 11:38:12 +02:00
Maarten L. Hekkelman
59865cdb44 Rotate and Translate of structure data
update unit-test for create_nonpoly
2021-09-14 16:09:08 +02:00
Maarten L. Hekkelman
c3434507da new find1 2021-09-14 11:25:59 +02:00
Maarten L. Hekkelman
79ecf20b85 Sometimes extracting archives does not work in cmake 2021-09-10 09:24:06 +02:00
Maarten L. Hekkelman
1de9681bb7 revert mrc test
extended nonpoly unit-test
2021-09-10 09:22:37 +02:00
Maarten L. Hekkelman
345c4778e6 start structure-test unit test
added compare functions for Datablock and Category
2021-09-08 16:58:50 +02:00
Maarten L. Hekkelman
0ccb2f88ca Added more 3d code (alignpoints) 2021-09-08 11:44:27 +02:00
Maarten L. Hekkelman
f7bef8b0e9 update dictionary
do not throw from Category::isValid()
2021-09-07 14:50:06 +02:00
Maarten L. Hekkelman
9da8608f8f Merge branch 'cmake' into trunk
install update script (optionally, unix only)
2021-09-07 10:12:46 +02:00
Maarten L. Hekkelman
496cb0b909 last minute changes for building inside CCP4 2021-09-07 10:10:38 +02:00
Maarten L. Hekkelman
583cafa91e Merge branch 'cmake' of github.com:PDB-REDO/libcifpp into cmake 2021-09-07 09:23:02 +02:00
Maarten L. Hekkelman
01da665243 test nieuwe CCP4 regels 2021-09-07 09:15:47 +02:00
Maarten L. Hekkelman
e900cd1e3d Windows 2021-09-06 14:58:47 +02:00
Maarten L. Hekkelman
a8a838b33e extract using gzip for cmake < 3.19 (?) 2021-09-02 08:43:12 +02:00
Maarten L. Hekkelman
072be25335 install update script 2021-09-01 16:53:05 +02:00
Maarten L. Hekkelman
5f50429cdb last minute changes to cmake files 2021-08-31 15:53:29 +02:00
Maarten L. Hekkelman
db3fb04172 Merged cmake changes
Updated version to 1.1.1
2021-08-31 15:50:36 +02:00
Maarten L. Hekkelman
839385c3fb update readme 2021-08-31 15:45:01 +02:00
Maarten L. Hekkelman
d508b7b2df updated changelog 2021-08-31 15:43:43 +02:00
Maarten L. Hekkelman
b1456b87c0 Updated readme 2021-08-31 14:27:51 +02:00
Maarten L. Hekkelman
58d2dcaef2 fix weak linking in Linux (when resources are not available) 2021-08-31 13:56:04 +02:00
Maarten L. Hekkelman
a9468d1cbb Fix test in cmake file 2021-08-31 12:49:52 +02:00
Maarten L. Hekkelman
a29e3e8da3 create symop table 2021-08-30 12:06:36 +02:00
Maarten L. Hekkelman
dd5df1bb2a debug code: print atom id 2021-08-25 13:08:15 +02:00
Maarten L. Hekkelman
d5d6f3a7b3 Merge branch 'newer-cmake-files' of github.com:PDB-REDO/libcifpp into newer-cmake-files 2021-08-24 12:50:26 +02:00
Maarten L. Hekkelman
9d2f2b3026 pkgconfig support 2021-08-24 12:50:20 +02:00
Maarten L. Hekkelman
74717a3047 Do not bail out in bondmap creation if compound is unknown 2021-08-24 10:52:18 +02:00
Maarten L. Hekkelman
c13ee92f1e on windows 2021-08-23 17:20:45 +02:00
Maarten L. Hekkelman
0ca04bed4f Updated cmake file, configurable data dir 2021-08-23 17:00:49 +02:00
Maarten L. Hekkelman
89850de660 export symbols in windows 2021-08-18 21:21:14 +02:00
Maarten L. Hekkelman
8bb4ebd897 update cmake rules 2021-08-18 16:31:44 +02:00
Maarten L. Hekkelman
6a67208d24 date in revision file 2021-08-18 15:19:41 +02:00
Maarten L. Hekkelman
139f32c3e8 correct dependency for tests 2021-08-18 14:29:40 +02:00
Maarten L. Hekkelman
81c0d01944 Cleaning up all warnings in MSVC 2021-08-18 14:12:56 +02:00
Maarten L. Hekkelman
1d2f997efb export stuff 2021-08-18 09:53:46 +02:00
Maarten L. Hekkelman
f126b1dac3 include boost libs 2021-08-17 14:35:51 +02:00
Maarten L. Hekkelman
bbc38262ce setting up tests in cmake 2021-08-17 14:11:19 +02:00
Maarten L. Hekkelman
caeafd3189 clean up 2021-08-17 13:43:01 +02:00
Maarten L. Hekkelman
98e3c47cdf remove configure 2021-08-17 13:38:32 +02:00
Maarten L. Hekkelman
390b230cac generate version string with cmake 2021-08-17 13:30:38 +02:00
Maarten L. Hekkelman
c5c3950c91 revision, first attempt 2021-08-17 11:33:22 +02:00
Maarten L. Hekkelman
2aea0b3b1f resources in Windows 2021-08-13 11:38:48 +02:00
Maarten L. Hekkelman
6b16e02b34 clean up warning on Windows, start using resources on Windows 2021-08-12 12:01:48 +02:00
Maarten L. Hekkelman
bb2f81318a Newer CMakeLists.txt file, now creating more correct config files. 2021-08-10 16:21:02 +02:00
Maarten L. Hekkelman
ec91d0fb22 fix test isWater in Residue when mCompound is null 2021-08-10 11:23:56 +02:00
Maarten L. Hekkelman
760e23693e remove suprious error messages,
fix getUniqueID to use correct key field
2021-08-09 15:11:18 +02:00
Maarten L. Hekkelman
cfba00ae46 Merge branch 'trunk' of github.com:PDB-REDO/libcifpp into trunk 2021-08-09 10:01:20 +02:00
Maarten L. Hekkelman
dc1cfb60ff Fix reading AlphaFold files (missing auth_seq_id error) 2021-08-09 10:00:50 +02:00
Maarten L. Hekkelman
92148304ee Safer CompoundFactoryImpl 2021-07-12 11:25:39 +02:00
Maarten L. Hekkelman
9329c0c0f6 optimisation of creating compound 2021-07-12 10:51:52 +02:00
Maarten L. Hekkelman
de3ac001fc added import statement for Windows DLL 2021-07-07 13:06:43 +02:00
Maarten L. Hekkelman
b1047154a4 missing include, export symbols on Windows 2021-06-29 10:39:47 +02:00
Maarten L. Hekkelman
c361af3792 z and bz2 finding, component.cif download 2021-05-26 14:59:59 +02:00
Maarten L. Hekkelman
73487fc24b updated for windows 2021-05-25 15:51:37 +02:00
Maarten L. Hekkelman
73513fd700 cmake file, now working on windows 2021-05-25 15:25:39 +02:00
Maarten L. Hekkelman
6b7723eb2a cmake file can now build unit-test 2021-05-25 09:42:21 +02:00
Maarten L. Hekkelman
7056c15366 Merge branch 'trunk' of github.com:PDB-REDO/libcifpp into trunk 2021-05-21 09:25:34 +02:00
Maarten L. Hekkelman
8539e050ae add code to load default components.cif file 2021-05-21 09:25:20 +02:00
Maarten L. Hekkelman
5d4c2641f6 fix cmake file, now creates unit-test 2021-05-19 15:37:07 +02:00
Maarten L. Hekkelman
bc32071576 fix cmake file 2021-05-18 15:36:46 +02:00
Maarten L. Hekkelman
3b2c57314f initial cmake file 2021-05-18 13:54:03 +02:00
Maarten L. Hekkelman
36351a0608 fix for libc++, not using in_avail anymore 2021-05-17 10:38:06 +02:00
Maarten L. Hekkelman
047b454c1d disable download ccd in configure, for travis 2021-04-28 16:49:14 +02:00
Maarten L. Hekkelman
3f5e620102 loading compound info, finished with error checking and verbose mode 2021-04-28 16:18:08 +02:00
Maarten L. Hekkelman
851a43ba4b Alternative layering of compound factory object implementations 2021-04-26 16:52:18 +02:00
Maarten L. Hekkelman
47ae50f704 only load compound when really needed 2021-04-26 13:16:58 +02:00
Maarten L. Hekkelman
33bdd6ae82 Merge branch 'trunk' of github.com:PDB-REDO/libcifpp into trunk 2021-04-21 16:03:07 +02:00
Maarten L. Hekkelman
433021727e count molecules 2021-04-21 16:02:22 +02:00
Maarten L. Hekkelman
7f23c84287 clean-up 2021-04-21 15:36:46 +02:00
Maarten L. Hekkelman
74bd2585e7 renaming, nonpoly_scheme 2021-04-21 14:41:06 +02:00
Maarten L. Hekkelman
ebb27638ff renaming compound code... 2021-04-21 14:20:36 +02:00
Maarten L. Hekkelman
3eb7e4c5bf Potential fix 2021-04-21 11:38:36 +02:00
Maarten L. Hekkelman
112f859b19 ms windows work 2021-04-21 08:32:10 +02:00
Maarten L. Hekkelman
fd08678ff6 backup 2021-04-20 17:18:15 +02:00
Maarten L. Hekkelman
2e2fc11fe1 renaming, first steps 2021-04-20 13:33:56 +02:00
Maarten L. Hekkelman
d44ed57cf9 load correct dictionary 2021-04-20 13:30:08 +02:00
Maarten L. Hekkelman
aa31acb056 no atomic? 2021-04-15 09:26:45 +02:00
Maarten L. Hekkelman
232003cb2e added sample PDB file 2021-04-14 17:31:30 +02:00
Maarten L. Hekkelman
db21dd1659 fix making, testing 2021-04-14 17:15:02 +02:00
Maarten L. Hekkelman
2f3279a5ff stand alone, write complete update scripts and config 2021-04-14 17:03:00 +02:00
Maarten L. Hekkelman
ab21317156 at least some tests should now work 2021-04-14 16:25:08 +02:00
Maarten L. Hekkelman
43cb312225 addFileResource added 2021-04-14 16:02:22 +02:00
Maarten L. Hekkelman
ce28cb7a48 Moved BondMap from libpdb-redo to libcifpp 2021-04-14 14:55:55 +02:00
Maarten L. Hekkelman
1e47fa557c indexed CCD file 2021-04-14 11:32:03 +02:00
Maarten L. Hekkelman
1ae3cf7b99 moving towards using CCD, parsing single datablock 2021-04-14 10:59:58 +02:00
Maarten L. Hekkelman
915d6504a2 First steps, remove CCP4 info from compound 2021-04-13 16:39:03 +02:00
Maarten L. Hekkelman
5e63ca7a82 Check for zlib/bzip2 linking 2021-04-13 14:13:25 +02:00
Maarten L. Hekkelman
e0777e74c2 minor updates 2021-04-08 09:26:10 +02:00
Maarten L. Hekkelman
cf465134fd fixing linux again 2021-03-10 16:46:10 +01:00
Maarten L. Hekkelman
873ac70d18 Build with MSVC 2021-03-10 14:10:25 +01:00
Maarten L. Hekkelman
9ca3c50c83 Build with MSVC 2021-03-10 14:10:02 +01:00
Maarten L. Hekkelman
cc1c7c39b1 do not build pdb2cif test for now 2021-03-10 10:37:45 +01:00
Maarten L. Hekkelman
2c6222984d link distance calculation 2021-03-10 08:46:14 +01:00
Maarten L. Hekkelman
58d7e17165 Add Anomalous remark 3 fields for phenix 2021-03-09 11:50:46 +01:00
Maarten L. Hekkelman
57618095bf fix LINK record (length position) 2021-03-09 09:09:33 +01:00
Maarten L. Hekkelman
492a1ad8ec LINK distance 2021-03-08 18:55:54 +01:00
Maarten L. Hekkelman
71da0ce345 fix in fixing distance for LINK records 2021-03-08 16:56:11 +01:00
Maarten L. Hekkelman
7dc574b534 Merge branch 'trunk' of github.com:PDB-REDO/libcifpp into trunk 2021-03-05 11:50:53 +01:00
Maarten L. Hekkelman
ff8a7a1bfd for g++-11 2021-03-05 11:50:08 +01:00
Maarten L. Hekkelman
0f963eeab1 @travis 2021-02-22 19:22:45 +01:00
Maarten L. Hekkelman
8f02665e6d symop table generator, now requires output argument 2021-02-22 17:13:50 +01:00
Maarten L. Hekkelman
8604c3ab03 merged 2021-02-22 15:23:51 +01:00
Maarten L. Hekkelman
7a61129388 refactor configure 2021-02-22 15:21:47 +01:00
Maarten L. Hekkelman
516db3d8be for travis 2021-02-20 19:40:07 +01:00
Maarten L. Hekkelman
34bdc5056a fix parsing PDB files containing carriage returns 2021-02-20 19:23:14 +01:00
Maarten L. Hekkelman
9402fd5cf3 boost flags order 2021-02-17 20:54:27 +01:00
Maarten L. Hekkelman
a6faa5ce0c fix libcifpp.pc, ax_pkg_require is not implemented in this configure yet 2021-02-17 19:44:02 +01:00
Maarten L. Hekkelman
5735a70e47 using resources... 2021-02-17 15:27:05 +01:00
Maarten L. Hekkelman
8f997658d7 update configure to configure data directories 2021-02-17 11:28:50 +01:00
Maarten L. Hekkelman
5069316326 When converting pdb to cif, calculate distance for LINKR records 2021-02-16 09:55:54 +01:00
Maarten L. Hekkelman
143f17fb2a reorganize resources 2021-02-10 13:55:40 +01:00
Maarten L. Hekkelman
900d7fa07a moved dictionaries 2021-02-10 13:28:33 +01:00
Maarten L. Hekkelman
a4389542fd pic 2021-02-10 10:42:49 +01:00
Maarten L. Hekkelman
b7f4e40917 ouch... wrong type in verbose output generation 2021-02-09 16:37:21 +01:00
Maarten L. Hekkelman
a0447ba91c implemented missing function cif::Category::find1 2021-02-08 16:24:02 +01:00
Maarten L. Hekkelman
17c9d208ad revert back to boost::regex for validator since gnu std::regex implementation is recursive without proper checks... 2021-01-25 16:51:12 +01:00
Maarten L. Hekkelman
e89311fcff init compound factory in absence of CLIBD_MON 2021-01-18 14:25:27 +01:00
Maarten L. Hekkelman
bab750fa6c USE_RSRC is really needed 2021-01-12 11:33:39 +01:00
Maarten L. Hekkelman
0caaf23767 Thread local compound factory, for servers that manipulate the factory. 2021-01-12 09:37:38 +01:00
Maarten L. Hekkelman
c5676f1dfb accept compressed raw data in mmcif::File constructor 2021-01-12 09:36:43 +01:00
Maarten L. Hekkelman
86854581f8 Add contructor loading raw data to mmcif::File 2021-01-11 16:37:18 +01:00
Maarten L. Hekkelman
ef81944826 fix hang in pdb parsing with single line file 2021-01-11 16:36:30 +01:00
Maarten L. Hekkelman
b3b53ebcc0 travis job with clang 2021-01-11 13:19:52 +01:00
Maarten L. Hekkelman
3bc0384100 Merge branch 'trunk' of github.com:PDB-REDO/libcifpp into trunk 2021-01-11 13:01:28 +01:00
Maarten L. Hekkelman
24b1c2ae58 remove Config.hpp from list of files to install 2021-01-11 13:01:20 +01:00
Maarten L. Hekkelman
c996bfcfaf added pthread flags 2021-01-11 13:00:06 +01:00
Maarten L. Hekkelman
3814635aa0 shared libraries, disable by default. Not my favourite, but hey, we need to build on MacOS as well... 2021-01-11 11:54:40 +01:00
Maarten L. Hekkelman
2b6c09cfad shared libraries, default action again 2021-01-11 11:19:34 +01:00
Maarten L. Hekkelman
9ee474081e search data_dir as well as cache_dir, for MacOS 2021-01-11 10:38:51 +01:00
Maarten L. Hekkelman
5bab298f74 search data_dir as well as cache_dir, for MacOS 2021-01-11 10:31:57 +01:00
Maarten L. Hekkelman
fd42b7f443 search data_dir as well as cache_dir, for MacOS 2021-01-11 10:28:49 +01:00
Maarten L. Hekkelman
edcea220f6 search data_dir as well as cache_dir, for MacOS 2021-01-11 10:12:14 +01:00
Maarten L. Hekkelman
a92e85f8db config.h file 2021-01-11 09:12:23 +01:00
Maarten L. Hekkelman
6fbe8bb192 refactored config file, avoid clashes in defines by autoconf 2021-01-11 08:54:49 +01:00
Maarten L. Hekkelman
5f45fd9b5b revert writing SOURCE_DATE_EPOCH since that is a Debian thing 2021-01-06 14:54:38 +01:00
Maarten L. Hekkelman
46925331c7 Merge branch 'trunk' of github.com:PDB-REDO/libcifpp into trunk 2021-01-06 13:04:06 +01:00
Maarten L. Hekkelman
84123df996 changes from Debian included 2021-01-06 13:03:52 +01:00
drlemmus
641b446195 Update update-dictionary-script
Updated URL for the mmcif dictionary download to HTTPS.
2021-01-06 08:53:54 +01:00
Maarten L. Hekkelman
34bbf06793 update config.hpp.in, fix update script to write correct filename 2020-12-17 08:49:39 +01:00
Maarten L. Hekkelman
53a88e236b check for libatomic in configure 2020-12-16 08:51:03 +01:00
Maarten L. Hekkelman
c2069a12b4 stupid typo 2020-12-15 20:24:31 +01:00
Maarten L. Hekkelman
791ab245ca Fix makefile for renamed script 2020-12-15 19:15:00 +01:00
Maarten L. Hekkelman
43287736bb Revert renaming update script 2020-12-15 16:46:09 +01:00
Maarten L. Hekkelman
34ee3321d8 update makefile, to match debian 2020-12-15 16:37:53 +01:00
Maarten L. Hekkelman
6e433ae784 fix makefile for new configure script 2020-12-15 16:16:04 +01:00
Maarten L. Hekkelman
cd370275da Fix for 32-bit architectures 2020-12-15 15:47:41 +01:00
Maarten L. Hekkelman
7ed0f4c8ae clean up configure script 2020-12-02 15:21:17 +01:00
Maarten L. Hekkelman
ea7d8ce766 do not install the cron job by default 2020-11-19 16:27:21 +01:00
Maarten L. Hekkelman
f12e877251 for travis 2020-11-19 14:19:47 +01:00
Maarten L. Hekkelman
57ce90ce7c for travis 2020-11-19 14:18:54 +01:00
Maarten L. Hekkelman
b61321e360 for travis 2020-11-19 14:11:13 +01:00
Maarten L. Hekkelman
6416056958 disable resources on macOS 2020-11-19 13:39:14 +01:00
Maarten L. Hekkelman
4fdfd03c04 update clean target 2020-11-19 12:35:17 +01:00
Maarten L. Hekkelman
a1d2438341 and this one too 2020-11-19 12:27:53 +01:00
Maarten L. Hekkelman
952aa15d6e Fixed the --enable-revision argument for configure 2020-11-19 12:15:52 +01:00
Maarten L. Hekkelman
b3e45eb0b6 typo 2020-11-19 12:06:49 +01:00
Maarten L. Hekkelman
a548b39677 revision writing 2020-11-18 16:51:16 +01:00
Maarten L. Hekkelman
d5d96c58e4 resource loading 2020-11-18 08:35:23 +01:00
Maarten L. Hekkelman
9b61a06ef1 Revert "Update .travis.yml"
This reverts commit 7dc999ef39.
2020-11-17 19:24:40 +01:00
Maarten L. Hekkelman
3dbf19ac0b added #include <array> to fix building on FreeBSD 2020-11-17 19:19:54 +01:00
Maarten L. Hekkelman
7dc999ef39 Update .travis.yml
Seems the compiler on macOS is a bit out of date?
2020-11-17 16:06:24 +01:00
Maarten L. Hekkelman
697028b706 - remove mrc usage entirely
- added example as a simple test case
2020-11-17 15:48:59 +01:00
Maarten L. Hekkelman
c260fccdb5 versioning 2020-11-17 12:55:04 +01:00
Maarten L. Hekkelman
d9bf7c941b more fixes for rename 2020-11-17 11:32:32 +01:00
Maarten L. Hekkelman
af64151c60 rename libcif++ to libcifpp 2020-11-17 11:27:40 +01:00
Maarten L. Hekkelman
da94d65c6b prepare for 1.0.0 release 2020-11-17 10:33:25 +01:00
Maarten L. Hekkelman
d51340000f - fix new row iterators
- Residue constructor for sugars
2020-11-10 09:09:02 +01:00
Maarten L. Hekkelman
6f93fa3758 new conditional iterator type 2020-11-04 15:02:58 +01:00
Maarten L. Hekkelman
598f953cc1 writing sugar trees 2020-11-04 09:15:03 +01:00
Maarten L. Hekkelman
c39304281d sugar tree work in pdb2cif 2020-11-02 15:25:39 +01:00
Maarten L. Hekkelman
5e5e5c21ed sugar support, start 2020-11-02 08:47:07 +01:00
Maarten L. Hekkelman
299e270594 Merge branch 'trunk' of github.com:PDB-REDO/libcifpp into trunk 2020-11-02 08:45:35 +01:00
Maarten L. Hekkelman
bd8a4e3639 new pdbx dictionary, clean up 2020-10-30 19:45:56 +01:00
Maarten L. Hekkelman
b3b5d05bfc boost is already installed at travis-ci 2020-10-27 14:30:09 +01:00
Maarten L. Hekkelman
268cefcb51 formal charge format in PDB fix 2020-10-27 10:44:55 +01:00
Maarten L. Hekkelman
f4e860bc2c iterate children, set property of atom 2020-10-27 09:19:24 +01:00
Maarten L. Hekkelman
b65aa46daa better symop table 2020-10-21 08:38:14 +02:00
Maarten L. Hekkelman
faef95a84d new layout of symop table to work around compiler alignment issues 2020-10-19 16:29:41 +02:00
Maarten L. Hekkelman
25dfdd2ff6 - alternates handling
- getResidue in structure
2020-10-14 15:46:16 +02:00
Maarten L. Hekkelman
88879a5de9 for usage with clipper 2020-10-13 15:56:34 +02:00
Maarten L. Hekkelman
52919f96a7 Merge branch 'trunk' of github.com:PDB-REDO/libcifpp into trunk 2020-10-07 10:56:10 +02:00
Maarten L. Hekkelman
402505098a Work around limitation in travis-ci 2020-10-07 10:55:55 +02:00
Maarten L. Hekkelman
e8d8b8be60 do check makefile 2020-10-07 10:28:27 +02:00
Maarten Hekkelman
5ff7d01bd2 added missing #include <iomanip> 2020-10-07 10:20:33 +02:00
Maarten L. Hekkelman
3f8849680b export version number of lib 2020-10-07 10:00:26 +02:00
Maarten L. Hekkelman
e450fee020 Fixed processing links 2020-10-07 09:34:12 +02:00
Maarten L. Hekkelman
d7c162c71c links fixed, again 2020-10-06 16:55:53 +02:00
Maarten L. Hekkelman
f211fa4b5e oops 2020-10-06 16:51:05 +02:00
Maarten L. Hekkelman
c3963bc453 Fixed linked update (regression) 2020-10-06 16:32:36 +02:00
Maarten L. Hekkelman
23bd51ac9c removed ItemReference operator<< 2020-10-05 15:49:26 +02:00
Maarten L. Hekkelman
9e200b947e better check for filesystem 2020-10-05 13:48:00 +02:00
Maarten L. Hekkelman
2e661d5ff4 fixed compare 2020-10-05 13:23:28 +02:00
Maarten L. Hekkelman
766d5a4d7e case insensitve match, when defined by dictionary 2020-10-05 11:25:39 +02:00
Maarten L. Hekkelman
1f24937e65 simplify condtion code. 2020-10-05 10:38:01 +02:00
Maarten L. Hekkelman
aba35c3440 fix writing HETSYN records in PDB 2020-10-05 09:00:26 +02:00
Maarten L. Hekkelman
3a8fd0ebb1 remove requirement of a full CCP4 installation at runtime 2020-09-29 09:45:21 +02:00
Maarten L. Hekkelman
69a2d53277 Merge branch 'trunk' of github.com:PDB-REDO/libcifpp into trunk 2020-09-28 16:42:24 +02:00
Maarten L. Hekkelman
0b66d67ef3 fixing git repository 2020-09-28 16:42:00 +02:00
Maarten L. Hekkelman
1f22326db6 global replace is evil and should be forbidden 2020-09-28 16:23:47 +02:00
Maarten L. Hekkelman
b4dfdb5515 Revert "Work around dropped categories _pdbx_item_linked_group_list and _pdbx_item_linked_group"
This reverts commit 71a46cd10e.
2020-09-28 16:23:22 +02:00
Maarten L. Hekkelman
25512340c8 Revert "Work around dropped categories _pdbx_item_linked_group_list and _pdbx_item_linked_group"
This reverts commit 71a46cd10e.
2020-09-28 15:35:35 +02:00
Maarten L. Hekkelman
d2d322ba30 unit test 2020-09-28 13:22:55 +02:00
Maarten L. Hekkelman
96a26eae4a Added a unit test 2020-09-28 11:48:56 +02:00
Maarten L. Hekkelman
71a46cd10e Work around dropped categories _pdbx_item_linked_group_list and _pdbx_item_linked_group 2020-09-28 10:50:50 +02:00
Maarten L. Hekkelman
013af6af46 update debian files 2020-09-28 09:49:50 +02:00
202 changed files with 389846 additions and 227311 deletions

22
.gitignore vendored
View File

@@ -1,14 +1,10 @@
obj.dbg/
obj/
.libs/
build/
.vscode/
autom4te.cache/
GNUmakefile
include/cif++/Config.hpp
tools/symop-map-generator
test/unit-test
libcif++.pc
libcif++.la
config.status
config.log
libtool
.vs/
tools/update-libcifpp-data
data/components.cif*
CMakeSettings.json
msvc/
src/revision.hpp
test/test-create_sugar_?.cif
Testing/

View File

@@ -1,34 +0,0 @@
language: cpp
os:
- linux
- osx
dist: focal
osx_image:
- xcode12
compiler:
- gcc
# - clang
addons:
apt:
packages:
- libboost-all-dev
before_install:
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew update ; fi
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew install boost make; fi
script:
- ./configure
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then gmake ; else make ; fi
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then gmake test ; else make test ; fi
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then sudo gmake install; else sudo make install; fi
jobs:
allow_failures:
- os: osx

510
CMakeLists.txt Normal file
View File

@@ -0,0 +1,510 @@
# SPDX-License-Identifier: BSD-2-Clause
# Copyright (c) 2021 NKI/AVL, Netherlands Cancer Institute
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# 1. Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
cmake_minimum_required(VERSION 3.16)
# set the project name
project(cifpp VERSION 5.1.0 LANGUAGES CXX)
list(PREPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
include(GNUInstallDirs)
include(CheckFunctionExists)
include(CheckIncludeFiles)
include(CheckLibraryExists)
include(CMakePackageConfigHelpers)
include(CheckCXXSourceCompiles)
include(Dart)
include(GenerateExportHeader)
set(CXX_EXTENSIONS OFF)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# set(CMAKE_CXX_VISIBILITY_PRESET hidden)
# set(CMAKE_VISIBILITY_INLINES_HIDDEN 1)
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")
endif()
# Building shared libraries?
option(BUILD_SHARED_LIBS "Build a shared library instead of a static one" OFF)
# We do not want to write an export file for all our symbols...
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)
# Lots of code depend on the availability of the components.cif file
option(CIFPP_DOWNLOAD_CCD "Download the CCD file components.cif during installation" ON)
# An optional cron script can be installed to keep the data files up-to-date
if(UNIX)
option(CIFPP_INSTALL_UPDATE_SCRIPT "Install the script to update CCD and dictionary files" ON)
endif()
# When CCP4 is sourced in the environment, we can recreate the symmetry operations table
if(EXISTS "$ENV{CCP4}")
if(EXISTS "$ENV{CLIBD}/syminfo.lib")
option(CIFPP_RECREATE_SYMOP_DATA "Recreate SymOp data table in case it is out of date" ON)
else()
set(CIFPP_RECREATE_SYMOP_DATA OFF)
message(WARNING "Symop data table recreation requested, but file syminfo.lib was not found in $ENV{CLIBD}")
endif()
else()
set(CIFPP_RECREATE_SYMOP_DATA OFF)
message("Not trying to recreate symop_table_data.hpp since CCP4 is not defined")
endif()
# Unit tests
option(ENABLE_TESTING "Build test exectuables" 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")
else()
list(APPEND CMAKE_MODULE_PATH "$ENV{CCP4}")
list(APPEND CMAKE_PREFIX_PATH "$ENV{CCP4}")
set(CMAKE_INSTALL_PREFIX "$ENV{CCP4}")
set(CMAKE_INSTALL_FULL_DATADIR "${CMAKE_INSTALL_PREFIX}/share/libcifpp")
if(WIN32)
set(BUILD_SHARED_LIBS ON)
endif()
endif()
endif()
if(MSVC)
# make msvc standards compliant...
add_compile_options(/permissive-)
macro(get_WIN32_WINNT version)
if(CMAKE_SYSTEM_VERSION)
set(ver ${CMAKE_SYSTEM_VERSION})
string(REGEX MATCH "^([0-9]+).([0-9])" ver ${ver})
string(REGEX MATCH "^([0-9]+)" verMajor ${ver})
# Check for Windows 10, b/c we'll need to convert to hex 'A'.
if("${verMajor}" MATCHES "10")
set(verMajor "A")
string(REGEX REPLACE "^([0-9]+)" ${verMajor} ver ${ver})
endif()
# Remove all remaining '.' characters.
string(REPLACE "." "" ver ${ver})
# Prepend each digit with a zero.
string(REGEX REPLACE "([0-9A-Z])" "0\\1" ver ${ver})
set(${version} "0x${ver}")
endif()
endmacro()
get_WIN32_WINNT(ver)
add_definitions(-D_WIN32_WINNT=${ver})
endif()
# Libraries
# Start by finding out if std:regex is usable. Note that the current
# implementation in GCC is not acceptable, it crashes on long lines.
# The implementation in libc++ (clang) and MSVC seem to be OK.
check_cxx_source_compiles("
#include <iostream>
#ifndef __GLIBCXX__
#error
#endif
int main(int argc, char *argv[]) { return 0; }" GXX_LIBSTDCPP)
if(GXX_LIBSTDCPP)
message(STATUS "Testing for known regex bug, since you're using GNU libstdc++")
try_run(STD_REGEX_RUNNING STD_REGEX_COMPILING
${CMAKE_CURRENT_BINARY_DIR}/test ${PROJECT_SOURCE_DIR}/cmake/test-rx.cpp)
if(STD_REGEX_RUNNING STREQUAL FAILED_TO_RUN)
message(STATUS "You are probably trying to compile using the g++ standard library which contains a crashing std::regex implementation. Will use boost::regex instead")
add_subdirectory(regex EXCLUDE_FROM_ALL)
set(BOOST_REGEX ON)
endif()
endif()
set(CMAKE_THREAD_PREFER_PTHREAD)
set(THREADS_PREFER_PTHREAD_FLAG)
find_package(Threads)
if(MSVC)
# Avoid linking the shared library of zlib
# Search ZLIB_ROOT first if it is set.
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)
foreach(search ${_ZLIB_SEARCHES})
find_library(ZLIB_LIBRARY NAMES zlibstatic NAMES_PER_DIR ${${search}} PATH_SUFFIXES lib)
endforeach()
endif()
find_package(ZLIB REQUIRED)
find_package(Eigen3 REQUIRED)
include(FindFilesystem)
list(APPEND CIFPP_REQUIRED_LIBRARIES ${STDCPPFS_LIBRARY})
include(FindAtomic)
list(APPEND CIFPP_REQUIRED_LIBRARIES ${STDCPPATOMIC_LIBRARY})
if(MSVC)
# this dependency can go once MSVC supports std::experimental::is_detected
find_package(zeep 5.1.8 REQUIRED)
list(APPEND CIFPP_REQUIRED_LIBRARIES zeep::zeep)
endif()
# Create a revision file, containing the current git version info
include(VersionString)
write_version_header(${PROJECT_SOURCE_DIR}/src/ "LibCIFPP")
# SymOp data table
if(CIFPP_RECREATE_SYMOP_DATA)
# The tool to create the table
add_executable(symop-map-generator "${PROJECT_SOURCE_DIR}/src/symop-map-generator.cpp")
add_custom_command(
OUTPUT ${PROJECT_SOURCE_DIR}/src/symop_table_data.hpp
COMMAND $<TARGET_FILE:symop-map-generator> $ENV{CLIBD}/syminfo.lib $ENV{CLIBD}/symop.lib ${PROJECT_SOURCE_DIR}/src/symop_table_data.hpp
)
add_custom_target(
OUTPUT ${PROJECT_SOURCE_DIR}/src/symop_table_data.hpp
DEPENDS symop-map-generator "$ENV{CLIBD}/syminfo.lib" "$ENV{CLIBD}/symop.lib"
)
endif()
# Sources
set(project_sources
${PROJECT_SOURCE_DIR}/src/category.cpp
${PROJECT_SOURCE_DIR}/src/condition.cpp
${PROJECT_SOURCE_DIR}/src/datablock.cpp
${PROJECT_SOURCE_DIR}/src/dictionary_parser.cpp
${PROJECT_SOURCE_DIR}/src/file.cpp
${PROJECT_SOURCE_DIR}/src/item.cpp
${PROJECT_SOURCE_DIR}/src/parser.cpp
${PROJECT_SOURCE_DIR}/src/row.cpp
${PROJECT_SOURCE_DIR}/src/validate.cpp
${PROJECT_SOURCE_DIR}/src/text.cpp
${PROJECT_SOURCE_DIR}/src/utilities.cpp
${PROJECT_SOURCE_DIR}/src/atom_type.cpp
${PROJECT_SOURCE_DIR}/src/compound.cpp
${PROJECT_SOURCE_DIR}/src/point.cpp
${PROJECT_SOURCE_DIR}/src/symmetry.cpp
${PROJECT_SOURCE_DIR}/src/model.cpp
${PROJECT_SOURCE_DIR}/src/pdb/cif2pdb.cpp
${PROJECT_SOURCE_DIR}/src/pdb/pdb2cif.cpp
${PROJECT_SOURCE_DIR}/src/pdb/pdb2cif_remark_3.cpp
${PROJECT_SOURCE_DIR}/src/pdb/tls.cpp
)
set(project_headers
${PROJECT_SOURCE_DIR}/include/cif++.hpp
${PROJECT_SOURCE_DIR}/include/cif++/utilities.hpp
${PROJECT_SOURCE_DIR}/include/cif++/item.hpp
${PROJECT_SOURCE_DIR}/include/cif++/datablock.hpp
${PROJECT_SOURCE_DIR}/include/cif++/file.hpp
${PROJECT_SOURCE_DIR}/include/cif++/validate.hpp
${PROJECT_SOURCE_DIR}/include/cif++/iterator.hpp
${PROJECT_SOURCE_DIR}/include/cif++/parser.hpp
${PROJECT_SOURCE_DIR}/include/cif++/forward_decl.hpp
${PROJECT_SOURCE_DIR}/include/cif++/dictionary_parser.hpp
${PROJECT_SOURCE_DIR}/include/cif++/condition.hpp
${PROJECT_SOURCE_DIR}/include/cif++/category.hpp
${PROJECT_SOURCE_DIR}/include/cif++/row.hpp
${PROJECT_SOURCE_DIR}/include/cif++/atom_type.hpp
${PROJECT_SOURCE_DIR}/include/cif++/compound.hpp
${PROJECT_SOURCE_DIR}/include/cif++/point.hpp
${PROJECT_SOURCE_DIR}/include/cif++/symmetry.hpp
${PROJECT_SOURCE_DIR}/include/cif++/model.hpp
${PROJECT_SOURCE_DIR}/include/cif++/pdb/cif2pdb.hpp
${PROJECT_SOURCE_DIR}/include/cif++/pdb/io.hpp
${PROJECT_SOURCE_DIR}/include/cif++/pdb/pdb2cif.hpp
${PROJECT_SOURCE_DIR}/include/cif++/pdb/pdb2cif_remark_3.hpp
${PROJECT_SOURCE_DIR}/include/cif++/pdb/tls.hpp
)
add_library(cifpp ${project_sources} ${project_headers} ${PROJECT_SOURCE_DIR}/src/symop_table_data.hpp)
add_library(cifpp::cifpp ALIAS cifpp)
generate_export_header(cifpp EXPORT_FILE_NAME cif++/exports.hpp)
if(BOOST_REGEX)
target_compile_definitions(cifpp PRIVATE USE_BOOST_REGEX=1 BOOST_REGEX_STANDALONE=1)
target_include_directories(cifpp PRIVATE regex/include)
endif()
if(MSVC)
target_compile_definitions(cifpp PUBLIC NOMINMAX=1)
endif()
set_target_properties(cifpp PROPERTIES POSITION_INDEPENDENT_CODE ON)
target_include_directories(cifpp
PUBLIC
"$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include;${PROJECT_BINARY_DIR};${EIGEN3_INCLUDE_DIR}>"
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
)
target_link_libraries(cifpp PUBLIC Threads::Threads ZLIB::ZLIB ${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")
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)
file(MAKE_DIRECTORY ${PROJECT_SOURCE_DIR}/data/)
endif()
find_program(GUNZIP gunzip)
if(GUNZIP)
file(DOWNLOAD ftp://ftp.wwpdb.org/pub/pdb/data/monomers/components.cif.gz ${COMPONENTS_CIF}.gz
SHOW_PROGRESS)
add_custom_command(OUTPUT ${COMPONENTS_CIF}
COMMAND ${GUNZIP} ${COMPONENTS_CIF}.gz
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/data/)
else()
file(DOWNLOAD ftp://ftp.wwpdb.org/pub/pdb/data/monomers/components.cif ${COMPONENTS_CIF}
SHOW_PROGRESS)
endif()
endif()
add_custom_target(COMPONENTS ALL DEPENDS ${COMPONENTS_CIF})
endif()
# Installation directories
set(CIFPP_DATA_DIR "${CMAKE_INSTALL_FULL_DATADIR}/libcifpp")
target_compile_definitions(cifpp PUBLIC DATA_DIR="${CIFPP_DATA_DIR}")
if(UNIX)
set(CIFPP_CACHE_DIR "${CMAKE_INSTALL_FULL_LOCALSTATEDIR}/cache/libcifpp")
target_compile_definitions(cifpp PUBLIC CACHE_DIR="${CIFPP_CACHE_DIR}")
set(CIFPP_ETC_DIR "${CMAKE_INSTALL_FULL_SYSCONFDIR}")
endif()
# Install rules
install(TARGETS cifpp
EXPORT cifppTargets
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
if(MSVC AND BUILD_SHARED_LIBS)
install(
FILES $<TARGET_PDB_FILE:${PROJECT_NAME}>
DESTINATION ${CMAKE_INSTALL_LIBDIR}
OPTIONAL)
endif()
install(EXPORT cifppTargets
FILE "cifppTargets.cmake"
NAMESPACE cifpp::
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/cifpp
)
install(
DIRECTORY include/cif++
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
COMPONENT Devel
)
install(
FILES include/cif++.hpp
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
COMPONENT Devel
)
install(
FILES ${PROJECT_BINARY_DIR}/cif++/exports.hpp
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/cif++
COMPONENT Devel
)
install(FILES
${PROJECT_SOURCE_DIR}/rsrc/mmcif_ddl.dic
${PROJECT_SOURCE_DIR}/rsrc/mmcif_pdbx.dic
${PROJECT_SOURCE_DIR}/rsrc/mmcif_ma.dic
${COMPONENTS_CIF}
DESTINATION ${CIFPP_DATA_DIR}
)
if(${CIFPP_CACHE_DIR})
install(FILES
${PROJECT_SOURCE_DIR}/rsrc/mmcif_ddl.dic
${PROJECT_SOURCE_DIR}/rsrc/mmcif_pdbx.dic
${PROJECT_SOURCE_DIR}/rsrc/mmcif_ma.dic
${COMPONENTS_CIF}
DESTINATION ${CIFPP_CACHE_DIR}
)
endif()
set(CONFIG_TEMPLATE_FILE ${PROJECT_SOURCE_DIR}/cmake/cifppConfig.cmake.in)
configure_package_config_file(
${CONFIG_TEMPLATE_FILE}
${CMAKE_CURRENT_BINARY_DIR}/cifpp/cifppConfig.cmake
INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/cifpp
PATH_VARS CIFPP_DATA_DIR
)
install(FILES
"${CMAKE_CURRENT_BINARY_DIR}/cifpp/cifppConfig.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/cifpp/cifppConfigVersion.cmake"
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/cifpp
COMPONENT Devel
)
set(cifpp_MAJOR_VERSION ${CMAKE_PROJECT_VERSION_MAJOR})
set_target_properties(cifpp PROPERTIES
VERSION ${PROJECT_VERSION}
SOVERSION ${cifpp_MAJOR_VERSION}
INTERFACE_cifpp_MAJOR_VERSION ${cifpp_MAJOR_VERSION})
set_property(TARGET cifpp APPEND PROPERTY
COMPATIBLE_INTERFACE_STRING cifpp_MAJOR_VERSION
)
write_basic_package_version_file(
"${CMAKE_CURRENT_BINARY_DIR}/cifpp/cifppConfigVersion.cmake"
VERSION ${PROJECT_VERSION}
COMPATIBILITY AnyNewerVersion
)
# pkgconfig support
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})
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/libcifpp.pc.in
${CMAKE_CURRENT_BINARY_DIR}/libcifpp.pc.in @ONLY)
file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/libcifpp.pc
INPUT ${CMAKE_CURRENT_BINARY_DIR}/libcifpp.pc.in)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libcifpp.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
if(ENABLE_TESTING)
enable_testing()
find_package(Boost REQUIRED)
list(APPEND CIFPP_tests unit-v2 unit-3d format model rename-compound sugar spinner)
foreach(CIFPP_TEST IN LISTS CIFPP_tests)
set(CIFPP_TEST "${CIFPP_TEST}-test")
set(CIFPP_TEST_SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/test/${CIFPP_TEST}.cpp")
add_executable(${CIFPP_TEST} ${CIFPP_TEST_SOURCE})
target_link_libraries(${CIFPP_TEST} PRIVATE Threads::Threads cifpp::cifpp Boost::boost)
if(MSVC)
# Specify unwind semantics so that MSVC knowns how to handle exceptions
target_compile_options(${CIFPP_TEST} PRIVATE /EHsc)
endif()
add_custom_target("run-${CIFPP_TEST}" DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/Run${CIFPP_TEST}.touch ${CIFPP_TEST})
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Run${CIFPP_TEST}.touch
COMMAND $<TARGET_FILE:${CIFPP_TEST}> -- ${CMAKE_CURRENT_SOURCE_DIR}/test)
add_test(NAME ${CIFPP_TEST}
COMMAND $<TARGET_FILE:${CIFPP_TEST}> -- ${CMAKE_CURRENT_SOURCE_DIR}/test)
endforeach()
endif()
# Optionally install the update scripts for CCD and dictionary files
if(CIFPP_INSTALL_UPDATE_SCRIPT)
if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
set(CIFPP_CRON_DIR "${CIFPP_ETC_DIR}/cron.weekly")
elseif(UNIX) # assume all others are like FreeBSD...
set(CIFPP_CRON_DIR "${CIFPP_ETC_DIR}/periodic/weekly")
else()
message(FATAL_ERROR "Don't know where to install the update script")
endif()
configure_file(${PROJECT_SOURCE_DIR}/tools/update-libcifpp-data.in update-libcifpp-data @ONLY)
install(
FILES ${CMAKE_CURRENT_BINARY_DIR}/update-libcifpp-data
DESTINATION ${CIFPP_CRON_DIR}
PERMISSIONS OWNER_EXECUTE OWNER_READ GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ
)
install(DIRECTORY DESTINATION ${CIFPP_CACHE_DIR})
install(DIRECTORY DESTINATION "${CIFPP_ETC_DIR}/libcifpp/cache-update.d")
# a config to, to make it complete
if(NOT EXISTS "${CIFPP_ETC_DIR}/libcifpp.conf")
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/libcifpp.conf [[# Uncomment the next line to enable automatic updates
# update=true
]])
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libcifpp.conf DESTINATION "${CIFPP_ETC_DIR}")
install(CODE "message(\"A configuration file has been written to ${CIFPP_ETC_DIR}/libcifpp.conf, please edit this file to enable automatic updates\")")
endif()
target_compile_definitions(cifpp PUBLIC CACHE_DIR="${CIFPP_CACHE_DIR}")
endif()
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE")
set(CPACK_SOURCE_TGZ ON)
set(CPACK_SOURCE_TBZ2 OFF)
set(CPACK_SOURCE_TXZ OFF)
set(CPACK_SOURCE_TZ OFF)
set(CPACK_SOURCE_IGNORE_FILES "/data/components.cif;/build;/.vscode;/.git")
set(CPACK_PACKAGE_FILE_NAME "${PROJECT_NAME}-${PROJECT_VERSION}")
set(CPACK_SOURCE_PACKAGE_FILE_NAME ${CPACK_PACKAGE_FILE_NAME})
include(CPack)

View File

@@ -1,229 +0,0 @@
# 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
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# makefile for libcif++
.PHONY: firstTarget
firstTarget: all
CXX = @CXX@
CXXFLAGS = @CXXFLAGS@ @BOOST_CPPFLAGS@ @LIBBZ2_CPPFLAGS@
LDFLAGS = @LDFLAGS@ @LIBS@ @BOOST_LDFLAGS@ @LIBBZ2_LDFLAGS@
LIBS = @LIBS@ \
@BOOST_IOSTREAMS_LIB@
prefix = @prefix@
exec_prefix = @exec_prefix@
libdir = @libdir@
includedir = @includedir@
datarootdir = @datarootdir@
datadir = @datadir@
pkgconfigdir = $(libdir)/pkgconfig
LIB_NAME = @PACKAGE_NAME@
LIB_TARGET = $(LIB_NAME).la
CCP4DIR = @CCP4@
CLIBD ?= $(CCP4DIR)/lib/data
DATADIR = $(datadir)/libcifpp
ifeq "$(CHECK_CONFIG)" "1"
GNUmakefile: config.status GNUmakefile.in
$(SHELL) ./config.status
config.status: configure
$(SHELL) ./config.status --recheck
configure: configure.ac
autoconf
LIBTOOL_DEPS = @LIBTOOL_DEPS@
libtool: $(LIBTOOL_DEPS)
$(SHELL) ./config.status --recheck
endif
# libtool stuff
LIBTOOL = $(SHELL) ./libtool
CXXCOMPILE = $(LIBTOOL) --silent --tag=CXX --mode=compile $(CXX) $(CXXFLAGS)
CXXLINK = $(LIBTOOL) --silent --tag=CXX --mode=link $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@
# main build variables
CXXFLAGS += -I. -pthread -I include/
CXXFLAGS += -Wall -Wno-multichar
# Use the DEBUG flag to build debug versions of the code
DEBUG = @DEBUG@
ifeq "$(DEBUG)" "1"
DEFINES += DEBUG
CXXFLAGS += -g -O0
LDFLAGS += -g
else
CXXFLAGS += -O2
DEFINES += NDEBUG
endif
# targets
VPATH += src:test
CXXFLAGS += $(DEFINES:%=-D%)
OBJDIR = obj
ifeq "$(DEBUG)" "1"
OBJDIR := $(OBJDIR).dbg
endif
$(OBJDIR):
mkdir -p $(OBJDIR)
LIBCIF_SRC = AtomType.cpp \
Cif2PDB.cpp \
Cif++.cpp \
CifParser.cpp \
CifUtils.cpp \
CifValidator.cpp \
Compound.cpp \
PDB2Cif.cpp \
PDB2CifRemark3.cpp \
Point.cpp \
Secondary.cpp \
Structure.cpp \
Symmetry.cpp \
TlsParser.cpp
SOURCES = $(addprefix src/,$(LIBCIF_SRC))
OBJECTS = $(addprefix $(OBJDIR)/, $(notdir $(SOURCES:%.cpp=%.lo)))
ifneq "$(CCP4DIR)" ""
# Special rules to generate symmetry operation number table
tools/symop-map-generator: tools/symop-map-generator.cpp
src/SymOpTable_data.cpp: tools/symop-map-generator $(CLIBD)/symop.lib
tools/symop-map-generator > $@
$(OBJDIR)/Symmetry.lo: src/SymOpTable_data.cpp
endif
$(LIB_TARGET): $(OBJECTS)
$(CXXLINK) -rpath $(libdir) $(OBJECTS) $(LIBS)
lib: $(LIB_TARGET)
.PHONY: libs
all: lib
.PHONY: all
-include $(OBJECTS:%.lo=%.d)
$(OBJECTS:.lo=.d):
$(OBJDIR)/%.lo: %.cpp | $(OBJDIR)
@ echo ">>" $<
@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(OBJDIR)/$*.d -c -o $@ $<
$(OBJDIR)/%.o: %.cpp | $(OBJDIR)
@ echo ">>" $<
@ $(CXX) $(CXXFLAGS) -MT $@ -MD -MP -MF $(OBJDIR)/$*.d -c -o $@ $<
.PHONY: clean
clean:
rm -rf .libs $(OBJDIR)/* $(LIB_TARGET)
.PHONY: distclean
distclean: clean
rm -f libtool config.lt
rm -f config.status config.cache config.log configure.lineno config.status.lineno
rm -f GNUmakefile
# Test rules
define TEST_template =
-include $$(OBJDIR)/$(1)-test.d
$(1)_OBJECTS = $$(OBJDIR)/$(1)-test.o
test/$(1)-test: $(LIB_TARGET) $$($(1)_OBJECTS)
@ echo ">>> building $(1)-test"
$(LIBTOOL) --silent --tag=CXX --mode=link $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $$@ $$($(1)_OBJECTS) -L.libs -lcif++ $(LIBS)
.PHONY: $(1)-test
$(1)-test: test/$(1)-test
cd test; ./$(1)-test $$($(1)_PARAMS)
endef
TESTS = unit
$(foreach part,$(TESTS),$(eval $(call TEST_template,$(part))))
.PHONY: test
test: $(TESTS:%=%-test)
HEADERS = \
AtomType.hpp \
CifParser.hpp \
Compound.hpp \
PDB2CifRemark3.hpp \
Structure.hpp \
Cif2PDB.hpp \
CifUtils.hpp \
Config.hpp \
Point.hpp \
Symmetry.hpp \
Cif++.hpp \
CifValidator.hpp \
PDB2Cif.hpp \
Secondary.hpp \
TlsParser.hpp
.PHONY: install-lib
install-lib: lib
install -d $(libdir)
$(LIBTOOL) --mode=install install $(LIB_TARGET) $(libdir)
install -d $(DATADIR)/dictionaries
for d in mmcif_ddl.dic mmcif_pdbx.dic; do \
install -m644 rsrc/dictionaries/$$d $(DATADIR)/dictionaries/$$d; \
done
.PHONY: install-dev
install-dev:
install -d $(includedir)/cif++
for f in $(HEADERS); do install include/cif++/$$f $(includedir)/cif++/$$f; done
install -d $(pkgconfigdir)
install -m 644 $(LIB_NAME).pc $(pkgconfigdir)/$(LIB_NAME).pc
.PHONY: install
install: install-lib install-dev
dist-clean: clean
FORCE:

View File

@@ -1,6 +1,7 @@
SPDX-License-Identifier: BSD-2-Clause
BSD-2-Clause License
Copyright (c) 2020 NKI/AVL, Netherlands Cancer Institute
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
@@ -20,4 +21,4 @@ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -1,32 +1,101 @@
[![Build Status](https://travis-ci.org/PDB-REDO/libcifpp.svg?branch=trunk)](https://travis-ci.org/PDB-REDO/libcifpp)
libcif++
libcifpp
========
This library contains code to work with mmCIF and PDB files.
Synopsis
--------
```c++
// A simple program counting residues with an OXT atom
#include <filesystem>
#include <iostream>
#include <cif++.hpp>
namespace fs = std::filesystem;
int main(int argc, char *argv[])
{
if (argc != 2)
exit(1);
// Read file, can be PDB or mmCIF and can even be compressed with gzip.
cif::file file = cif::pdb::read(argv[1]);
if (file.empty())
{
std::cerr << "Empty file" << std::endl;
exit(1);
}
auto &db = file.front();
auto &atom_site = db["atom_site"];
auto n = atom_site.find(cif::key("label_atom_id") == "OXT").size();
std::cout << "File contains " << atom_site.size() << " atoms of which "
<< n << (n == 1 ? " is" : " are") << " OXT" << std::endl
<< "residues with an OXT are:" << std::endl;
for (const auto &[asym, comp, seqnr] :
atom_site.find<std::string, std::string, int>(
cif::key("label_atom_id") == "OXT",
"label_asym_id", "label_comp_id", "label_seq_id"))
{
std::cout << asym << ' ' << comp << ' ' << seqnr << std::endl;
}
return 0;
}
```
Requirements
------------
The code for this library was written in C++17. You therefore need a
recent compiler to build it. For the development gcc 9.3 and clang 9.0
have been used.
recent compiler to build it. For the development gcc 9.4 and clang 9.0
have been used as well as MSVC version 2019.
Other requirements are:
- GNU make version 4.1 or higher.
- Boost libraries, at least version 1.71
- [mrc](https://github.com/mhekkel/mrc), a resource compiler that
allows including data files into the executable making them easier to
install. Strictly this is optional, but at the expense of a lot of
install. Strictly speaking this is optional, but at the expense of
functionality.
- [libeigen](https://eigen.tuxfamily.org/index.php?title=Main_Page), a
library to do amongst others matrix calculations. This usually can be
installed using your package manager, in Debian/Ubuntu it is called
`libeigen3-dev`
- zlib, the development version of this library. On Debian/Ubuntu this
is the package `zlib1g-dev`.
- [boost](https://www.boost.org). The boost libraries are only needed if
you want to build the testing code.
When building using MS Visual Studio, you will also need [libzeep](https://github.com/mhekkel/libzeep)
since MSVC does not yet provide a C++ template required by libcifpp.
Building
--------
Simply configure, make and make install.
This library uses [cmake](https://cmake.org). The usual way of building
and installing is to create a `build` directory and run cmake there.
There's one configure flag that might be of interest: if you specify
DEBUG=1 the make will create a debug version by default. Otherwise,
you can run make with DEBUG=1 to create a debug version.
On linux e.g. you would issue the following commands to build and install
libcifpp in your `$HOME/.local` folder:
```bash
git clone https://github.com/PDB-REDO/libcifpp.git --recurse-submodules
cd libcifpp
cmake -S . -B build -DCMAKE_INSTALL_PREFIX=$HOME/.local -DCMAKE_BUILD_TYPE=Release
cmake --build build
cmake --install build
```
This checks out the source code from github, creates a new directory
where cmake stores its files. Run a configure, build the code and then
it installs the library and auxiliary files.
If you want to run the tests before installing, you should add `-DENABLE_TESTING=ON`
to the first cmake command.

1685
aclocal.m4 vendored

File diff suppressed because it is too large Load Diff

142
changelog Normal file
View File

@@ -0,0 +1,142 @@
Version 5.1
- New parser, optimised for speed
- Fix in unique ID generator
Version 5.0.10
- Fix in progress_bar, was using too much CPU
- Optimised mmCIF parser
Version 5.0.9
- Fix in dihedral angle calculations
- Added create_water to model
- Writing twin domain info in PDB files and more PDB fixes
- remove_atom improved (remove struct_conn records)
- Added a specialisation for category::find1<std::optional>
- fix memory leak in category
Version 5.0.8
- implemented find_first, find_min, find_max and count in category
- find1 now throws an exception if condition does not not exactly match one row
- Change in writing out PDB files, now looking up the original auth_seq_num
via the pdbx_xxx_scheme categories based on the atom_site.auth_seq_num ->
pdbx_xxx_scheme.pdb_seq_num relationship.
- fix memory leak in category
Version 5.0.7.1
- Use the implementation from zeep for std::experimental::is_detected
Version 5.0.7
- Reintroduce exports file. For DLL's
Version 5.0.6
- Fix file::contains, using iequals
- Fix is_cis
Version 5.0.5
- Fix code to work on 32 bit machines
Version 5.0.4
- Revert removal of CIFPP_SHARE_DIR export
Version 5.0.3
- Fix installation of libcifpp into the correct locations
Version 5.0.2
- Fix export of CISPEP records in PDB format
- Better support for exporting package_source
Version 5.0.1
- Fix loading dictionaries
- Support for cifv1.0 files
Version 5.0.0
- Total rewrite of cif part
- Removed DSSP code, moved into dssp project itself
Version 4.2.1
- Improved REMARK 3 parser (for TLS in large molecules)
Version 4.2.0
- Yet another rewrite of resource loading
Version 4.1.1
- Fall back to zero charge for scattering factors if the atom
was not found in the table.
- Improve code to locate resources, failing less.
Version 4.1.0
- Some interface changes for mmcif::Atom
Version 4.0.1
- Added a bunch of const methods to Datablock and Category.
- Changed PDB writing interface to accept Datablock instead of File.
Version 4.0.0
- getResidue in mmcif::Structure now requires both a
sequence ID and an auth sequence ID. As a result the code was cleaned
up considerably.
Version 3.0.5
- mmcif::Structure redesign. It is now a wrapper around a cif::Datablock.
Version 3.0.4
- Fix in mmCIF parser, now correctly handles the unquoted
string ??
Version 3.0.3
- Better configuration checks, for atomic e.g.
- Fixed a problem introduced in refactoring mmcif::Atom
- Version string creation
Version 3.0.2
- refactored mmcif::Atom for performance reasons
Version 3.0.1
- Fixed processing of proline restraints file from CCP4, proline
is a peptide, really.
- Added code to facilitate DSSP
Version 3.0.0
- Replaced many strings in the API with string_view for
performance reasons.
- Upgraded mmcif::Structure
- various other small fixes
Version 2.0.5
- Backporting updated CMakeLists.txt file
Version 2.0.4
- Reverted a too strict test when reading cif files.
Version 2.0.3
- Fixed reading mmCIF files where model numbers are used and
model number 1 is missing.
Version 2.0.2
- Added configuration flag to disable downloading CCD data during build
Note that there are now two flags for CCD data:
DOWNLOAD_CCD to enable downloading during build
INSTALL_UPDATE_SCRIPT to install an update mechanism for this file
- Updated unit tests to work even if no CCD data is available
Version 2.0.1
- Fixed the generator for the symmetry operator table
Version 2.0.0
- New API interface for accessing query results
- Removed bzip2 support
- improved makefiles
Version 1.1.1
- Now with full support for MS Windows
Version 1.1.0
- Changed from GNU configure to CMake.
- Loading compound information from CCD file
Version 1.0.1
- Changed the way resources are looked up, local dir first,
then /var/cache and finally compiled in resources (with mrc).
Version 1.0.0
- First public release

62
cmake/FindAtomic.cmake Normal file
View File

@@ -0,0 +1,62 @@
# Simple check to see if we need a library for std::atomic
if(TARGET std::atomic)
return()
endif()
cmake_minimum_required(VERSION 3.10)
include(CMakePushCheckState)
include(CheckIncludeFileCXX)
include(CheckCXXSourceRuns)
cmake_push_check_state()
check_include_file_cxx("atomic" _CXX_ATOMIC_HAVE_HEADER)
mark_as_advanced(_CXX_ATOMIC_HAVE_HEADER)
set(code [[
#include <atomic>
int main(int argc, char** argv) {
std::atomic<long long> s;
++s;
return 0;
}
]])
check_cxx_source_runs("${code}" _CXX_ATOMIC_BUILTIN)
if(_CXX_ATOMIC_BUILTIN)
set(_found 1)
else()
list(APPEND CMAKE_REQUIRED_LIBRARIES atomic)
list(APPEND FOLLY_LINK_LIBRARIES atomic)
check_cxx_source_runs("${code}" _CXX_ATOMIC_LIB_NEEDED)
if (NOT _CXX_ATOMIC_LIB_NEEDED)
message(FATAL_ERROR "unable to link C++ std::atomic code: you may need \
to install GNU libatomic")
else()
set(_found 1)
endif()
endif()
if(_found)
add_library(std::atomic INTERFACE IMPORTED)
set_property(TARGET std::atomic APPEND PROPERTY INTERFACE_COMPILE_FEATURES cxx_std_14)
if(_CXX_ATOMIC_BUILTIN)
# Nothing to add...
elseif(_CXX_ATOMIC_LIB_NEEDED)
set_target_properties(std::atomic PROPERTIES IMPORTED_LIBNAME atomic)
set(STDCPPATOMIC_LIBRARY atomic)
endif()
endif()
cmake_pop_check_state()
set(Atomic_FOUND ${_found} CACHE BOOL "TRUE if we can run a program using std::atomic" FORCE)
if(Atomic_FIND_REQUIRED AND NOT Atomic_FOUND)
message(FATAL_ERROR "Cannot run simple program using std::atomic")
endif()

View File

@@ -0,0 +1,74 @@
# Simplistic reimplementation of https://github.com/vector-of-bool/CMakeCM/blob/master/modules/FindFilesystem.cmake
if(TARGET std::filesystem)
return()
endif()
cmake_minimum_required(VERSION 3.10)
include(CMakePushCheckState)
include(CheckIncludeFileCXX)
include(CheckCXXSourceCompiles)
cmake_push_check_state()
check_include_file_cxx("filesystem" _CXX_FILESYSTEM_HAVE_HEADER)
mark_as_advanced(_CXX_FILESYSTEM_HAVE_HEADER)
set(code [[
#include <cstdlib>
#include <filesystem>
int main() {
auto cwd = std::filesystem::current_path();
return EXIT_SUCCESS;
}
]])
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS_EQUAL 8.4.0)
# >> https://stackoverflow.com/questions/63902528/program-crashes-when-filesystempath-is-destroyed
set(CXX_FILESYSTEM_NO_LINK_NEEDED 0)
else()
# Check a simple filesystem program without any linker flags
check_cxx_source_compiles("${code}" CXX_FILESYSTEM_NO_LINK_NEEDED)
endif()
if(CXX_FILESYSTEM_NO_LINK_NEEDED)
set(_found 1)
else()
set(prev_libraries ${CMAKE_REQUIRED_LIBRARIES})
# Add the libstdc++ flag
set(CMAKE_REQUIRED_LIBRARIES ${prev_libraries} -lstdc++fs)
check_cxx_source_compiles("${code}" CXX_FILESYSTEM_STDCPPFS_NEEDED)
set(_found ${CXX_FILESYSTEM_STDCPPFS_NEEDED})
if(NOT CXX_FILESYSTEM_STDCPPFS_NEEDED)
# Try the libc++ flag
set(CMAKE_REQUIRED_LIBRARIES ${prev_libraries} -lc++fs)
check_cxx_source_compiles("${code}" CXX_FILESYSTEM_CPPFS_NEEDED)
set(_found ${CXX_FILESYSTEM_CPPFS_NEEDED})
endif()
endif()
if(_found)
add_library(std::filesystem INTERFACE IMPORTED)
set_property(TARGET std::filesystem APPEND PROPERTY INTERFACE_COMPILE_FEATURES cxx_std_17)
if(CXX_FILESYSTEM_NO_LINK_NEEDED)
# Nothing to add...
elseif(CXX_FILESYSTEM_STDCPPFS_NEEDED)
set_target_properties(std::filesystem PROPERTIES IMPORTED_LIBNAME stdc++fs)
set(STDCPPFS_LIBRARY stdc++fs)
elseif(CXX_FILESYSTEM_CPPFS_NEEDED)
set_target_properties(std::filesystem PROPERTIES IMPORTED_LIBNAME c++fs)
set(STDCPPFS_LIBRARY c++fs)
endif()
endif()
cmake_pop_check_state()
set(Filesystem_FOUND ${_found} CACHE BOOL "TRUE if we can run a program using std::filesystem" FORCE)
if(Filesystem_FIND_REQUIRED AND NOT Filesystem_FOUND)
message(FATAL_ERROR "Cannot run simple program using std::filesystem")
endif()

View File

@@ -0,0 +1,284 @@
# - Returns a version string from Git
#
# These functions force a re-configure on each git commit so that you can
# trust the values of the variables in your build system.
#
# get_git_head_revision(<refspecvar> <hashvar> [ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR])
#
# Returns the refspec and sha hash of the current head revision
#
# git_describe(<var> [<additional arguments to git describe> ...])
#
# Returns the results of git describe on the source tree, and adjusting
# the output so that it tests false if an error occurs.
#
# git_describe_working_tree(<var> [<additional arguments to git describe> ...])
#
# Returns the results of git describe on the working tree (--dirty option),
# and adjusting the output so that it tests false if an error occurs.
#
# git_get_exact_tag(<var> [<additional arguments to git describe> ...])
#
# Returns the results of git describe --exact-match on the source tree,
# and adjusting the output so that it tests false if there was no exact
# matching tag.
#
# git_local_changes(<var>)
#
# Returns either "CLEAN" or "DIRTY" with respect to uncommitted changes.
# Uses the return code of "git diff-index --quiet HEAD --".
# Does not regard untracked files.
#
# Requires CMake 2.6 or newer (uses the 'function' command)
#
# Original Author:
# 2009-2020 Ryan Pavlik <ryan.pavlik@gmail.com> <abiryan@ryand.net>
# http://academic.cleardefinition.com
#
# Copyright 2009-2013, Iowa State University.
# Copyright 2013-2020, Ryan Pavlik
# Copyright 2013-2020, Contributors
# SPDX-License-Identifier: BSL-1.0
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
if(__get_git_revision_description)
return()
endif()
set(__get_git_revision_description YES)
# We must run the following at "include" time, not at function call time,
# to find the path to this module rather than the path to a calling list file
get_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH)
# Function _git_find_closest_git_dir finds the next closest .git directory
# that is part of any directory in the path defined by _start_dir.
# The result is returned in the parent scope variable whose name is passed
# as variable _git_dir_var. If no .git directory can be found, the
# function returns an empty string via _git_dir_var.
#
# Example: Given a path C:/bla/foo/bar and assuming C:/bla/.git exists and
# neither foo nor bar contain a file/directory .git. This wil return
# C:/bla/.git
#
function(_git_find_closest_git_dir _start_dir _git_dir_var)
set(cur_dir "${_start_dir}")
set(git_dir "${_start_dir}/.git")
while(NOT EXISTS "${git_dir}")
# .git dir not found, search parent directories
set(git_previous_parent "${cur_dir}")
get_filename_component(cur_dir "${cur_dir}" DIRECTORY)
if(cur_dir STREQUAL git_previous_parent)
# We have reached the root directory, we are not in git
set(${_git_dir_var}
""
PARENT_SCOPE)
return()
endif()
set(git_dir "${cur_dir}/.git")
endwhile()
set(${_git_dir_var}
"${git_dir}"
PARENT_SCOPE)
endfunction()
function(get_git_head_revision _refspecvar _hashvar)
_git_find_closest_git_dir("${CMAKE_CURRENT_SOURCE_DIR}" GIT_DIR)
if("${ARGN}" STREQUAL "ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR")
set(ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR TRUE)
else()
set(ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR FALSE)
endif()
if(NOT "${GIT_DIR}" STREQUAL "")
file(RELATIVE_PATH _relative_to_source_dir "${CMAKE_SOURCE_DIR}"
"${GIT_DIR}")
if("${_relative_to_source_dir}" MATCHES "[.][.]" AND NOT ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR)
# We've gone above the CMake root dir.
set(GIT_DIR "")
endif()
endif()
if("${GIT_DIR}" STREQUAL "")
set(${_refspecvar}
"GITDIR-NOTFOUND"
PARENT_SCOPE)
set(${_hashvar}
"GITDIR-NOTFOUND"
PARENT_SCOPE)
return()
endif()
# Check if the current source dir is a git submodule or a worktree.
# In both cases .git is a file instead of a directory.
#
if(NOT IS_DIRECTORY ${GIT_DIR})
# The following git command will return a non empty string that
# points to the super project working tree if the current
# source dir is inside a git submodule.
# Otherwise the command will return an empty string.
#
execute_process(
COMMAND "${GIT_EXECUTABLE}" rev-parse
--show-superproject-working-tree
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
OUTPUT_VARIABLE out
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
if(NOT "${out}" STREQUAL "")
# If out is empty, GIT_DIR/CMAKE_CURRENT_SOURCE_DIR is in a submodule
file(READ ${GIT_DIR} submodule)
string(REGEX REPLACE "gitdir: (.*)$" "\\1" GIT_DIR_RELATIVE
${submodule})
string(STRIP ${GIT_DIR_RELATIVE} GIT_DIR_RELATIVE)
get_filename_component(SUBMODULE_DIR ${GIT_DIR} PATH)
get_filename_component(GIT_DIR ${SUBMODULE_DIR}/${GIT_DIR_RELATIVE}
ABSOLUTE)
set(HEAD_SOURCE_FILE "${GIT_DIR}/HEAD")
else()
# GIT_DIR/CMAKE_CURRENT_SOURCE_DIR is in a worktree
file(READ ${GIT_DIR} worktree_ref)
# The .git directory contains a path to the worktree information directory
# inside the parent git repo of the worktree.
#
string(REGEX REPLACE "gitdir: (.*)$" "\\1" git_worktree_dir
${worktree_ref})
string(STRIP ${git_worktree_dir} git_worktree_dir)
_git_find_closest_git_dir("${git_worktree_dir}" GIT_DIR)
set(HEAD_SOURCE_FILE "${git_worktree_dir}/HEAD")
endif()
else()
set(HEAD_SOURCE_FILE "${GIT_DIR}/HEAD")
endif()
set(GIT_DATA "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data")
if(NOT EXISTS "${GIT_DATA}")
file(MAKE_DIRECTORY "${GIT_DATA}")
endif()
if(NOT EXISTS "${HEAD_SOURCE_FILE}")
return()
endif()
set(HEAD_FILE "${GIT_DATA}/HEAD")
configure_file("${HEAD_SOURCE_FILE}" "${HEAD_FILE}" COPYONLY)
configure_file("${_gitdescmoddir}/GetGitRevisionDescription.cmake.in"
"${GIT_DATA}/grabRef.cmake" @ONLY)
include("${GIT_DATA}/grabRef.cmake")
set(${_refspecvar}
"${HEAD_REF}"
PARENT_SCOPE)
set(${_hashvar}
"${HEAD_HASH}"
PARENT_SCOPE)
endfunction()
function(git_describe _var)
if(NOT GIT_FOUND)
find_package(Git QUIET)
endif()
get_git_head_revision(refspec hash)
if(NOT GIT_FOUND)
set(${_var}
"GIT-NOTFOUND"
PARENT_SCOPE)
return()
endif()
if(NOT hash)
set(${_var}
"HEAD-HASH-NOTFOUND"
PARENT_SCOPE)
return()
endif()
# TODO sanitize
#if((${ARGN}" MATCHES "&&") OR
# (ARGN MATCHES "||") OR
# (ARGN MATCHES "\\;"))
# message("Please report the following error to the project!")
# message(FATAL_ERROR "Looks like someone's doing something nefarious with git_describe! Passed arguments ${ARGN}")
#endif()
#message(STATUS "Arguments to execute_process: ${ARGN}")
execute_process(
COMMAND "${GIT_EXECUTABLE}" describe --tags --always ${hash} ${ARGN}
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
RESULT_VARIABLE res
OUTPUT_VARIABLE out
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
if(NOT res EQUAL 0)
set(out "${out}-${res}-NOTFOUND")
endif()
set(${_var}
"${out}"
PARENT_SCOPE)
endfunction()
function(git_describe_working_tree _var)
if(NOT GIT_FOUND)
find_package(Git QUIET)
endif()
if(NOT GIT_FOUND)
set(${_var}
"GIT-NOTFOUND"
PARENT_SCOPE)
return()
endif()
execute_process(
COMMAND "${GIT_EXECUTABLE}" describe --dirty ${ARGN}
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
RESULT_VARIABLE res
OUTPUT_VARIABLE out
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
if(NOT res EQUAL 0)
set(out "${out}-${res}-NOTFOUND")
endif()
set(${_var}
"${out}"
PARENT_SCOPE)
endfunction()
function(git_get_exact_tag _var)
git_describe(out --exact-match ${ARGN})
set(${_var}
"${out}"
PARENT_SCOPE)
endfunction()
function(git_local_changes _var)
if(NOT GIT_FOUND)
find_package(Git QUIET)
endif()
get_git_head_revision(refspec hash)
if(NOT GIT_FOUND)
set(${_var}
"GIT-NOTFOUND"
PARENT_SCOPE)
return()
endif()
if(NOT hash)
set(${_var}
"HEAD-HASH-NOTFOUND"
PARENT_SCOPE)
return()
endif()
execute_process(
COMMAND "${GIT_EXECUTABLE}" diff-index --quiet HEAD --
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
RESULT_VARIABLE res
OUTPUT_VARIABLE out
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
if(res EQUAL 0)
set(${_var}
"CLEAN"
PARENT_SCOPE)
else()
set(${_var}
"DIRTY"
PARENT_SCOPE)
endif()
endfunction()

View File

@@ -0,0 +1,43 @@
#
# Internal file for GetGitRevisionDescription.cmake
#
# Requires CMake 2.6 or newer (uses the 'function' command)
#
# Original Author:
# 2009-2010 Ryan Pavlik <rpavlik@iastate.edu> <abiryan@ryand.net>
# http://academic.cleardefinition.com
# Iowa State University HCI Graduate Program/VRAC
#
# Copyright 2009-2012, Iowa State University
# Copyright 2011-2015, Contributors
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
# SPDX-License-Identifier: BSL-1.0
set(HEAD_HASH)
file(READ "@HEAD_FILE@" HEAD_CONTENTS LIMIT 1024)
string(STRIP "${HEAD_CONTENTS}" HEAD_CONTENTS)
if(HEAD_CONTENTS MATCHES "ref")
# named branch
string(REPLACE "ref: " "" HEAD_REF "${HEAD_CONTENTS}")
if(EXISTS "@GIT_DIR@/${HEAD_REF}")
configure_file("@GIT_DIR@/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY)
else()
configure_file("@GIT_DIR@/packed-refs" "@GIT_DATA@/packed-refs" COPYONLY)
file(READ "@GIT_DATA@/packed-refs" PACKED_REFS)
if(${PACKED_REFS} MATCHES "([0-9a-z]*) ${HEAD_REF}")
set(HEAD_HASH "${CMAKE_MATCH_1}")
endif()
endif()
else()
# detached HEAD
configure_file("@GIT_DIR@/HEAD" "@GIT_DATA@/head-ref" COPYONLY)
endif()
if(NOT HEAD_HASH)
file(READ "@GIT_DATA@/head-ref" HEAD_HASH LIMIT 1024)
string(STRIP "${HEAD_HASH}" HEAD_HASH)
endif()

81
cmake/VersionString.cmake Normal file
View File

@@ -0,0 +1,81 @@
# SPDX-License-Identifier: BSD-2-Clause
# Copyright (c) 2021 NKI/AVL, Netherlands Cancer Institute
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# 1. Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
cmake_minimum_required(VERSION 3.15)
# Create a revision file, containing the current git version info, if any
function(write_version_header dir)
# parameter check
if(NOT IS_DIRECTORY ${dir})
message(FATAL_ERROR "First parameter to write_version_header should be a directory where the final revision.hpp file will be placed")
endif()
include(GetGitRevisionDescription)
if(NOT(GIT-NOTFOUND OR HEAD-HASH-NOTFOUND))
git_describe_working_tree(BUILD_VERSION_STRING --match=build --dirty)
if(BUILD_VERSION_STRING MATCHES "build-([0-9]+)-g([0-9a-f]+)(-dirty)?")
set(BUILD_GIT_TAGREF "${CMAKE_MATCH_2}")
if(CMAKE_MATCH_3)
set(BUILD_VERSION_STRING "${CMAKE_MATCH_1}*")
else()
set(BUILD_VERSION_STRING "${CMAKE_MATCH_1}")
endif()
endif()
else()
message(WARNING "no git info available, cannot update version string")
endif()
string(TIMESTAMP BUILD_DATE_TIME "%Y-%m-%dT%H:%M:%SZ" UTC)
if(ARGC GREATER 1)
set(VAR_PREFIX "${ARGV1}")
endif()
file(WRITE "${PROJECT_BINARY_DIR}/revision.hpp.in" [[// Generated revision file
#pragma once
#include <ostream>
const char k@VAR_PREFIX@ProjectName[] = "@PROJECT_NAME@";
const char k@VAR_PREFIX@VersionNumber[] = "@PROJECT_VERSION@";
const char k@VAR_PREFIX@VersionGitTag[] = "@BUILD_GIT_TAGREF@";
const char k@VAR_PREFIX@BuildInfo[] = "@BUILD_VERSION_STRING@";
const char k@VAR_PREFIX@BuildDate[] = "@BUILD_DATE_TIME@";
inline void write_version_string(std::ostream &os, bool verbose)
{
os << k@VAR_PREFIX@ProjectName << " version " << k@VAR_PREFIX@VersionNumber << std::endl;
if (verbose)
{
os << "build: " << k@VAR_PREFIX@BuildInfo << ' ' << k@VAR_PREFIX@BuildDate << std::endl;
if (k@VAR_PREFIX@VersionGitTag[0] != 0)
os << "git tag: " << k@VAR_PREFIX@VersionGitTag << std::endl;
}
}
]])
configure_file("${PROJECT_BINARY_DIR}/revision.hpp.in" "${dir}/revision.hpp" @ONLY)
endfunction()

View File

@@ -0,0 +1,16 @@
@PACKAGE_INIT@
include(CMakeFindDependencyMacro)
find_dependency(Threads)
find_dependency(ZLIB REQUIRED)
if(MSVC)
find_dependency(zeep REQUIRED)
endif()
INCLUDE("${CMAKE_CURRENT_LIST_DIR}/cifppTargets.cmake")
set_and_check(CIFPP_SHARE_DIR "@PACKAGE_CIFPP_DATA_DIR@")
check_required_components(cifpp)

18
cmake/test-rx.cpp Normal file
View File

@@ -0,0 +1,18 @@
// See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86164
#include <iostream>
#include <regex>
int main()
{
std::string s(100'000, '*');
std::smatch m;
std::regex r("^(.*?)$");
std::regex_search(s, m, r);
std::cout << s.substr(0, 10) << std::endl;
std::cout << m.str(1).substr(0, 10) << std::endl;
return 0;
}

View File

@@ -1,19 +0,0 @@
#include <algorithm>
template<typename COMP>
class foo
{
public:
foo(int a, COMP&& b)
: m_a(a), m_b(std::move(b)) {}
int m_a;
COMP m_b;
};
void bar(const int& b)
{
int c = 1;
auto f = new foo(c, [tag = c, b](const int& x)
{ x < b; });
}

1480
config/config.guess vendored

File diff suppressed because it is too large Load Diff

1801
config/config.sub vendored

File diff suppressed because it is too large Load Diff

View File

@@ -1,518 +0,0 @@
#!/bin/sh
# install - install a program, script, or datafile
scriptversion=2018-03-11.20; # UTC
# This originates from X11R5 (mit/util/scripts/install.sh), which was
# later released in X11R6 (xc/config/util/install.sh) with the
# following copyright and license.
#
# Copyright (C) 1994 X Consortium
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
# Except as contained in this notice, the name of the X Consortium shall not
# be used in advertising or otherwise to promote the sale, use or other deal-
# ings in this Software without prior written authorization from the X Consor-
# tium.
#
#
# FSF changes to this file are in the public domain.
#
# Calling this script install-sh is preferred over install.sh, to prevent
# 'make' implicit rules from creating a file called install from it
# when there is no Makefile.
#
# This script is compatible with the BSD install script, but was written
# from scratch.
tab=' '
nl='
'
IFS=" $tab$nl"
# Set DOITPROG to "echo" to test this script.
doit=${DOITPROG-}
doit_exec=${doit:-exec}
# Put in absolute file names if you don't have them in your path;
# or use environment vars.
chgrpprog=${CHGRPPROG-chgrp}
chmodprog=${CHMODPROG-chmod}
chownprog=${CHOWNPROG-chown}
cmpprog=${CMPPROG-cmp}
cpprog=${CPPROG-cp}
mkdirprog=${MKDIRPROG-mkdir}
mvprog=${MVPROG-mv}
rmprog=${RMPROG-rm}
stripprog=${STRIPPROG-strip}
posix_mkdir=
# Desired mode of installed file.
mode=0755
chgrpcmd=
chmodcmd=$chmodprog
chowncmd=
mvcmd=$mvprog
rmcmd="$rmprog -f"
stripcmd=
src=
dst=
dir_arg=
dst_arg=
copy_on_change=false
is_target_a_directory=possibly
usage="\
Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
or: $0 [OPTION]... SRCFILES... DIRECTORY
or: $0 [OPTION]... -t DIRECTORY SRCFILES...
or: $0 [OPTION]... -d DIRECTORIES...
In the 1st form, copy SRCFILE to DSTFILE.
In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
In the 4th, create DIRECTORIES.
Options:
--help display this help and exit.
--version display version info and exit.
-c (ignored)
-C install only if different (preserve the last data modification time)
-d create directories instead of installing files.
-g GROUP $chgrpprog installed files to GROUP.
-m MODE $chmodprog installed files to MODE.
-o USER $chownprog installed files to USER.
-s $stripprog installed files.
-t DIRECTORY install into DIRECTORY.
-T report an error if DSTFILE is a directory.
Environment variables override the default commands:
CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
RMPROG STRIPPROG
"
while test $# -ne 0; do
case $1 in
-c) ;;
-C) copy_on_change=true;;
-d) dir_arg=true;;
-g) chgrpcmd="$chgrpprog $2"
shift;;
--help) echo "$usage"; exit $?;;
-m) mode=$2
case $mode in
*' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
echo "$0: invalid mode: $mode" >&2
exit 1;;
esac
shift;;
-o) chowncmd="$chownprog $2"
shift;;
-s) stripcmd=$stripprog;;
-t)
is_target_a_directory=always
dst_arg=$2
# Protect names problematic for 'test' and other utilities.
case $dst_arg in
-* | [=\(\)!]) dst_arg=./$dst_arg;;
esac
shift;;
-T) is_target_a_directory=never;;
--version) echo "$0 $scriptversion"; exit $?;;
--) shift
break;;
-*) echo "$0: invalid option: $1" >&2
exit 1;;
*) break;;
esac
shift
done
# We allow the use of options -d and -T together, by making -d
# take the precedence; this is for compatibility with GNU install.
if test -n "$dir_arg"; then
if test -n "$dst_arg"; then
echo "$0: target directory not allowed when installing a directory." >&2
exit 1
fi
fi
if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
# When -d is used, all remaining arguments are directories to create.
# When -t is used, the destination is already specified.
# Otherwise, the last argument is the destination. Remove it from $@.
for arg
do
if test -n "$dst_arg"; then
# $@ is not empty: it contains at least $arg.
set fnord "$@" "$dst_arg"
shift # fnord
fi
shift # arg
dst_arg=$arg
# Protect names problematic for 'test' and other utilities.
case $dst_arg in
-* | [=\(\)!]) dst_arg=./$dst_arg;;
esac
done
fi
if test $# -eq 0; then
if test -z "$dir_arg"; then
echo "$0: no input file specified." >&2
exit 1
fi
# It's OK to call 'install-sh -d' without argument.
# This can happen when creating conditional directories.
exit 0
fi
if test -z "$dir_arg"; then
if test $# -gt 1 || test "$is_target_a_directory" = always; then
if test ! -d "$dst_arg"; then
echo "$0: $dst_arg: Is not a directory." >&2
exit 1
fi
fi
fi
if test -z "$dir_arg"; then
do_exit='(exit $ret); exit $ret'
trap "ret=129; $do_exit" 1
trap "ret=130; $do_exit" 2
trap "ret=141; $do_exit" 13
trap "ret=143; $do_exit" 15
# Set umask so as not to create temps with too-generous modes.
# However, 'strip' requires both read and write access to temps.
case $mode in
# Optimize common cases.
*644) cp_umask=133;;
*755) cp_umask=22;;
*[0-7])
if test -z "$stripcmd"; then
u_plus_rw=
else
u_plus_rw='% 200'
fi
cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
*)
if test -z "$stripcmd"; then
u_plus_rw=
else
u_plus_rw=,u+rw
fi
cp_umask=$mode$u_plus_rw;;
esac
fi
for src
do
# Protect names problematic for 'test' and other utilities.
case $src in
-* | [=\(\)!]) src=./$src;;
esac
if test -n "$dir_arg"; then
dst=$src
dstdir=$dst
test -d "$dstdir"
dstdir_status=$?
else
# Waiting for this to be detected by the "$cpprog $src $dsttmp" command
# might cause directories to be created, which would be especially bad
# if $src (and thus $dsttmp) contains '*'.
if test ! -f "$src" && test ! -d "$src"; then
echo "$0: $src does not exist." >&2
exit 1
fi
if test -z "$dst_arg"; then
echo "$0: no destination specified." >&2
exit 1
fi
dst=$dst_arg
# If destination is a directory, append the input filename.
if test -d "$dst"; then
if test "$is_target_a_directory" = never; then
echo "$0: $dst_arg: Is a directory" >&2
exit 1
fi
dstdir=$dst
dstbase=`basename "$src"`
case $dst in
*/) dst=$dst$dstbase;;
*) dst=$dst/$dstbase;;
esac
dstdir_status=0
else
dstdir=`dirname "$dst"`
test -d "$dstdir"
dstdir_status=$?
fi
fi
case $dstdir in
*/) dstdirslash=$dstdir;;
*) dstdirslash=$dstdir/;;
esac
obsolete_mkdir_used=false
if test $dstdir_status != 0; then
case $posix_mkdir in
'')
# Create intermediate dirs using mode 755 as modified by the umask.
# This is like FreeBSD 'install' as of 1997-10-28.
umask=`umask`
case $stripcmd.$umask in
# Optimize common cases.
*[2367][2367]) mkdir_umask=$umask;;
.*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
*[0-7])
mkdir_umask=`expr $umask + 22 \
- $umask % 100 % 40 + $umask % 20 \
- $umask % 10 % 4 + $umask % 2
`;;
*) mkdir_umask=$umask,go-w;;
esac
# With -d, create the new directory with the user-specified mode.
# Otherwise, rely on $mkdir_umask.
if test -n "$dir_arg"; then
mkdir_mode=-m$mode
else
mkdir_mode=
fi
posix_mkdir=false
case $umask in
*[123567][0-7][0-7])
# POSIX mkdir -p sets u+wx bits regardless of umask, which
# is incompatible with FreeBSD 'install' when (umask & 300) != 0.
;;
*)
# Note that $RANDOM variable is not portable (e.g. dash); Use it
# here however when possible just to lower collision chance.
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
trap 'ret=$?; rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null; exit $ret' 0
# Because "mkdir -p" follows existing symlinks and we likely work
# directly in world-writeable /tmp, make sure that the '$tmpdir'
# directory is successfully created first before we actually test
# 'mkdir -p' feature.
if (umask $mkdir_umask &&
$mkdirprog $mkdir_mode "$tmpdir" &&
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
then
if test -z "$dir_arg" || {
# Check for POSIX incompatibilities with -m.
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
# other-writable bit of parent directory when it shouldn't.
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
test_tmpdir="$tmpdir/a"
ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
case $ls_ld_tmpdir in
d????-?r-*) different_mode=700;;
d????-?--*) different_mode=755;;
*) false;;
esac &&
$mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
}
}
then posix_mkdir=:
fi
rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
else
# Remove any dirs left behind by ancient mkdir implementations.
rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
fi
trap '' 0;;
esac;;
esac
if
$posix_mkdir && (
umask $mkdir_umask &&
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
)
then :
else
# The umask is ridiculous, or mkdir does not conform to POSIX,
# or it failed possibly due to a race condition. Create the
# directory the slow way, step by step, checking for races as we go.
case $dstdir in
/*) prefix='/';;
[-=\(\)!]*) prefix='./';;
*) prefix='';;
esac
oIFS=$IFS
IFS=/
set -f
set fnord $dstdir
shift
set +f
IFS=$oIFS
prefixes=
for d
do
test X"$d" = X && continue
prefix=$prefix$d
if test -d "$prefix"; then
prefixes=
else
if $posix_mkdir; then
(umask=$mkdir_umask &&
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
# Don't fail if two instances are running concurrently.
test -d "$prefix" || exit 1
else
case $prefix in
*\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
*) qprefix=$prefix;;
esac
prefixes="$prefixes '$qprefix'"
fi
fi
prefix=$prefix/
done
if test -n "$prefixes"; then
# Don't fail if two instances are running concurrently.
(umask $mkdir_umask &&
eval "\$doit_exec \$mkdirprog $prefixes") ||
test -d "$dstdir" || exit 1
obsolete_mkdir_used=true
fi
fi
fi
if test -n "$dir_arg"; then
{ test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
{ test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
else
# Make a couple of temp file names in the proper directory.
dsttmp=${dstdirslash}_inst.$$_
rmtmp=${dstdirslash}_rm.$$_
# Trap to clean up those temp files at exit.
trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
# Copy the file name to the temp name.
(umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
# and set any options; do chmod last to preserve setuid bits.
#
# If any of these fail, we abort the whole thing. If we want to
# ignore errors from any of these, just make sure not to ignore
# errors from the above "$doit $cpprog $src $dsttmp" command.
#
{ test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
{ test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
{ test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
# If -C, don't bother to copy if it wouldn't change the file.
if $copy_on_change &&
old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
set -f &&
set X $old && old=:$2:$4:$5:$6 &&
set X $new && new=:$2:$4:$5:$6 &&
set +f &&
test "$old" = "$new" &&
$cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
then
rm -f "$dsttmp"
else
# Rename the file to the real destination.
$doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
# The rename failed, perhaps because mv can't rename something else
# to itself, or perhaps because mv is so ancient that it does not
# support -f.
{
# Now remove or move aside any old file at destination location.
# We try this two ways since rm can't unlink itself on some
# systems and the destination file might be busy for other
# reasons. In this case, the final cleanup might fail but the new
# file should still install successfully.
{
test ! -f "$dst" ||
$doit $rmcmd -f "$dst" 2>/dev/null ||
{ $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
{ $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
} ||
{ echo "$0: cannot unlink or rename $dst" >&2
(exit 1); exit 1
}
} &&
# Now rename the file to the real destination.
$doit $mvcmd "$dsttmp" "$dst"
}
fi || exit 1
trap '' 0
fi
done
# Local variables:
# eval: (add-hook 'before-save-hook 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC0"
# time-stamp-end: "; # UTC"
# End:

File diff suppressed because it is too large Load Diff

8394
config/m4/libtool.m4 vendored

File diff suppressed because it is too large Load Diff

437
config/m4/ltoptions.m4 vendored
View File

@@ -1,437 +0,0 @@
# Helper functions for option handling. -*- Autoconf -*-
#
# Copyright (C) 2004-2005, 2007-2009, 2011-2015 Free Software
# Foundation, Inc.
# Written by Gary V. Vaughan, 2004
#
# This file is free software; the Free Software Foundation gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
# serial 8 ltoptions.m4
# This is to help aclocal find these macros, as it can't see m4_define.
AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])])
# _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME)
# ------------------------------------------
m4_define([_LT_MANGLE_OPTION],
[[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])])
# _LT_SET_OPTION(MACRO-NAME, OPTION-NAME)
# ---------------------------------------
# Set option OPTION-NAME for macro MACRO-NAME, and if there is a
# matching handler defined, dispatch to it. Other OPTION-NAMEs are
# saved as a flag.
m4_define([_LT_SET_OPTION],
[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl
m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]),
_LT_MANGLE_DEFUN([$1], [$2]),
[m4_warning([Unknown $1 option '$2'])])[]dnl
])
# _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET])
# ------------------------------------------------------------
# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
m4_define([_LT_IF_OPTION],
[m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])])
# _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET)
# -------------------------------------------------------
# Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME
# are set.
m4_define([_LT_UNLESS_OPTIONS],
[m4_foreach([_LT_Option], m4_split(m4_normalize([$2])),
[m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option),
[m4_define([$0_found])])])[]dnl
m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3
])[]dnl
])
# _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST)
# ----------------------------------------
# OPTION-LIST is a space-separated list of Libtool options associated
# with MACRO-NAME. If any OPTION has a matching handler declared with
# LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about
# the unknown option and exit.
m4_defun([_LT_SET_OPTIONS],
[# Set options
m4_foreach([_LT_Option], m4_split(m4_normalize([$2])),
[_LT_SET_OPTION([$1], _LT_Option)])
m4_if([$1],[LT_INIT],[
dnl
dnl Simply set some default values (i.e off) if boolean options were not
dnl specified:
_LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no
])
_LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no
])
dnl
dnl If no reference was made to various pairs of opposing options, then
dnl we run the default mode handler for the pair. For example, if neither
dnl 'shared' nor 'disable-shared' was passed, we enable building of shared
dnl archives by default:
_LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED])
_LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC])
_LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC])
_LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install],
[_LT_ENABLE_FAST_INSTALL])
_LT_UNLESS_OPTIONS([LT_INIT], [aix-soname=aix aix-soname=both aix-soname=svr4],
[_LT_WITH_AIX_SONAME([aix])])
])
])# _LT_SET_OPTIONS
## --------------------------------- ##
## Macros to handle LT_INIT options. ##
## --------------------------------- ##
# _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME)
# -----------------------------------------
m4_define([_LT_MANGLE_DEFUN],
[[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])])
# LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE)
# -----------------------------------------------
m4_define([LT_OPTION_DEFINE],
[m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl
])# LT_OPTION_DEFINE
# dlopen
# ------
LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes
])
AU_DEFUN([AC_LIBTOOL_DLOPEN],
[_LT_SET_OPTION([LT_INIT], [dlopen])
AC_DIAGNOSE([obsolete],
[$0: Remove this warning and the call to _LT_SET_OPTION when you
put the 'dlopen' option into LT_INIT's first parameter.])
])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], [])
# win32-dll
# ---------
# Declare package support for building win32 dll's.
LT_OPTION_DEFINE([LT_INIT], [win32-dll],
[enable_win32_dll=yes
case $host in
*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*)
AC_CHECK_TOOL(AS, as, false)
AC_CHECK_TOOL(DLLTOOL, dlltool, false)
AC_CHECK_TOOL(OBJDUMP, objdump, false)
;;
esac
test -z "$AS" && AS=as
_LT_DECL([], [AS], [1], [Assembler program])dnl
test -z "$DLLTOOL" && DLLTOOL=dlltool
_LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl
test -z "$OBJDUMP" && OBJDUMP=objdump
_LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl
])# win32-dll
AU_DEFUN([AC_LIBTOOL_WIN32_DLL],
[AC_REQUIRE([AC_CANONICAL_HOST])dnl
_LT_SET_OPTION([LT_INIT], [win32-dll])
AC_DIAGNOSE([obsolete],
[$0: Remove this warning and the call to _LT_SET_OPTION when you
put the 'win32-dll' option into LT_INIT's first parameter.])
])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], [])
# _LT_ENABLE_SHARED([DEFAULT])
# ----------------------------
# implement the --enable-shared flag, and supports the 'shared' and
# 'disable-shared' LT_INIT options.
# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'.
m4_define([_LT_ENABLE_SHARED],
[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl
AC_ARG_ENABLE([shared],
[AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@],
[build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])],
[p=${PACKAGE-default}
case $enableval in
yes) enable_shared=yes ;;
no) enable_shared=no ;;
*)
enable_shared=no
# Look at the argument we got. We use all the common list separators.
lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
for pkg in $enableval; do
IFS=$lt_save_ifs
if test "X$pkg" = "X$p"; then
enable_shared=yes
fi
done
IFS=$lt_save_ifs
;;
esac],
[enable_shared=]_LT_ENABLE_SHARED_DEFAULT)
_LT_DECL([build_libtool_libs], [enable_shared], [0],
[Whether or not to build shared libraries])
])# _LT_ENABLE_SHARED
LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])])
LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])])
# Old names:
AC_DEFUN([AC_ENABLE_SHARED],
[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared])
])
AC_DEFUN([AC_DISABLE_SHARED],
[_LT_SET_OPTION([LT_INIT], [disable-shared])
])
AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)])
AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AM_ENABLE_SHARED], [])
dnl AC_DEFUN([AM_DISABLE_SHARED], [])
# _LT_ENABLE_STATIC([DEFAULT])
# ----------------------------
# implement the --enable-static flag, and support the 'static' and
# 'disable-static' LT_INIT options.
# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'.
m4_define([_LT_ENABLE_STATIC],
[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl
AC_ARG_ENABLE([static],
[AS_HELP_STRING([--enable-static@<:@=PKGS@:>@],
[build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])],
[p=${PACKAGE-default}
case $enableval in
yes) enable_static=yes ;;
no) enable_static=no ;;
*)
enable_static=no
# Look at the argument we got. We use all the common list separators.
lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
for pkg in $enableval; do
IFS=$lt_save_ifs
if test "X$pkg" = "X$p"; then
enable_static=yes
fi
done
IFS=$lt_save_ifs
;;
esac],
[enable_static=]_LT_ENABLE_STATIC_DEFAULT)
_LT_DECL([build_old_libs], [enable_static], [0],
[Whether or not to build static libraries])
])# _LT_ENABLE_STATIC
LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])])
LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])])
# Old names:
AC_DEFUN([AC_ENABLE_STATIC],
[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static])
])
AC_DEFUN([AC_DISABLE_STATIC],
[_LT_SET_OPTION([LT_INIT], [disable-static])
])
AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)])
AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AM_ENABLE_STATIC], [])
dnl AC_DEFUN([AM_DISABLE_STATIC], [])
# _LT_ENABLE_FAST_INSTALL([DEFAULT])
# ----------------------------------
# implement the --enable-fast-install flag, and support the 'fast-install'
# and 'disable-fast-install' LT_INIT options.
# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'.
m4_define([_LT_ENABLE_FAST_INSTALL],
[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl
AC_ARG_ENABLE([fast-install],
[AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@],
[optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])],
[p=${PACKAGE-default}
case $enableval in
yes) enable_fast_install=yes ;;
no) enable_fast_install=no ;;
*)
enable_fast_install=no
# Look at the argument we got. We use all the common list separators.
lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
for pkg in $enableval; do
IFS=$lt_save_ifs
if test "X$pkg" = "X$p"; then
enable_fast_install=yes
fi
done
IFS=$lt_save_ifs
;;
esac],
[enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT)
_LT_DECL([fast_install], [enable_fast_install], [0],
[Whether or not to optimize for fast installation])dnl
])# _LT_ENABLE_FAST_INSTALL
LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])])
LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])])
# Old names:
AU_DEFUN([AC_ENABLE_FAST_INSTALL],
[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install])
AC_DIAGNOSE([obsolete],
[$0: Remove this warning and the call to _LT_SET_OPTION when you put
the 'fast-install' option into LT_INIT's first parameter.])
])
AU_DEFUN([AC_DISABLE_FAST_INSTALL],
[_LT_SET_OPTION([LT_INIT], [disable-fast-install])
AC_DIAGNOSE([obsolete],
[$0: Remove this warning and the call to _LT_SET_OPTION when you put
the 'disable-fast-install' option into LT_INIT's first parameter.])
])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], [])
dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], [])
# _LT_WITH_AIX_SONAME([DEFAULT])
# ----------------------------------
# implement the --with-aix-soname flag, and support the `aix-soname=aix'
# and `aix-soname=both' and `aix-soname=svr4' LT_INIT options. DEFAULT
# is either `aix', `both' or `svr4'. If omitted, it defaults to `aix'.
m4_define([_LT_WITH_AIX_SONAME],
[m4_define([_LT_WITH_AIX_SONAME_DEFAULT], [m4_if($1, svr4, svr4, m4_if($1, both, both, aix))])dnl
shared_archive_member_spec=
case $host,$enable_shared in
power*-*-aix[[5-9]]*,yes)
AC_MSG_CHECKING([which variant of shared library versioning to provide])
AC_ARG_WITH([aix-soname],
[AS_HELP_STRING([--with-aix-soname=aix|svr4|both],
[shared library versioning (aka "SONAME") variant to provide on AIX, @<:@default=]_LT_WITH_AIX_SONAME_DEFAULT[@:>@.])],
[case $withval in
aix|svr4|both)
;;
*)
AC_MSG_ERROR([Unknown argument to --with-aix-soname])
;;
esac
lt_cv_with_aix_soname=$with_aix_soname],
[AC_CACHE_VAL([lt_cv_with_aix_soname],
[lt_cv_with_aix_soname=]_LT_WITH_AIX_SONAME_DEFAULT)
with_aix_soname=$lt_cv_with_aix_soname])
AC_MSG_RESULT([$with_aix_soname])
if test aix != "$with_aix_soname"; then
# For the AIX way of multilib, we name the shared archive member
# based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o',
# and 'shr.imp' or 'shr_64.imp', respectively, for the Import File.
# Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag,
# the AIX toolchain works better with OBJECT_MODE set (default 32).
if test 64 = "${OBJECT_MODE-32}"; then
shared_archive_member_spec=shr_64
else
shared_archive_member_spec=shr
fi
fi
;;
*)
with_aix_soname=aix
;;
esac
_LT_DECL([], [shared_archive_member_spec], [0],
[Shared archive member basename, for filename based shared library versioning on AIX])dnl
])# _LT_WITH_AIX_SONAME
LT_OPTION_DEFINE([LT_INIT], [aix-soname=aix], [_LT_WITH_AIX_SONAME([aix])])
LT_OPTION_DEFINE([LT_INIT], [aix-soname=both], [_LT_WITH_AIX_SONAME([both])])
LT_OPTION_DEFINE([LT_INIT], [aix-soname=svr4], [_LT_WITH_AIX_SONAME([svr4])])
# _LT_WITH_PIC([MODE])
# --------------------
# implement the --with-pic flag, and support the 'pic-only' and 'no-pic'
# LT_INIT options.
# MODE is either 'yes' or 'no'. If omitted, it defaults to 'both'.
m4_define([_LT_WITH_PIC],
[AC_ARG_WITH([pic],
[AS_HELP_STRING([--with-pic@<:@=PKGS@:>@],
[try to use only PIC/non-PIC objects @<:@default=use both@:>@])],
[lt_p=${PACKAGE-default}
case $withval in
yes|no) pic_mode=$withval ;;
*)
pic_mode=default
# Look at the argument we got. We use all the common list separators.
lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
for lt_pkg in $withval; do
IFS=$lt_save_ifs
if test "X$lt_pkg" = "X$lt_p"; then
pic_mode=yes
fi
done
IFS=$lt_save_ifs
;;
esac],
[pic_mode=m4_default([$1], [default])])
_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl
])# _LT_WITH_PIC
LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])])
LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])])
# Old name:
AU_DEFUN([AC_LIBTOOL_PICMODE],
[_LT_SET_OPTION([LT_INIT], [pic-only])
AC_DIAGNOSE([obsolete],
[$0: Remove this warning and the call to _LT_SET_OPTION when you
put the 'pic-only' option into LT_INIT's first parameter.])
])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_LIBTOOL_PICMODE], [])
## ----------------- ##
## LTDL_INIT Options ##
## ----------------- ##
m4_define([_LTDL_MODE], [])
LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive],
[m4_define([_LTDL_MODE], [nonrecursive])])
LT_OPTION_DEFINE([LTDL_INIT], [recursive],
[m4_define([_LTDL_MODE], [recursive])])
LT_OPTION_DEFINE([LTDL_INIT], [subproject],
[m4_define([_LTDL_MODE], [subproject])])
m4_define([_LTDL_TYPE], [])
LT_OPTION_DEFINE([LTDL_INIT], [installable],
[m4_define([_LTDL_TYPE], [installable])])
LT_OPTION_DEFINE([LTDL_INIT], [convenience],
[m4_define([_LTDL_TYPE], [convenience])])

124
config/m4/ltsugar.m4 vendored
View File

@@ -1,124 +0,0 @@
# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*-
#
# Copyright (C) 2004-2005, 2007-2008, 2011-2015 Free Software
# Foundation, Inc.
# Written by Gary V. Vaughan, 2004
#
# This file is free software; the Free Software Foundation gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
# serial 6 ltsugar.m4
# This is to help aclocal find these macros, as it can't see m4_define.
AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])])
# lt_join(SEP, ARG1, [ARG2...])
# -----------------------------
# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their
# associated separator.
# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier
# versions in m4sugar had bugs.
m4_define([lt_join],
[m4_if([$#], [1], [],
[$#], [2], [[$2]],
[m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])])
m4_define([_lt_join],
[m4_if([$#$2], [2], [],
[m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])])
# lt_car(LIST)
# lt_cdr(LIST)
# ------------
# Manipulate m4 lists.
# These macros are necessary as long as will still need to support
# Autoconf-2.59, which quotes differently.
m4_define([lt_car], [[$1]])
m4_define([lt_cdr],
[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])],
[$#], 1, [],
[m4_dquote(m4_shift($@))])])
m4_define([lt_unquote], $1)
# lt_append(MACRO-NAME, STRING, [SEPARATOR])
# ------------------------------------------
# Redefine MACRO-NAME to hold its former content plus 'SEPARATOR''STRING'.
# Note that neither SEPARATOR nor STRING are expanded; they are appended
# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked).
# No SEPARATOR is output if MACRO-NAME was previously undefined (different
# than defined and empty).
#
# This macro is needed until we can rely on Autoconf 2.62, since earlier
# versions of m4sugar mistakenly expanded SEPARATOR but not STRING.
m4_define([lt_append],
[m4_define([$1],
m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])])
# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...])
# ----------------------------------------------------------
# Produce a SEP delimited list of all paired combinations of elements of
# PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list
# has the form PREFIXmINFIXSUFFIXn.
# Needed until we can rely on m4_combine added in Autoconf 2.62.
m4_define([lt_combine],
[m4_if(m4_eval([$# > 3]), [1],
[m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl
[[m4_foreach([_Lt_prefix], [$2],
[m4_foreach([_Lt_suffix],
]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[,
[_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])])
# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ])
# -----------------------------------------------------------------------
# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited
# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ.
m4_define([lt_if_append_uniq],
[m4_ifdef([$1],
[m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1],
[lt_append([$1], [$2], [$3])$4],
[$5])],
[lt_append([$1], [$2], [$3])$4])])
# lt_dict_add(DICT, KEY, VALUE)
# -----------------------------
m4_define([lt_dict_add],
[m4_define([$1($2)], [$3])])
# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE)
# --------------------------------------------
m4_define([lt_dict_add_subkey],
[m4_define([$1($2:$3)], [$4])])
# lt_dict_fetch(DICT, KEY, [SUBKEY])
# ----------------------------------
m4_define([lt_dict_fetch],
[m4_ifval([$3],
m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]),
m4_ifdef([$1($2)], [m4_defn([$1($2)])]))])
# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE])
# -----------------------------------------------------------------
m4_define([lt_if_dict_fetch],
[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4],
[$5],
[$6])])
# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...])
# --------------------------------------------------------------
m4_define([lt_dict_filter],
[m4_if([$5], [], [],
[lt_join(m4_quote(m4_default([$4], [[, ]])),
lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]),
[lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl
])

View File

@@ -1,23 +0,0 @@
# ltversion.m4 -- version numbers -*- Autoconf -*-
#
# Copyright (C) 2004, 2011-2015 Free Software Foundation, Inc.
# Written by Scott James Remnant, 2004
#
# This file is free software; the Free Software Foundation gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
# @configure_input@
# serial 4179 ltversion.m4
# This file is part of GNU Libtool
m4_define([LT_PACKAGE_VERSION], [2.4.6])
m4_define([LT_PACKAGE_REVISION], [2.4.6])
AC_DEFUN([LTVERSION_VERSION],
[macro_version='2.4.6'
macro_revision='2.4.6'
_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?])
_LT_DECL(, macro_revision, 0)
])

View File

@@ -1,99 +0,0 @@
# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*-
#
# Copyright (C) 2004-2005, 2007, 2009, 2011-2015 Free Software
# Foundation, Inc.
# Written by Scott James Remnant, 2004.
#
# This file is free software; the Free Software Foundation gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
# serial 5 lt~obsolete.m4
# These exist entirely to fool aclocal when bootstrapping libtool.
#
# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN),
# which have later been changed to m4_define as they aren't part of the
# exported API, or moved to Autoconf or Automake where they belong.
#
# The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN
# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us
# using a macro with the same name in our local m4/libtool.m4 it'll
# pull the old libtool.m4 in (it doesn't see our shiny new m4_define
# and doesn't know about Autoconf macros at all.)
#
# So we provide this file, which has a silly filename so it's always
# included after everything else. This provides aclocal with the
# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything
# because those macros already exist, or will be overwritten later.
# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6.
#
# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here.
# Yes, that means every name once taken will need to remain here until
# we give up compatibility with versions before 1.7, at which point
# we need to keep only those names which we still refer to.
# This is to help aclocal find these macros, as it can't see m4_define.
AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])])
m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])])
m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])])
m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])])
m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])])
m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])])
m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])])
m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])])
m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])])
m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])])
m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])])
m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])])
m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])])
m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])])
m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])])
m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])])
m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])])
m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])])
m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])])
m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])])
m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])])
m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])])
m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])])
m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])])
m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])])
m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])])
m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])])
m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])])
m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])])
m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])])
m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])])
m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])])
m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])])
m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])])
m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])])
m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])])
m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])])
m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])])
m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])])
m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])])
m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])])
m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])])
m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])])
m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])])
m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])])
m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])])
m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])])
m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])])
m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])])
m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])])
m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])])
m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])])
m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])])
m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])])
m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])])
m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])])
m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])])
m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])])
m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])])
m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])])
m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])])
m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])])

19579
configure vendored

File diff suppressed because it is too large Load Diff

View File

@@ -1,57 +0,0 @@
AC_PREREQ([2.69])
AC_INIT([libcif++], 1.0, [m.hekkelman@nki.nl])
dnl Switch to a C++ compiler, and check if it works.
AC_LANG(C++)
AX_CXX_COMPILE_STDCXX_17([noext])
AX_CHECK_COMPILE_FLAG([-fstandalone-debug], [ CXXFLAGS="$CXXFLAGS -fstandalone-debug" ], , [-Werror])
AC_CONFIG_SRCDIR([src/Cif++.cpp])
AC_CONFIG_AUX_DIR(config)
AC_CONFIG_MACRO_DIR([config/m4])
AC_CONFIG_HEADERS([include/cif++/Config.hpp])
AC_PREFIX_DEFAULT(/usr/local)
dnl AC_DEFUN([read_test], [AC_LANG_SOURCE(
dnl esyscmd(tools/m4esc.sh config-tests/$1))])
dnl
dnl AC_MSG_CHECKING([compiler standards compliance])
dnl AC_COMPILE_IFELSE(
dnl [read_test(cpp-17-test.cpp)], [],
dnl [AC_MSG_ERROR([Your c++ compiler is not capable of compiling libcifpp, please upgrade])])
dnl AC_MSG_RESULT(ok)
AC_PROG_INSTALL
AC_ENABLE_STATIC
AC_DISABLE_SHARED
AC_PROG_LIBTOOL
AC_SUBST(LIBTOOL_DEPS)
AC_ARG_VAR([DEBUG], [Build a debug version of the library])
AC_ARG_VAR([CCP4], [The location where CCP4 is installed])
AC_PATH_PROG([PKG_CONFIG], [pkg-config])
AC_CHECK_FUNCS([floor pow rint sqrt strchr strerror])
AC_CHECK_HEADERS([sys/ioctl.h])
AC_CHECK_HEADERS([termios.h])
AC_CHECK_HEADER_STDBOOL
AC_CHECK_TYPES([ptrdiff_t])
AC_PROG_MAKE_SET
AX_BOOST_BASE([1.71], [], [
AC_MSG_ERROR([Sorry, your boost is not found or not up-to-date.])
])
AX_BOOST_IOSTREAMS
AX_CHECK_LIBRARY([LIBZ], [zlib.h], [z], [],
[AC_MSG_ERROR([libz not found - compressed files not supported])])
AX_CHECK_LIBRARY([LIBBZ2], [bzlib.h], [bz2], [],
[AC_MSG_ERROR([libbz2 not found - compressed files not supported])])
AC_OUTPUT([GNUmakefile
libcif++.pc])

2715
data/ccd-subset.cif Normal file

File diff suppressed because it is too large Load Diff

5
debian/changelog vendored
View File

@@ -1,5 +0,0 @@
libcifpp (0.1.0-1) unstable; urgency=medium
* Initial release. (Closes: #XXXXXX)
-- Maarten L. Hekkelman <maarten@hekkelman.com> Mon, 28 Sep 2020 08:34:16 +0200

44
debian/control vendored
View File

@@ -1,44 +0,0 @@
Source: libcifpp
Maintainer: Debian Med Packaging Team <debian-med-packaging@lists.alioth.debian.org>
Uploaders: Maarten L. Hekkelman <maarten@hekkelman.com>,
Andreas Tille <tille@debian.org>
Section: libs
Priority: optional
Build-Depends: debhelper-compat (= 13),
autoconf-archive,
libboost-dev,
libboost-iostreams-dev,
libboost-system-dev,
zlib1g-dev,
libbz2-dev
Standards-Version: 4.5.0
Vcs-Browser: https://salsa.debian.org/med-team/libcifpp
Vcs-Git: https://salsa.debian.org/med-team/libcifpp.git
Homepage: https://github.com/PDB-REDO/libcifpp
Rules-Requires-Root: no
Package: libcifpp-dev
Architecture: any
Section: libdevel
Depends: ${misc:Depends},
libcifpp0.1 (= ${binary:Version}),
libboost-dev,
libboost-iostreams-dev,
pkg-config
Suggests: libcifpp-doc
Description: Development files for libcifpp
Libcifpp is a C++ library used to create and manipulate
mmCIF and PDB files containing macro molecular structure information.
.
This specific package contains all files needed to develop new
software using libcifpp.
Package: libcifpp0.1
Architecture: any
Depends: ${misc:Depends},
${shlibs:Depends}
Description: Library files for libcifpp
Libcifpp is a C++ library used to create and manipulate
mmCIF and PDB files containing macro molecular structure information.
.
This package contains the library file only.

0
debian/copyright vendored
View File

View File

@@ -1 +0,0 @@
README.md

View File

@@ -1 +0,0 @@
README.md

39
debian/rules vendored
View File

@@ -1,39 +0,0 @@
#!/usr/bin/make -f
DH_VERBOSE := 1
export DEB_BUILD_MAINT_OPTIONS=hardening=+all
# Fixing reproducible builds
LC_ALL := C.UTF-8
export LC_ALL
export LIBRARY_VERSION=0.1
%:
dh $@
override_dh_auto_configure:
dh_auto_configure -- --enable-documentation
override_dh_auto_install:
$(MAKE) DESTDIR=$(CURDIR)/debian/libcifpp0.1 install-lib
$(MAKE) DESTDIR=$(CURDIR)/debian/libcifpp-dev install-dev
override_dh_auto_configure-arch:
dh_auto_configure -- --enable-shared
override_dh_auto_configure-indep:
dh_auto_configure -- --enable-shared
override_dh_auto_test:
ifeq (,$(filter nocheck,$(DEB_BUILD_OPTIONS)))
$(MAKE) test
endif
override_dh_install:
## cleaning up dependency_libs filed in *.la files
sed -i "/dependency_libs/ s/'.*'/''/" `find . -name '*.la'`
dh_install
override_dh_makeshlibs:
dh_makeshlibs -- -v$(LIBRARY_VERSION)

View File

@@ -1 +0,0 @@
3.0 (quilt)

View File

View File

@@ -1,2 +0,0 @@
extend-diff-ignore = "(^|/)(\.gitignore|\.travis\.yml)$"

View File

@@ -1,5 +0,0 @@
---
Bug-Database: https://github.com/PDB-REDO/libcifpp/issues
Bug-Submit: https://github.com/PDB-REDO/libcifpp/issues/new
Repository: https://github.com/PDB-REDO/libcifpp.git
Repository-Browse: https://github.com/PDB-REDO/libcifpp

3
debian/watch vendored
View File

@@ -1,3 +0,0 @@
version=4
opts=filenamemangle=s/.+\/v?(\d\S+)\.tar\.gz/libcifpp-$1\.tar\.gz/ \
https://github.com/PDB-REDO/libcifpp/tags .*/v?(\d\S+)\.tar\.gz

BIN
examples/1cbs.cif.gz Normal file

Binary file not shown.

35
examples/example.cpp Normal file
View File

@@ -0,0 +1,35 @@
#include <filesystem>
#include <iostream>
#include <cif++.hpp>
namespace fs = std::filesystem;
int main(int argc, char *argv[])
{
if (argc != 2)
exit(1);
cif::file file = cif::pdb::read(argv[1]);
if (file.empty())
{
std::cerr << "Empty file" << std::endl;
exit(1);
}
auto &db = file.front();
auto &atom_site = db["atom_site"];
auto n = atom_site.find(cif::key("label_atom_id") == "OXT").size();
std::cout << "File contains " << atom_site.size() << " atoms of which " << n << (n == 1 ? " is" : " are") << " OXT" << std::endl
<< "residues with an OXT are:" << std::endl;
for (const auto &[asym, comp, seqnr] : atom_site.find<std::string, std::string, int>(
cif::key("label_atom_id") == "OXT", "label_asym_id", "label_comp_id", "label_seq_id"))
{
std::cout << asym << ' ' << comp << ' ' << seqnr << std::endl;
}
return 0;
}

8
examples/makefile Normal file
View File

@@ -0,0 +1,8 @@
CXX = c++ -std=c++17
CXXFLAGS = $(shell pkg-config --cflags libcifpp)
LIBS = $(shell pkg-config --libs libcifpp)
all: example
example: example.cpp
$(CXX) -o $@ $? $(CXXFLAGS) $(LIBS)

41
include/cif++.hpp Normal file
View File

@@ -0,0 +1,41 @@
/*-
* 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
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include "cif++/utilities.hpp"
#include "cif++/file.hpp"
#include "cif++/parser.hpp"
#include "cif++/format.hpp"
#include "cif++/compound.hpp"
#include "cif++/point.hpp"
#include "cif++/symmetry.hpp"
#include "cif++/model.hpp"
#include "cif++/pdb/io.hpp"
#include "cif++/gzio.hpp"

View File

@@ -1,247 +0,0 @@
/*-
* 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
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// Lib for working with structures as contained in mmCIF and PDB files
#pragma once
#include <cstdint>
#include <string>
#include <stdexcept>
#include "cif++/Config.hpp"
namespace mmcif
{
enum AtomType : uint8_t
{
Nn = 0, // Unknown
H = 1, // Hydro­gen
He = 2, // He­lium
Li = 3, // Lith­ium
Be = 4, // Beryl­lium
B = 5, // Boron
C = 6, // Carbon
N = 7, // Nitro­gen
O = 8, // Oxy­gen
F = 9, // Fluor­ine
Ne = 10, // Neon
Na = 11, // So­dium
Mg = 12, // Magne­sium
Al = 13, // Alumin­ium
Si = 14, // Sili­con
P = 15, // Phos­phorus
S = 16, // Sulfur
Cl = 17, // Chlor­ine
Ar = 18, // Argon
K = 19, // Potas­sium
Ca = 20, // Cal­cium
Sc = 21, // Scan­dium
Ti = 22, // Tita­nium
V = 23, // Vana­dium
Cr = 24, // Chrom­ium
Mn = 25, // Manga­nese
Fe = 26, // Iron
Co = 27, // Cobalt
Ni = 28, // Nickel
Cu = 29, // Copper
Zn = 30, // Zinc
Ga = 31, // Gallium
Ge = 32, // Germa­nium
As = 33, // Arsenic
Se = 34, // Sele­nium
Br = 35, // Bromine
Kr = 36, // Kryp­ton
Rb = 37, // Rubid­ium
Sr = 38, // Stront­ium
Y = 39, // Yttrium
Zr = 40, // Zirco­nium
Nb = 41, // Nio­bium
Mo = 42, // Molyb­denum
Tc = 43, // Tech­netium
Ru = 44, // Ruthe­nium
Rh = 45, // Rho­dium
Pd = 46, // Pallad­ium
Ag = 47, // Silver
Cd = 48, // Cad­mium
In = 49, // Indium
Sn = 50, // Tin
Sb = 51, // Anti­mony
Te = 52, // Tellurium
I = 53, // Iodine
Xe = 54, // Xenon
Cs = 55, // Cae­sium
Ba = 56, // Ba­rium
La = 57, // Lan­thanum
Hf = 72, // Haf­nium
Ta = 73, // Tanta­lum
W = 74, // Tung­sten
Re = 75, // Rhe­nium
Os = 76, // Os­mium
Ir = 77, // Iridium
Pt = 78, // Plat­inum
Au = 79, // Gold
Hg = 80, // Mer­cury
Tl = 81, // Thallium
Pb = 82, // Lead
Bi = 83, // Bis­muth
Po = 84, // Polo­nium
At = 85, // Asta­tine
Rn = 86, // Radon
Fr = 87, // Fran­cium
Ra = 88, // Ra­dium
Ac = 89, // Actin­ium
Rf = 104, // Ruther­fordium
Db = 105, // Dub­nium
Sg = 106, // Sea­borgium
Bh = 107, // Bohr­ium
Hs = 108, // Has­sium
Mt = 109, // Meit­nerium
Ds = 110, // Darm­stadtium
Rg = 111, // Roent­genium
Cn = 112, // Coper­nicium
Nh = 113, // Nihon­ium
Fl = 114, // Flerov­ium
Mc = 115, // Moscov­ium
Lv = 116, // Liver­morium
Ts = 117, // Tenness­ine
Og = 118, // Oga­nesson
Ce = 58, // Cerium
Pr = 59, // Praseo­dymium
Nd = 60, // Neo­dymium
Pm = 61, // Prome­thium
Sm = 62, // Sama­rium
Eu = 63, // Europ­ium
Gd = 64, // Gadolin­ium
Tb = 65, // Ter­bium
Dy = 66, // Dyspro­sium
Ho = 67, // Hol­mium
Er = 68, // Erbium
Tm = 69, // Thulium
Yb = 70, // Ytter­bium
Lu = 71, // Lute­tium
Th = 90, // Thor­ium
Pa = 91, // Protac­tinium
U = 92, // Ura­nium
Np = 93, // Neptu­nium
Pu = 94, // Pluto­nium
Am = 95, // Ameri­cium
Cm = 96, // Curium
Bk = 97, // Berkel­ium
Cf = 98, // Califor­nium
Es = 99, // Einstei­nium
Fm = 100, // Fer­mium
Md = 101, // Mende­levium
No = 102, // Nobel­ium
Lr = 103, // Lawren­cium
D = 129, // Deuterium
};
// --------------------------------------------------------------------
// AtomTypeInfo
enum RadiusType {
eRadiusCalculated,
eRadiusEmpirical,
eRadiusCovalentEmpirical,
eRadiusSingleBond,
eRadiusDoubleBond,
eRadiusTripleBond,
eRadiusVanderWaals,
eRadiusTypeCount
};
struct AtomTypeInfo
{
AtomType type;
std::string name;
std::string symbol;
float weight;
bool metal;
float radii[eRadiusTypeCount];
};
extern const AtomTypeInfo kKnownAtoms[];
// --------------------------------------------------------------------
// AtomTypeTraits
class AtomTypeTraits
{
public:
AtomTypeTraits(AtomType a);
AtomTypeTraits(const std::string& symbol);
AtomType type() const { return mInfo->type; }
std::string name() const { return mInfo->name; }
std::string symbol() const { return mInfo->symbol; }
float weight() const { return mInfo->weight; }
bool isMetal() const { return mInfo->metal; }
static bool isElement(const std::string& symbol);
static bool isMetal(const std::string& symbol);
float radius(RadiusType type = eRadiusSingleBond) const
{
if (type >= eRadiusTypeCount)
throw std::invalid_argument("invalid radius requested");
return mInfo->radii[type] / 100.f;
}
// data type encapsulating the Waasmaier & Kirfel scattering factors
// in a simplified form (only a and b).
// Added the electrion scattering factors as well
struct SFData
{
double a[6], b[6];
};
// to get the Cval and Siva values, use this constant as charge:
enum { kWKSFVal = -99 };
const SFData& wksf(int charge = 0) const;
const SFData& elsf() const;
private:
const struct AtomTypeInfo* mInfo;
};
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,238 +0,0 @@
/*-
* 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
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include "cif++/Cif++.hpp"
#include <stack>
namespace cif
{
// --------------------------------------------------------------------
class CifParserError : public std::runtime_error
{
public:
CifParserError(uint32_t lineNr, const std::string& message);
};
// --------------------------------------------------------------------
extern const uint32_t kMaxLineLength;
extern const uint8_t kCharTraitsTable[128];
enum CharTraitsMask: uint8_t {
kOrdinaryMask = 1 << 0,
kNonBlankMask = 1 << 1,
kTextLeadMask = 1 << 2,
kAnyPrintMask = 1 << 3
};
inline bool isWhite(int ch)
{
return std::isspace(ch) or ch == '#';
}
inline bool isOrdinary(int ch)
{
return ch >= 0x20 and ch <= 0x7f and (kCharTraitsTable[ch - 0x20] & kOrdinaryMask) != 0;
}
inline bool isNonBlank(int ch)
{
return ch > 0x20 and ch <= 0x7f and (kCharTraitsTable[ch - 0x20] & kNonBlankMask) != 0;
}
inline bool isTextLead(int ch)
{
return ch >= 0x20 and ch <= 0x7f and (kCharTraitsTable[ch - 0x20] & kTextLeadMask) != 0;
}
inline bool isAnyPrint(int ch)
{
return ch == '\t' or
(ch >= 0x20 and ch <= 0x7f and (kCharTraitsTable[ch - 0x20] & kAnyPrintMask) != 0);
}
inline bool isUnquotedString(const char* s)
{
bool result = isOrdinary(*s++);
while (result and *s != 0)
{
result = isNonBlank(*s);
++s;
}
return result;
}
// --------------------------------------------------------------------
std::tuple<std::string,std::string> splitTagName(const std::string& tag);
// --------------------------------------------------------------------
// sac Parser, analogous to SAX Parser (simple api for xml)
class SacParser
{
public:
SacParser(std::istream& is);
virtual ~SacParser() {}
enum CIFToken
{
eCIFTokenUnknown,
eCIFTokenEOF,
eCIFTokenDATA,
eCIFTokenLOOP,
eCIFTokenGLOBAL,
eCIFTokenSAVE,
eCIFTokenSTOP,
eCIFTokenTag,
eCIFTokenValue,
};
static const char* kTokenName[];
enum CIFValueType
{
eCIFValueInt,
eCIFValueFloat,
eCIFValueNumeric,
eCIFValueString,
eCIFValueTextField,
eCIFValueInapplicable,
eCIFValueUnknown
};
static const char* kValueName[];
int getNextChar();
void retract();
void restart();
CIFToken getNextToken();
void match(CIFToken token);
void parseFile();
void parseGlobal();
void parseDataBlock();
virtual void parseSaveFrame();
void parseDictionary();
void error(const std::string& msg);
// production methods, these are pure virtual here
virtual void produceDatablock(const std::string& name) = 0;
virtual void produceCategory(const std::string& name) = 0;
virtual void produceRow() = 0;
virtual void produceItem(const std::string& category, const std::string& item, const std::string& value) = 0;
protected:
enum State
{
eStateStart,
eStateWhite,
eStateComment,
eStateQuestionMark,
eStateDot,
eStateQuotedString,
eStateQuotedStringQuote,
eStateUnquotedString,
eStateTag,
eStateTextField,
eStateFloat = 100,
eStateInt = 110,
// eStateNumericSuffix = 200,
eStateValue = 300
};
std::istream& mData;
// Parser state
bool mValidate;
uint32_t mLineNr;
bool mBol;
int mState, mStart;
CIFToken mLookahead;
std::string mTokenValue;
CIFValueType mTokenType;
std::stack<int> mBuffer;
};
// --------------------------------------------------------------------
class Parser : public SacParser
{
public:
Parser(std::istream& is, File& f);
virtual void produceDatablock(const std::string& name);
virtual void produceCategory(const std::string& name);
virtual void produceRow();
virtual void produceItem(const std::string& category, const std::string& item, const std::string& value);
protected:
File& mFile;
Datablock* mDataBlock;
Datablock::iterator mCat;
Row mRow;
};
// --------------------------------------------------------------------
class DictParser : public Parser
{
public:
DictParser(Validator& validator, std::istream& is);
~DictParser();
void loadDictionary();
private:
virtual void parseSaveFrame();
bool collectItemTypes();
void linkItems();
Validator& mValidator;
File mFile;
struct DictParserDataImpl* mImpl;
bool mCollectedItemTypes = false;
};
}

View File

@@ -1,289 +0,0 @@
/*-
* 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
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include "cif++/Config.hpp"
#include <vector>
#include <set>
#include <cassert>
#include <memory>
#include <list>
#include <unistd.h>
struct rsrc_imp
{
unsigned int m_next;
unsigned int m_child;
unsigned int m_name;
unsigned int m_size;
unsigned int m_data;
};
#if USE_RSRC
extern const rsrc_imp gResourceIndex[];
extern const char gResourceData[];
extern const char gResourceName[];
#endif
namespace cif
{
// some basic utilities: Since we're using ASCII input only, we define for optimisation
// our own case conversion routines.
bool iequals(const std::string& a, const std::string& b);
int icompare(const std::string& a, const std::string& b);
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);
// To make life easier, we also define iless and iset using iequals
struct iless
{
bool operator()(const std::string& a, const std::string& b) const
{
return icompare(a, b) < 0;
}
};
typedef std::set<std::string, iless> iset;
// --------------------------------------------------------------------
// This really makes a difference, having our own tolower routines
extern const uint8_t kCharToLowerMap[256];
inline char tolower(char ch)
{
return static_cast<char>(kCharToLowerMap[static_cast<uint8_t>(ch)]);
}
// --------------------------------------------------------------------
std::tuple<std::string,std::string> splitTagName(const std::string& tag);
// --------------------------------------------------------------------
// custom wordwrapping routine
std::vector<std::string> wordWrap(const std::string& text, unsigned int width);
// --------------------------------------------------------------------
// Code helping with terminal i/o
uint32_t get_terminal_width();
// --------------------------------------------------------------------
// Path of the current executable
std::string get_executable_path();
// --------------------------------------------------------------------
// some manipulators to write coloured text to terminals
enum StringColour {
scBLACK = 0, scRED, scGREEN, scYELLOW, scBLUE, scMAGENTA, scCYAN, scWHITE, scNONE = 9 };
template<typename String, typename CharT>
struct ColouredString
{
static_assert(std::is_reference<String>::value or std::is_pointer<String>::value, "String type must be pointer or reference");
ColouredString(String s, StringColour fore, StringColour back, bool bold = true)
: m_s(s), m_fore(fore), m_back(back), m_bold(bold) {}
ColouredString& operator=(const ColouredString&) = delete;
String m_s;
StringColour m_fore, m_back;
bool m_bold;
};
template<typename CharT, typename Traits>
std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os, const ColouredString<const CharT*,CharT>& s)
{
if (isatty(STDOUT_FILENO))
{
std::basic_ostringstream<CharT, Traits> ostr;
ostr << "\033[" << (30 + s.m_fore) << ';' << (s.m_bold ? "1" : "22") << ';' << (40 + s.m_back) << 'm'
<< s.m_s
<< "\033[0m";
return os << ostr.str();
}
else
return os << s.m_s;
}
template<typename CharT, typename Traits, typename String>
std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os, const ColouredString<String,CharT>& s)
{
if (isatty(STDOUT_FILENO))
{
std::basic_ostringstream<CharT, Traits> ostr;
ostr << "\033[" << (30 + s.m_fore) << ';' << (s.m_bold ? "1" : "22") << ';' << (40 + s.m_back) << 'm'
<< s.m_s
<< "\033[0m";
return os << ostr.str();
}
else
return os << s.m_s;
}
template<typename CharT>
inline auto coloured(const CharT* s, StringColour fore = scWHITE, StringColour back = scRED, bool bold = true)
{
return ColouredString<const CharT*, CharT>(s, fore, back, bold);
}
template<typename CharT, typename Traits, typename Alloc>
inline auto coloured(const std::basic_string<CharT, Traits, Alloc>& s, StringColour fore = scWHITE, StringColour back = scRED, bool bold = true)
{
return ColouredString<const std::basic_string<CharT, Traits, Alloc>, CharT>(s, fore, back, bold);
}
template<typename CharT, typename Traits, typename Alloc>
inline auto coloured(std::basic_string<CharT, Traits, Alloc>& s, StringColour fore = scWHITE, StringColour back = scRED, bool bold = true)
{
return ColouredString<std::basic_string<CharT, Traits, Alloc>, CharT>(s, fore, back, bold);
}
// --------------------------------------------------------------------
// A progress bar
class Progress
{
public:
Progress(int64_t inMax, const std::string& inAction);
virtual ~Progress();
void consumed(int64_t inConsumed); // consumed is relative
void progress(int64_t inProgress); // progress is absolute
void message(const std::string& inMessage);
private:
Progress(const Progress&);
Progress& operator=(const Progress&);
struct ProgressImpl* mImpl;
};
// --------------------------------------------------------------------
// The new default is to load 'resource' files from the file system
// since not everyone likes mrc. But if you do want to use mrc to load
// resources, specify the compile time flag USE_RSRC.
/// \brief Simple class containing the data for a resource
class rsrc
{
public:
rsrc()
: m_data(nullptr), m_size(0) {}
rsrc(const char* data, size_t size)
: m_data(data), m_size(size) {}
rsrc(const rsrc& rhs)
: m_data(rhs.m_data), m_size(rhs.m_size) {}
rsrc& operator=(const rsrc& rhs)
{
m_data = rhs.m_data;
m_size = rhs.m_size;
return *this;
}
explicit operator bool()
{
return m_data != nullptr and m_size > 0;
}
const char* data() const { return m_data; }
size_t size() const { return m_size; }
private:
const char* m_data;
size_t m_size;
};
/// \brief loader types
enum class rsrc_loader_type { mrsrc, file };
/// \brief loader info
struct rsrc_loader_info
{
rsrc_loader_type type;
std::string info;
const void* ptrs[3];
};
class rsrc_loader
{
public:
static void init(std::initializer_list<rsrc_loader_info> loaders =
{
{ rsrc_loader_type::file, "." },
#if USE_RSRC
{ rsrc_loader_type::mrsrc, "", { gResourceIndex, gResourceData, gResourceName } }
#endif
})
{
assert(not s_instance);
s_instance.reset(new rsrc_loader(loaders));
}
static rsrc load(const std::string& name)
{
assert(s_instance);
if (not s_instance)
init();
return s_instance->do_load(name);
}
~rsrc_loader();
private:
rsrc_loader(const std::initializer_list<rsrc_loader_info>& loaders);
rsrc do_load(const std::string& name);
static std::unique_ptr<rsrc_loader> s_instance;
std::list<struct rsrc_loader_impl*> m_loaders;
};
}

View File

@@ -1,197 +0,0 @@
/*-
* 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
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include "cif++/Cif++.hpp"
//// the std regex of gcc is crashing....
// #include <boost/regex.hpp>
#include <regex>
#include <set>
namespace cif
{
struct ValidateCategory;
// --------------------------------------------------------------------
class ValidationError : public std::exception
{
public:
ValidationError(const std::string& msg);
ValidationError(const std::string& cat, const std::string& item,
const std::string& msg);
const char* what() const noexcept { return mMsg.c_str(); }
std::string mMsg;
};
// --------------------------------------------------------------------
enum DDL_PrimitiveType
{
ptChar, ptUChar, ptNumb
};
DDL_PrimitiveType mapToPrimitiveType(const std::string& s);
struct ValidateType
{
std::string mName;
DDL_PrimitiveType mPrimitiveType;
std::regex mRx;
bool operator<(const ValidateType& rhs) const
{
return icompare(mName, rhs.mName) < 0;
}
// compare values based on type
// int compare(const std::string& a, const std::string& b) const
// {
// return compare(a.c_str(), b.c_str());
// }
int compare(const char* a, const char* b) const;
};
struct ValidateItem
{
std::string mTag;
bool mMandatory;
const ValidateType* mType;
cif::iset mEnums;
std::string mDefault;
bool mDefaultIsNull;
ValidateCategory* mCategory = nullptr;
// ItemLinked is used for non-key links
struct ItemLinked
{
ValidateItem* mParent;
std::string mParentItem;
std::string mChildItem;
};
std::vector<ItemLinked> mLinked;
bool operator<(const ValidateItem& rhs) const
{
return icompare(mTag, rhs.mTag) < 0;
}
bool operator==(const ValidateItem& rhs) const
{
return iequals(mTag, rhs.mTag);
}
void operator()(std::string value) const;
};
struct ValidateCategory
{
std::string mName;
std::vector<std::string> mKeys;
cif::iset mGroups;
cif::iset mMandatoryFields;
std::set<ValidateItem> mItemValidators;
bool operator<(const ValidateCategory& rhs) const
{
return icompare(mName, rhs.mName) < 0;
}
void addItemValidator(ValidateItem&& v);
const ValidateItem* getValidatorForItem(std::string tag) const;
const std::set<ValidateItem>& itemValidators() const
{
return mItemValidators;
}
};
struct ValidateLink
{
int mLinkGroupID;
std::string mParentCategory;
std::vector<std::string> mParentKeys;
std::string mChildCategory;
std::vector<std::string> mChildKeys;
std::string mLinkGroupLabel;
};
// --------------------------------------------------------------------
class Validator
{
public:
friend class DictParser;
Validator();
~Validator();
Validator(const Validator& rhs) = delete;
Validator& operator=(const Validator& rhs) = delete;
Validator(Validator&& rhs);
Validator& operator=(Validator&& rhs);
void addTypeValidator(ValidateType&& v);
const ValidateType* getValidatorForType(std::string typeCode) const;
void addCategoryValidator(ValidateCategory&& v);
const ValidateCategory* getValidatorForCategory(std::string category) const;
void addLinkValidator(ValidateLink&& v);
std::vector<const ValidateLink*> getLinksForParent(const std::string& category) const;
std::vector<const ValidateLink*> getLinksForChild(const std::string& category) const;
void reportError(const std::string& msg, bool fatal);
std::string dictName() const { return mName; }
void dictName(const std::string& name) { mName = name; }
std::string dictVersion() const { return mVersion; }
void dictVersion(const std::string& version) { mVersion = version; }
private:
// name is fully qualified here:
ValidateItem* getValidatorForItem(std::string name) const;
std::string mName;
std::string mVersion;
bool mStrict = false;
// std::set<uint32_t> mSubCategories;
std::set<ValidateType> mTypeValidators;
std::set<ValidateCategory> mCategoryValidators;
std::vector<ValidateLink> mLinkValidators;
};
}

View File

@@ -1,342 +0,0 @@
/*-
* 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
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include <set>
#include <tuple>
#include <vector>
#include <map>
#include "cif++/AtomType.hpp"
#include "cif++/Cif++.hpp"
namespace mmcif
{
// --------------------------------------------------------------------
// The chemical composition of the structure in an mmCIF file is
// defined in the class composition. A compositon consists of
// entities. Each Entity can be either a polymer, a non-polymer
// a macrolide or a water molecule.
// Entities themselves are made up of compounds. And compounds
// contain CompoundAtom records for each atom.
class Compound;
class Link;
struct CompoundAtom;
enum BondType { singleBond, doubleBond, tripleBond, delocalizedBond };
// --------------------------------------------------------------------
// struct containing information about an atom in a chemical compound
// This information comes from the CCP4 monomer library.
struct CompoundAtom
{
std::string id;
AtomType typeSymbol;
std::string typeEnergy;
float partialCharge;
};
// --------------------------------------------------------------------
// struct containing information about the bonds
// This information comes from the CCP4 monomer library.
struct CompoundBond
{
std::string atomID[2];
BondType type;
float distance;
float esd;
};
// --------------------------------------------------------------------
// struct containing information about the bond-angles
// This information comes from the CCP4 monomer library.
struct CompoundAngle
{
std::string atomID[3];
float angle;
float esd;
};
// --------------------------------------------------------------------
// struct containing information about the bond-angles
// This information comes from the CCP4 monomer library.
struct CompoundTorsion
{
std::string atomID[4];
float angle;
float esd;
int period;
};
// --------------------------------------------------------------------
// struct containing information about the bond-angles
// This information comes from the CCP4 monomer library.
struct CompoundPlane
{
std::string id;
std::vector<std::string> atomID;
float esd;
};
// --------------------------------------------------------------------
// struct containing information about a chiral centre
// This information comes from the CCP4 monomer library.
enum ChiralVolumeSign { negativ, positiv, both };
struct CompoundChiralCentre
{
std::string id;
std::string atomIDCentre;
std::string atomID[3];
ChiralVolumeSign volumeSign;
};
// --------------------------------------------------------------------
// a class that contains information about a chemical compound.
// This information is derived from the ccp4 monomer library by default.
// To create compounds, you'd best use the factory method.
class Compound
{
public:
Compound(const std::string& file, const std::string& id, const std::string& name,
const std::string& group);
// factory method, create a Compound based on the three letter code
// (for amino acids) or the one-letter code (for bases) or the
// code as it is known in the CCP4 monomer library.
static const Compound* create(const std::string& id);
// this second factory method can create a Compound even if it is not
// recorded in the library. It will take the values from the CCP4 lib
// unless the value passed to this function is not empty.
static const Compound* create(const std::string& id, const std::string& name,
const std::string& type, const std::string& formula);
// add an additional path to the monomer library.
static void addMonomerLibraryPath(const std::string& dir);
// accessors
std::string id() const { return mID; }
std::string name() const { return mName; }
std::string type() const;
std::string group() const { return mGroup; }
std::vector<CompoundAtom> atoms() const { return mAtoms; }
std::vector<CompoundBond> bonds() const { return mBonds; }
std::vector<CompoundAngle> angles() const { return mAngles; }
std::vector<CompoundChiralCentre> chiralCentres() const
{ return mChiralCentres; }
std::vector<CompoundPlane> planes() const { return mPlanes; }
std::vector<CompoundTorsion> torsions() const { return mTorsions; }
CompoundAtom getAtomByID(const std::string& atomID) const;
bool atomsBonded(const std::string& atomId_1, const std::string& atomId_2) const;
float atomBondValue(const std::string& atomId_1, const std::string& atomId_2) const;
float bondAngle(const std::string& atomId_1, const std::string& atomId_2, const std::string& atomId_3) const;
float chiralVolume(const std::string& centreID) const;
std::string formula() const;
float formulaWeight() const;
int charge() const;
bool isWater() const;
bool isSugar() const;
std::vector<std::string> isomers() const;
bool isIsomerOf(const Compound& c) const;
std::vector<std::tuple<std::string,std::string>> mapToIsomer(const Compound& c) const;
private:
~Compound();
cif::File mCF;
std::string mID;
std::string mName;
std::string mGroup;
std::vector<CompoundAtom> mAtoms;
std::vector<CompoundBond> mBonds;
std::vector<CompoundAngle> mAngles;
std::vector<CompoundTorsion>mTorsions;
std::vector<CompoundChiralCentre>
mChiralCentres;
std::vector<CompoundPlane> mPlanes;
};
// --------------------------------------------------------------------
// struct containing information about the bonds
// This information comes from the CCP4 monomer library.
struct LinkAtom
{
int compID;
std::string atomID;
bool operator==(const LinkAtom& rhs) const { return compID == rhs.compID and atomID == rhs.atomID; }
};
struct LinkBond
{
LinkAtom atom[2];
BondType type;
float distance;
float esd;
};
// --------------------------------------------------------------------
// struct containing information about the bond-angles
// This information comes from the CCP4 monomer library.
struct LinkAngle
{
LinkAtom atom[3];
float angle;
float esd;
};
// --------------------------------------------------------------------
// struct containing information about the bond-torsions
// This information comes from the CCP4 monomer library.
struct LinkTorsion
{
LinkAtom atom[4];
float angle;
float esd;
int period;
};
// --------------------------------------------------------------------
// struct containing information about the bond-angles
// This information comes from the CCP4 monomer library.
struct LinkPlane
{
std::string id;
std::vector<LinkAtom> atoms;
float esd;
};
// --------------------------------------------------------------------
// struct containing information about a chiral centre
// This information comes from the CCP4 monomer library.
struct LinkChiralCentre
{
std::string id;
LinkAtom atomCentre;
LinkAtom atom[3];
ChiralVolumeSign volumeSign;
};
// --------------------------------------------------------------------
// a class that contains information about a chemical link between compounds.
// This information is derived from the ccp4 monomer library by default.
class Link
{
public:
Link(cif::Datablock& db);
// Factory method.
static const Link& create(const std::string& id);
// accessors
std::string id() const { return mID; }
std::vector<LinkBond> bonds() const { return mBonds; }
std::vector<LinkAngle> angles() const { return mAngles; }
std::vector<LinkChiralCentre> chiralCentres() const { return mChiralCentres; }
std::vector<LinkPlane> planes() const { return mPlanes; }
std::vector<LinkTorsion> torsions() const { return mTorsions; }
float atomBondValue(const LinkAtom& atomId_1, const LinkAtom& atomId_2) const;
float bondAngle(const LinkAtom& atomId_1, const LinkAtom& atomId_2, const LinkAtom& atomId_3) const;
float chiralVolume(const std::string& id) const;
private:
~Link();
std::string mID;
std::vector<LinkBond> mBonds;
std::vector<LinkAngle> mAngles;
std::vector<LinkTorsion> mTorsions;
std::vector<LinkChiralCentre> mChiralCentres;
std::vector<LinkPlane> mPlanes;
};
// --------------------------------------------------------------------
// Factory class for Compound and Link objects
extern const std::map<std::string,char> kAAMap, kBaseMap;
class CompoundFactory
{
public:
static CompoundFactory& instance();
void pushDictionary(const std::string& inDictFile);
void popDictionary();
bool isKnownPeptide(const std::string& res_name) const;
bool isKnownBase(const std::string& res_name) const;
std::string unalias(const std::string& res_name) const;
const Compound* get(std::string id);
const Compound* create(std::string id);
const Link* getLink(std::string id);
const Link* createLink(std::string id);
private:
CompoundFactory();
~CompoundFactory();
CompoundFactory(const CompoundFactory&) = delete;
CompoundFactory& operator=(const CompoundFactory&) = delete;
static CompoundFactory* sInstance;
class CompoundFactoryImpl* mImpl;
};
}

View File

@@ -1,82 +0,0 @@
/* include/cif++/Config.hpp.in. Generated from configure.ac by autoheader. */
/* define if the Boost library is available */
#undef HAVE_BOOST
/* define if the Boost::Regex library is available */
#undef HAVE_BOOST_REGEX
/* define if the compiler supports basic C++17 syntax */
#undef HAVE_CXX17
/* Define to 1 if you have the <dlfcn.h> header file. */
#undef HAVE_DLFCN_H
/* Define to 1 if you have the `floor' function. */
#undef HAVE_FLOOR
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define to 1 if LIBBZ2 is found */
#undef HAVE_LIBBZ2
/* Define to 1 if LIBZ is found */
#undef HAVE_LIBZ
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define to 1 if you have the `pow' function. */
#undef HAVE_POW
/* Define to 1 if the system has the type `ptrdiff_t'. */
#undef HAVE_PTRDIFF_T
/* Define to 1 if you have the `rint' function. */
#undef HAVE_RINT
/* Define to 1 if you have the `sqrt' function. */
#undef HAVE_SQRT
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define to 1 if you have the `strchr' function. */
#undef HAVE_STRCHR
/* Define to 1 if you have the `strerror' function. */
#undef HAVE_STRERROR
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define to 1 if you have the <sys/ioctl.h> header file. */
#undef HAVE_SYS_IOCTL_H
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
/* Define to 1 if you have the <termios.h> header file. */
#undef HAVE_TERMIOS_H
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Define to 1 if the system has the type `_Bool'. */
#undef HAVE__BOOL
/* Define to the sub-directory where libtool stores uninstalled libraries. */
#undef LT_OBJDIR
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS

View File

@@ -1,412 +0,0 @@
/*-
* 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
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include <functional>
#include "cif++/Config.hpp"
#include <boost/math/quaternion.hpp>
namespace mmcif
{
typedef boost::math::quaternion<float> quaternion;
const long double
kPI = 3.141592653589793238462643383279502884L;
// --------------------------------------------------------------------
// Point, a location with x, y and z coordinates as floating point.
// This one is derived from a tuple<float,float,float> so
// you can do things like:
//
// float x, y, z;
// tie(x, y, z) = atom.loc();
template<typename F>
struct PointF
{
typedef F FType;
FType mX, mY, mZ;
PointF() : mX(0), mY(0), mZ(0) {}
PointF(FType x, FType y, FType z) : mX(x), mY(y), mZ(z) {}
// PointF(const clipper::Coord_orth& pt): mX(pt[0]), mY(pt[1]), mZ(pt[2]) {}
template<typename PF>
PointF(const PointF<PF>& pt)
: mX(static_cast<F>(pt.mX))
, mY(static_cast<F>(pt.mY))
, mZ(static_cast<F>(pt.mZ)) {}
// PointF& operator=(const clipper::Coord_orth& rhs)
// {
// mX = rhs[0];
// mY = rhs[1];
// mZ = rhs[2];
// return *this;
// }
template<typename PF>
PointF& operator=(const PointF<PF>& rhs)
{
mX = static_cast<F>(rhs.mX);
mY = static_cast<F>(rhs.mY);
mZ = static_cast<F>(rhs.mZ);
return *this;
}
FType& getX() { return mX; }
FType getX() const { return mX; }
void setX(FType x) { mX = x; }
FType& getY() { return mY; }
FType getY() const { return mY; }
void setY(FType y) { mY = y; }
FType& getZ() { return mZ; }
FType getZ() const { return mZ; }
void setZ(FType z) { mZ = z; }
PointF& operator+=(const PointF& rhs)
{
mX += rhs.mX;
mY += rhs.mY;
mZ += rhs.mZ;
return *this;
}
PointF& operator+=(FType d)
{
mX += d;
mY += d;
mZ += d;
return *this;
}
PointF& operator-=(const PointF& rhs)
{
mX -= rhs.mX;
mY -= rhs.mY;
mZ -= rhs.mZ;
return *this;
}
PointF& operator-=(FType d)
{
mX -= d;
mY -= d;
mZ -= d;
return *this;
}
PointF& operator*=(FType rhs)
{
mX *= rhs;
mY *= rhs;
mZ *= rhs;
return *this;
}
PointF& operator/=(FType rhs)
{
mX /= rhs;
mY /= rhs;
mZ /= rhs;
return *this;
}
FType normalize()
{
auto length = mX * mX + mY * mY + mZ * mZ;
if (length > 0)
{
length = std::sqrt(length);
operator/=(length);
}
return length;
}
void rotate(const boost::math::quaternion<FType>& q)
{
boost::math::quaternion<FType> p(0, mX, mY, mZ);
p = q * p * boost::math::conj(q);
mX = p.R_component_2();
mY = p.R_component_3();
mZ = p.R_component_4();
}
// operator clipper::Coord_orth() const
// {
// return clipper::Coord_orth(mX, mY, mZ);
// }
operator std::tuple<const FType&, const FType&, const FType&>() const
{
return std::make_tuple(std::ref(mX), std::ref(mY), std::ref(mZ));
}
operator std::tuple<FType&,FType&,FType&>()
{
return std::make_tuple(std::ref(mX), std::ref(mY), std::ref(mZ));
}
bool operator==(const PointF& rhs) const
{
return mX == rhs.mX and mY == rhs.mY and mZ == rhs.mZ;
}
// consider point as a vector... perhaps I should rename Point?
FType lengthsq() const
{
return mX * mX + mY * mY + mZ * mZ;
}
FType length() const
{
return sqrt(mX * mX + mY * mY + mZ * mZ);
}
};
typedef PointF<float> Point;
typedef PointF<double> DPoint;
template<typename F>
inline std::ostream& operator<<(std::ostream& os, const PointF<F>& pt)
{
os << '(' << pt.mX << ',' << pt.mY << ',' << pt.mZ << ')';
return os;
}
template<typename F>
inline PointF<F> operator+(const PointF<F>& lhs, const PointF<F>& rhs)
{
return PointF<F>(lhs.mX + rhs.mX, lhs.mY + rhs.mY, lhs.mZ + rhs.mZ);
}
template<typename F>
inline PointF<F> operator-(const PointF<F>& lhs, const PointF<F>& rhs)
{
return PointF<F>(lhs.mX - rhs.mX, lhs.mY - rhs.mY, lhs.mZ - rhs.mZ);
}
template<typename F>
inline PointF<F> operator-(const PointF<F>& pt)
{
return PointF<F>(-pt.mX, -pt.mY, -pt.mZ);
}
template<typename F>
inline PointF<F> operator*(const PointF<F>& pt, F f)
{
return PointF<F>(pt.mX * f, pt.mY * f, pt.mZ * f);
}
template<typename F>
inline PointF<F> operator*(F f, const PointF<F>& pt)
{
return PointF<F>(pt.mX * f, pt.mY * f, pt.mZ * f);
}
template<typename F>
inline PointF<F> operator/(const PointF<F>& pt, F f)
{
return PointF<F>(pt.mX / f, pt.mY / f, pt.mZ / f);
}
// --------------------------------------------------------------------
// several standard 3d operations
template<typename F>
inline double DistanceSquared(const PointF<F>& a, const PointF<F>& b)
{
return
(a.mX - b.mX) * (a.mX - b.mX) +
(a.mY - b.mY) * (a.mY - b.mY) +
(a.mZ - b.mZ) * (a.mZ - b.mZ);
}
template<typename F>
inline double Distance(const PointF<F>& a, const PointF<F>& b)
{
return sqrt(
(a.mX - b.mX) * (a.mX - b.mX) +
(a.mY - b.mY) * (a.mY - b.mY) +
(a.mZ - b.mZ) * (a.mZ - b.mZ));
}
template<typename F>
inline F DotProduct(const PointF<F>& a, const PointF<F>& b)
{
return a.mX * b.mX + a.mY * b.mY + a.mZ * b.mZ;
}
template<typename F>
inline PointF<F> CrossProduct(const PointF<F>& a, const PointF<F>& b)
{
return PointF<F>(a.mY * b.mZ - b.mY * a.mZ,
a.mZ * b.mX - b.mZ * a.mX,
a.mX * b.mY - b.mX * a.mY);
}
template<typename F>
double Angle(const PointF<F>& p1, const PointF<F>& p2, const PointF<F>& p3)
{
PointF<F> v1 = p1 - p2;
PointF<F> v2 = p3 - p2;
return std::acos(DotProduct(v1, v2) / (v1.length() * v2.length())) * 180 / kPI;
}
template<typename F>
double DihedralAngle(const PointF<F>& p1, const PointF<F>& p2, const PointF<F>& p3, const PointF<F>& p4)
{
PointF<F> v12 = p1 - p2; // vector from p2 to p1
PointF<F> v43 = p4 - p3; // vector from p3 to p4
PointF<F> z = p2 - p3; // vector from p3 to p2
PointF<F> p = CrossProduct(z, v12);
PointF<F> x = CrossProduct(z, v43);
PointF<F> y = CrossProduct(z, x);
double u = DotProduct(x, x);
double v = DotProduct(y, y);
double result = 360;
if (u > 0 and v > 0)
{
u = DotProduct(p, x) / sqrt(u);
v = DotProduct(p, y) / sqrt(v);
if (u != 0 or v != 0)
result = atan2(v, u) * 180 / kPI;
}
return result;
}
template<typename F>
double CosinusAngle(const PointF<F>& p1, const PointF<F>& p2, const PointF<F>& p3, const PointF<F>& p4)
{
PointF<F> v12 = p1 - p2;
PointF<F> v34 = p3 - p4;
double result = 0;
double x = DotProduct(v12, v12) * DotProduct(v34, v34);
if (x > 0)
result = DotProduct(v12, v34) / sqrt(x);
return result;
}
// --------------------------------------------------------------------
// For e.g. simulated annealing, returns a new point that is moved in
// a random direction with a distance randomly chosen from a normal
// distribution with a stddev of offset.
template<typename F>
PointF<F> Nudge(PointF<F> p, F offset);
// --------------------------------------------------------------------
// We use quaternions to do rotations in 3d space
quaternion Normalize(quaternion q);
//std::tuple<double,Point> QuaternionToAngleAxis(quaternion q);
Point Centroid(std::vector<Point>& Points);
Point CenterPoints(std::vector<Point>& Points);
quaternion AlignPoints(const std::vector<Point>& a, const std::vector<Point>& b);
double RMSd(const std::vector<Point>& a, const std::vector<Point>& b);
// --------------------------------------------------------------------
// Helper class to generate evenly divided Points on a sphere
// we use a fibonacci sphere to calculate even distribution of the dots
template<int N>
class SphericalDots
{
public:
enum { P = 2 * N + 1 };
typedef typename std::array<Point,P> array_type;
typedef typename array_type::const_iterator iterator;
static SphericalDots& instance()
{
static SphericalDots sInstance;
return sInstance;
}
size_t size() const { return mPoints.size(); }
const Point operator[](uint32_t inIx) const { return mPoints[inIx]; }
iterator begin() const { return mPoints.begin(); }
iterator end() const { return mPoints.end(); }
double weight() const { return mWeight; }
SphericalDots()
{
using namespace std;
const double
kGoldenRatio = (1 + std::sqrt(5.0)) / 2;
mWeight = (4 * kPI) / P;
auto p = mPoints.begin();
for (int32_t i = -N; i <= N; ++i)
{
double lat = std::asin((2.0 * i) / P);
double lon = std::fmod(i, kGoldenRatio) * 2 * kPI / kGoldenRatio;
p->mX = sin(lon) * cos(lat);
p->mY = cos(lon) * cos(lat);
p->mZ = sin(lat);
++p;
}
}
private:
array_type mPoints;
double mWeight;
};
typedef SphericalDots<50> SphericalDots_50;
}

View File

@@ -1,218 +0,0 @@
/*-
* 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
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// Calculate DSSP-like secondary structure information
#pragma once
namespace mmcif
{
class Structure;
class Monomer;
struct Res;
extern const float
kCouplingConstant, kMinHBondEnergy, kMaxHBondEnergy;
enum SecondaryStructureType : char
{
ssLoop = ' ',
ssAlphahelix = 'H',
ssBetabridge = 'B',
ssStrand = 'E',
ssHelix_3 = 'G',
ssHelix_5 = 'I',
ssHelix_PPII = 'P',
ssTurn = 'T',
ssBend = 'S'
};
enum class HelixType
{
rh_3_10, rh_alpha, rh_pi, rh_pp
};
enum class Helix
{
None, Start, End, StartAndEnd, Middle
};
//struct HBond
//{
// std::string labelAsymID;
// int labelSeqID;
// double energy;
//};
//
//struct BridgePartner
//{
// std::string labelAsymID;
// int labelSeqID;
// int ladder;
// bool parallel;
//};
struct SecondaryStructure
{
SecondaryStructureType type;
// HBond donor[2], acceptor[2];
// BridgePartner beta[2];
// int sheet;
// bool bend;
};
//void CalculateSecondaryStructure(Structure& s);
const size_t
kHistogramSize = 30;
struct DSSP_Statistics
{
uint32_t nrOfResidues, nrOfChains, nrOfSSBridges, nrOfIntraChainSSBridges, nrOfHBonds;
uint32_t nrOfHBondsInAntiparallelBridges, nrOfHBondsInParallelBridges;
uint32_t nrOfHBondsPerDistance[11] = {};
double accessibleSurface = 0;
uint32_t residuesPerAlphaHelixHistogram[kHistogramSize] = {};
uint32_t parallelBridgesPerLadderHistogram[kHistogramSize] = {};
uint32_t antiparallelBridgesPerLadderHistogram[kHistogramSize] = {};
uint32_t laddersPerSheetHistogram[kHistogramSize] = {};
};
enum class ChainBreak
{
None, NewChain, Gap
};
class DSSP
{
public:
DSSP(const Structure& s, int min_poly_proline_stretch_length, bool calculateSurfaceAccessibility);
~DSSP();
DSSP(const DSSP&) = delete;
DSSP& operator=(const DSSP&) = delete;
SecondaryStructureType operator()(const std::string& inAsymID, int inSeqID) const;
SecondaryStructureType operator()(const Monomer& m) const;
double accessibility(const std::string& inAsymID, int inSeqID) const;
double accessibility(const Monomer& m) const;
bool isAlphaHelixEndBeforeStart(const Monomer& m) const;
bool isAlphaHelixEndBeforeStart(const std::string& inAsymID, int inSeqID) const;
DSSP_Statistics GetStatistics() const;
class iterator;
using res_iter = typename std::vector<Res>::iterator;
class ResidueInfo
{
public:
friend class iterator;
explicit operator bool() const { return not empty(); }
bool empty() const { return mImpl == nullptr; }
const Monomer& residue() const;
std::string alt_id() const;
/// \brief return 0 if not a break, ' ' in case of a new chain and '*' in case of a broken chain
ChainBreak chainBreak() const;
/// \brief the internal number in DSSP
int nr() const;
SecondaryStructureType ss() const;
int ssBridgeNr() const;
Helix helix(HelixType helixType) const;
bool bend() const;
double accessibility() const;
/// \brief returns resinfo, ladder and parallel
std::tuple<ResidueInfo,int,bool> bridgePartner(int i) const;
int sheet() const;
/// \brief return resinfo and the energy of the bond
std::tuple<ResidueInfo,double> acceptor(int i) const;
std::tuple<ResidueInfo,double> donor(int i) const;
private:
ResidueInfo(Res* res);
Res* mImpl;
};
class iterator
{
public:
using iterator_category = std::input_iterator_tag;
using value_type = ResidueInfo;
using difference_type = std::ptrdiff_t;
using pointer = value_type*;
using reference = value_type&;
iterator(const iterator& i);
iterator(res_iter cur);
iterator& operator=(const iterator& i);
reference operator*() { return mCurrent; }
pointer operator->() { return &mCurrent; }
iterator& operator++();
iterator operator++(int)
{
auto tmp(*this);
this->operator++();
return tmp;
}
bool operator==(const iterator& rhs) const { return mCurrent.mImpl == rhs.mCurrent.mImpl; }
bool operator!=(const iterator& rhs) const { return mCurrent.mImpl != rhs.mCurrent.mImpl; }
private:
ResidueInfo mCurrent;
};
iterator begin() const;
iterator end() const;
bool empty() const { return begin() == end(); }
private:
struct DSSPImpl* mImpl;
};
}

View File

@@ -1,539 +0,0 @@
/*-
* 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
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include <numeric>
#include "cif++/AtomType.hpp"
#include "cif++/Point.hpp"
#include "cif++/Compound.hpp"
#include "cif++/Cif++.hpp"
/*
To modify a structure, you will have to use actions.
The currently supported actions are:
// - Move atom to new location
- Remove atom
// - Add new atom that was formerly missing
// - Add alternate Residue
-
*/
namespace mmcif
{
class Atom;
class Residue;
class Monomer;
class Polymer;
class Structure;
class File;
// --------------------------------------------------------------------
class Atom
{
public:
// Atom(const structure& s, const std::string& id);
Atom();
Atom(struct AtomImpl* impl);
Atom(const Atom& rhs);
~Atom();
explicit operator bool() const { return mImpl_ != nullptr; }
// return a copy of this atom, with data copied instead of referenced
Atom clone() const;
Atom& operator=(const Atom& rhs);
const std::string& id() const;
AtomType type() const;
Point location() const;
void location(Point p);
// Atom symmetryCopy(const Point& d, const clipper::RTop_orth& rt);
// bool isSymmetryCopy() const;
// std::string symmetry() const;
// const clipper::RTop_orth& symop() const;
const Compound& comp() const;
bool isWater() const;
int charge() const;
float uIso() const;
bool getAnisoU(float anisou[6]) const;
float occupancy() const;
template<typename T>
T property(const std::string& name) const;
template<typename T>
void property(const std::string& name, const T& value);
// specifications
std::string labelAtomID() const;
std::string labelCompID() const;
std::string labelAsymID() const;
int labelSeqID() const;
std::string labelAltID() const;
bool isAlternate() const;
std::string authAtomID() const;
std::string authCompID() const;
std::string authAsymID() const;
std::string authSeqID() const;
std::string pdbxAuthInsCode() const;
std::string pdbxAuthAltID() const;
std::string labelID() const;// label_comp_id + '_' + label_asym_id + '_' + label_seq_id
std::string pdbID() const; // auth_comp_id + '_' + auth_asym_id + '_' + auth_seq_id + pdbx_PDB_ins_code
bool operator==(const Atom& rhs) const;
// // get clipper format Atom
// clipper::Atom toClipper() const;
// Radius calculation based on integrating the density until perc of electrons is found
void calculateRadius(float resHigh, float resLow, float perc);
float radius() const;
// access data in compound for this atom
// the energy-type field
std::string energyType() const;
// convenience routine
bool isBackBone() const
{
auto atomID = labelAtomID();
return atomID == "N" or atomID == "O" or atomID == "C" or atomID == "CA";
}
void swap(Atom& b)
{
std::swap(mImpl_, b.mImpl_);
}
int compare(const Atom& b) const;
bool operator<(const Atom& rhs) const
{
return compare(rhs) < 0;
}
friend std::ostream& operator<<(std::ostream& os, const Atom& atom);
private:
friend class Structure;
void setID(int id);
AtomImpl* impl();
const AtomImpl* impl() const;
struct AtomImpl* mImpl_;
};
inline void swap(mmcif::Atom& a, mmcif::Atom& b)
{
a.swap(b);
}
inline double Distance(const Atom& a, const Atom& b)
{
return Distance(a.location(), b.location());
}
inline double DistanceSquared(const Atom& a, const Atom& b)
{
return DistanceSquared(a.location(), b.location());
}
typedef std::vector<Atom> AtomView;
// --------------------------------------------------------------------
class Residue
{
public:
// constructors should be private, but that's not possible for now (needed in emplace)
// constructor for waters
Residue(const Structure& structure, const std::string& compoundID,
const std::string& asymID, const std::string& authSeqID);
Residue(const Structure& structure, const std::string& compoundID,
const std::string& asymID, int seqID = 0);
Residue(const Residue& rhs) = delete;
Residue& operator=(const Residue& rhs) = delete;
Residue(Residue&& rhs);
Residue& operator=(Residue&& rhs);
virtual ~Residue();
const Compound& compound() const;
const AtomView& atoms() const;
/// \brief Unique atoms returns only the atoms without alternates and the first of each alternate atom id.
AtomView unique_atoms() const;
/// \brief The alt ID used for the unique atoms
std::string unique_alt_id() const;
Atom atomByID(const std::string& atomID) const;
const std::string& compoundID() const { return mCompoundID; }
const std::string& asymID() const { return mAsymID; }
int seqID() const { return mSeqID; }
std::string authAsymID() const;
std::string authSeqID() const;
std::string authInsCode() const;
// return a human readable PDB-like auth id (chain+seqnr+iCode)
std::string authID() const;
// similar for mmCIF space
std::string labelID() const;
// Is this residue a single entity?
bool isEntity() const;
bool isWater() const { return mCompoundID == "HOH"; }
const Structure& structure() const { return *mStructure; }
bool empty() const { return mStructure == nullptr; }
bool hasAlternateAtoms() const;
// some routines for 3d work
std::tuple<Point,float> centerAndRadius() const;
friend std::ostream& operator<<(std::ostream& os, const Residue& res);
protected:
Residue() {}
friend class Polymer;
const Structure* mStructure = nullptr;
std::string mCompoundID, mAsymID;
int mSeqID = 0;
std::string mAuthSeqID;
AtomView mAtoms;
};
// --------------------------------------------------------------------
// a monomer models a single Residue in a protein chain
class Monomer : public Residue
{
public:
// Monomer();
Monomer(const Monomer& rhs) = delete;
Monomer& operator=(const Monomer& rhs) = delete;
Monomer(Monomer&& rhs);
Monomer& operator=(Monomer&& rhs);
// Monomer(const Polymer& polymer, uint32_t index);
Monomer(const Polymer& polymer, uint32_t index, int seqID,
const std::string& compoundID);
bool is_first_in_chain() const;
bool is_last_in_chain() const;
// convenience
bool has_alpha() const;
bool has_kappa() const;
// Assuming this is really an amino acid...
float phi() const;
float psi() const;
float alpha() const;
float kappa() const;
float tco() const;
float omega() const;
// torsion angles
size_t nrOfChis() const;
float chi(size_t i) const;
bool isCis() const;
/// \brief Returns true if the four atoms C, CA, N and O are present
bool isComplete() const;
/// \brief Returns true if any of the backbone atoms has an alternate
bool hasAlternateBackboneAtoms() const;
Atom CAlpha() const { return atomByID("CA"); }
Atom C() const { return atomByID("C"); }
Atom N() const { return atomByID("N"); }
Atom O() const { return atomByID("O"); }
Atom H() const { return atomByID("H"); }
bool isBondedTo(const Monomer& rhs) const
{
return this != &rhs and areBonded(*this, rhs);
}
static bool areBonded(const Monomer& a, const Monomer& b, float errorMargin = 0.5f);
static bool isCis(const Monomer& a, const Monomer& b);
static float omega(const Monomer& a, const Monomer& b);
// for LEU and VAL
float chiralVolume() const;
private:
const Polymer* mPolymer;
uint32_t mIndex;
};
// --------------------------------------------------------------------
class Polymer : public std::vector<Monomer>
{
public:
Polymer(const Structure& s, const std::string& entityID, const std::string& asymID);
Polymer(const Polymer&) = delete;
Polymer& operator=(const Polymer&) = delete;
// Polymer(Polymer&& rhs) = delete;
// Polymer& operator=(Polymer&& rhs) = de;
Monomer& getBySeqID(int seqID);
const Monomer& getBySeqID(int seqID) const;
Structure* structure() const { return mStructure; }
std::string asymID() const { return mAsymID; }
std::string entityID() const { return mEntityID; }
std::string chainID() const;
int Distance(const Monomer& a, const Monomer& b) const;
private:
Structure* mStructure;
std::string mEntityID;
std::string mAsymID;
cif::RowSet mPolySeq;
};
// --------------------------------------------------------------------
// file is a reference to the data stored in e.g. the cif file.
// This object is not copyable.
class File : public std::enable_shared_from_this<File>
{
public:
File();
File(const std::string& path);
~File();
File(const File&) = delete;
File& operator=(const File&) = delete;
void load(const std::string& path);
void save(const std::string& path);
Structure* model(size_t nr = 1);
struct FileImpl& impl() const { return *mImpl; }
cif::Datablock& data();
cif::File& file();
private:
struct FileImpl* mImpl;
};
// --------------------------------------------------------------------
enum class StructureOpenOptions
{
SkipHydrogen = 1 << 0
};
inline bool operator&(StructureOpenOptions a, StructureOpenOptions b)
{
return static_cast<int>(a) bitand static_cast<int>(b);
}
// --------------------------------------------------------------------
class Structure
{
public:
Structure(File& p, uint32_t modelNr = 1, StructureOpenOptions options = {});
Structure& operator=(const Structure&) = delete;
~Structure();
// Create a read-only clone of the current structure (for multithreaded calculations that move atoms)
Structure(const Structure&);
File& getFile() const;
const AtomView& atoms() const { return mAtoms; }
AtomView waters() const;
const std::list<Polymer>& polymers() const { return mPolymers; }
std::list<Polymer>& polymers() { return mPolymers; }
const std::vector<Residue>& nonPolymers() const { return mNonPolymers; }
Atom getAtomByID(std::string id) const;
// Atom getAtomByLocation(Point pt, float maxDistance) const;
Atom getAtomByLabel(const std::string& atomID, const std::string& asymID,
const std::string& compID, int seqID, const std::string& altID = "");
// Atom getAtomByAuth(const std::string& atomID, const std::string& asymID,
// const std::string& compID, int seqID, const std::string& altID = "",
// const std::string& pdbxAuthInsCode = "");
// map between auth and label locations
std::tuple<std::string,int,std::string> MapAuthToLabel(const std::string& asymID,
const std::string& seqID, const std::string& compID, const std::string& insCode = "");
std::tuple<std::string,std::string,std::string,std::string> MapLabelToAuth(
const std::string& asymID, int seqID, const std::string& compID);
// returns chain, seqnr, icode
std::tuple<char,int,char> MapLabelToAuth(
const std::string& asymID, int seqID) const;
// returns chain,seqnr,comp,iCode
std::tuple<std::string,int,std::string,std::string> MapLabelToPDB(
const std::string& asymID, int seqID, const std::string& compID,
const std::string& authSeqID) const;
std::tuple<std::string,int,std::string> MapPDBToLabel(
const std::string& asymID, int seqID, const std::string& compID, const std::string& iCode) const;
// Actions
void removeAtom(Atom& a);
void swapAtoms(Atom& a1, Atom& a2); // swap the labels for these atoms
void moveAtom(Atom& a, Point p); // move atom to a new location
void changeResidue(const Residue& res, const std::string& newCompound,
const std::vector<std::tuple<std::string,std::string>>& remappedAtoms);
/// To sort the atoms in order of model > asym-id > res-id > atom-id
/// Will asssign new atom_id's to all atoms. Be carefull
void sortAtoms();
// iterator for all residues
class residue_iterator : public std::iterator<std::forward_iterator_tag, const Residue>
{
public:
typedef std::iterator<std::forward_iterator_tag, const Residue> baseType;
typedef typename baseType::pointer pointer;
typedef typename baseType::reference reference;
typedef std::list<Polymer>::const_iterator poly_iterator;
residue_iterator(const Structure* s, poly_iterator polyIter, size_t polyResIndex, size_t nonPolyIndex);
reference operator*();
pointer operator->();
residue_iterator& operator++();
residue_iterator operator++(int);
bool operator==(const residue_iterator& rhs) const;
bool operator!=(const residue_iterator& rhs) const;
private:
const Structure& mStructure;
poly_iterator mPolyIter;
size_t mPolyResIndex;
size_t mNonPolyIndex;
};
class residue_view
{
public:
residue_view(const Structure* s) : mStructure(s) {}
residue_view(const residue_view& rhs) : mStructure(rhs.mStructure) {}
residue_view& operator=(residue_view& rhs)
{
mStructure = rhs.mStructure;
return *this;
}
residue_iterator begin() const { return residue_iterator(mStructure, mStructure->mPolymers.begin(), 0, 0); }
residue_iterator end() const { return residue_iterator(mStructure, mStructure->mPolymers.end(), 0, mStructure->mNonPolymers.size()); }
size_t size() const
{
size_t ps = std::accumulate(mStructure->mPolymers.begin(), mStructure->mPolymers.end(), 0UL, [](size_t s, auto& p) { return s + p.size(); });
return ps + mStructure->mNonPolymers.size();
}
private:
const Structure* mStructure;
};
residue_view residues() const { return residue_view(this); }
private:
friend Polymer;
friend Residue;
friend residue_view;
friend residue_iterator;
cif::Category& category(const char* name) const;
cif::Datablock& datablock() const;
void insertCompound(const std::string& compoundID, bool isEntity);
void loadData();
void updateAtomIndex();
File& mFile;
uint32_t mModelNr;
AtomView mAtoms;
std::vector<size_t> mAtomIndex;
std::list<Polymer> mPolymers;
std::vector<Residue> mNonPolymers;
};
}

281
include/cif++/atom_type.hpp Normal file
View File

@@ -0,0 +1,281 @@
/*-
* 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
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// Lib for working with structures as contained in mmCIF and PDB files
#pragma once
#include <cstdint>
#include <stdexcept>
#include <string>
namespace cif
{
enum atom_type : uint8_t
{
Nn = 0, // Unknown
H = 1, // Hydro­gen
He = 2, // He­lium
Li = 3, // Lith­ium
Be = 4, // Beryl­lium
B = 5, // Boron
C = 6, // Carbon
N = 7, // Nitro­gen
O = 8, // Oxy­gen
F = 9, // Fluor­ine
Ne = 10, // Neon
Na = 11, // So­dium
Mg = 12, // Magne­sium
Al = 13, // Alumin­ium
Si = 14, // Sili­con
P = 15, // Phos­phorus
S = 16, // Sulfur
Cl = 17, // Chlor­ine
Ar = 18, // Argon
K = 19, // Potas­sium
Ca = 20, // Cal­cium
Sc = 21, // Scan­dium
Ti = 22, // Tita­nium
V = 23, // Vana­dium
Cr = 24, // Chrom­ium
Mn = 25, // Manga­nese
Fe = 26, // Iron
Co = 27, // Cobalt
Ni = 28, // Nickel
Cu = 29, // Copper
Zn = 30, // Zinc
Ga = 31, // Gallium
Ge = 32, // Germa­nium
As = 33, // Arsenic
Se = 34, // Sele­nium
Br = 35, // Bromine
Kr = 36, // Kryp­ton
Rb = 37, // Rubid­ium
Sr = 38, // Stront­ium
Y = 39, // Yttrium
Zr = 40, // Zirco­nium
Nb = 41, // Nio­bium
Mo = 42, // Molyb­denum
Tc = 43, // Tech­netium
Ru = 44, // Ruthe­nium
Rh = 45, // Rho­dium
Pd = 46, // Pallad­ium
Ag = 47, // Silver
Cd = 48, // Cad­mium
In = 49, // Indium
Sn = 50, // Tin
Sb = 51, // Anti­mony
Te = 52, // Tellurium
I = 53, // Iodine
Xe = 54, // Xenon
Cs = 55, // Cae­sium
Ba = 56, // Ba­rium
La = 57, // Lan­thanum
Hf = 72, // Haf­nium
Ta = 73, // Tanta­lum
W = 74, // Tung­sten
Re = 75, // Rhe­nium
Os = 76, // Os­mium
Ir = 77, // Iridium
Pt = 78, // Plat­inum
Au = 79, // Gold
Hg = 80, // Mer­cury
Tl = 81, // Thallium
Pb = 82, // Lead
Bi = 83, // Bis­muth
Po = 84, // Polo­nium
At = 85, // Asta­tine
Rn = 86, // Radon
Fr = 87, // Fran­cium
Ra = 88, // Ra­dium
Ac = 89, // Actin­ium
Rf = 104, // Ruther­fordium
Db = 105, // Dub­nium
Sg = 106, // Sea­borgium
Bh = 107, // Bohr­ium
Hs = 108, // Has­sium
Mt = 109, // Meit­nerium
Ds = 110, // Darm­stadtium
Rg = 111, // Roent­genium
Cn = 112, // Coper­nicium
Nh = 113, // Nihon­ium
Fl = 114, // Flerov­ium
Mc = 115, // Moscov­ium
Lv = 116, // Liver­morium
Ts = 117, // Tenness­ine
Og = 118, // Oga­nesson
Ce = 58, // Cerium
Pr = 59, // Praseo­dymium
Nd = 60, // Neo­dymium
Pm = 61, // Prome­thium
Sm = 62, // Sama­rium
Eu = 63, // Europ­ium
Gd = 64, // Gadolin­ium
Tb = 65, // Ter­bium
Dy = 66, // Dyspro­sium
Ho = 67, // Hol­mium
Er = 68, // Erbium
Tm = 69, // Thulium
Yb = 70, // Ytter­bium
Lu = 71, // Lute­tium
Th = 90, // Thor­ium
Pa = 91, // Protac­tinium
U = 92, // Ura­nium
Np = 93, // Neptu­nium
Pu = 94, // Pluto­nium
Am = 95, // Ameri­cium
Cm = 96, // Curium
Bk = 97, // Berkel­ium
Cf = 98, // Califor­nium
Es = 99, // Einstei­nium
Fm = 100, // Fer­mium
Md = 101, // Mende­levium
No = 102, // Nobel­ium
Lr = 103, // Lawren­cium
D = 119, // Deuterium
};
// --------------------------------------------------------------------
// atom_type_info
enum class radius_type
{
calculated,
empirical,
covalent_empirical,
single_bond,
double_bond,
triple_bond,
van_der_waals,
type_count
};
constexpr size_t kRadiusTypeCount = static_cast<size_t>(radius_type::type_count);
enum class ionic_radius_type
{
effective, crystal
};
struct atom_type_info
{
atom_type type;
std::string name;
std::string symbol;
float weight;
bool metal;
float radii[kRadiusTypeCount];
};
extern CIFPP_EXPORT const atom_type_info kKnownAtoms[];
// --------------------------------------------------------------------
// AtomTypeTraits
class atom_type_traits
{
public:
atom_type_traits(atom_type a);
atom_type_traits(const std::string &symbol);
atom_type type() const { return m_info->type; }
std::string name() const { return m_info->name; }
std::string symbol() const { return m_info->symbol; }
float weight() const { return m_info->weight; }
bool is_metal() const { return m_info->metal; }
static bool is_element(const std::string &symbol);
static bool is_metal(const std::string &symbol);
float radius(radius_type type = radius_type::single_bond) const
{
if (type >= radius_type::type_count)
throw std::invalid_argument("invalid radius requested");
return m_info->radii[static_cast<size_t>(type)] / 100.f;
}
/// \brief Return the radius for a charged version of this atom in a solid crystal
///
/// \param charge The charge of the ion
/// \return The radius of the ion
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;
/// \brief Return the radius for a charged version of this atom, returns the effective radius by default
///
/// \param charge The charge of the ion
/// \return The radius of the ion
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);
}
// data type encapsulating the Waasmaier & Kirfel scattering factors
// in a simplified form (only a and b).
// Added the electrion scattering factors as well
struct SFData
{
double a[6], b[6];
};
// to get the Cval and Siva values, use this constant as charge:
enum
{
kWKSFVal = -99
};
const SFData &wksf(int charge = 0) const;
const SFData &elsf() const;
// Clipper doesn't like atoms with charges that do not have a scattering factor. And
// rightly so, but we need to know in advance if this is the case
bool has_sf(int charge) const;
private:
const struct atom_type_info *m_info;
};
} // namespace pdbx

766
include/cif++/category.hpp Normal file
View File

@@ -0,0 +1,766 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2022 NKI/AVL, Netherlands Cancer Institute
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include "cif++/forward_decl.hpp"
#include "cif++/condition.hpp"
#include "cif++/iterator.hpp"
#include "cif++/row.hpp"
#include "cif++/validate.hpp"
#include <array>
// TODO: implement all of:
// https://en.cppreference.com/w/cpp/named_req/Container
// https://en.cppreference.com/w/cpp/named_req/SequenceContainer
// and more?
namespace cif
{
// --------------------------------------------------------------------
// special exception
class duplicate_key_error : public std::runtime_error
{
public:
duplicate_key_error(const std::string &msg)
: std::runtime_error(msg)
{
}
};
class multiple_results_error : public std::runtime_error
{
public:
multiple_results_error()
: std::runtime_error("query should have returned exactly one row")
{
}
};
// --------------------------------------------------------------------
// These should be moved elsewhere, one day.
template<typename _Tp> inline constexpr bool is_optional_v = false;
template<typename _Tp> inline constexpr bool is_optional_v<std::optional<_Tp>> = true;
// --------------------------------------------------------------------
class category
{
public:
friend class row_handle;
template <typename, typename...>
friend class iterator_impl;
using value_type = row_handle;
using reference = value_type;
using const_reference = const value_type;
using iterator = iterator_impl<category>;
using const_iterator = iterator_impl<const category>;
category() = default;
category(std::string_view name);
category(const category &rhs);
category(category &&rhs);
category &operator=(const category &rhs);
category &operator=(category &&rhs);
~category();
// --------------------------------------------------------------------
const std::string &name() const { return m_name; }
iset key_fields() const;
std::set<uint16_t> key_field_indices() const;
void set_validator(const validator *v, datablock &db);
void update_links(datablock &db);
const validator *get_validator() const { return m_validator; }
const category_validator *get_cat_validator() const { return m_cat_validator; }
bool is_valid() const;
bool validate_links() const;
bool operator==(const category &rhs) const;
bool operator!=(const category &rhs) const
{
return not operator==(rhs);
}
// --------------------------------------------------------------------
reference front()
{
return { *this, *m_head };
}
const_reference front() const
{
return { const_cast<category &>(*this), const_cast<row &>(*m_head) };
}
reference back()
{
return { *this, *m_tail };
}
const_reference back() const
{
return { const_cast<category &>(*this), const_cast<row &>(*m_tail) };
}
iterator begin()
{
return { *this, m_head };
}
iterator end()
{
return { *this, nullptr };
}
const_iterator begin() const
{
return { *this, m_head };
}
const_iterator end() const
{
return { *this, nullptr };
}
const_iterator cbegin() const
{
return { *this, m_head };
}
const_iterator cend() const
{
return { *this, nullptr };
}
size_t size() const
{
return std::distance(cbegin(), cend());
}
bool empty() const
{
return m_head == nullptr;
}
// --------------------------------------------------------------------
// A category can have a key, as defined by the validator/dictionary
/// @brief The key type
using key_type = row_initializer;
/// @brief Return a row_handle for the row specified by \a key
/// @param key The value for the key, fields specified in the dictionary should have a value
/// @return The row found in the index, or an undefined row_handle
row_handle operator[](const key_type &key);
const row_handle operator[](const key_type &key) const
{
return const_cast<category *>(this)->operator[](key);
}
// --------------------------------------------------------------------
template <typename... Ts, typename... Ns>
iterator_proxy<const category, Ts...> rows(Ns... names) const
{
static_assert(sizeof...(Ts) == sizeof...(Ns), "The number of column titles should be equal to the number of types to return");
return iterator_proxy<const category, Ts...>(*this, begin(), { names... });
}
template <typename... Ts, typename... Ns>
iterator_proxy<category, Ts...> rows(Ns... names)
{
static_assert(sizeof...(Ts) == sizeof...(Ns), "The number of column titles should be equal to the number of types to return");
return iterator_proxy<category, Ts...>(*this, begin(), { names... });
}
// --------------------------------------------------------------------
conditional_iterator_proxy<category> find(condition &&cond)
{
return find(begin(), std::move(cond));
}
conditional_iterator_proxy<category> find(iterator pos, condition &&cond)
{
return { *this, pos, std::move(cond) };
}
conditional_iterator_proxy<const category> find(condition &&cond) const
{
return find(cbegin(), std::move(cond));
}
conditional_iterator_proxy<const category> find(const_iterator pos, condition &&cond) const
{
return conditional_iterator_proxy<const category>{ *this, pos, std::move(cond) };
}
template <typename... Ts, typename... Ns>
conditional_iterator_proxy<category, Ts...> find(condition &&cond, Ns... names)
{
static_assert(sizeof...(Ts) == sizeof...(Ns), "The number of column titles should be equal to the number of types to return");
return find<Ts...>(cbegin(), std::move(cond), std::forward<Ns>(names)...);
}
template <typename... Ts, typename... Ns>
conditional_iterator_proxy<const category, Ts...> find(condition &&cond, Ns... names) const
{
static_assert(sizeof...(Ts) == sizeof...(Ns), "The number of column titles should be equal to the number of types to return");
return find<Ts...>(cbegin(), std::move(cond), std::forward<Ns>(names)...);
}
template <typename... Ts, typename... Ns>
conditional_iterator_proxy<category, Ts...> find(const_iterator pos, condition &&cond, Ns... names)
{
static_assert(sizeof...(Ts) == sizeof...(Ns), "The number of column titles should be equal to the number of types to return");
return { *this, pos, std::move(cond), std::forward<Ns>(names)... };
}
template <typename... Ts, typename... Ns>
conditional_iterator_proxy<const category, Ts...> find(const_iterator pos, condition &&cond, Ns... names) const
{
static_assert(sizeof...(Ts) == sizeof...(Ns), "The number of column titles should be equal to the number of types to return");
return { *this, pos, std::move(cond), std::forward<Ns>(names)... };
}
// --------------------------------------------------------------------
// if you only expect a single row
row_handle find1(condition &&cond)
{
return find1(begin(), std::move(cond));
}
row_handle find1(iterator pos, condition &&cond)
{
auto h = find(pos, std::move(cond));
if (h.size() != 1)
throw multiple_results_error();
return *h.begin();
}
const row_handle find1(condition &&cond) const
{
return find1(cbegin(), std::move(cond));
}
const row_handle find1(const_iterator pos, condition &&cond) const
{
auto h = find(pos, std::move(cond));
if (h.size() != 1)
throw multiple_results_error();
return *h.begin();
}
template <typename T>
T find1(condition &&cond, const char *column) const
{
return find1<T>(cbegin(), std::move(cond), column);
}
template <typename T, std::enable_if_t<not is_optional_v<T>, int> = 0>
T find1(const_iterator pos, condition &&cond, const char *column) const
{
auto h = find<T>(pos, std::move(cond), column);
if (h.size() != 1)
throw multiple_results_error();
return *h.begin();
}
template <typename T, std::enable_if_t<is_optional_v<T>, int> = 0>
T find1(const_iterator pos, condition &&cond, const char *column) const
{
auto h = find<typename T::value_type>(pos, std::move(cond), column);
if (h.size() > 1)
throw multiple_results_error();
if (h.empty())
return {};
return *h.begin();
}
template <typename... Ts, typename... Cs, typename U = std::enable_if_t<sizeof...(Ts) != 1>>
std::tuple<Ts...> find1(condition &&cond, Cs... columns) const
{
static_assert(sizeof...(Ts) == sizeof...(Cs), "The number of column titles should be equal to the number of types to return");
// static_assert(std::is_same_v<Cs, const char*>..., "The column names should be const char");
return find1<Ts...>(cbegin(), std::move(cond), std::forward<Cs>(columns)...);
}
template <typename... Ts, typename... Cs, typename U = std::enable_if_t<sizeof...(Ts) != 1>>
std::tuple<Ts...> find1(const_iterator pos, condition &&cond, Cs... columns) const
{
static_assert(sizeof...(Ts) == sizeof...(Cs), "The number of column titles should be equal to the number of types to return");
auto h = find<Ts...>(pos, std::move(cond), std::forward<Cs>(columns)...);
if (h.size() != 1)
throw multiple_results_error();
return *h.begin();
}
// --------------------------------------------------------------------
// if you want only a first hit
row_handle find_first(condition &&cond)
{
return find_first(begin(), std::move(cond));
}
row_handle find_first(iterator pos, condition &&cond)
{
auto h = find(pos, std::move(cond));
return h.empty() ? row_handle{} : *h.begin();
}
const row_handle find_first(condition &&cond) const
{
return find_first(cbegin(), std::move(cond));
}
const row_handle find_first(const_iterator pos, condition &&cond) const
{
auto h = find(pos, std::move(cond));
return h.empty() ? row_handle{} : *h.begin();
}
template <typename T>
T find_first(condition &&cond, const char *column) const
{
return find_first<T>(cbegin(), std::move(cond), column);
}
template <typename T>
T find_first(const_iterator pos, condition &&cond, const char *column) const
{
auto h = find<T>(pos, std::move(cond), column);
return h.empty() ? T{} : *h.begin();
}
template <typename... Ts, typename... Cs, typename U = std::enable_if_t<sizeof...(Ts) != 1>>
std::tuple<Ts...> find_first(condition &&cond, Cs... columns) const
{
static_assert(sizeof...(Ts) == sizeof...(Cs), "The number of column titles should be equal to the number of types to return");
// static_assert(std::is_same_v<Cs, const char*>..., "The column names should be const char");
return find_first<Ts...>(cbegin(), std::move(cond), std::forward<Cs>(columns)...);
}
template <typename... Ts, typename... Cs, typename U = std::enable_if_t<sizeof...(Ts) != 1>>
std::tuple<Ts...> find_first(const_iterator pos, condition &&cond, Cs... columns) const
{
static_assert(sizeof...(Ts) == sizeof...(Cs), "The number of column titles should be equal to the number of types to return");
auto h = find<Ts...>(pos, std::move(cond), std::forward<Cs>(columns)...);
return h.empty() ? std::tuple<Ts...>{} : *h.begin();
}
// --------------------------------------------------------------------
template <typename T, std::enable_if_t<std::is_arithmetic_v<T>, int> = 0>
T find_max(const char *column, condition &&cond) const
{
T result = std::numeric_limits<T>::min();
for (auto v : find<T>(std::move(cond), column))
{
if (result < v)
result = v;
}
return result;
}
template <typename T, std::enable_if_t<std::is_arithmetic_v<T>, int> = 0>
T find_max(const char *column) const
{
return find_max<T>(column, all());
}
template <typename T, std::enable_if_t<std::is_arithmetic_v<T>, int> = 0>
T find_min(const char *column, condition &&cond) const
{
T result = std::numeric_limits<T>::max();
for (auto v : find<T>(std::move(cond), column))
{
if (result > v)
result = v;
}
return result;
}
template <typename T, std::enable_if_t<std::is_arithmetic_v<T>, int> = 0>
T find_min(const char *column) const
{
return find_min<T>(column, all());
}
bool exists(condition &&cond) const
{
bool result = false;
if (cond)
{
cond.prepare(*this);
auto sh = cond.single();
if (sh.has_value() and *sh)
result = true;
else
{
for (auto r : *this)
{
if (cond(r))
{
result = true;
break;
}
}
}
}
return result;
}
size_t count(condition &&cond) const
{
size_t result = 0;
if (cond)
{
cond.prepare(*this);
auto sh = cond.single();
if (sh.has_value() and *sh)
result = 1;
else
{
for (auto r : *this)
{
if (cond(r))
++result;
}
}
}
return result;
}
// --------------------------------------------------------------------
bool has_children(row_handle r) const;
bool has_parents(row_handle r) const;
std::vector<row_handle> get_children(row_handle r, const category &childCat) const;
std::vector<row_handle> get_parents(row_handle r, const category &parentCat) const;
std::vector<row_handle> get_linked(row_handle r, const category &cat) const;
// --------------------------------------------------------------------
// void insert(const_iterator pos, const row_initializer &row)
// {
// insert_impl(pos, row);
// }
// void insert(const_iterator pos, row_initializer &&row)
// {
// insert_impl(pos, std::move(row));
// }
iterator erase(iterator pos);
void erase(row_handle rh)
{
erase(iterator(*this, rh.m_row));
}
size_t erase(condition &&cond);
size_t erase(condition &&cond, std::function<void(row_handle)> &&visit);
iterator emplace(row_initializer &&ri)
{
return this->emplace(ri.begin(), ri.end());
}
template <typename ItemIter>
iterator emplace(ItemIter b, ItemIter e)
{
row *r = this->create_row();
try
{
for (auto i = b; i != e; ++i)
{
// item_value *new_item = this->create_item(*i);
r->append(add_column(i->name()), { i->value() });
}
}
catch (...)
{
if (r != nullptr)
this->delete_row(r);
throw;
}
return insert_impl(cend(), r);
}
void clear();
// --------------------------------------------------------------------
/// \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::cif_id_for_number);
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
{
uint16_t result;
for (result = 0; result < m_columns.size(); ++result)
{
if (iequals(column_name, m_columns[result].m_name))
break;
}
if (VERBOSE > 0 and result == m_columns.size() and m_cat_validator != nullptr) // validate the name, if it is known at all (since it was not found)
{
auto iv = m_cat_validator->get_validator_for_item(column_name);
if (iv == nullptr)
std::cerr << "Invalid name used '" << column_name << "' is not a known column in " + m_name << std::endl;
}
return result;
}
std::string_view get_column_name(uint16_t ix) const
{
if (ix >= m_columns.size())
throw std::out_of_range("column index is out of range");
return m_columns[ix].m_name;
}
uint16_t add_column(std::string_view column_name)
{
using namespace std::literals;
uint16_t result = get_column_ix(column_name);
if (result == m_columns.size())
{
const item_validator *item_validator = nullptr;
if (m_cat_validator != nullptr)
{
item_validator = m_cat_validator->get_validator_for_item(column_name);
if (item_validator == nullptr)
m_validator->report_error("tag " + std::string(column_name) + " not allowed in category " + m_name, false);
}
m_columns.emplace_back(column_name, item_validator);
}
return result;
}
bool has_column(std::string_view name) const
{
return get_column_ix(name) < m_columns.size();
}
iset get_columns() const;
// --------------------------------------------------------------------
void sort(std::function<int(row_handle, row_handle)> f);
void reorder_by_index();
// --------------------------------------------------------------------
std::vector<std::string> get_tag_order() const;
void write(std::ostream &os) const;
void write(std::ostream &os, const std::vector<std::string> &order, bool addMissingColumns = true);
private:
void write(std::ostream &os, const std::vector<uint16_t> &order, bool includeEmptyColumns) const;
public:
friend std::ostream &operator<<(std::ostream &os, const category &cat)
{
cat.write(os);
return os;
}
private:
void update_value(row *row, uint16_t column, std::string_view value, bool updateLinked, bool validate = true);
private:
void erase_orphans(condition &&cond, category &parent);
using allocator_type = std::allocator<void>;
constexpr allocator_type get_allocator() const
{
return {};
}
using char_allocator_type = typename std::allocator_traits<allocator_type>::template rebind_alloc<char>;
using char_allocator_traits = std::allocator_traits<char_allocator_type>;
using row_allocator_type = typename std::allocator_traits<allocator_type>::template rebind_alloc<row>;
using row_allocator_traits = std::allocator_traits<row_allocator_type>;
row_allocator_traits::pointer get_row()
{
row_allocator_type ra(get_allocator());
return row_allocator_traits::allocate(ra, 1);
}
row *create_row()
{
auto p = this->get_row();
row_allocator_type ra(get_allocator());
row_allocator_traits::construct(ra, p);
return p;
}
row *clone_row(const row &r);
void delete_row(row *r);
row_handle create_copy(row_handle r);
struct item_column
{
std::string m_name;
const item_validator *m_validator;
item_column(std::string_view name, const item_validator *validator)
: m_name(name)
, m_validator(validator)
{
}
};
struct link
{
link(category *linked, const link_validator *v)
: linked(linked)
, v(v)
{
}
category *linked;
const link_validator *v;
};
// proxy methods for every insertion
iterator insert_impl(const_iterator pos, row *n);
iterator erase_impl(const_iterator pos);
// --------------------------------------------------------------------
condition get_parents_condition(row_handle rh, const category &parentCat) const;
condition get_children_condition(row_handle rh, const category &childCat) const;
// --------------------------------------------------------------------
void swap_item(uint16_t column_ix, row_handle &a, row_handle &b);
// --------------------------------------------------------------------
std::string m_name;
std::vector<item_column> m_columns;
const validator *m_validator = nullptr;
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;
};
} // namespace cif

197
include/cif++/compound.hpp Normal file
View File

@@ -0,0 +1,197 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2020-2022 NKI/AVL, Netherlands Cancer Institute
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
/// \file This file contains the definition for the class compound, encapsulating
/// the information found for compounds in the CCD.
#include "cif++/atom_type.hpp"
#include "cif++/point.hpp"
#include <map>
#include <set>
#include <tuple>
#include <vector>
namespace cif
{
// --------------------------------------------------------------------
class compound;
struct compound_atom;
class compound_factory_impl;
/// \brief The bond type as defined in the CCD, possible values taken from the mmcif_pdbx file
enum class bond_type
{
sing, // 'single bond'
doub, // 'double bond'
trip, // 'triple bond'
quad, // 'quadruple bond'
arom, // 'aromatic bond'
poly, // 'polymeric bond'
delo, // 'delocalized double bond'
pi, // 'pi bond'
};
std::string to_string(bond_type bondType);
bond_type from_string(const std::string &bondType);
/// --------------------------------------------------------------------
/// \brief struct containing information about an atom in a chemical compound.
/// This is a subset of the available information. Contact the author if you need more fields.
struct compound_atom
{
std::string id;
atom_type type_symbol;
int charge = 0;
bool aromatic = false;
bool leaving_atom = false;
bool stereo_config = false;
float x, y, z;
point get_location() const
{
return { x, y, z };
}
};
/// --------------------------------------------------------------------
/// \brief struct containing information about the bonds
struct compound_bond
{
std::string atom_id[2];
bond_type type;
bool aromatic = false, stereo_config = false;
};
/// --------------------------------------------------------------------
/// \brief a class that contains information about a chemical compound.
/// This information is derived from the CDD by default.
///
/// To create compounds, you use the factory method. You can add your own
/// compound definitions by calling the addExtraComponents function and
/// pass it a valid CCD formatted file.
class compound
{
public:
// accessors
std::string id() const { return m_id; }
std::string name() const { return m_name; }
std::string type() const { return m_type; }
std::string group() const { return m_group; }
std::string formula() const { return m_formula; }
float formula_weight() const { return m_formula_weight; }
int formal_charge() const { return m_formal_charge; }
const std::vector<compound_atom> &atoms() const { return m_atoms; }
const std::vector<compound_bond> &bonds() const { return m_bonds; }
compound_atom get_atom_by_atom_id(const std::string &atom_id) const;
bool atoms_bonded(const std::string &atomId_1, const std::string &atomId_2) const;
float bond_length(const std::string &atomId_1, const std::string &atomId_2) const;
bool is_water() const
{
return m_id == "HOH" or m_id == "H2O" or m_id == "WAT";
}
private:
friend class compound_factory_impl;
friend class CCD_compound_factory_impl;
friend class CCP4_compound_factory_impl;
compound(cif::datablock &db);
compound(cif::datablock &db, const std::string &id, const std::string &name, const std::string &type, const std::string &group);
std::string m_id;
std::string m_name;
std::string m_type;
std::string m_group;
std::string m_formula;
float m_formula_weight = 0;
int m_formal_charge = 0;
std::vector<compound_atom> m_atoms;
std::vector<compound_bond> m_bonds;
};
// --------------------------------------------------------------------
// Factory class for compound and Link objects
class compound_factory
{
public:
/// \brief Initialise a singleton instance.
///
/// If you have a multithreaded application and want to have different
/// compounds in each thread (e.g. a web service processing user requests
/// with different sets of compounds) you can set the \a useThreadLocalInstanceOnly
/// flag to true.
static void init(bool useThreadLocalInstanceOnly);
static compound_factory &instance();
static void clear();
void set_default_dictionary(const std::filesystem::path &inDictFile);
void push_dictionary(const std::filesystem::path &inDictFile);
void pop_dictionary();
bool is_known_peptide(const std::string &res_name) const;
bool is_known_base(const std::string &res_name) const;
/// \brief Create the compound object for \a id
///
/// This will create the compound instance for \a id if it doesn't exist already.
/// The result is owned by this factory and should not be deleted by the user.
/// \param id The compound ID, a three letter code usually
/// \result The compound, or nullptr if it could not be created (missing info)
const compound *create(std::string id);
~compound_factory();
static CIFPP_EXPORT const std::map<std::string, char> kAAMap, kBaseMap;
private:
compound_factory();
compound_factory(const compound_factory &) = delete;
compound_factory &operator=(const compound_factory &) = delete;
static std::unique_ptr<compound_factory> s_instance;
static thread_local std::unique_ptr<compound_factory> tl_instance;
static bool s_use_thread_local_instance;
std::shared_ptr<compound_factory_impl> m_impl;
};
} // namespace cif

894
include/cif++/condition.hpp Normal file
View File

@@ -0,0 +1,894 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2022 NKI/AVL, Netherlands Cancer Institute
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include "cif++/row.hpp"
#include <cassert>
#include <functional>
#include <iostream>
#include <regex>
#include <utility>
namespace cif
{
// --------------------------------------------------------------------
// let's make life easier
iset get_category_fields(const category &cat);
uint16_t get_column_ix(const category &cat, std::string_view col);
bool is_column_type_uchar(const category &cat, std::string_view col);
// --------------------------------------------------------------------
// some more templates to be able to do querying
namespace detail
{
struct condition_impl
{
virtual ~condition_impl() {}
virtual condition_impl *prepare(const category &) { return this; }
virtual bool test(row_handle) const = 0;
virtual void str(std::ostream &) const = 0;
virtual std::optional<row_handle> single() const { return {}; };
virtual bool equals([[maybe_unused]] const condition_impl *rhs) const { return false; }
};
struct all_condition_impl : public condition_impl
{
bool test(row_handle) const override { return true; }
void str(std::ostream &os) const override { os << "*"; }
};
struct or_condition_impl;
struct and_condition_impl;
struct not_condition_impl;
} // namespace detail
class condition
{
public:
using condition_impl = detail::condition_impl;
condition()
: m_impl(nullptr)
{
}
explicit condition(condition_impl *impl)
: m_impl(impl)
{
}
condition(const condition &) = delete;
condition(condition &&rhs) noexcept
: m_impl(nullptr)
{
std::swap(m_impl, rhs.m_impl);
}
condition &operator=(const condition &) = delete;
condition &operator=(condition &&rhs) noexcept
{
std::swap(m_impl, rhs.m_impl);
return *this;
}
~condition()
{
delete m_impl;
m_impl = nullptr;
}
void prepare(const category &c);
bool operator()(row_handle r) const
{
assert(this->m_impl != nullptr);
assert(this->m_prepared);
return m_impl ? m_impl->test(r) : false;
}
explicit operator bool() { return not empty(); }
bool empty() const { return m_impl == nullptr; }
std::optional<row_handle> single() const
{
return m_impl ? m_impl->single() : std::optional<row_handle>();
}
friend condition operator||(condition &&a, condition &&b);
friend condition operator&&(condition &&a, condition &&b);
friend struct detail::or_condition_impl;
friend struct detail::and_condition_impl;
friend struct detail::not_condition_impl;
void swap(condition &rhs)
{
std::swap(m_impl, rhs.m_impl);
std::swap(m_prepared, rhs.m_prepared);
}
friend std::ostream &operator<<(std::ostream &os, const condition &cond)
{
if (cond.m_impl)
cond.m_impl->str(os);
return os;
}
private:
void optimise(condition_impl *&impl);
condition_impl *m_impl;
bool m_prepared = false;
};
namespace detail
{
struct key_is_empty_condition_impl : public condition_impl
{
key_is_empty_condition_impl(const std::string &item_tag)
: m_item_tag(item_tag)
{
}
condition_impl *prepare(const category &c) override
{
m_item_ix = get_column_ix(c, m_item_tag);
return this;
}
bool test(row_handle r) const override
{
return r[m_item_ix].empty();
}
void str(std::ostream &os) const override
{
os << m_item_tag << " IS NULL";
}
std::string m_item_tag;
uint16_t m_item_ix = 0;
};
struct key_is_not_empty_condition_impl : public condition_impl
{
key_is_not_empty_condition_impl(const std::string &item_tag)
: m_item_tag(item_tag)
{
}
condition_impl *prepare(const category &c) override
{
m_item_ix = get_column_ix(c, m_item_tag);
return this;
}
bool test(row_handle r) const override
{
return not r[m_item_ix].empty();
}
void str(std::ostream &os) const override
{
os << m_item_tag << " IS NOT NULL";
}
std::string m_item_tag;
uint16_t m_item_ix = 0;
};
struct key_equals_condition_impl : public condition_impl
{
key_equals_condition_impl(item &&i)
: m_item_tag(i.name())
, m_value(i.value())
{
}
condition_impl *prepare(const category &c) override;
bool test(row_handle r) const override
{
return m_single_hit.has_value() ? *m_single_hit == r : r[m_item_ix].compare(m_value, m_icase) == 0;
}
void str(std::ostream &os) const override
{
os << m_item_tag << (m_icase ? "^ " : " ") << " == " << m_value;
}
virtual std::optional<row_handle> single() const override
{
return m_single_hit;
}
virtual bool equals(const condition_impl *rhs) const override
{
if (typeid(*rhs) == typeid(key_equals_condition_impl))
{
auto ri = static_cast<const key_equals_condition_impl *>(rhs);
if (m_single_hit.has_value() or ri->m_single_hit.has_value())
return m_single_hit == ri->m_single_hit;
else
// watch out, both m_item_ix might be the same while tags might be diffent (in case they both do not exist in the category)
return m_item_ix == ri->m_item_ix and m_value == ri->m_value and m_item_tag == ri->m_item_tag;
}
return this == rhs;
}
std::string m_item_tag;
uint16_t m_item_ix = 0;
bool m_icase = false;
std::string m_value;
std::optional<row_handle> m_single_hit;
};
struct key_equals_or_empty_condition_impl : public condition_impl
{
key_equals_or_empty_condition_impl(key_equals_condition_impl *equals)
: m_item_tag(equals->m_item_tag)
, m_value(equals->m_value)
, m_icase(equals->m_icase)
, m_single_hit(equals->m_single_hit)
{
}
condition_impl *prepare(const category &c) override
{
m_item_ix = get_column_ix(c, m_item_tag);
m_icase = is_column_type_uchar(c, m_item_tag);
return this;
}
bool test(row_handle r) const override
{
bool result = false;
if (m_single_hit.has_value())
result = *m_single_hit == r;
else
result = r[m_item_ix].empty() or r[m_item_ix].compare(m_value, m_icase) == 0;
return result;
}
void str(std::ostream &os) const override
{
os << '(' << m_item_tag << (m_icase ? "^ " : " ") << " == " << m_value << " OR " << m_item_tag << " IS NULL)";
}
virtual std::optional<row_handle> single() const override
{
return m_single_hit;
}
virtual bool equals(const condition_impl *rhs) const override
{
if (typeid(*rhs) == typeid(key_equals_or_empty_condition_impl))
{
auto ri = static_cast<const key_equals_or_empty_condition_impl *>(rhs);
if (m_single_hit.has_value() or ri->m_single_hit.has_value())
return m_single_hit == ri->m_single_hit;
else
// watch out, both m_item_ix might be the same while tags might be diffent (in case they both do not exist in the category)
return m_item_ix == ri->m_item_ix and m_value == ri->m_value and m_item_tag == ri->m_item_tag;
}
return this == rhs;
}
std::string m_item_tag;
uint16_t m_item_ix = 0;
std::string m_value;
bool m_icase = false;
std::optional<row_handle> m_single_hit;
};
struct key_compare_condition_impl : public condition_impl
{
template <typename COMP>
key_compare_condition_impl(const std::string &item_tag, COMP &&comp, const std::string &s)
: m_item_tag(item_tag)
, m_compare(std::move(comp))
, m_str(s)
{
}
condition_impl *prepare(const category &c) override
{
m_item_ix = get_column_ix(c, m_item_tag);
m_icase = is_column_type_uchar(c, m_item_tag);
return this;
}
bool test(row_handle r) const override
{
return m_compare(r, m_icase);
}
void str(std::ostream &os) const override
{
os << m_item_tag << (m_icase ? "^ " : " ") << m_str;
}
std::string m_item_tag;
uint16_t m_item_ix = 0;
bool m_icase = false;
std::function<bool(row_handle, bool)> m_compare;
std::string m_str;
};
struct key_matches_condition_impl : public condition_impl
{
key_matches_condition_impl(const std::string &item_tag, const std::regex &rx)
: m_item_tag(item_tag)
, m_item_ix(0)
, mRx(rx)
{
}
condition_impl *prepare(const category &c) override
{
m_item_ix = get_column_ix(c, m_item_tag);
return this;
}
bool test(row_handle r) const override
{
std::string_view txt = r[m_item_ix].text();
return std::regex_match(txt.begin(), txt.end(), mRx);
}
void str(std::ostream &os) const override
{
os << m_item_tag << " =~ expression";
}
std::string m_item_tag;
uint16_t m_item_ix;
std::regex mRx;
};
template <typename T>
struct any_is_condition_impl : public condition_impl
{
typedef T valueType;
any_is_condition_impl(const valueType &value)
: mValue(value)
{
}
bool test(row_handle r) const override
{
auto &c = r.get_category();
bool result = false;
for (auto &f : get_category_fields(c))
{
try
{
if (r[f].compare(mValue) == 0)
{
result = true;
break;
}
}
catch (...)
{
}
}
return result;
}
void str(std::ostream &os) const override
{
os << "<any> == " << mValue;
}
valueType mValue;
};
struct any_matches_condition_impl : public condition_impl
{
any_matches_condition_impl(const std::regex &rx)
: mRx(rx)
{
}
bool test(row_handle r) const override
{
auto &c = r.get_category();
bool result = false;
for (auto &f : get_category_fields(c))
{
try
{
std::string_view txt = r[f].text();
if (std::regex_match(txt.begin(), txt.end(), mRx))
{
result = true;
break;
}
}
catch (...)
{
}
}
return result;
}
void str(std::ostream &os) const override
{
os << "<any> =~ expression";
}
std::regex mRx;
};
// TODO: Optimize and_condition by having a list of sub items.
// That way you can also collapse multiple _is_ conditions in
// case they make up an indexed tuple.
struct and_condition_impl : public condition_impl
{
and_condition_impl() = default;
and_condition_impl(condition &&a, condition &&b)
{
if (typeid(*a.m_impl) == typeid(*this))
{
and_condition_impl *ai = static_cast<and_condition_impl *>(a.m_impl);
std::swap(m_sub, ai->m_sub);
m_sub.emplace_back(std::exchange(b.m_impl, nullptr));
}
else if (typeid(*b.m_impl) == typeid(*this))
{
and_condition_impl *bi = static_cast<and_condition_impl *>(b.m_impl);
std::swap(m_sub, bi->m_sub);
m_sub.emplace_back(std::exchange(a.m_impl, nullptr));
}
else
{
m_sub.emplace_back(std::exchange(a.m_impl, nullptr));
m_sub.emplace_back(std::exchange(b.m_impl, nullptr));
}
}
~and_condition_impl()
{
for (auto sub : m_sub)
delete sub;
}
condition_impl *prepare(const category &c) override
{
for (auto &sub : m_sub)
sub = sub->prepare(c);
return this;
}
bool test(row_handle r) const override
{
bool result = true;
for (auto sub : m_sub)
{
if (sub->test(r))
continue;
result = false;
break;
}
return result;
}
void str(std::ostream &os) const override
{
os << '(';
bool first = true;
for (auto sub : m_sub)
{
if (first)
first = false;
else
os << " AND ";
sub->str(os);
}
os << ')';
}
virtual std::optional<row_handle> single() const override
{
std::optional<row_handle> result;
for (auto sub : m_sub)
{
auto s = sub->single();
if (not result.has_value())
{
result = s;
continue;
}
if (s == result)
continue;
result.reset();
break;
}
return result;
}
static condition_impl *combine_equal(std::vector<and_condition_impl *> &subs, or_condition_impl *oc);
std::vector<condition_impl *> m_sub;
};
struct or_condition_impl : public condition_impl
{
or_condition_impl(condition &&a, condition &&b)
{
if (typeid(*a.m_impl) == typeid(*this))
{
or_condition_impl *ai = static_cast<or_condition_impl *>(a.m_impl);
std::swap(m_sub, ai->m_sub);
m_sub.emplace_back(std::exchange(b.m_impl, nullptr));
}
else if (typeid(*b.m_impl) == typeid(*this))
{
or_condition_impl *bi = static_cast<or_condition_impl *>(b.m_impl);
std::swap(m_sub, bi->m_sub);
m_sub.emplace_back(std::exchange(a.m_impl, nullptr));
}
else
{
m_sub.emplace_back(std::exchange(a.m_impl, nullptr));
m_sub.emplace_back(std::exchange(b.m_impl, nullptr));
}
}
~or_condition_impl()
{
for (auto sub : m_sub)
delete sub;
}
condition_impl *prepare(const category &c) override;
bool test(row_handle r) const override
{
bool result = false;
for (auto sub : m_sub)
{
if (not sub->test(r))
continue;
result = true;
break;
}
return result;
}
void str(std::ostream &os) const override
{
bool first = true;
os << '(';
for (auto sub : m_sub)
{
if (first)
first = false;
else
os << " OR ";
sub->str(os);
}
os << ')';
}
virtual std::optional<row_handle> single() const override
{
std::optional<row_handle> result;
for (auto sub : m_sub)
{
auto s = sub->single();
if (not result.has_value())
{
result = s;
continue;
}
if (s == result)
continue;
result.reset();
break;
}
return result;
}
std::vector<condition_impl *> m_sub;
};
struct not_condition_impl : public condition_impl
{
not_condition_impl(condition &&a)
: mA(nullptr)
{
std::swap(mA, a.m_impl);
}
~not_condition_impl()
{
delete mA;
}
condition_impl *prepare(const category &c) override
{
mA = mA->prepare(c);
return this;
}
bool test(row_handle r) const override
{
return not mA->test(r);
}
void str(std::ostream &os) const override
{
os << "NOT (";
mA->str(os);
os << ')';
}
condition_impl *mA;
};
} // namespace detail
inline condition operator and(condition &&a, condition &&b)
{
if (a.m_impl and b.m_impl)
return condition(new detail::and_condition_impl(std::move(a), std::move(b)));
if (a.m_impl)
return condition(std::move(a));
return condition(std::move(b));
}
inline condition operator or(condition &&a, condition &&b)
{
if (a.m_impl and b.m_impl)
{
if (typeid(*a.m_impl) == typeid(detail::key_equals_condition_impl) and
typeid(*b.m_impl) == typeid(detail::key_is_empty_condition_impl))
{
auto ci = static_cast<detail::key_equals_condition_impl *>(a.m_impl);
auto ce = static_cast<detail::key_is_empty_condition_impl *>(b.m_impl);
if (ci->m_item_tag == ce->m_item_tag)
return condition(new detail::key_equals_or_empty_condition_impl(ci));
}
else if (typeid(*b.m_impl) == typeid(detail::key_equals_condition_impl) and
typeid(*a.m_impl) == typeid(detail::key_is_empty_condition_impl))
{
auto ci = static_cast<detail::key_equals_condition_impl *>(b.m_impl);
auto ce = static_cast<detail::key_is_empty_condition_impl *>(a.m_impl);
if (ci->m_item_tag == ce->m_item_tag)
return condition(new detail::key_equals_or_empty_condition_impl(ci));
}
return condition(new detail::or_condition_impl(std::move(a), std::move(b)));
}
if (a.m_impl)
return condition(std::move(a));
return condition(std::move(b));
}
struct empty_type
{
};
/// \brief A helper to make it possible to have conditions like ("id"_key == cif::null)
inline constexpr empty_type null = empty_type();
struct key
{
explicit key(const std::string &itemTag)
: m_item_tag(itemTag)
{
}
explicit key(const char *itemTag)
: m_item_tag(itemTag)
{
}
key(const key &) = delete;
key &operator=(const key &) = delete;
std::string m_item_tag;
};
template <typename T>
condition operator==(const key &key, const T &v)
{
return condition(new detail::key_equals_condition_impl({ key.m_item_tag, v }));
}
inline condition operator==(const key &key, const char *value)
{
if (value != nullptr and *value != 0)
return condition(new detail::key_equals_condition_impl({ key.m_item_tag, value }));
else
return condition(new detail::key_is_empty_condition_impl(key.m_item_tag));
}
// inline condition_t operator==(const key& key, const detail::ItemReference& v)
// {
// if (v.empty())
// return condition_t(new detail::key_is_empty_condition_impl(key.m_item_tag));
// else
// return condition_t(new detail::key_compare_condition_impl(key.m_item_tag, [tag = key.m_item_tag, v](const category& c, const row& r, bool icase)
// { return r[tag].template compare<(v, icase) == 0; }));
// }
template <typename T>
condition operator!=(const key &key, const T &v)
{
return condition(new detail::not_condition_impl(operator==(key, v)));
}
inline condition operator!=(const key &key, const char *v)
{
std::string value(v ? v : "");
return condition(new detail::not_condition_impl(operator==(key, value)));
}
template <typename T>
condition operator>(const key &key, const T &v)
{
std::ostringstream s;
s << " > " << v;
return condition(new detail::key_compare_condition_impl(
key.m_item_tag, [tag = key.m_item_tag, v](row_handle r, bool icase)
{ return r[tag].template compare<T>(v, icase) > 0; },
s.str()));
}
template <typename T>
condition operator>=(const key &key, const T &v)
{
std::ostringstream s;
s << " >= " << v;
return condition(new detail::key_compare_condition_impl(
key.m_item_tag, [tag = key.m_item_tag, v](row_handle r, bool icase)
{ return r[tag].template compare<T>(v, icase) >= 0; },
s.str()));
}
template <typename T>
condition operator<(const key &key, const T &v)
{
std::ostringstream s;
s << " < " << v;
return condition(new detail::key_compare_condition_impl(
key.m_item_tag, [tag = key.m_item_tag, v](row_handle r, bool icase)
{ return r[tag].template compare<T>(v, icase) < 0; },
s.str()));
}
template <typename T>
condition operator<=(const key &key, const T &v)
{
std::ostringstream s;
s << " <= " << v;
return condition(new detail::key_compare_condition_impl(
key.m_item_tag, [tag = key.m_item_tag, v](row_handle r, bool icase)
{ return r[tag].template compare<T>(v, icase) <= 0; },
s.str()));
}
inline condition operator==(const key &key, const std::regex &rx)
{
return condition(new detail::key_matches_condition_impl(key.m_item_tag, rx));
}
inline condition operator==(const key &key, const empty_type &)
{
return condition(new detail::key_is_empty_condition_impl(key.m_item_tag));
}
inline condition operator!=(const key &key, const empty_type &)
{
return condition(new detail::key_is_not_empty_condition_impl(key.m_item_tag));
}
inline condition operator not(condition &&rhs)
{
return condition(new detail::not_condition_impl(std::move(rhs)));
}
struct any_type
{
};
inline constexpr any_type any = any_type{};
template <typename T>
condition operator==(const any_type &, const T &v)
{
return condition(new detail::any_is_condition_impl<T>(v));
}
inline condition operator==(const any_type &, const std::regex &rx)
{
return condition(new detail::any_matches_condition_impl(rx));
}
inline condition all()
{
return condition(new detail::all_condition_impl());
}
namespace literals
{
inline key operator""_key(const char *text, size_t length)
{
return key(std::string(text, length));
}
} // namespace literals
} // namespace cif

View File

@@ -0,0 +1,98 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2022 NKI/AVL, Netherlands Cancer Institute
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include "cif++/category.hpp"
#include "cif++/forward_decl.hpp"
namespace cif
{
// --------------------------------------------------------------------
class datablock : public std::list<category>
{
public:
datablock() = default;
datablock(std::string_view name)
: m_name(name)
{
}
datablock(const datablock &);
datablock(datablock &&) = default;
datablock &operator=(const datablock &);
datablock &operator=(datablock &&) = default;
// --------------------------------------------------------------------
const std::string &name() const { return m_name; }
void set_name(std::string_view name)
{
m_name = name;
}
void set_validator(const validator *v);
const validator *get_validator() const;
bool is_valid() const;
bool validate_links() const;
// --------------------------------------------------------------------
category &operator[](std::string_view name);
const category &operator[](std::string_view name) const;
category *get(std::string_view name);
const category *get(std::string_view name) const;
std::tuple<iterator, bool> emplace(std::string_view name);
std::vector<std::string> get_tag_order() const;
void write(std::ostream &os) const;
void write(std::ostream &os, const std::vector<std::string> &tag_order);
friend std::ostream &operator<<(std::ostream &os, const datablock &db)
{
db.write(os);
return os;
}
// --------------------------------------------------------------------
bool operator==(const datablock &rhs) const;
private:
std::string m_name;
const validator *m_validator = nullptr;
};
} // namespace cif

View File

@@ -1,17 +1,17 @@
/*-
* 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
@@ -26,9 +26,12 @@
#pragma once
namespace mmcif
#include "cif++/validate.hpp"
namespace cif
{
int GetSpacegroupNumber(std::string spacegroup); // alternative for clipper's parsing code
validator parse_dictionary(std::string_view name, std::istream &is);
void extend_dictionary(validator &v, std::istream &is);
}
} // namespace cif

123
include/cif++/file.hpp Normal file
View File

@@ -0,0 +1,123 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2022 NKI/AVL, Netherlands Cancer Institute
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include <list>
#include "cif++/exports.hpp"
#include "cif++/datablock.hpp"
#include "cif++/parser.hpp"
namespace cif
{
// --------------------------------------------------------------------
class file : public std::list<datablock>
{
public:
file() = default;
explicit file(const std::filesystem::path &p)
{
load(p);
}
explicit file(std::istream &is)
{
load(is);
}
explicit file(const char *data, size_t length)
{
struct membuf : public std::streambuf
{
membuf(char *text, size_t length)
{
this->setg(text, text, text + length);
}
} buffer(const_cast<char *>(data), length);
std::istream is(&buffer);
load(is);
}
file(const file &) = default;
file(file &&) = default;
file &operator=(const file &) = default;
file &operator=(file &&) = default;
void set_validator(const validator *v);
const validator *get_validator() const
{
return m_validator;
}
bool is_valid() const;
bool is_valid();
bool validate_links() const;
void load_dictionary();
void load_dictionary(std::string_view name);
bool contains(std::string_view name) const;
datablock &front()
{
assert(not empty());
return std::list<datablock>::front();
}
const datablock &front() const
{
assert(not empty());
return std::list<datablock>::front();
}
datablock &operator[](std::string_view name);
const datablock &operator[](std::string_view name) const;
std::tuple<iterator, bool> emplace(std::string_view name);
void load(const std::filesystem::path &p);
void load(std::istream &is);
void save(const std::filesystem::path &p) const;
void save(std::ostream &os) const;
friend std::ostream &operator<<(std::ostream &os, const file &f)
{
f.save(os);
return os;
}
private:
const validator *m_validator = nullptr;
};
} // namespace cif

206
include/cif++/format.hpp Normal file
View File

@@ -0,0 +1,206 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2022 NKI/AVL, Netherlands Cancer Institute
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include <string>
/// \file format.hpp
/// File containing a basic reimplementation of boost::format
/// but then a bit more simplistic. Still this allowed me to move my code
/// from using boost::format to something without external dependency easily.
namespace cif
{
namespace detail
{
template <typename T>
struct to_varg
{
using type = T;
to_varg(const T &v)
: m_value(v)
{
}
type operator*() { return m_value; }
T m_value;
};
template <>
struct to_varg<const char *>
{
using type = const char *;
to_varg(const char *v)
: m_value(v)
{
}
type operator*() { return m_value.c_str(); }
std::string m_value;
};
template <>
struct to_varg<std::string>
{
using type = const char *;
to_varg(const std::string &v)
: m_value(v)
{
}
type operator*() { return m_value.c_str(); }
std::string m_value;
};
} // namespace
template <typename... Args>
class format_plus_arg
{
public:
using args_vector_type = std::tuple<detail::to_varg<Args>...>;
using vargs_vector_type = std::tuple<typename detail::to_varg<Args>::type...>;
format_plus_arg(const format_plus_arg &) = delete;
format_plus_arg &operator=(const format_plus_arg &) = delete;
format_plus_arg(std::string_view fmt, Args... args)
: m_fmt(fmt)
, m_args(std::forward<Args>(args)...)
{
auto ix = std::make_index_sequence<sizeof...(Args)>();
copy_vargs(ix);
}
std::string str()
{
char buffer[1024];
std::string::size_type r = std::apply(snprintf, std::tuple_cat(std::make_tuple(buffer, sizeof(buffer), m_fmt.c_str()), m_vargs));
return { buffer, r };
}
friend std::ostream &operator<<(std::ostream &os, const format_plus_arg &f)
{
char buffer[1024];
std::string::size_type r = std::apply(snprintf, std::tuple_cat(std::make_tuple(buffer, sizeof(buffer), f.m_fmt.c_str()), f.m_vargs));
os.write(buffer, r);
return os;
}
private:
template <size_t... I>
void copy_vargs(std::index_sequence<I...>)
{
((std::get<I>(m_vargs) = *std::get<I>(m_args)), ...);
}
std::string m_fmt;
args_vector_type m_args;
vargs_vector_type m_vargs;
};
template <typename... Args>
constexpr auto format(std::string_view fmt, Args... args)
{
return format_plus_arg(fmt, std::forward<Args>(args)...);
}
// --------------------------------------------------------------------
/// A streambuf that fills out lines with spaces up until a specified width
class fill_out_streambuf : public std::streambuf
{
public:
using base_type = std::streambuf;
using int_type = base_type::int_type;
using char_type = base_type::char_type;
using traits_type = base_type::traits_type;
fill_out_streambuf(std::ostream &os, int width = 80)
: m_os(os)
, m_upstream(os.rdbuf())
, m_width(width)
{
}
~fill_out_streambuf()
{
m_os.rdbuf(m_upstream);
}
virtual int_type
overflow(int_type ic = traits_type::eof())
{
char ch = traits_type::to_char_type(ic);
int_type result = ic;
if (ch == '\n')
{
for (int i = m_column_count; result != traits_type::eof() and i < m_width; ++i)
result = m_upstream->sputc(' ');
}
if (result != traits_type::eof())
result = m_upstream->sputc(ch);
if (result != traits_type::eof())
{
if (ch == '\n')
{
m_column_count = 0;
++m_line_count;
}
else
++m_column_count;
}
return result;
}
std::streambuf *get_upstream() const { return m_upstream; }
int get_line_count() const { return m_line_count; }
private:
std::ostream &m_os;
std::streambuf *m_upstream;
int m_width;
int m_line_count = 0;
int m_column_count = 0;
};
} // namespace pdbx

View File

@@ -0,0 +1,48 @@
/*-
* 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
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include "cif++/exports.hpp"
#include <string>
#include <vector>
namespace cif
{
class category;
class datablock;
class file;
class parser;
class row;
class row_handle;
class item;
struct item_handle;
} // namespace cif

1036
include/cif++/gzio.hpp Normal file

File diff suppressed because it is too large Load Diff

567
include/cif++/item.hpp Normal file
View File

@@ -0,0 +1,567 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2022 NKI/AVL, Netherlands Cancer Institute
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include "cif++/exports.hpp"
#include "cif++/forward_decl.hpp"
#include "cif++/text.hpp"
#include "cif++/utilities.hpp"
#include <cassert>
#include <charconv>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <limits>
#include <memory>
#include <optional>
#include <utility>
/// \file item.hpp
/// This file contains the declaration of item but also the item_value and item_handle
/// These handle the storage of and access to the data for a single data field.
namespace cif
{
// --------------------------------------------------------------------
/// \brief item is a transient class that is used to pass data into rows
/// but it also takes care of formatting data.
class item
{
public:
/// \brief Default constructor, empty item
item() = default;
/// \brief constructor for an item with name \a name and as
/// content a single character string with content \a value
item(std::string_view name, char value)
: m_name(name)
, m_value({ value })
{
}
/// \brief constructor for an item with name \a name and as
/// content a the formatted floating point value \a value with
/// precision \a precision
template <typename T, std::enable_if_t<std::is_floating_point_v<T>, int> = 0>
item(std::string_view name, const T &value, int precision)
: m_name(name)
{
using namespace std;
using namespace cif;
char buffer[32];
auto r = to_chars(buffer, buffer + sizeof(buffer) - 1, value, chars_format::fixed, precision);
if (r.ec != std::errc())
throw std::runtime_error("Could not format number");
assert(r.ptr >= buffer and r.ptr < buffer + sizeof(buffer));
*r.ptr = 0;
m_value.assign(buffer, r.ptr - buffer);
}
/// \brief constructor for an item with name \a name and as
/// content a formatted floating point value \a value with
/// so-called general formatting
template <typename T, std::enable_if_t<std::is_floating_point_v<T>, int> = 0>
item(const std::string_view name, const T &value)
: m_name(name)
{
using namespace std;
using namespace cif;
char buffer[32];
auto r = to_chars(buffer, buffer + sizeof(buffer) - 1, value, chars_format::general);
if (r.ec != std::errc())
throw std::runtime_error("Could not format number");
assert(r.ptr >= buffer and r.ptr < buffer + sizeof(buffer));
*r.ptr = 0;
m_value.assign(buffer, r.ptr - buffer);
}
/// \brief constructor for an item with name \a name and as
/// content a the formatted integral value \a value
template <typename T, std::enable_if_t<std::is_integral_v<T> and not std::is_same_v<T,bool>, int> = 0>
item(const std::string_view name, const T &value)
: m_name(name)
{
char buffer[32];
auto r = std::to_chars(buffer, buffer + sizeof(buffer) - 1, value);
if (r.ec != std::errc())
throw std::runtime_error("Could not format number");
assert(r.ptr >= buffer and r.ptr < buffer + sizeof(buffer));
*r.ptr = 0;
m_value.assign(buffer, r.ptr - buffer);
}
/// \brief constructor for an item with name \a name and as
/// content a the formatted boolean value \a value
template <typename T, std::enable_if_t<std::is_same_v<T,bool>, int> = 0>
item(const std::string_view name, const T &value)
: m_name(name)
{
m_value.assign(value ? "y" : "n");
}
/// \brief constructor for an item with name \a name and as
/// content value \a value
item(const std::string_view name, const std::string_view value)
: m_name(name)
, m_value(value)
{
}
item(const item &rhs) = default;
item(item &&rhs) noexcept = default;
item &operator=(const item &rhs) = default;
item &operator=(item &&rhs) noexcept = default;
std::string_view name() const { return m_name; }
std::string_view value() const { return m_value; }
/// \brief replace the content of the stored value with \a v
void value(std::string_view v) { m_value = v; }
/// \brief empty means either null or unknown
bool empty() const { return m_value.empty(); }
/// \brief returns true if the field contains '.'
bool is_null() const { return m_value == "."; }
/// \brief returns true if the field contains '?'
bool is_unknown() const { return m_value == "?"; }
/// \brief the length of the value string
size_t length() const { return m_value.length(); }
/// \brief support for structured binding
template<size_t N>
decltype(auto) get() const
{
if constexpr (N == 0) return name();
else if constexpr (N == 1) return value();
}
private:
std::string_view m_name;
std::string m_value;
};
// --------------------------------------------------------------------
/// \brief the internal storage for items in a category
///
/// Internal storage, strictly forward linked list with minimal space
/// requirements. Strings of size 7 or shorter are stored internally.
/// Typically, more than 99% of the strings in an mmCIF file are less
/// than 8 bytes in length.
struct item_value
{
item_value() = default;
/// \brief constructor
item_value(std::string_view text)
: m_length(text.length())
, m_storage(0)
{
if (m_length >= kBufferSize)
{
m_data = new char[m_length + 1];
std::copy(text.begin(), text.end(), m_data);
m_data[m_length] = 0;
}
else
{
std::copy(text.begin(), text.end(), m_local_data);
m_local_data[m_length] = 0;
}
}
item_value(item_value &&rhs)
: m_length(std::exchange(rhs.m_length, 0))
, m_storage(std::exchange(rhs.m_storage, 0))
{
}
item_value &operator=(item_value &&rhs)
{
if (this != &rhs)
{
m_length = std::exchange(rhs.m_length, m_length);
m_storage = std::exchange(rhs.m_storage, m_storage);
}
return *this;
}
~item_value()
{
if (m_length >= kBufferSize)
delete[] m_data;
m_storage = 0;
m_length = 0;
}
item_value(const item_value &) = delete;
item_value &operator=(const item_value &) = delete;
explicit operator bool() const
{
return m_length != 0;
}
size_t m_length = 0;
union
{
char m_local_data[8];
char *m_data;
uint64_t m_storage;
};
static constexpr size_t kBufferSize = sizeof(m_local_data);
// By using std::string_view instead of c_str we obain a
// nice performance gain since we avoid many calls to strlen.
constexpr inline std::string_view text() const
{
return { m_length >= kBufferSize ? m_data : m_local_data, m_length };
}
};
// --------------------------------------------------------------------
// Transient object to access stored data
/// \brief This is item_handle, it is used to access the data stored in item_value.
struct item_handle
{
public:
// conversion helper class
template <typename T, typename = void>
struct item_value_as;
template <typename T>
item_handle &operator=(const T &value)
{
item v{ "", value };
assign_value(v);
return *this;
}
template <typename... Ts>
void os(const Ts &...v)
{
std::ostringstream ss;
((ss << v), ...);
this->operator=(ss.str());
}
void swap(item_handle &b);
template <typename T = std::string>
auto as() const -> T
{
using value_type = std::remove_cv_t<std::remove_reference_t<T>>;
return item_value_as<value_type>::convert(*this);
}
template <typename T>
auto value_or(const T &dv) const
{
return empty() ? dv : this->as<T>();
}
template <typename T>
int compare(const T &value, bool icase = true) const
{
return item_value_as<T>::compare(*this, value, icase);
}
template <typename T>
bool operator==(const T &value) const
{
// TODO: icase or not icase?
return item_value_as<T>::compare(*this, value, true) == 0;
}
// We may not have C++20 yet...
template <typename T>
bool operator!=(const T &value) const
{
return not operator==(value);
}
// empty means either null or unknown
bool empty() const
{
auto txt = text();
return txt.empty() or (txt.length() == 1 and (txt.front() == '.' or txt.front() == '?'));
}
explicit operator bool() const { return not empty(); }
// is_null means the field contains '.'
bool is_null() const
{
auto txt = text();
return txt.length() == 1 and txt.front() == '.';
}
// is_unknown means the field contains '?'
bool is_unknown() const
{
auto txt = text();
return txt.length() == 1 and txt.front() == '?';
}
std::string_view text() const;
item_handle(uint16_t column, row_handle &row)
: m_column(column)
, m_row_handle(row)
{
}
static CIFPP_EXPORT const item_handle s_null_item;
friend void swap(item_handle a, item_handle b)
{
a.swap(b);
}
private:
item_handle();
uint16_t m_column;
row_handle &m_row_handle;
void assign_value(const item &value);
};
// So sad that older gcc implementations of from_chars did not support floats yet...
template <typename T>
struct item_handle::item_value_as<T, std::enable_if_t<std::is_arithmetic_v<T> and not std::is_same_v<T, bool>>>
{
using value_type = std::remove_reference_t<std::remove_cv_t<T>>;
static value_type convert(const item_handle &ref)
{
value_type result = {};
if (not ref.empty())
{
auto txt = ref.text();
std::from_chars_result r = selected_charconv<value_type>::from_chars(txt.data(), txt.data() + txt.size(), result);
if (r.ec != std::errc())
{
result = {};
if (cif::VERBOSE)
{
if (r.ec == std::errc::invalid_argument)
std::cerr << "Attempt to convert " << std::quoted(txt) << " into a number" << std::endl;
else if (r.ec == std::errc::result_out_of_range)
std::cerr << "Conversion of " << std::quoted(txt) << " into a type that is too small" << std::endl;
}
}
}
return result;
}
static int compare(const item_handle &ref, const T &value, bool icase)
{
int result = 0;
auto txt = ref.text();
if (txt.empty())
result = 1;
else
{
value_type v = {};
std::from_chars_result r = selected_charconv<value_type>::from_chars(txt.data(), txt.data() + txt.size(), v);
if (r.ec != std::errc())
{
if (cif::VERBOSE)
{
if (r.ec == std::errc::invalid_argument)
std::cerr << "Attempt to convert " << std::quoted(txt) << " into a number" << std::endl;
else if (r.ec == std::errc::result_out_of_range)
std::cerr << "Conversion of " << std::quoted(txt) << " into a type that is too small" << std::endl;
}
result = 1;
}
else if (v < value)
result = -1;
else if (v > value)
result = 1;
}
return result;
}
};
template <typename T>
struct item_handle::item_value_as<std::optional<T>>
{
static std::optional<T> convert(const item_handle &ref)
{
std::optional<T> result;
if (ref)
result = ref.as<T>();
return result;
}
static int compare(const item_handle &ref, std::optional<T> value, bool icase)
{
if (ref.empty() and not value)
return 0;
if (ref.empty())
return -1;
else if (not value)
return 1;
else
return ref.compare(*value, icase);
}
};
template <typename T>
struct item_handle::item_value_as<T, std::enable_if_t<std::is_same_v<T, bool>>>
{
static bool convert(const item_handle &ref)
{
bool result = false;
if (not ref.empty())
result = iequals(ref.text(), "y");
return result;
}
static int compare(const item_handle &ref, bool value, bool icase)
{
bool rv = convert(ref);
return value && rv ? 0
: (rv < value ? -1 : 1);
}
};
template <size_t N>
struct item_handle::item_value_as<char[N]>
{
static std::string convert(const item_handle &ref)
{
if (ref.empty())
return {};
return { ref.text().data(), ref.text().size() };
}
static int compare(const item_handle &ref, const char (&value)[N], bool icase)
{
return icase ? cif::icompare(ref.text(), value) : ref.text().compare(value);
}
};
template <typename T>
struct item_handle::item_value_as<T, std::enable_if_t<std::is_same_v<T, const char *>>>
{
static std::string convert(const item_handle &ref)
{
if (ref.empty())
return {};
return { ref.text().data(), ref.text().size() };
}
static int compare(const item_handle &ref, const char *value, bool icase)
{
return icase ? cif::icompare(ref.text(), value) : ref.text().compare(value);
}
};
template <typename T>
struct item_handle::item_value_as<T, std::enable_if_t<std::is_same_v<T, std::string_view>>>
{
static std::string convert(const item_handle &ref)
{
if (ref.empty())
return {};
return { ref.text().data(), ref.text().size() };
}
static int compare(const item_handle &ref, const std::string_view &value, bool icase)
{
return icase ? cif::icompare(ref.text(), value) : ref.text().compare(value);
}
};
template <typename T>
struct item_handle::item_value_as<T, std::enable_if_t<std::is_same_v<T, std::string>>>
{
static std::string convert(const item_handle &ref)
{
if (ref.empty())
return {};
return { ref.text().data(), ref.text().size() };
}
static int compare(const item_handle &ref, const std::string &value, bool icase)
{
return icase ? cif::icompare(ref.text(), value) : ref.text().compare(value);
}
};
} // namespace cif
namespace std
{
template<> struct tuple_size<::cif::item>
: public std::integral_constant<std::size_t, 2> {};
template<> struct tuple_element<0, ::cif::item>
{
using type = decltype(std::declval<::cif::item>().name());
};
template<> struct tuple_element<1, ::cif::item>
{
using type = decltype(std::declval<::cif::item>().value());
};
}

678
include/cif++/iterator.hpp Normal file
View File

@@ -0,0 +1,678 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2022 NKI/AVL, Netherlands Cancer Institute
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include "cif++/row.hpp"
#include <array>
namespace cif
{
// --------------------------------------------------------------------
template <typename Category, typename... Ts>
class iterator_impl
{
public:
template <typename, typename...>
friend class iterator_impl;
friend class category;
static constexpr size_t N = sizeof...(Ts);
using category_type = std::remove_cv_t<Category>;
using row_type = std::conditional_t<std::is_const_v<Category>, const row, row>;
using tuple_type = std::tuple<Ts...>;
using iterator_category = std::forward_iterator_tag;
using value_type = tuple_type;
using difference_type = std::ptrdiff_t;
using pointer = value_type *;
using reference = value_type &;
iterator_impl() = default;
iterator_impl(const iterator_impl &rhs) = default;
template <typename C2, typename... T2s>
iterator_impl(const iterator_impl<C2, T2s...> &rhs)
: m_category(rhs.m_category)
, m_current(rhs.m_current)
, m_value(rhs.m_value)
, m_column_ix(rhs.m_column_ix)
{
}
template <typename IRowType>
iterator_impl(iterator_impl<IRowType, Ts...> &rhs)
: m_category(rhs.m_category)
, m_current(const_cast<row_type *>(rhs.m_current))
, m_value(rhs.m_value)
, m_column_ix(rhs.m_column_ix)
{
m_value = get(std::make_index_sequence<N>());
}
template <typename IRowType>
iterator_impl(const iterator_impl<IRowType> &rhs, const std::array<uint16_t, N> &cix)
: m_category(rhs.m_category)
, m_current(rhs.m_current)
, m_column_ix(cix)
{
m_value = get(std::make_index_sequence<N>());
}
iterator_impl &operator=(const iterator_impl &i)
{
m_category = i.m_category;
m_current = i.m_current;
m_column_ix = i.m_column_ix;
m_value = i.m_value;
return *this;
}
virtual ~iterator_impl() = default;
reference operator*()
{
return m_value;
}
pointer operator->()
{
return &m_value;
}
operator const row_handle() const
{
return { *m_category, *m_current };
}
operator row_handle()
{
return { *m_category, *m_current };
}
iterator_impl &operator++()
{
if (m_current != nullptr)
m_current = m_current->m_next;
m_value = get(std::make_index_sequence<N>());
return *this;
}
iterator_impl operator++(int)
{
iterator_impl result(*this);
this->operator++();
return result;
}
bool operator==(const iterator_impl &rhs) const { return m_current == rhs.m_current; }
bool operator!=(const iterator_impl &rhs) const { return m_current != rhs.m_current; }
template <typename IRowType, typename... ITs>
bool operator==(const iterator_impl<IRowType, ITs...> &rhs) const
{
return m_current == rhs.m_current;
}
template <typename IRowType, typename... ITs>
bool operator!=(const iterator_impl<IRowType, ITs...> &rhs) const
{
return m_current != rhs.m_current;
}
private:
template <size_t... Is>
tuple_type get(std::index_sequence<Is...>) const
{
if (m_current != nullptr)
{
row_handle rh{*m_category, *m_current};
return tuple_type{rh[m_column_ix[Is]].template as<Ts>()...};
}
return {};
}
category_type *m_category = nullptr;
row_type *m_current = nullptr;
value_type m_value;
std::array<uint16_t, N> m_column_ix;
};
template<typename Category>
class iterator_impl<Category>
{
public:
template <typename, typename...>
friend class iterator_impl;
friend class category;
using category_type = std::remove_cv_t<Category>;
using row_type = std::conditional_t<std::is_const_v<Category>, const row, row>;
using iterator_category = std::forward_iterator_tag;
using value_type = row_handle;
using difference_type = std::ptrdiff_t;
using pointer = row_handle;
using reference = row_handle;
iterator_impl() = default;
iterator_impl(const iterator_impl &rhs) = default;
template <typename C2>
iterator_impl(const iterator_impl<C2> &rhs)
: m_category(rhs.m_category)
, m_current(const_cast<row_type*>(rhs.m_current))
{
}
iterator_impl(Category &cat, row *current)
: m_category(const_cast<category_type *>(&cat))
, m_current(current)
{
}
template <typename IRowType>
iterator_impl(const iterator_impl<IRowType> &rhs, const std::array<uint16_t, 0> &)
: m_category(rhs.m_category)
, m_current(rhs.m_current)
{
}
iterator_impl &operator=(const iterator_impl &i)
{
m_category = i.m_category;
m_current = i.m_current;
return *this;
}
virtual ~iterator_impl() = default;
reference operator*()
{
return {*m_category, *m_current};
}
pointer operator->()
{
return &m_current;
}
operator const row_handle() const
{
return { *m_category, *m_current };
}
operator row_handle()
{
return { *m_category, *m_current };
}
iterator_impl &operator++()
{
if (m_current != nullptr)
m_current = m_current->m_next;
return *this;
}
iterator_impl operator++(int)
{
iterator_impl result(*this);
this->operator++();
return result;
}
bool operator==(const iterator_impl &rhs) const { return m_current == rhs.m_current; }
bool operator!=(const iterator_impl &rhs) const { return m_current != rhs.m_current; }
template <typename IRowType, typename... ITs>
bool operator==(const iterator_impl<IRowType, ITs...> &rhs) const
{
return m_current == rhs.m_current;
}
template <typename IRowType, typename... ITs>
bool operator!=(const iterator_impl<IRowType, ITs...> &rhs) const
{
return m_current != rhs.m_current;
}
private:
category_type *m_category = nullptr;
row_type *m_current = nullptr;
};
template<typename Category, typename T>
class iterator_impl<Category, T>
{
public:
template <typename, typename...>
friend class iterator_impl;
friend class category;
using category_type = std::remove_cv_t<Category>;
using row_type = std::conditional_t<std::is_const_v<Category>, const row, row>;
using iterator_category = std::forward_iterator_tag;
using value_type = T;
using difference_type = std::ptrdiff_t;
using pointer = value_type *;
using reference = value_type &;
iterator_impl() = default;
iterator_impl(const iterator_impl &rhs) = default;
template <typename C2, typename T2>
iterator_impl(const iterator_impl<C2, T2> &rhs)
: m_category(rhs.m_category)
, m_current(rhs.m_current)
, m_value(rhs.m_value)
, m_column_ix(rhs.m_column_ix)
{
}
template <typename IRowType>
iterator_impl(iterator_impl<IRowType, T> &rhs)
: m_category(rhs.m_category)
, m_current(const_cast<row_type *>(rhs.m_current))
, m_value(rhs.m_value)
, m_column_ix(rhs.m_column_ix)
{
m_value = get(m_current);
}
template <typename IRowType>
iterator_impl(const iterator_impl<IRowType> &rhs, const std::array<uint16_t, 1> &cix)
: m_category(rhs.m_category)
, m_current(rhs.m_current)
, m_column_ix(cix[0])
{
m_value = get();
}
iterator_impl &operator=(const iterator_impl &i)
{
m_category = i.m_category;
m_current = i.m_current;
m_column_ix = i.m_column_ix;
m_value = i.m_value;
return *this;
}
virtual ~iterator_impl() = default;
reference operator*()
{
return m_value;
}
pointer operator->()
{
return &m_value;
}
operator const row_handle() const
{
return { *m_category, *m_current };
}
operator row_handle()
{
return { *m_category, *m_current };
}
iterator_impl &operator++()
{
if (m_current != nullptr)
m_current = m_current->m_next;
m_value = get();
return *this;
}
iterator_impl operator++(int)
{
iterator_impl result(*this);
this->operator++();
return result;
}
bool operator==(const iterator_impl &rhs) const { return m_current == rhs.m_current; }
bool operator!=(const iterator_impl &rhs) const { return m_current != rhs.m_current; }
template <typename IRowType, typename... ITs>
bool operator==(const iterator_impl<IRowType, ITs...> &rhs) const
{
return m_current == rhs.m_current;
}
template <typename IRowType, typename... ITs>
bool operator!=(const iterator_impl<IRowType, ITs...> &rhs) const
{
return m_current != rhs.m_current;
}
private:
value_type get() const
{
if (m_current != nullptr)
{
row_handle rh{*m_category, *m_current};
return rh[m_column_ix].template as<T>();
}
return {};
}
category_type *m_category = nullptr;
row_type *m_current = nullptr;
value_type m_value;
uint16_t m_column_ix;
};
// --------------------------------------------------------------------
// iterator proxy
template <typename Category, typename... Ts>
class iterator_proxy
{
public:
static constexpr const size_t N = sizeof...(Ts);
using category_type = Category;
using row_type = std::conditional_t<std::is_const_v<category_type>, const row, row>;
using iterator = iterator_impl<category_type, Ts...>;
using row_iterator = iterator_impl<category_type>;
iterator_proxy(category_type &cat, row_iterator pos, char const *const columns[N]);
iterator_proxy(category_type &cat, row_iterator pos, std::initializer_list<char const *> columns);
iterator_proxy(iterator_proxy &&p);
iterator_proxy &operator=(iterator_proxy &&p);
iterator_proxy(const iterator_proxy &) = delete;
iterator_proxy &operator=(const iterator_proxy &) = delete;
iterator begin() const { return iterator(m_begin, m_column_ix); }
iterator end() const { return iterator(m_end, m_column_ix); }
bool empty() const { return m_begin == m_end; }
explicit operator bool() const { return not empty(); }
size_t size() const { return std::distance(begin(), end()); }
// row front() { return *begin(); }
// row back() { return *(std::prev(end())); }
category_type &category() const { return *m_category; }
void swap(iterator_proxy &rhs)
{
std::swap(m_category, rhs.m_category);
std::swap(m_begin, rhs.m_begin);
std::swap(m_end, rhs.m_end);
std::swap(m_column_ix, rhs.m_column_ix);
}
private:
category_type *m_category;
row_iterator m_begin, m_end;
std::array<uint16_t, N> m_column_ix;
};
// --------------------------------------------------------------------
// conditional iterator proxy
template <typename CategoryType, typename... Ts>
class conditional_iterator_proxy
{
public:
static constexpr const size_t N = sizeof...(Ts);
using category_type = std::remove_cv_t<CategoryType>;
using base_iterator = iterator_impl<CategoryType, Ts...>;
using value_type = typename base_iterator::value_type;
using row_type = typename base_iterator::row_type;
using row_iterator = iterator_impl<CategoryType>;
class conditional_iterator_impl
{
public:
using iterator_category = std::forward_iterator_tag;
using value_type = conditional_iterator_proxy::value_type;
using difference_type = std::ptrdiff_t;
using pointer = value_type *;
using reference = value_type;
conditional_iterator_impl(CategoryType &cat, row_iterator pos, const condition &cond, const std::array<uint16_t, N> &cix);
conditional_iterator_impl(const conditional_iterator_impl &i) = default;
conditional_iterator_impl &operator=(const conditional_iterator_impl &i) = default;
virtual ~conditional_iterator_impl() = default;
reference operator*()
{
return *mBegin;
}
pointer operator->()
{
return &*mBegin;
}
conditional_iterator_impl &operator++()
{
while (mBegin != mEnd)
{
if (++mBegin == mEnd)
break;
if (m_condition->operator()(mBegin))
break;
}
return *this;
}
conditional_iterator_impl operator++(int)
{
conditional_iterator_impl result(*this);
this->operator++();
return result;
}
bool operator==(const conditional_iterator_impl &rhs) const { return mBegin == rhs.mBegin; }
bool operator!=(const conditional_iterator_impl &rhs) const { return mBegin != rhs.mBegin; }
template <typename IRowType, typename... ITs>
bool operator==(const iterator_impl<IRowType, ITs...> &rhs) const { return mBegin == rhs; }
template <typename IRowType, typename... ITs>
bool operator!=(const iterator_impl<IRowType, ITs...> &rhs) const { return mBegin != rhs; }
private:
CategoryType *mCat;
base_iterator mBegin, mEnd;
const condition *m_condition;
};
using iterator = conditional_iterator_impl;
using reference = typename iterator::reference;
template <typename... Ns>
conditional_iterator_proxy(CategoryType &cat, row_iterator pos, condition &&cond, Ns... names);
conditional_iterator_proxy(conditional_iterator_proxy &&p);
conditional_iterator_proxy &operator=(conditional_iterator_proxy &&p);
conditional_iterator_proxy(const conditional_iterator_proxy &) = delete;
conditional_iterator_proxy &operator=(const conditional_iterator_proxy &) = delete;
iterator begin() const;
iterator end() const;
bool empty() const;
explicit operator bool() const { return not empty(); }
size_t size() const { return std::distance(begin(), end()); }
row_handle front() { return *begin(); }
// row_handle back() { return *begin(); }
CategoryType &category() const { return *m_cat; }
void swap(conditional_iterator_proxy &rhs);
private:
CategoryType *m_cat;
condition m_condition;
row_iterator mCBegin, mCEnd;
std::array<uint16_t, N> mCix;
};
// --------------------------------------------------------------------
template <typename Category, typename... Ts>
iterator_proxy<Category, Ts...>::iterator_proxy(Category &cat, row_iterator pos, char const *const columns[N])
: m_category(&cat)
, m_begin(pos)
, m_end(cat.end())
{
for (uint16_t i = 0; i < N; ++i)
m_column_ix[i] = m_category->get_column_ix(columns[i]);
}
template <typename Category, typename... Ts>
iterator_proxy<Category, Ts...>::iterator_proxy(Category &cat, row_iterator pos, std::initializer_list<char const *> columns)
: m_category(&cat)
, m_begin(pos)
, m_end(cat.end())
{
// static_assert(columns.size() == N, "The list of column names should be exactly the same as the list of requested columns");
std::uint16_t i = 0;
for (auto column : columns)
m_column_ix[i++] = m_category->get_column_ix(column);
}
// --------------------------------------------------------------------
template <typename Category, typename... Ts>
conditional_iterator_proxy<Category, Ts...>::conditional_iterator_impl::conditional_iterator_impl(
Category &cat, row_iterator pos, const condition &cond, const std::array<uint16_t, N> &cix)
: mCat(&cat)
, mBegin(pos, cix)
, mEnd(cat.end(), cix)
, m_condition(&cond)
{
}
template <typename Category, typename... Ts>
conditional_iterator_proxy<Category, Ts...>::conditional_iterator_proxy(conditional_iterator_proxy &&p)
: m_cat(nullptr)
, mCBegin(p.mCBegin)
, mCEnd(p.mCEnd)
, mCix(p.mCix)
{
std::swap(m_cat, p.m_cat);
std::swap(mCix, p.mCix);
m_condition.swap(p.m_condition);
}
template <typename Category, typename... Ts>
template <typename... Ns>
conditional_iterator_proxy<Category, Ts...>::conditional_iterator_proxy(Category &cat, row_iterator pos, condition &&cond, Ns... names)
: m_cat(&cat)
, m_condition(std::move(cond))
, mCBegin(pos)
, mCEnd(cat.end())
{
static_assert(sizeof...(Ts) == sizeof...(Ns), "Number of column names should be equal to number of requested value types");
m_condition.prepare(cat);
while (mCBegin != mCEnd and not m_condition(*mCBegin))
++mCBegin;
uint16_t i = 0;
((mCix[i++] = m_cat->get_column_ix(names)), ...);
}
template <typename Category, typename... Ts>
conditional_iterator_proxy<Category, Ts...> &conditional_iterator_proxy<Category, Ts...>::operator=(conditional_iterator_proxy &&p)
{
swap(p);
return *this;
}
template <typename Category, typename... Ts>
typename conditional_iterator_proxy<Category, Ts...>::iterator conditional_iterator_proxy<Category, Ts...>::begin() const
{
return iterator(*m_cat, mCBegin, m_condition, mCix);
}
template <typename Category, typename... Ts>
typename conditional_iterator_proxy<Category, Ts...>::iterator conditional_iterator_proxy<Category, Ts...>::end() const
{
return iterator(*m_cat, mCEnd, m_condition, mCix);
}
template <typename Category, typename... Ts>
bool conditional_iterator_proxy<Category, Ts...>::empty() const
{
return mCBegin == mCEnd;
}
template <typename Category, typename... Ts>
void conditional_iterator_proxy<Category, Ts...>::swap(conditional_iterator_proxy &rhs)
{
std::swap(m_cat, rhs.m_cat);
m_condition.swap(rhs.m_condition);
std::swap(mCBegin, rhs.mCBegin);
std::swap(mCEnd, rhs.mCEnd);
std::swap(mCix, rhs.mCix);
}
} // namespace cif

531
include/cif++/matrix.hpp Normal file
View File

@@ -0,0 +1,531 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2023 NKI/AVL, Netherlands Cancer Institute
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include <array>
#include <cassert>
#include <cmath>
#include <cstdint>
#include <ostream>
#include <tuple>
#include <type_traits>
#include <vector>
namespace cif
{
// --------------------------------------------------------------------
// We're using expression templates here
template <typename M>
class matrix_expression
{
public:
constexpr uint32_t dim_m() const { return static_cast<const M &>(*this).dim_m(); }
constexpr uint32_t dim_n() const { return static_cast<const M &>(*this).dim_n(); }
constexpr auto &operator()(uint32_t i, uint32_t j)
{
return static_cast<M &>(*this).operator()(i, j);
}
constexpr auto operator()(uint32_t i, uint32_t j) const
{
return static_cast<const M &>(*this).operator()(i, j);
}
void swap_row(uint32_t r1, uint32_t r2)
{
for (uint32_t c = 0; c < dim_m(); ++c)
{
auto v = operator()(r1, c);
operator()(r1, c) = operator()(r2, c);
operator()(r2, c) = v;
}
}
void swap_col(uint32_t c1, uint32_t c2)
{
for (uint32_t r = 0; r < dim_n(); ++r)
{
auto &a = operator()(r, c1);
auto &b = operator()(r, c2);
std::swap(a, b);
}
}
friend std::ostream &operator<<(std::ostream &os, const matrix_expression &m)
{
os << '[';
for (size_t i = 0; i < m.dim_m(); ++i)
{
os << '[';
for (size_t j = 0; j < m.dim_n(); ++j)
{
os << m(i, j);
if (j + 1 < m.dim_n())
os << ", ";
}
if (i + 1 < m.dim_m())
os << ", ";
os << ']';
}
os << ']';
return os;
}
};
// --------------------------------------------------------------------
// matrix is m x n, addressing i,j is 0 <= i < m and 0 <= j < n
// element m i,j is mapped to [i * n + j] and thus storage is row major
template <typename F = float>
class matrix : public matrix_expression<matrix<F>>
{
public:
using value_type = F;
template <typename M2>
matrix(const matrix_expression<M2> &m)
: m_m(m.dim_m())
, m_n(m.dim_n())
, m_data(m_m * m_n)
{
for (uint32_t i = 0; i < m_m; ++i)
{
for (uint32_t j = 0; j < m_n; ++j)
operator()(i, j) = m(i, j);
}
}
matrix(size_t m, size_t n, value_type v = 0)
: m_m(m)
, m_n(n)
, m_data(m_m * m_n)
{
std::fill(m_data.begin(), m_data.end(), v);
}
matrix() = default;
matrix(matrix &&m) = default;
matrix(const matrix &m) = default;
matrix &operator=(matrix &&m) = default;
matrix &operator=(const matrix &m) = default;
constexpr size_t dim_m() const { return m_m; }
constexpr size_t dim_n() const { return m_n; }
constexpr value_type operator()(size_t i, size_t j) const
{
assert(i < m_m);
assert(j < m_n);
return m_data[i * m_n + j];
}
constexpr value_type &operator()(size_t i, size_t j)
{
assert(i < m_m);
assert(j < m_n);
return m_data[i * m_n + j];
}
private:
size_t m_m = 0, m_n = 0;
std::vector<value_type> m_data;
};
// --------------------------------------------------------------------
// special case, 3x3 matrix
template <typename F, size_t M, size_t N>
class matrix_fixed : public matrix_expression<matrix_fixed<F, M, N>>
{
public:
using value_type = F;
static constexpr size_t kSize = M * N;
template <typename M2>
matrix_fixed(const M2 &m)
{
assert(M == m.dim_m() and N == m.dim_n());
for (uint32_t i = 0; i < M; ++i)
{
for (uint32_t j = 0; j < N; ++j)
operator()(i, j) = m(i, j);
}
}
matrix_fixed(value_type v = 0)
{
m_data.fill(v);
}
matrix_fixed(const F (&v)[kSize])
{
fill(v, std::make_index_sequence<kSize>{});
}
matrix_fixed(matrix_fixed &&m) = default;
matrix_fixed(const matrix_fixed &m) = default;
matrix_fixed &operator=(matrix_fixed &&m) = default;
matrix_fixed &operator=(const matrix_fixed &m) = default;
template<size_t... Ixs>
matrix_fixed& fill(const F (&a)[kSize], std::index_sequence<Ixs...>)
{
m_data = { a[Ixs]... };
return *this;
}
constexpr size_t dim_m() const { return M; }
constexpr size_t dim_n() const { return N; }
constexpr value_type operator()(size_t i, size_t j) const
{
assert(i < M);
assert(j < N);
return m_data[i * N + j];
}
constexpr value_type &operator()(size_t i, size_t j)
{
assert(i < M);
assert(j < N);
return m_data[i * N + j];
}
private:
std::array<value_type, M * N> m_data;
};
template <typename F>
using matrix3x3 = matrix_fixed<F, 3, 3>;
template <typename F>
using matrix4x4 = matrix_fixed<F, 4, 4>;
// --------------------------------------------------------------------
template <typename F = float>
class symmetric_matrix : public matrix_expression<symmetric_matrix<F>>
{
public:
using value_type = F;
symmetric_matrix(uint32_t n, value_type v = 0)
: m_n(n)
, m_data((m_n * (m_n + 1)) / 2)
{
std::fill(m_data.begin(), m_data.end(), v);
}
symmetric_matrix() = default;
symmetric_matrix(symmetric_matrix &&m) = default;
symmetric_matrix(const symmetric_matrix &m) = default;
symmetric_matrix &operator=(symmetric_matrix &&m) = default;
symmetric_matrix &operator=(const symmetric_matrix &m) = default;
constexpr uint32_t dim_m() const { return m_n; }
constexpr uint32_t dim_n() const { return m_n; }
constexpr value_type operator()(uint32_t i, uint32_t j) const
{
return i < j
? m_data[(j * (j + 1)) / 2 + i]
: m_data[(i * (i + 1)) / 2 + j];
}
constexpr value_type &operator()(uint32_t i, uint32_t j)
{
if (i > j)
std::swap(i, j);
assert(j < m_n);
return m_data[(j * (j + 1)) / 2 + i];
}
private:
uint32_t m_n;
std::vector<value_type> m_data;
};
// --------------------------------------------------------------------
template <typename F, size_t M>
class symmetric_matrix_fixed : public matrix_expression<symmetric_matrix_fixed<F, M>>
{
public:
using value_type = F;
symmetric_matrix_fixed(value_type v = 0)
{
std::fill(m_data.begin(), m_data.end(), v);
}
symmetric_matrix_fixed(symmetric_matrix_fixed &&m) = default;
symmetric_matrix_fixed(const symmetric_matrix_fixed &m) = default;
symmetric_matrix_fixed &operator=(symmetric_matrix_fixed &&m) = default;
symmetric_matrix_fixed &operator=(const symmetric_matrix_fixed &m) = default;
constexpr uint32_t dim_m() const { return M; }
constexpr uint32_t dim_n() const { return M; }
constexpr value_type operator()(uint32_t i, uint32_t j) const
{
return i < j
? m_data[(j * (j + 1)) / 2 + i]
: m_data[(i * (i + 1)) / 2 + j];
}
constexpr value_type &operator()(uint32_t i, uint32_t j)
{
if (i > j)
std::swap(i, j);
assert(j < M);
return m_data[(j * (j + 1)) / 2 + i];
}
private:
std::array<value_type, (M * (M + 1)) / 2> m_data;
};
template <typename F>
using symmetric_matrix3x3 = symmetric_matrix_fixed<F, 3>;
template <typename F>
using symmetric_matrix4x4 = symmetric_matrix_fixed<F, 4>;
// --------------------------------------------------------------------
template <typename F = float>
class identity_matrix : public matrix_expression<identity_matrix<F>>
{
public:
using value_type = F;
identity_matrix(uint32_t n)
: m_n(n)
{
}
constexpr uint32_t dim_m() const { return m_n; }
constexpr uint32_t dim_n() const { return m_n; }
constexpr value_type operator()(uint32_t i, uint32_t j) const
{
return i == j ? 1 : 0;
}
private:
uint32_t m_n;
};
// --------------------------------------------------------------------
// matrix functions, implemented as expression templates
template <typename M1, typename M2>
class matrix_subtraction : public matrix_expression<matrix_subtraction<M1, M2>>
{
public:
matrix_subtraction(const M1 &m1, const M2 &m2)
: m_m1(m1)
, m_m2(m2)
{
assert(m_m1.dim_m() == m_m2.dim_m());
assert(m_m1.dim_n() == m_m2.dim_n());
}
constexpr uint32_t dim_m() const { return m_m1.dim_m(); }
constexpr uint32_t dim_n() const { return m_m1.dim_n(); }
constexpr auto operator()(uint32_t i, uint32_t j) const
{
return m_m1(i, j) - m_m2(i, j);
}
private:
const M1 &m_m1;
const M2 &m_m2;
};
template <typename M1, typename M2>
auto operator-(const matrix_expression<M1> &m1, const matrix_expression<M2> &m2)
{
return matrix_subtraction(m1, m2);
}
template <typename M1, typename M2>
class matrix_matrix_multiplication : public matrix_expression<matrix_matrix_multiplication<M1, M2>>
{
public:
matrix_matrix_multiplication(const M1 &m1, const M2 &m2)
: m_m1(m1)
, m_m2(m2)
{
assert(m1.dim_m() == m2.dim_n());
}
constexpr uint32_t dim_m() const { return m_m1.dim_m(); }
constexpr uint32_t dim_n() const { return m_m1.dim_n(); }
constexpr auto operator()(uint32_t i, uint32_t j) const
{
using value_type = decltype(m_m1(0, 0));
value_type result = {};
for (uint32_t k = 0; k < m_m1.dim_m(); ++k)
result += m_m1(i, k) * m_m2(k, j);
return result;
}
private:
const M1 &m_m1;
const M2 &m_m2;
};
template <typename M, typename T>
class matrix_scalar_multiplication : public matrix_expression<matrix_scalar_multiplication<M, T>>
{
public:
using value_type = T;
matrix_scalar_multiplication(const M &m, value_type v)
: m_m(m)
, m_v(v)
{
}
constexpr uint32_t dim_m() const { return m_m.dim_m(); }
constexpr uint32_t dim_n() const { return m_m.dim_n(); }
constexpr auto operator()(uint32_t i, uint32_t j) const
{
return m_m(i, j) * m_v;
}
private:
const M &m_m;
value_type m_v;
};
template <typename M1, typename T, std::enable_if_t<std::is_floating_point_v<T>, int> = 0>
auto operator*(const matrix_expression<M1> &m, T v)
{
return matrix_scalar_multiplication(m, v);
}
template <typename M1, typename M2, std::enable_if_t<not std::is_floating_point_v<M2>, int> = 0>
auto operator*(const matrix_expression<M1> &m1, const matrix_expression<M2> &m2)
{
return matrix_matrix_multiplication(m1, m2);
}
// --------------------------------------------------------------------
template <typename M>
auto determinant(const M &m);
template <typename F = float>
auto determinant(const matrix3x3<F> &m)
{
return (m(0, 0) * (m(1, 1) * m(2, 2) - m(1, 2) * m(2, 1)) +
m(0, 1) * (m(1, 2) * m(2, 0) - m(1, 0) * m(2, 2)) +
m(0, 2) * (m(1, 0) * m(2, 1) - m(1, 1) * m(2, 0)));
}
template <typename M>
M inverse(const M &m);
template <typename F = float>
matrix3x3<F> inverse(const matrix3x3<F> &m)
{
F det = determinant(m);
matrix3x3<F> result;
result(0, 0) = (m(1, 1) * m(2, 2) - m(1, 2) * m(2, 1)) / det;
result(1, 0) = (m(1, 2) * m(2, 0) - m(1, 0) * m(2, 2)) / det;
result(2, 0) = (m(1, 0) * m(2, 1) - m(1, 1) * m(2, 0)) / det;
result(0, 1) = (m(2, 1) * m(0, 2) - m(2, 2) * m(0, 1)) / det;
result(1, 1) = (m(2, 2) * m(0, 0) - m(2, 0) * m(0, 2)) / det;
result(2, 1) = (m(2, 0) * m(0, 1) - m(2, 1) * m(0, 0)) / det;
result(0, 2) = (m(0, 1) * m(1, 2) - m(0, 2) * m(1, 1)) / det;
result(1, 2) = (m(0, 2) * m(1, 0) - m(0, 0) * m(1, 2)) / det;
result(2, 2) = (m(0, 0) * m(1, 1) - m(0, 1) * m(1, 0)) / det;
return result;
}
// --------------------------------------------------------------------
template <typename M>
class matrix_cofactors : public matrix_expression<matrix_cofactors<M>>
{
public:
matrix_cofactors(const M &m)
: m_m(m)
{
}
constexpr uint32_t dim_m() const { return m_m.dim_m(); }
constexpr uint32_t dim_n() const { return m_m.dim_n(); }
constexpr auto operator()(uint32_t i, uint32_t j) const
{
const size_t ixs[4][3] = {
{ 1, 2, 3 },
{ 0, 2, 3 },
{ 0, 1, 3 },
{ 0, 1, 2 }
};
const size_t *ix = ixs[i];
const size_t *iy = ixs[j];
auto result =
m_m(ix[0], iy[0]) * m_m(ix[1], iy[1]) * m_m(ix[2], iy[2]) +
m_m(ix[0], iy[1]) * m_m(ix[1], iy[2]) * m_m(ix[2], iy[0]) +
m_m(ix[0], iy[2]) * m_m(ix[1], iy[0]) * m_m(ix[2], iy[1]) -
m_m(ix[0], iy[2]) * m_m(ix[1], iy[1]) * m_m(ix[2], iy[0]) -
m_m(ix[0], iy[1]) * m_m(ix[1], iy[0]) * m_m(ix[2], iy[2]) -
m_m(ix[0], iy[0]) * m_m(ix[1], iy[2]) * m_m(ix[2], iy[1]);
return (i + j) % 2 == 1 ? -result : result;
}
private:
const M &m_m;
};
} // namespace cif

917
include/cif++/model.hpp Normal file
View File

@@ -0,0 +1,917 @@
/*-
* 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
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include "cif++/atom_type.hpp"
#include <numeric>
#if __cpp_lib_format
#include <format>
#endif
namespace cif::mm
{
class atom;
class residue;
class monomer;
class polymer;
class structure;
// --------------------------------------------------------------------
class atom
{
private:
struct atom_impl : public std::enable_shared_from_this<atom_impl>
{
atom_impl(const datablock &db, std::string_view id)
: m_db(db)
, m_cat(db["atom_site"])
, m_id(id)
{
auto r = row();
if (r)
tie(m_location.m_x, m_location.m_y, m_location.m_z) = r.get("Cartn_x", "Cartn_y", "Cartn_z");
}
// constructor for a symmetry copy of an atom
atom_impl(const atom_impl &impl, const point &loc, const std::string &sym_op)
: atom_impl(impl)
{
m_location = loc;
m_symop = sym_op;
}
atom_impl(const atom_impl &i) = default;
void prefetch();
int compare(const atom_impl &b) const;
// bool getAnisoU(float anisou[6]) const;
int get_charge() const;
void moveTo(const point &p);
// const compound *compound() const;
std::string get_property(std::string_view name) const;
int get_property_int(std::string_view name) const;
float get_property_float(std::string_view name) const;
void set_property(const std::string_view name, const std::string &value);
row_handle row()
{
return m_cat[{{"id", m_id}}];
}
const row_handle row() const
{
return m_cat[{{"id", m_id}}];
}
row_handle row_aniso()
{
auto cat = m_db.get("atom_site_anisotrop");
return cat ? cat->operator[]({ {"id", m_id} }) : row_handle{};
}
const row_handle row_aniso() const
{
auto cat = m_db.get("atom_site_anisotrop");
return cat ? cat->operator[]({ {"id", m_id} }) : row_handle{};
}
const datablock &m_db;
const category &m_cat;
std::string m_id;
point m_location;
std::string m_symop = "1_555";
};
public:
atom() {}
atom(std::shared_ptr<atom_impl> impl)
: m_impl(impl)
{
}
atom(const atom &rhs)
: m_impl(rhs.m_impl)
{
}
atom(const datablock &db, const row_handle &row)
: atom(std::make_shared<atom_impl>(db, row["id"].as<std::string>()))
{
}
// a special constructor to create symmetry copies
atom(const atom &rhs, const point &symmmetry_location, const std::string &symmetry_operation)
: atom(std::make_shared<atom_impl>(*rhs.m_impl, symmmetry_location, symmetry_operation))
{
}
explicit operator bool() const { return (bool)m_impl; }
// // return a copy of this atom, with data copied instead of referenced
// atom clone() const
// {
// auto copy = std::make_shared<atom_impl>(*m_impl);
// copy->mClone = true;
// return atom(copy);
// }
atom &operator=(const atom &rhs) = default;
// template <typename T>
// T get_property(const std::string_view name) const;
std::string get_property(std::string_view name) const
{
if (not m_impl)
throw std::logic_error("Error trying to fetch a property from an uninitialized atom");
return m_impl->get_property(name);
}
int get_property_int(std::string_view name) const
{
if (not m_impl)
throw std::logic_error("Error trying to fetch a property from an uninitialized atom");
return m_impl->get_property_int(name);
}
float get_property_float(std::string_view name) const
{
if (not m_impl)
throw std::logic_error("Error trying to fetch a property from an uninitialized atom");
return m_impl->get_property_float(name);
}
void set_property(const std::string_view name, const std::string &value)
{
if (not m_impl)
throw std::logic_error("Error trying to modify an uninitialized atom");
m_impl->set_property(name, value);
}
template <typename T, std::enable_if_t<std::is_arithmetic_v<T>, int> = 0>
void set_property(const std::string_view name, const T &value)
{
set_property(name, std::to_string(value));
}
const std::string &id() const { return impl().m_id; }
cif::atom_type get_type() const { return atom_type_traits(get_property("type_symbol")).type(); }
point get_location() const { return impl().m_location; }
void set_location(point p)
{
if (not m_impl)
throw std::logic_error("Error trying to modify an uninitialized atom");
m_impl->moveTo(p);
}
/// \brief Translate the position of this atom by \a t
void translate(point t)
{
set_location(get_location() + t);
}
/// \brief Rotate the position of this atom by \a q
void rotate(quaternion q)
{
auto loc = get_location();
loc.rotate(q);
set_location(loc);
}
/// \brief rotate the coordinates of this atom by \a q around point \a p
void rotate(quaternion q, point p)
{
auto loc = get_location();
loc.rotate(q, p);
set_location(loc);
}
/// \brief Translate and rotate the position of this atom by \a t and \a q
void translate_and_rotate(point t, quaternion q)
{
auto loc = get_location();
loc += t;
loc.rotate(q);
set_location(loc);
}
/// \brief Translate, rotate and translate again the coordinates this atom by \a t1 , \a q and \a t2
void translate_rotate_and_translate(point t1, quaternion q, point t2)
{
auto loc = get_location();
loc += t1;
loc.rotate(q);
loc += t2;
set_location(loc);
}
// for direct access to underlying data, be careful!
const row_handle get_row() const { return impl().row(); }
const row_handle get_row_aniso() const { return impl().row_aniso(); }
bool is_symmetry_copy() const { return impl().m_symop != "1_555"; }
std::string symmetry() const { return impl().m_symop; }
// const compound &compound() const;
bool is_water() const
{
auto comp_id = get_label_comp_id();
return comp_id == "HOH" or comp_id == "H2O" or comp_id == "WAT";
}
int get_charge() const { return impl().get_charge(); }
// float uIso() const;
// bool getAnisoU(float anisou[6]) const { return impl().getAnisoU(anisou); }
float get_occupancy() const { return get_property_float("occupancy"); }
// specifications
std::string get_label_asym_id() const { return get_property("label_asym_id"); }
int get_label_seq_id() const { return get_property_int("label_seq_id"); }
std::string get_label_atom_id() const { return get_property("label_atom_id"); }
std::string get_label_alt_id() const { return get_property("label_alt_id"); }
std::string get_label_comp_id() const { return get_property("label_comp_id"); }
std::string get_label_entity_id() const { return get_property("label_entity_id"); }
std::string get_auth_asym_id() const { return get_property("auth_asym_id"); }
std::string get_auth_seq_id() const { return get_property("auth_seq_id"); }
std::string get_auth_atom_id() const { return get_property("auth_atom_id"); }
std::string get_auth_alt_id() const { return get_property("auth_alt_id"); }
std::string get_auth_comp_id() const { return get_property("auth_comp_id"); }
std::string get_pdb_ins_code() const { return get_property("pdbx_PDB_ins_code"); }
bool is_alternate() const { return not get_label_alt_id().empty(); }
// std::string labelID() const; // label_comp_id + '_' + label_asym_id + '_' + label_seq_id
std::string pdb_id() const
{
return get_label_comp_id() + '_' + get_auth_asym_id() + '_' + get_auth_seq_id() + get_pdb_ins_code();
}
bool operator==(const atom &rhs) const
{
if (m_impl == rhs.m_impl)
return true;
if (not(m_impl and rhs.m_impl))
return false;
return &m_impl->m_db == &rhs.m_impl->m_db and m_impl->m_id == rhs.m_impl->m_id;
}
bool operator!=(const atom &rhs) const
{
return not operator==(rhs);
}
// // access data in compound for this atom
// convenience routine
bool is_back_bone() const
{
auto atomID = get_label_atom_id();
return atomID == "N" or atomID == "O" or atomID == "C" or atomID == "CA";
}
void swap(atom &b)
{
std::swap(m_impl, b.m_impl);
}
int compare(const atom &b) const { return impl().compare(*b.m_impl); }
bool operator<(const atom &rhs) const
{
return compare(rhs) < 0;
}
friend std::ostream &operator<<(std::ostream &os, const atom &atom);
private:
friend class structure;
const atom_impl &impl() const
{
if (not m_impl)
throw std::runtime_error("Uninitialized atom, not found?");
return *m_impl;
}
std::shared_ptr<atom_impl> m_impl;
};
inline void swap(atom &a, atom &b)
{
a.swap(b);
}
inline float distance(const atom &a, const atom &b)
{
return distance(a.get_location(), b.get_location());
}
inline float distance_squared(const atom &a, const atom &b)
{
return distance_squared(a.get_location(), b.get_location());
}
// --------------------------------------------------------------------
enum class EntityType
{
polymer,
NonPolymer,
Macrolide,
Water,
Branched
};
// --------------------------------------------------------------------
class residue
{
public:
friend class structure;
// constructor
residue(structure &structure, const std::string &compoundID,
const std::string &asymID, int seqID,
const std::string &authAsymID, const std::string &authSeqID,
const std::string &pdbInsCode)
: m_structure(&structure)
, m_compound_id(compoundID)
, m_asym_id(asymID)
, m_seq_id(seqID)
, m_auth_asym_id(authAsymID)
, m_auth_seq_id(authSeqID)
, m_pdb_ins_code(pdbInsCode)
{
}
residue(structure &structure, const std::vector<atom> &atoms);
residue(const residue &rhs) = delete;
residue &operator=(const residue &rhs) = delete;
residue(residue &&rhs) = default;
residue &operator=(residue &&rhs) = default;
virtual ~residue() = default;
std::string get_entity_id() const;
EntityType entity_type() const;
const std::string &get_asym_id() const { return m_asym_id; }
int get_seq_id() const { return m_seq_id; }
const std::string get_auth_asym_id() const { return m_auth_asym_id; }
const std::string get_auth_seq_id() const { return m_auth_seq_id; }
std::string get_pdb_ins_code() const { return m_pdb_ins_code; }
const std::string &get_compound_id() const { return m_compound_id; }
void set_compound_id(const std::string &id) { m_compound_id = id; }
structure *get_structure() const { return m_structure; }
// const compound &compound() const;
std::vector<atom> &atoms()
{
return m_atoms;
}
const std::vector<atom> &atoms() const
{
return m_atoms;
}
void add_atom(atom &atom);
/// \brief Unique atoms returns only the atoms without alternates and the first of each alternate atom id.
std::vector<atom> unique_atoms() const;
/// \brief The alt ID used for the unique atoms
std::string unique_alt_id() const;
atom get_atom_by_atom_id(const std::string &atomID) const;
// Is this residue a single entity?
bool is_entity() const;
bool is_water() const { return m_compound_id == "HOH"; }
// bool empty() const { return m_structure == nullptr; }
bool has_alternate_atoms() const;
/// \brief Return the list of unique alt ID's present in this residue
std::set<std::string> get_alternate_ids() const;
/// \brief Return the list of unique atom ID's
std::set<std::string> get_atom_ids() const;
/// \brief Return the list of atoms having ID \a atomID
std::vector<atom> get_atoms_by_id(const std::string &atomID) const;
// some routines for 3d work
std::tuple<point, float> center_and_radius() const;
friend std::ostream &operator<<(std::ostream &os, const residue &res);
bool operator==(const residue &rhs) const
{
return this == &rhs or (m_structure == rhs.m_structure and
m_seq_id == rhs.m_seq_id and
m_asym_id == rhs.m_asym_id and
m_compound_id == rhs.m_compound_id and
m_auth_seq_id == rhs.m_auth_seq_id);
}
protected:
residue() {}
structure *m_structure = nullptr;
std::string m_compound_id, m_asym_id;
int m_seq_id = 0;
std::string m_auth_asym_id, m_auth_seq_id, m_pdb_ins_code;
std::vector<atom> m_atoms;
};
// --------------------------------------------------------------------
// a monomer models a single residue in a protein chain
class monomer : public residue
{
public:
// monomer();
monomer(const monomer &rhs) = delete;
monomer &operator=(const monomer &rhs) = delete;
monomer(monomer &&rhs);
monomer &operator=(monomer &&rhs);
monomer(const polymer &polymer, size_t index, int seqID, const std::string &authSeqID,
const std::string &pdbInsCode, const std::string &compoundID);
bool is_first_in_chain() const;
bool is_last_in_chain() const;
// convenience
bool has_alpha() const;
bool has_kappa() const;
// Assuming this is really an amino acid...
float phi() const;
float psi() const;
float alpha() const;
float kappa() const;
float tco() const;
float omega() const;
// torsion angles
size_t nr_of_chis() const;
float chi(size_t i) const;
bool is_cis() const;
/// \brief Returns true if the four atoms C, CA, N and O are present
bool is_complete() const;
/// \brief Returns true if any of the backbone atoms has an alternate
bool has_alternate_backbone_atoms() const;
atom CAlpha() const { return get_atom_by_atom_id("CA"); }
atom C() const { return get_atom_by_atom_id("C"); }
atom N() const { return get_atom_by_atom_id("N"); }
atom O() const { return get_atom_by_atom_id("O"); }
atom H() const { return get_atom_by_atom_id("H"); }
bool is_bonded_to(const monomer &rhs) const
{
return this != &rhs and are_bonded(*this, rhs);
}
static bool are_bonded(const monomer &a, const monomer &b, float errorMargin = 0.5f);
static bool is_cis(const monomer &a, const monomer &b);
static float omega(const monomer &a, const monomer &b);
// for LEU and VAL
float chiral_volume() const;
bool operator==(const monomer &rhs) const
{
return m_polymer == rhs.m_polymer and m_index == rhs.m_index;
}
private:
const polymer *m_polymer;
size_t m_index;
};
// --------------------------------------------------------------------
class polymer : public std::vector<monomer>
{
public:
polymer(structure &s, const std::string &entityID, const std::string &asymID, const std::string &auth_asym_id);
polymer(const polymer &) = delete;
polymer &operator=(const polymer &) = delete;
// monomer &getBySeqID(int seqID);
// const monomer &getBySeqID(int seqID) const;
structure *get_structure() const { return m_structure; }
std::string get_asym_id() const { return m_asym_id; }
std::string get_auth_asym_id() const { return m_auth_asym_id; } // The PDB chain ID, actually
std::string get_entity_id() const { return m_entity_id; }
// int Distance(const monomer &a, const monomer &b) const;
private:
structure *m_structure;
std::string m_entity_id;
std::string m_asym_id;
std::string m_auth_asym_id;
};
// --------------------------------------------------------------------
// sugar and branch, to describe glycosylation sites
class branch;
class sugar : public residue
{
public:
sugar(branch &branch, const std::string &compoundID,
const std::string &asymID, int authSeqID);
sugar(sugar &&rhs);
sugar &operator=(sugar &&rhs);
int num() const {
int result;
auto r = std::from_chars(m_auth_seq_id.data(), m_auth_seq_id.data() + m_auth_seq_id.length(), result);
if (r.ec != std::errc())
throw std::runtime_error("The auth_seq_id should be a number for a sugar");
return result;
}
std::string name() const;
/// \brief Return the atom the C1 is linked to
atom get_link() const { return m_link; }
void set_link(atom link) { m_link = link; }
size_t get_link_nr() const
{
size_t result = 0;
if (m_link)
result = m_link.get_property_int("auth_seq_id");
return result;
}
cif::mm::atom add_atom(row_initializer atom_info);
private:
branch *m_branch;
atom m_link;
};
class branch : public std::vector<sugar>
{
public:
branch(structure &structure, const std::string &asym_id, const std::string &entity_id);
branch(const branch &) = delete;
branch &operator=(const branch &) = delete;
branch(branch &&) = default;
branch &operator=(branch &&) = default;
void link_atoms();
std::string name() const;
float weight() const;
std::string get_asym_id() const { return m_asym_id; }
std::string get_entity_id() const { return m_entity_id; }
structure &get_structure() { return *m_structure; }
structure &get_structure() const { return *m_structure; }
sugar &get_sugar_by_num(int nr);
const sugar &get_sugar_by_num(int nr) const
{
return const_cast<branch *>(this)->get_sugar_by_num(nr);
}
sugar &construct_sugar(const std::string &compound_id);
sugar &construct_sugar(const std::string &compound_id, const std::string &atom_id,
int linked_sugar_nr, const std::string &linked_atom_id);
private:
friend sugar;
std::string name(const sugar &s) const;
structure *m_structure;
std::string m_asym_id, m_entity_id;
};
// --------------------------------------------------------------------
enum class StructureOpenOptions
{
SkipHydrogen = 1 << 0
};
constexpr inline bool operator&(StructureOpenOptions a, StructureOpenOptions b)
{
return static_cast<int>(a) bitand static_cast<int>(b);
}
// --------------------------------------------------------------------
class structure
{
public:
structure(file &p, size_t modelNr = 1, StructureOpenOptions options = {});
structure(datablock &db, size_t modelNr = 1, StructureOpenOptions options = {});
structure(structure &&s) = default;
// Create a read-only clone of the current structure (for multithreaded calculations that move atoms)
// NOTE: removed, simply create a new structure for each thread
structure(const structure &) = delete;
structure &operator=(const structure &) = delete;
// Structure &operator=(Structure &&s) = default;
~structure() = default;
size_t get_model_nr() const { return m_model_nr; }
const std::vector<atom> &atoms() const { return m_atoms; }
// std::vector<atom> &atoms() { return m_atoms; }
EntityType get_entity_type_for_entity_id(const std::string entityID) const;
EntityType get_entity_type_for_asym_id(const std::string asymID) const;
// std::vector<atom> waters() const;
const std::list<polymer> &polymers() const { return m_polymers; }
std::list<polymer> &polymers() { return m_polymers; }
polymer &get_polymer_by_asym_id(const std::string &asymID);
const polymer &get_polymer_by_asym_id(const std::string &asymID) const
{
return const_cast<structure *>(this)->get_polymer_by_asym_id(asymID);
}
const std::list<branch> &branches() const { return m_branches; }
std::list<branch> &branches() { return m_branches; }
branch &get_branch_by_asym_id(const std::string &asymID);
const branch &get_branch_by_asym_id(const std::string &asymID) const;
const std::vector<residue> &non_polymers() const { return m_non_polymers; }
bool has_atom_id(const std::string &id) const;
atom get_atom_by_id(const std::string &id) const;
// atom getAtomByLocation(point pt, float maxDistance) const;
atom get_atom_by_label(const std::string &atomID, const std::string &asymID,
const std::string &compID, int seqID, const std::string &altID = "");
// /// \brief Return the atom closest to point \a p
atom get_atom_by_position(point p) const;
/// \brief Return the atom closest to point \a p with atom type \a type in a residue of type \a res_type
atom get_atom_by_position_and_type(point p, std::string_view type, std::string_view res_type) const;
/// \brief Create a non-poly residue based on atoms already present in this structure.
residue &create_residue(const std::vector<atom> &atoms);
/// \brief Get a non-poly residue for an asym with id \a asymID
residue &get_residue(const std::string &asymID)
{
return get_residue(asymID, 0, "");
}
/// \brief Get a non-poly residue for an asym with id \a asymID
const residue &get_residue(const std::string &asymID) const
{
return get_residue(asymID, 0, "");
}
/// \brief Get a residue for an asym with id \a asymID seq id \a seqID and authSeqID \a authSeqID
residue &get_residue(const std::string &asymID, int seqID, const std::string &authSeqID);
/// \brief Get a the single residue for an asym with id \a asymID seq id \a seqID and authSeqID \a authSeqID
const residue &get_residue(const std::string &asymID, int seqID, const std::string &authSeqID) const
{
return const_cast<structure *>(this)->get_residue(asymID, seqID, authSeqID);
}
/// \brief Get a residue for an asym with id \a asymID, compound id \a compID, seq id \a seqID and authSeqID \a authSeqID
residue &get_residue(const std::string &asymID, const std::string &compID, int seqID, const std::string &authSeqID);
/// \brief Get a residue for an asym with id \a asymID, compound id \a compID, seq id \a seqID and authSeqID \a authSeqID
const residue &get_residue(const std::string &asymID, const std::string &compID, int seqID, const std::string &authSeqID) const
{
return const_cast<structure *>(this)->get_residue(asymID, compID, seqID, authSeqID);
}
/// \brief Get a the residue for atom \a atom
residue &get_residue(const atom &atom)
{
return get_residue(atom.get_label_asym_id(), atom.get_label_comp_id(), atom.get_label_seq_id(), atom.get_auth_seq_id());
}
/// \brief Get a the residue for atom \a atom
const residue &get_residue(const atom &atom) const
{
return get_residue(atom.get_label_asym_id(), atom.get_label_comp_id(), atom.get_label_seq_id(), atom.get_auth_seq_id());
}
// Actions
void remove_atom(atom &a)
{
remove_atom(a, true);
}
void swap_atoms(atom a1, atom a2); // swap the labels for these atoms
void move_atom(atom a, point p); // move atom to a new location
void change_residue(residue &res, const std::string &newcompound,
const std::vector<std::tuple<std::string, std::string>> &remappedAtoms);
/// \brief Remove a residue, can be monomer or nonpoly
///
/// \param asym_id The asym ID
/// \param seq_id The sequence ID
void remove_residue(const std::string &asym_id, int seq_id, const std::string &auth_seq_id);
/// \brief Create a new non-polymer entity, returns new ID
/// \param mon_id The mon_id for the new nonpoly, must be an existing and known compound from CCD
/// \return The ID of the created entity
std::string create_non_poly_entity(const std::string &mon_id);
/// \brief Create a new NonPolymer struct_asym with atoms constructed from \a atoms, returns asym_id.
/// This method assumes you are copying data from one cif file to another.
///
/// \param entity_id The entity ID of the new nonpoly
/// \param atoms The array of atom_site rows containing the data.
/// \return The newly create asym ID
std::string create_non_poly(const std::string &entity_id, const std::vector<atom> &atoms);
/// \brief Create a new NonPolymer struct_asym with atoms constructed from info in \a atom_info, returns asym_id.
/// This method creates new atom records filled with info from the info.
///
/// \param entity_id The entity ID of the new nonpoly
/// \param atoms The array of sets of item data containing the data for the atoms.
/// \return The newly create asym ID
std::string create_non_poly(const std::string &entity_id, std::vector<row_initializer> atoms);
/// \brief Create a new water with atom constructed from info in \a atom_info
/// This method creates a new atom record filled with info from the info.
///
/// \param atom The set of item data containing the data for the atoms.
void create_water(row_initializer atom);
/// \brief Create a new and empty (sugar) branch
branch &create_branch();
/// \brief Create a new (sugar) branch with one first NAG containing atoms constructed from \a atoms
branch &create_branch(std::vector<row_initializer> atoms);
/// \brief Extend an existing (sugar) branch identified by \a asymID with one sugar containing atoms constructed from \a atom_info
///
/// \param asym_id The asym id of the branch to extend
/// \param atom_info Array containing the info for the atoms to construct for the new sugar
/// \param link_sugar The sugar to link to, note: this is the sugar number (1 based)
/// \param link_atom The atom id of the atom linked in the sugar
branch &extend_branch(const std::string &asym_id, std::vector<row_initializer> atom_info,
int link_sugar, const std::string &link_atom);
/// \brief Remove \a branch
void remove_branch(branch &branch);
/// \brief Remove residue \a res
///
/// \param res The residue to remove
void remove_residue(residue &res);
/// \brief Translate the coordinates of all atoms in the structure by \a t
void translate(point t);
/// \brief Rotate the coordinates of all atoms in the structure by \a q
void rotate(quaternion t);
/// \brief Translate and rotate the coordinates of all atoms in the structure by \a t and \a q
void translate_and_rotate(point t, quaternion q);
/// \brief Translate, rotate and translate again the coordinates of all atoms in the structure by \a t1 , \a q and \a t2
void translate_rotate_and_translate(point t1, quaternion q, point t2);
void cleanup_empty_categories();
/// \brief Direct access to underlying data
category &get_category(std::string_view name) const
{
return m_db[name];
}
datablock &get_datablock() const
{
return m_db;
}
void validate_atoms() const;
// TODO: make this protected?
void load_atoms_for_model(StructureOpenOptions options);
template <typename... Args>
atom &emplace_atom(Args&... args)
{
return emplace_atom(atom{ std::forward<Args>(args)... });
}
atom &emplace_atom(atom &&atom);
private:
friend polymer;
friend residue;
std::string insert_compound(const std::string &compoundID, bool is_entity);
std::string create_entity_for_branch(branch &branch);
void load_data();
void remove_atom(atom &a, bool removeFromResidue);
void remove_sugar(sugar &sugar);
datablock &m_db;
size_t m_model_nr;
std::vector<atom> m_atoms;
std::vector<size_t> m_atom_index;
std::list<polymer> m_polymers;
std::list<branch> m_branches;
std::vector<residue> m_non_polymers;
};
// --------------------------------------------------------------------
/// \brief Reconstruct all missing categories for an assumed PDBx file.
/// Some people believe that simply dumping some atom records is enough.
/// \param db The cif::datablock that hopefully contains some valid data
void reconstruct_pdbx(datablock &db);
} // namespace cif::mm

253
include/cif++/parser.hpp Normal file
View File

@@ -0,0 +1,253 @@
/*-
* 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
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include "cif++/row.hpp"
#include <map>
namespace cif
{
// --------------------------------------------------------------------
class parse_error : public std::runtime_error
{
public:
parse_error(uint32_t line_nr, const std::string &message)
: std::runtime_error("parse error at line " + std::to_string(line_nr) + ": " + message)
{
}
};
// --------------------------------------------------------------------
// TODO: Need to implement support for transformed long lines
class sac_parser
{
public:
using datablock_index = std::map<std::string, std::size_t>;
virtual ~sac_parser() = default;
enum CharTraitsMask : uint8_t
{
kOrdinaryMask = 1 << 0,
kNonBlankMask = 1 << 1,
kTextLeadMask = 1 << 2,
kAnyPrintMask = 1 << 3
};
static constexpr bool is_space(int ch)
{
return ch == ' ' or ch == '\t' or ch == '\r' or ch == '\n';
}
static constexpr bool is_white(int ch)
{
return is_space(ch) or ch == '#';
}
static constexpr bool is_ordinary(int ch)
{
return ch >= 0x20 and ch <= 0x7f and (kCharTraitsTable[ch - 0x20] & kOrdinaryMask) != 0;
}
static constexpr bool is_non_blank(int ch)
{
return ch > 0x20 and ch <= 0x7f and (kCharTraitsTable[ch - 0x20] & kNonBlankMask) != 0;
}
static constexpr bool is_text_lead(int ch)
{
return ch >= 0x20 and ch <= 0x7f and (kCharTraitsTable[ch - 0x20] & kTextLeadMask) != 0;
}
static constexpr bool is_any_print(int ch)
{
return ch == '\t' or
(ch >= 0x20 and ch <= 0x7f and (kCharTraitsTable[ch - 0x20] & kAnyPrintMask) != 0);
}
static bool is_unquoted_string(std::string_view text);
protected:
static constexpr uint8_t kCharTraitsTable[128] = {
// 0 1 2 3 4 5 6 7 8 9 a b c d e f
14, 15, 14, 14, 14, 15, 15, 14, 15, 15, 15, 15, 15, 15, 15, 15, // 2
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 10, 15, 15, 15, 15, // 3
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, // 4
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 15, 14, 15, 14, // 5
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, // 6
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, // 7
};
enum class CIFToken
{
Unknown,
Eof,
DATA,
LOOP,
GLOBAL,
SAVE_,
SAVE_NAME,
STOP,
Tag,
Value
};
static constexpr const char *get_token_name(CIFToken token)
{
switch (token)
{
case CIFToken::Unknown: return "Unknown";
case CIFToken::Eof: return "Eof";
case CIFToken::DATA: return "DATA";
case CIFToken::LOOP: return "LOOP";
case CIFToken::GLOBAL: return "GLOBAL";
case CIFToken::SAVE_: return "SAVE";
case CIFToken::SAVE_NAME: return "SAVE+name";
case CIFToken::STOP: return "STOP";
case CIFToken::Tag: return "Tag";
case CIFToken::Value: return "Value";
default: return "Invalid token parameter";
}
}
// get_next_char takes the next character from the istream.
// This function also does carriage/linefeed translation.
int get_next_char();
// Put the last read character back into the istream
void retract();
CIFToken get_next_token();
void match(CIFToken token);
public:
bool parse_single_datablock(const std::string &datablock);
datablock_index index_datablocks();
bool parse_single_datablock(const std::string &datablock, const datablock_index &index);
void parse_file();
protected:
sac_parser(std::istream &is, bool init = true);
void parse_global();
void parse_datablock();
virtual void parse_save_frame();
void error(const std::string &msg)
{
if (cif::VERBOSE > 0)
std::cerr << "Error parsing mmCIF: " << msg << std::endl;
throw parse_error(m_line_nr, msg);
}
void warning(const std::string &msg)
{
if (cif::VERBOSE > 0)
std::cerr << "parser warning at line " << m_line_nr << ": " << msg << std::endl;
}
// production methods, these are pure virtual here
virtual void produce_datablock(std::string_view name) = 0;
virtual void produce_category(std::string_view name) = 0;
virtual void produce_row() = 0;
virtual void produce_item(std::string_view category, std::string_view item, std::string_view value) = 0;
protected:
enum class State
{
Start,
White,
Esc,
Comment,
QuestionMark,
Dot,
QuotedString,
QuotedStringQuote,
UnquotedString,
Tag,
TextField,
TextFieldNL,
Reserved,
Value
};
std::streambuf &m_source;
// Parser state
uint32_t m_line_nr;
bool m_bol;
CIFToken m_lookahead;
// token buffer
std::vector<char> m_token_buffer;
std::string_view m_token_value;
};
// --------------------------------------------------------------------
class parser : public sac_parser
{
public:
parser(std::istream &is, file &file)
: sac_parser(is)
, m_file(file)
{
}
void produce_datablock(std::string_view name) override;
void produce_category(std::string_view name) override;
void produce_row() override;
void produce_item(std::string_view category, std::string_view item, std::string_view value) override;
protected:
file &m_file;
datablock *m_datablock = nullptr;
category *m_category = nullptr;
row_handle m_row;
};
} // namespace cif

View File

@@ -1,17 +1,17 @@
/*-
* 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
@@ -26,14 +26,17 @@
#pragma once
#include "cif++/Cif++.hpp"
#include "cif++/datablock.hpp"
void WritePDBFile(std::ostream& pdbFile, cif::File& cifFile);
namespace cif::pdb
{
/// \brief Just the HEADER, COMPND, SOURCE and AUTHOR lines
void WritePDBHeaderLines(std::ostream& os, cif::File& cifFile);
void write_header_lines(std::ostream &os, const datablock &data);
std::string GetPDBHEADERLine(cif::File& cifFile, std::string::size_type truncate_at = 127);
std::string GetPDBCOMPNDLine(cif::File& cifFile, std::string::size_type truncate_at = 127);
std::string GetPDBSOURCELine(cif::File& cifFile, std::string::size_type truncate_at = 127);
std::string GetPDBAUTHORLine(cif::File& cifFile, std::string::size_type truncate_at = 127);
std::string get_HEADER_line(const datablock &data, std::string::size_type truncate_at = 127);
std::string get_COMPND_line(const datablock &data, std::string::size_type truncate_at = 127);
std::string get_SOURCE_line(const datablock &data, std::string::size_type truncate_at = 127);
std::string get_AUTHOR_line(const datablock &data, std::string::size_type truncate_at = 127);
} // namespace pdbx

60
include/cif++/pdb/io.hpp Normal file
View File

@@ -0,0 +1,60 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2022 NKI/AVL, Netherlands Cancer Institute
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include "cif++/datablock.hpp"
namespace cif::pdb
{
/// \brief Read a file in either mmCIF or PDB format, compressed or not,
/// depending on the content.
file read(const std::filesystem::path &file);
/// \brief Read a file in either mmCIF or PDB format, compressed or not,
/// depending on the content.
file read(std::istream &is);
/// \brief Write out a file in PDB format
void write(std::ostream &os, const datablock &db);
/// \brief Write out a file in PDB format
inline void write(std::ostream &os, const file &f)
{
write(os, f.front());
}
/// \brief Write out a file in PDB format or mmCIF format, depending on the filename extension
void write(const std::filesystem::path &file, const datablock &db);
/// \brief Write out a file in PDB format or mmCIF format, depending on the filename extension
inline void write(const std::filesystem::path &p, const file &f)
{
write(p, f.front());
}
}

View File

@@ -1,17 +1,17 @@
/*-
* 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
@@ -26,28 +26,31 @@
#pragma once
#include "cif++/Cif++.hpp"
#include "cif++/file.hpp"
namespace cif::pdb
{
// --------------------------------------------------------------------
struct PDBRecord
{
PDBRecord* mNext;
uint32_t mLineNr;
char mName[11];
size_t mVlen;
char mValue[0];
PDBRecord *mNext;
uint32_t mLineNr;
char mName[11];
size_t mVlen;
char mValue[1];
PDBRecord(uint32_t lineNr, const std::string& name, const std::string& value);
PDBRecord(uint32_t lineNr, const std::string &name, const std::string &value);
~PDBRecord();
void* operator new(size_t);
void* operator new(size_t size, size_t vLen);
void operator delete(void* p);
bool is(const char* name) const;
void *operator new(size_t);
void *operator new(size_t size, size_t vLen);
void operator delete(void *p);
void operator delete(void *p, size_t vLen);
bool is(const char *name) const;
char vC(size_t column);
std::string vS(size_t columnFirst, size_t columnLast = std::numeric_limits<size_t>::max());
int vI(int columnFirst, int columnLast);
@@ -56,4 +59,6 @@ struct PDBRecord
// --------------------------------------------------------------------
void ReadPDBFile(std::istream& pdbFile, cif::File& cifFile);
void ReadPDBFile(std::istream &pdbFile, file &cifFile);
} // namespace pdbx

View File

@@ -1,17 +1,17 @@
/*-
* 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
@@ -26,10 +26,13 @@
#pragma once
#include "cif++/PDB2Cif.hpp"
#include "pdb2cif.hpp"
// --------------------------------------------------------------------
namespace cif::pdb
{
struct TemplateLine;
class Remark3Parser
@@ -37,37 +40,36 @@ class Remark3Parser
public:
virtual ~Remark3Parser() {}
static bool parse(const std::string& expMethod, PDBRecord* r, cif::Datablock& db);
static bool parse(const std::string &expMethod, PDBRecord *r, cif::datablock &db);
virtual std::string program();
virtual std::string version();
protected:
Remark3Parser(const std::string& name, const std::string& expMethod, PDBRecord* r, cif::Datablock& db,
const TemplateLine templatelines[], uint32_t templateLineCount, std::regex programVersion);
Remark3Parser(const std::string &name, const std::string &expMethod, PDBRecord *r, cif::datablock &db,
const TemplateLine templatelines[], uint32_t templateLineCount, std::regex programVersion);
virtual float parse();
std::string nextLine();
bool match(const char* expr, int nextState);
void storeCapture(const char* category, std::initializer_list<const char*> items, bool createNew = false);
void storeRefineLsRestr(const char* type, std::initializer_list<const char*> values);
void updateRefineLsRestr(const char* type, std::initializer_list<const char*> values);
bool match(const char *expr, int nextState);
void storeCapture(const char *category, std::initializer_list<const char *> items, bool createNew = false);
void storeRefineLsRestr(const char *type, std::initializer_list<const char *> values);
void updateRefineLsRestr(const char *type, std::initializer_list<const char *> values);
virtual void fixup() {}
std::string mName;
std::string mExpMethod;
PDBRecord* mRec;
cif::Datablock mDb;
std::string mLine;
std::smatch mM;
uint32_t mState;
std::string mName;
std::string mExpMethod;
PDBRecord *mRec;
cif::datablock mDb;
std::string mLine;
std::smatch mM;
uint32_t mState;
const TemplateLine* mTemplate;
uint32_t mTemplateCount;
std::regex mProgramVersion;
const TemplateLine *mTemplate;
uint32_t mTemplateCount;
std::regex mProgramVersion;
};
} // namespace pdbx

View File

@@ -1,17 +1,17 @@
/*-
* 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
@@ -26,32 +26,26 @@
#pragma once
#include <vector>
#include "cif++/datablock.hpp"
#include <string>
#include <tuple>
#include "cif++/Cif++.hpp"
#include <vector>
namespace cif
{
extern const int
kResidueNrWildcard,
kNoSeqNum;
struct TLSSelection;
typedef std::unique_ptr<TLSSelection> TLSSelectionPtr;
struct tls_selection;
struct tls_residue;
struct TLSResidue;
struct TLSSelection
struct tls_selection
{
virtual ~TLSSelection() {}
virtual void CollectResidues(cif::Datablock& db, std::vector<TLSResidue>& residues, int indentLevel = 0) const = 0;
std::vector<std::tuple<std::string,int,int>> GetRanges(cif::Datablock& db, bool pdbNamespace) const;
virtual ~tls_selection() {}
virtual void collect_residues(cif::datablock &db, std::vector<tls_residue> &residues, std::size_t indentLevel = 0) const = 0;
std::vector<std::tuple<std::string, int, int>> get_ranges(cif::datablock &db, bool pdbNamespace) const;
};
// Low level: get the selections
TLSSelectionPtr ParseSelectionDetails(const std::string& program, const std::string& selection);
std::unique_ptr<tls_selection> parse_tls_selection_details(const std::string &program, const std::string &selection);
}
} // namespace cif

766
include/cif++/point.hpp Normal file
View File

@@ -0,0 +1,766 @@
/*-
* 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
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include "cif++/exports.hpp"
#include <array>
#include <cmath>
#include <complex>
#include <functional>
#include <valarray>
#if __has_include(<clipper/core/coords.h>)
#define HAVE_LIBCLIPPER 1
#include <clipper/core/coords.h>
#endif
namespace cif
{
// --------------------------------------------------------------------
const double
kPI = 3.141592653589793238462643383279502884;
// --------------------------------------------------------------------
// A stripped down quaternion implementation, based on boost::math::quaternion
// We use quaternions to do rotations in 3d space
template <typename T>
class quaternion_type
{
public:
using value_type = T;
constexpr explicit quaternion_type(value_type const &value_a = {}, value_type const &value_b = {}, value_type const &value_c = {}, value_type const &value_d = {})
: a(value_a)
, b(value_b)
, c(value_c)
, d(value_d)
{
}
constexpr explicit quaternion_type(std::complex<value_type> const &z0, std::complex<value_type> const &z1 = std::complex<value_type>())
: a(z0.real())
, b(z0.imag())
, c(z1.real())
, d(z1.imag())
{
}
constexpr quaternion_type(quaternion_type const &) = default;
constexpr quaternion_type(quaternion_type &&) = default;
template <typename X>
constexpr explicit quaternion_type(quaternion_type<X> const &rhs)
: a(static_cast<value_type>(rhs.a))
, b(static_cast<value_type>(rhs.b))
, c(static_cast<value_type>(rhs.c))
, d(static_cast<value_type>(rhs.d))
{
}
// accessors
//
// Note: Like complex number, quaternions do have a meaningful notion of "real part",
// but unlike them there is no meaningful notion of "imaginary part".
// Instead there is an "unreal part" which itself is a quaternion, and usually
// nothing simpler (as opposed to the complex number case).
// However, for practicality, there are accessors for the other components
// (these are necessary for the templated copy constructor, for instance).
constexpr value_type real() const
{
return a;
}
constexpr quaternion_type unreal() const
{
return { 0, b, c, d };
}
constexpr void swap(quaternion_type &o)
{
std::swap(a, o.a);
std::swap(b, o.b);
std::swap(c, o.c);
std::swap(d, o.d);
}
// assignment operators
template <typename X>
constexpr quaternion_type &operator=(quaternion_type<X> const &rhs)
{
a = static_cast<value_type>(rhs.a);
b = static_cast<value_type>(rhs.b);
c = static_cast<value_type>(rhs.c);
d = static_cast<value_type>(rhs.d);
return *this;
}
constexpr quaternion_type &operator=(quaternion_type const &rhs)
{
a = rhs.a;
b = rhs.b;
c = rhs.c;
d = rhs.d;
return *this;
}
constexpr quaternion_type &operator=(value_type const &rhs)
{
a = rhs;
b = c = d = static_cast<value_type>(0);
return *this;
}
constexpr quaternion_type &operator=(std::complex<value_type> const &rhs)
{
a = rhs.real();
b = rhs.imag();
c = d = static_cast<value_type>(0);
return *this;
}
// other assignment-related operators
//
// NOTE: Quaternion multiplication is *NOT* commutative;
// symbolically, "q *= rhs;" means "q = q * rhs;"
// and "q /= rhs;" means "q = q * inverse_of(rhs);"
constexpr quaternion_type &operator+=(value_type const &rhs)
{
a += rhs;
return *this;
}
constexpr quaternion_type &operator+=(std::complex<value_type> const &rhs)
{
a += std::real(rhs);
b += std::imag(rhs);
return *this;
}
template <class X>
constexpr quaternion_type &operator+=(quaternion_type<X> const &rhs)
{
a += rhs.a;
b += rhs.b;
c += rhs.c;
d += rhs.d;
return *this;
}
constexpr quaternion_type &operator-=(value_type const &rhs)
{
a -= rhs;
return *this;
}
constexpr quaternion_type &operator-=(std::complex<value_type> const &rhs)
{
a -= std::real(rhs);
b -= std::imag(rhs);
return *this;
}
template <class X>
constexpr quaternion_type &operator-=(quaternion_type<X> const &rhs)
{
a -= rhs.a;
b -= rhs.b;
c -= rhs.c;
d -= rhs.d;
return *this;
}
constexpr quaternion_type &operator*=(value_type const &rhs)
{
a *= rhs;
b *= rhs;
c *= rhs;
d *= rhs;
return *this;
}
constexpr quaternion_type &operator*=(std::complex<value_type> const &rhs)
{
value_type ar = rhs.real();
value_type br = rhs.imag();
quaternion_type result(a * ar - b * br, a * br + b * ar, c * ar + d * br, -c * br + d * ar);
swap(result);
return *this;
}
constexpr friend quaternion_type operator*(const quaternion_type &a, const quaternion_type &b)
{
auto result = a;
result *= b;
return result;
}
template <typename X>
constexpr quaternion_type &operator*=(quaternion_type<X> const &rhs)
{
value_type ar = static_cast<value_type>(rhs.a);
value_type br = static_cast<value_type>(rhs.b);
value_type cr = static_cast<value_type>(rhs.c);
value_type dr = static_cast<value_type>(rhs.d);
quaternion_type result(a * ar - b * br - c * cr - d * dr, a * br + b * ar + c * dr - d * cr, a * cr - b * dr + c * ar + d * br, a * dr + b * cr - c * br + d * ar);
swap(result);
return *this;
}
constexpr quaternion_type &operator/=(value_type const &rhs)
{
a /= rhs;
b /= rhs;
c /= rhs;
d /= rhs;
return *this;
}
constexpr quaternion_type &operator/=(std::complex<value_type> const &rhs)
{
value_type ar = rhs.real();
value_type br = rhs.imag();
value_type denominator = ar * ar + br * br;
quaternion_type result((+a * ar + b * br) / denominator, (-a * br + b * ar) / denominator, (+c * ar - d * br) / denominator, (+c * br + d * ar) / denominator);
swap(result);
return *this;
}
template <typename X>
constexpr quaternion_type &operator/=(quaternion_type<X> const &rhs)
{
value_type ar = static_cast<value_type>(rhs.a);
value_type br = static_cast<value_type>(rhs.b);
value_type cr = static_cast<value_type>(rhs.c);
value_type dr = static_cast<value_type>(rhs.d);
value_type denominator = ar * ar + br * br + cr * cr + dr * dr;
quaternion_type result((+a * ar + b * br + c * cr + d * dr) / denominator, (-a * br + b * ar - c * dr + d * cr) / denominator, (-a * cr + b * dr + c * ar - d * br) / denominator, (-a * dr - b * cr + c * br + d * ar) / denominator);
swap(result);
return *this;
}
constexpr friend quaternion_type normalize(quaternion_type q)
{
std::valarray<value_type> t(4);
t[0] = q.a;
t[1] = q.b;
t[2] = q.c;
t[3] = q.d;
t *= t;
value_type length = std::sqrt(t.sum());
if (length > 0.001)
q /= static_cast<value_type>(length);
else
q = quaternion_type(1, 0, 0, 0);
return q;
}
constexpr friend quaternion_type conj(quaternion_type q)
{
return quaternion_type{ +q.a, -q.b, -q.c, -q.d };
}
constexpr value_type get_a() const { return a; }
constexpr value_type get_b() const { return b; }
constexpr value_type get_c() const { return c; }
constexpr value_type get_d() const { return d; }
constexpr bool operator==(const quaternion_type &rhs) const
{
return a == rhs.a and b == rhs.b and c == rhs.c and d == rhs.d;
}
constexpr bool operator!=(const quaternion_type &rhs) const
{
return a != rhs.a or b != rhs.b or c != rhs.c or d != rhs.d;
}
constexpr operator bool() const
{
return a != 0 or b != 0 or c != 0 or d != 0;
}
private:
value_type a, b, c, d;
};
template <typename T>
inline quaternion_type<T> spherical(T const &rho, T const &theta, T const &phi1, T const &phi2)
{
T cos_phi1 = std::cos(phi1);
T cos_phi2 = std::cos(phi2);
T a = std::cos(theta) * cos_phi1 * cos_phi2;
T b = std::sin(theta) * cos_phi1 * cos_phi2;
T c = std::sin(phi1) * cos_phi2;
T d = std::sin(phi2);
quaternion_type result(a, b, c, d);
result *= rho;
return result;
}
using quaternion = quaternion_type<float>;
// --------------------------------------------------------------------
// point, a location with x, y and z coordinates as floating point.
// This one is derived from a tuple<float,float,float> so
// you can do things like:
//
// float x, y, z;
// tie(x, y, z) = atom.loc();
template <typename F>
struct point_type
{
using value_type = F;
value_type m_x, m_y, m_z;
constexpr point_type()
: m_x(0)
, m_y(0)
, m_z(0)
{
}
constexpr point_type(value_type x, value_type y, value_type z)
: m_x(x)
, m_y(y)
, m_z(z)
{
}
template <typename PF>
constexpr point_type(const point_type<PF> &pt)
: m_x(static_cast<F>(pt.m_x))
, m_y(static_cast<F>(pt.m_y))
, m_z(static_cast<F>(pt.m_z))
{
}
constexpr point_type(const std::tuple<value_type, value_type, value_type> &pt)
: point_type(std::get<0>(pt), std::get<1>(pt), std::get<2>(pt))
{
}
#if HAVE_LIBCLIPPER
constexpr point_type(const clipper::Coord_orth &pt)
: m_x(pt[0])
, m_y(pt[1])
, m_z(pt[2])
{
}
constexpr point_type &operator=(const clipper::Coord_orth &rhs)
{
m_x = rhs[0];
m_y = rhs[1];
m_z = rhs[2];
return *this;
}
#endif
template <typename PF>
constexpr point_type &operator=(const point_type<PF> &rhs)
{
m_x = static_cast<F>(rhs.m_x);
m_y = static_cast<F>(rhs.m_y);
m_z = static_cast<F>(rhs.m_z);
return *this;
}
constexpr value_type &get_x() { return m_x; }
constexpr value_type get_x() const { return m_x; }
constexpr void set_x(value_type x) { m_x = x; }
constexpr value_type &get_y() { return m_y; }
constexpr value_type get_y() const { return m_y; }
constexpr void set_y(value_type y) { m_y = y; }
constexpr value_type &get_z() { return m_z; }
constexpr value_type get_z() const { return m_z; }
constexpr void set_z(value_type z) { m_z = z; }
constexpr point_type &operator+=(const point_type &rhs)
{
m_x += rhs.m_x;
m_y += rhs.m_y;
m_z += rhs.m_z;
return *this;
}
constexpr point_type &operator+=(value_type d)
{
m_x += d;
m_y += d;
m_z += d;
return *this;
}
constexpr point_type &operator-=(const point_type &rhs)
{
m_x -= rhs.m_x;
m_y -= rhs.m_y;
m_z -= rhs.m_z;
return *this;
}
constexpr point_type &operator-=(value_type d)
{
m_x -= d;
m_y -= d;
m_z -= d;
return *this;
}
constexpr point_type &operator*=(value_type rhs)
{
m_x *= rhs;
m_y *= rhs;
m_z *= rhs;
return *this;
}
constexpr point_type &operator/=(value_type rhs)
{
m_x /= rhs;
m_y /= rhs;
m_z /= rhs;
return *this;
}
constexpr value_type normalize()
{
auto length = m_x * m_x + m_y * m_y + m_z * m_z;
if (length > 0)
{
length = std::sqrt(length);
operator/=(length);
}
return length;
}
constexpr void rotate(const quaternion &q)
{
quaternion_type<value_type> p(0, m_x, m_y, m_z);
p = q * p * conj(q);
m_x = p.get_b();
m_y = p.get_c();
m_z = p.get_d();
}
constexpr void rotate(const quaternion &q, point_type pivot)
{
operator-=(pivot);
rotate(q);
operator+=(pivot);
}
#if HAVE_LIBCLIPPER
operator clipper::Coord_orth() const
{
return clipper::Coord_orth(m_x, m_y, m_z);
}
#endif
constexpr operator std::tuple<const value_type &, const value_type &, const value_type &>() const
{
return std::make_tuple(std::ref(m_x), std::ref(m_y), std::ref(m_z));
}
constexpr operator std::tuple<value_type &, value_type &, value_type &>()
{
return std::make_tuple(std::ref(m_x), std::ref(m_y), std::ref(m_z));
}
constexpr bool operator==(const point_type &rhs) const
{
return m_x == rhs.m_x and m_y == rhs.m_y and m_z == rhs.m_z;
}
// consider point as a vector... perhaps I should rename point?
constexpr value_type length_sq() const
{
return m_x * m_x + m_y * m_y + m_z * m_z;
}
constexpr value_type length() const
{
return std::sqrt(m_x * m_x + m_y * m_y + m_z * m_z);
}
};
using point = point_type<float>;
template <typename F>
inline constexpr std::ostream &operator<<(std::ostream &os, const point_type<F> &pt)
{
os << '(' << pt.m_x << ',' << pt.m_y << ',' << pt.m_z << ')';
return os;
}
template <typename F>
inline constexpr point_type<F> operator+(const point_type<F> &lhs, const point_type<F> &rhs)
{
return point_type<F>(lhs.m_x + rhs.m_x, lhs.m_y + rhs.m_y, lhs.m_z + rhs.m_z);
}
template <typename F>
inline constexpr point_type<F> operator-(const point_type<F> &lhs, const point_type<F> &rhs)
{
return point_type<F>(lhs.m_x - rhs.m_x, lhs.m_y - rhs.m_y, lhs.m_z - rhs.m_z);
}
template <typename F>
inline constexpr point_type<F> operator-(const point_type<F> &pt)
{
return point_type<F>(-pt.m_x, -pt.m_y, -pt.m_z);
}
template <typename F>
inline constexpr point_type<F> operator*(const point_type<F> &pt, F f)
{
return point_type<F>(pt.m_x * f, pt.m_y * f, pt.m_z * f);
}
template <typename F>
inline constexpr point_type<F> operator*(F f, const point_type<F> &pt)
{
return point_type<F>(pt.m_x * f, pt.m_y * f, pt.m_z * f);
}
template <typename F>
inline constexpr point_type<F> operator/(const point_type<F> &pt, F f)
{
return point_type<F>(pt.m_x / f, pt.m_y / f, pt.m_z / f);
}
// --------------------------------------------------------------------
// several standard 3d operations
template <typename F>
inline constexpr auto distance_squared(const point_type<F> &a, const point_type<F> &b)
{
return (a.m_x - b.m_x) * (a.m_x - b.m_x) +
(a.m_y - b.m_y) * (a.m_y - b.m_y) +
(a.m_z - b.m_z) * (a.m_z - b.m_z);
}
template <typename F>
inline constexpr auto distance(const point_type<F> &a, const point_type<F> &b)
{
return std::sqrt(
(a.m_x - b.m_x) * (a.m_x - b.m_x) +
(a.m_y - b.m_y) * (a.m_y - b.m_y) +
(a.m_z - b.m_z) * (a.m_z - b.m_z));
}
template <typename F>
inline constexpr auto dot_product(const point_type<F> &a, const point_type<F> &b)
{
return a.m_x * b.m_x + a.m_y * b.m_y + a.m_z * b.m_z;
}
template <typename F>
inline constexpr point_type<F> cross_product(const point_type<F> &a, const point_type<F> &b)
{
return point_type<F>(a.m_y * b.m_z - b.m_y * a.m_z,
a.m_z * b.m_x - b.m_z * a.m_x,
a.m_x * b.m_y - b.m_x * a.m_y);
}
template <typename F>
constexpr auto angle(const point_type<F> &p1, const point_type<F> &p2, const point_type<F> &p3)
{
point_type<F> v1 = p1 - p2;
point_type<F> v2 = p3 - p2;
return std::acos(dot_product(v1, v2) / (v1.length() * v2.length())) * 180 / kPI;
}
template <typename F>
constexpr auto dihedral_angle(const point_type<F> &p1, const point_type<F> &p2, const point_type<F> &p3, const point_type<F> &p4)
{
point_type<F> v12 = p1 - p2; // vector from p2 to p1
point_type<F> v43 = p4 - p3; // vector from p3 to p4
point_type<F> z = p2 - p3; // vector from p3 to p2
point_type<F> p = cross_product(z, v12);
point_type<F> x = cross_product(z, v43);
point_type<F> y = cross_product(z, x);
auto u = dot_product(x, x);
auto v = dot_product(y, y);
F result = 360;
if (u > 0 and v > 0)
{
u = dot_product(p, x) / std::sqrt(u);
v = dot_product(p, y) / std::sqrt(v);
if (u != 0 or v != 0)
result = std::atan2(v, u) * static_cast<F>(180 / kPI);
}
return result;
}
template <typename F>
constexpr auto cosinus_angle(const point_type<F> &p1, const point_type<F> &p2, const point_type<F> &p3, const point_type<F> &p4)
{
point_type<F> v12 = p1 - p2;
point_type<F> v34 = p3 - p4;
auto x = dot_product(v12, v12) * dot_product(v34, v34);
return x > 0 ? dot_product(v12, v34) / std::sqrt(x) : 0;
}
template <typename F>
constexpr auto distance_point_to_line(const point_type<F> &l1, const point_type<F> &l2, const point_type<F> &p)
{
auto line = l2 - l1;
auto p_to_l1 = p - l1;
auto p_to_l2 = p - l2;
auto cross = cross_product(p_to_l1, p_to_l2);
return cross.length() / line.length();
}
// --------------------------------------------------------------------
// For e.g. simulated annealing, returns a new point that is moved in
// a random direction with a distance randomly chosen from a normal
// distribution with a stddev of offset.
point nudge(point p, float offset);
// --------------------------------------------------------------------
quaternion construct_from_angle_axis(float angle, point axis);
std::tuple<double, point> quaternion_to_angle_axis(quaternion q);
/// @brief Given four points and an angle, return the quaternion required to rotate
/// point p4 along the p2-p3 axis and around point p3 to obtain the required within
/// an accuracy of esd
quaternion construct_for_dihedral_angle(point p1, point p2, point p3, point p4,
float angle, float esd);
point centroid(const std::vector<point> &Points);
point center_points(std::vector<point> &Points);
/// \brief Returns how the two sets of points \a a and \b b can be aligned
///
/// \param a The first set of points
/// \param b The second set of points
/// \result The quaternion which should be applied to the points in \a a to
/// obtain the best superposition.
quaternion align_points(const std::vector<point> &a, const std::vector<point> &b);
/// \brief The RMSd for the points in \a a and \a b
double RMSd(const std::vector<point> &a, const std::vector<point> &b);
// --------------------------------------------------------------------
// Helper class to generate evenly divided points on a sphere
// we use a fibonacci sphere to calculate even distribution of the dots
template <int N>
class spherical_dots
{
public:
constexpr static int P = 2 * N * 1;
using array_type = typename std::array<point, P>;
using iterator = typename array_type::const_iterator;
static spherical_dots &instance()
{
static spherical_dots sInstance;
return sInstance;
}
size_t size() const { return m_points.size(); }
const point operator[](uint32_t inIx) const { return m_points[inIx]; }
iterator begin() const { return m_points.begin(); }
iterator end() const { return m_points.end(); }
double weight() const { return m_weight; }
spherical_dots()
{
const double
kGoldenRatio = (1 + std::sqrt(5.0)) / 2;
m_weight = (4 * kPI) / P;
auto p = m_points.begin();
for (int32_t i = -N; i <= N; ++i)
{
double lat = std::asin((2.0 * i) / P);
double lon = std::fmod(i, kGoldenRatio) * 2 * kPI / kGoldenRatio;
p->m_x = std::sin(lon) * std::cos(lat);
p->m_y = std::cos(lon) * std::cos(lat);
p->m_z = std::sin(lat);
++p;
}
}
private:
array_type m_points;
double m_weight;
};
} // namespace cif

307
include/cif++/row.hpp Normal file
View File

@@ -0,0 +1,307 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2022 NKI/AVL, Netherlands Cancer Institute
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include "cif++/item.hpp"
#include <array>
namespace cif
{
namespace detail
{
// some helper classes to help create tuple result types
template <typename... C>
struct get_row_result
{
static constexpr size_t N = sizeof...(C);
get_row_result(const row_handle &r, std::array<uint16_t, N> &&columns)
: m_row(r)
, m_columns(std::move(columns))
{
}
const item_handle operator[](uint16_t ix) const
{
return m_row[m_columns[ix]];
}
template <typename... Ts, std::enable_if_t<N == sizeof...(Ts), int> = 0>
operator std::tuple<Ts...>() const
{
return get<Ts...>(std::index_sequence_for<Ts...>{});
}
template <typename... Ts, size_t... Is>
std::tuple<Ts...> get(std::index_sequence<Is...>) const
{
return std::tuple<Ts...>{ m_row[m_columns[Is]].template as<Ts>()... };
}
const row_handle &m_row;
std::array<uint16_t, N> m_columns;
};
// we want to be able to tie some variables to a get_row_result, for this we use tiewraps
template <typename... Ts>
struct tie_wrap
{
tie_wrap(Ts... args)
: m_value(args...)
{
}
template <typename RR>
void operator=(const RR &&rr)
{
// get_row_result will do the conversion, but only if the types
// are compatible. That means the number of parameters to the get()
// of the row should be equal to the number of items in the tuple
// you are trying to tie.
using RType = std::tuple<typename std::remove_reference<Ts>::type...>;
m_value = static_cast<RType>(rr);
}
std::tuple<Ts...> m_value;
};
} // namespace detail
template <typename... Ts>
auto tie(Ts &...v)
{
return detail::tie_wrap<Ts &...>(std::forward<Ts &>(v)...);
}
// --------------------------------------------------------------------
/// \brief the row class, this one is not directly accessible from the outside
class row : public std::vector<item_value>
{
public:
row() = default;
item_value* get(uint16_t ix)
{
return ix < size() ? &data()[ix] : nullptr;
}
const item_value* get(uint16_t ix) const
{
return ix < size() ? &data()[ix] : nullptr;
}
private:
friend class category;
friend class category_index;
template <typename, typename...>
friend class iterator_impl;
void append(uint16_t ix, item_value &&iv)
{
if (ix >= size())
resize(ix + 1);
at(ix) = std::move(iv);
}
void remove(uint16_t ix)
{
if (ix < size())
at(ix) = item_value{};
}
row *m_next = nullptr;
};
// --------------------------------------------------------------------
/// \brief row_handle is the way to access data stored in rows
class row_handle
{
public:
friend struct item_handle;
friend class category;
friend class category_index;
friend class row_initializer;
row_handle() = default;
row_handle(const row_handle &) = default;
row_handle(row_handle &&) = default;
row_handle &operator=(const row_handle &) = default;
row_handle &operator=(row_handle &&) = default;
row_handle(const category &cat, const row &r)
: m_category(const_cast<category *>(&cat))
, m_row(const_cast<row *>(&r))
{
}
const category &get_category() const
{
return *m_category;
}
bool empty() const
{
return m_category == nullptr or m_row == nullptr;
}
explicit operator bool() const
{
return not empty();
}
item_handle operator[](uint16_t column_ix)
{
return empty() ? item_handle::s_null_item : item_handle(column_ix, *this);
}
const item_handle operator[](uint16_t column_ix) const
{
return empty() ? item_handle::s_null_item : item_handle(column_ix, const_cast<row_handle &>(*this));
}
item_handle operator[](std::string_view column_name)
{
return empty() ? item_handle::s_null_item : item_handle(add_column(column_name), *this);
}
const item_handle operator[](std::string_view column_name) const
{
return empty() ? item_handle::s_null_item : item_handle(get_column_ix(column_name), const_cast<row_handle &>(*this));
}
template <typename... C>
auto get(C... columns) const
{
return detail::get_row_result<C...>(*this, { get_column_ix(columns)... });
}
template <typename... Ts, typename... C, std::enable_if_t<sizeof...(Ts) == sizeof...(C) and sizeof...(C) != 1, int> = 0>
std::tuple<Ts...> get(C... columns) const
{
return detail::get_row_result<Ts...>(*this, { get_column_ix(columns)... });
}
template <typename T>
T get(const char *column) const
{
return operator[](get_column_ix(column)).template as<T>();
}
void assign(const std::vector<item> &values)
{
for (auto &value : values)
assign(value, true);
}
void assign(std::string_view name, std::string_view value, bool updateLinked, bool validate = true)
{
assign(add_column(name), value, updateLinked, validate);
}
void assign(uint16_t column, std::string_view value, bool updateLinked, bool validate = true);
bool operator==(const row_handle &rhs) const { return m_category == rhs.m_category and m_row == rhs.m_row; }
bool operator!=(const row_handle &rhs) const { return m_category != rhs.m_category or m_row != rhs.m_row; }
private:
uint16_t get_column_ix(std::string_view name) const;
std::string_view get_column_name(uint16_t ix) const;
uint16_t add_column(std::string_view name);
row *get_row()
{
return m_row;
}
const row *get_row() const
{
return m_row;
}
void assign(const item &i, bool updateLinked)
{
assign(i.name(), i.value(), updateLinked);
}
void swap(uint16_t column, row_handle &r);
category *m_category = nullptr;
row *m_row = nullptr;
};
// --------------------------------------------------------------------
class row_initializer : public std::vector<item>
{
public:
friend class category;
row_initializer() = default;
row_initializer(const row_initializer &) = default;
row_initializer(row_initializer &&) = default;
row_initializer &operator=(const row_initializer &) = default;
row_initializer &operator=(row_initializer &&) = default;
row_initializer(std::initializer_list<item> items)
: std::vector<item>(items)
{
}
template <typename ItemIter, std::enable_if_t<std::is_same_v<typename ItemIter::value_type, item>, int> = 0>
row_initializer(ItemIter b, ItemIter e)
: std::vector<item>(b, e)
{
}
row_initializer(row_handle rh);
void set_value(std::string_view name, std::string_view value);
void set_value(const item &i)
{
set_value(i.name(), i.value());
}
void set_value_if_empty(std::string_view name, std::string_view value);
void set_value_if_empty(const item &i)
{
set_value_if_empty(i.name(), i.value());
}
};
} // namespace cif

418
include/cif++/symmetry.hpp Normal file
View File

@@ -0,0 +1,418 @@
/*-
* 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
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include "cif++/exports.hpp"
#include "cif++/matrix.hpp"
#include "cif++/point.hpp"
#include <array>
#include <cstdint>
#include <string>
/// \file cif++/symmetry.hpp
/// This file contains code to do symmetry operations based on the
/// operations as specified in the International Tables.
namespace cif
{
// --------------------------------------------------------------------
inline point operator*(const matrix3x3<float> &m, const point &pt)
{
return {
m(0, 0) * pt.m_x + m(0, 1) * pt.m_y + m(0, 2) * pt.m_z,
m(1, 0) * pt.m_x + m(1, 1) * pt.m_y + m(1, 2) * pt.m_z,
m(2, 0) * pt.m_x + m(2, 1) * pt.m_y + m(2, 2) * pt.m_z
};
}
// --------------------------------------------------------------------
enum class space_group_name
{
full,
xHM,
Hall
};
struct space_group
{
const char *name;
const char *xHM;
const char *Hall;
int nr;
};
extern CIFPP_EXPORT const space_group kSpaceGroups[];
extern CIFPP_EXPORT const std::size_t kNrOfSpaceGroups;
// --------------------------------------------------------------------
struct symop_data
{
constexpr symop_data(const std::array<int, 15> &data)
: m_packed((data[0] bitand 0x03ULL) << 34 bitor
(data[1] bitand 0x03ULL) << 32 bitor
(data[2] bitand 0x03ULL) << 30 bitor
(data[3] bitand 0x03ULL) << 28 bitor
(data[4] bitand 0x03ULL) << 26 bitor
(data[5] bitand 0x03ULL) << 24 bitor
(data[6] bitand 0x03ULL) << 22 bitor
(data[7] bitand 0x03ULL) << 20 bitor
(data[8] bitand 0x03ULL) << 18 bitor
(data[9] bitand 0x07ULL) << 15 bitor
(data[10] bitand 0x07ULL) << 12 bitor
(data[11] bitand 0x07ULL) << 9 bitor
(data[12] bitand 0x07ULL) << 6 bitor
(data[13] bitand 0x07ULL) << 3 bitor
(data[14] bitand 0x07ULL) << 0)
{
}
bool operator==(const symop_data &rhs) const
{
return m_packed == rhs.m_packed;
}
bool operator<(const symop_data &rhs) const
{
return m_packed < rhs.m_packed;
}
inline constexpr int unpack3(int offset) const
{
int result = (m_packed >> offset) bitand 0x03;
return result == 3 ? -1 : result;
}
inline constexpr int unpack7(int offset) const
{
return (m_packed >> offset) bitand 0x07;
}
constexpr std::array<int, 15> data() const
{
return {
unpack3(34),
unpack3(32),
unpack3(30),
unpack3(28),
unpack3(26),
unpack3(24),
unpack3(22),
unpack3(20),
unpack3(18),
unpack7(15),
unpack7(12),
unpack7(9),
unpack7(6),
unpack7(3),
unpack7(0)
};
}
private:
friend struct symop_datablock;
const uint64_t kPackMask = (~0ULL >> (64 - 36));
symop_data(uint64_t v)
: m_packed(v bitand kPackMask)
{
}
uint64_t m_packed;
};
struct symop_datablock
{
constexpr symop_datablock(int spacegroup, int rotational_number, const std::array<int, 15> &rt_data)
: m_v((spacegroup bitand 0xffffULL) << 48 bitor
(rotational_number bitand 0xffULL) << 40 bitor
symop_data(rt_data).m_packed)
{
}
uint16_t spacegroup() const { return m_v >> 48; }
symop_data symop() const { return symop_data(m_v); }
uint8_t rotational_number() const { return (m_v >> 40) bitand 0xff; }
private:
uint64_t m_v;
};
static_assert(sizeof(symop_datablock) == sizeof(uint64_t), "Size of symop_data is wrong");
extern CIFPP_EXPORT const symop_datablock kSymopNrTable[];
extern CIFPP_EXPORT const std::size_t kSymopNrTableSize;
// --------------------------------------------------------------------
// Some more symmetry related stuff here.
class datablock;
class cell;
class spacegroup;
class rtop;
class sym_op;
/// @brief A class that encapsulates the symmetry operations as used in PDB files, i.e. a rotational number and a translation vector
/// The syntax in string format follows the syntax as used in mmCIF files, i.e. rotational number followed by underscore and the
/// three translations where 5 is no movement.
struct sym_op
{
public:
sym_op(uint8_t nr = 1, uint8_t ta = 5, uint8_t tb = 5, uint8_t tc = 5)
: m_nr(nr)
, m_ta(ta)
, m_tb(tb)
, m_tc(tc)
{
}
explicit sym_op(std::string_view s);
sym_op(const sym_op &) = default;
sym_op(sym_op &&) = default;
sym_op &operator=(const sym_op &) = default;
sym_op &operator=(sym_op &&) = default;
constexpr bool is_identity() const
{
return m_nr == 1 and m_ta == 5 and m_tb == 5 and m_tc == 5;
}
explicit constexpr operator bool() const
{
return not is_identity();
}
std::string string() const;
#if defined(__cpp_impl_three_way_comparison)
constexpr auto operator<=>(const sym_op &rhs) const = default;
#else
constexpr bool operator==(const sym_op &rhs) const
{
return m_nr == rhs.m_nr and m_ta == rhs.m_ta and m_tb == rhs.m_tb and m_tc == rhs.m_tc;
}
constexpr bool operator!=(const sym_op &rhs) const
{
return not operator==(rhs);
}
#endif
uint8_t m_nr;
uint8_t m_ta, m_tb, m_tc;
};
static_assert(sizeof(sym_op) == 4, "Sym_op should be four bytes");
namespace literals
{
inline sym_op operator""_symop(const char *text, size_t length)
{
return sym_op({ text, length });
}
} // namespace literals
// --------------------------------------------------------------------
// The transformation class
class transformation
{
public:
transformation(const symop_data &data);
transformation(const matrix3x3<float> &r, const cif::point &t);
transformation(const transformation &) = default;
transformation(transformation &&) = default;
transformation &operator=(const transformation &) = default;
transformation &operator=(transformation &&) = default;
point operator()(point pt) const
{
if (m_q)
pt.rotate(m_q);
else
pt = m_rotation * pt;
return pt + m_translation;
}
friend transformation operator*(const transformation &lhs, const transformation &rhs);
friend transformation inverse(const transformation &t);
transformation operator-() const
{
return inverse(*this);
}
friend class spacegroup;
private:
// Most rotation matrices provided by the International Tables
// are really rotation matrices, in those cases we can construct
// a quaternion. Unfortunately, that doesn't work for all of them
void try_create_quaternion();
matrix3x3<float> m_rotation;
quaternion m_q;
point m_translation;
};
// --------------------------------------------------------------------
// class cell
class cell
{
public:
cell(float a, float b, float c, float alpha = 90.f, float beta = 90.f, float gamma = 90.f);
cell(const datablock &db);
float get_a() const { return m_a; }
float get_b() const { return m_b; }
float get_c() const { return m_c; }
float get_alpha() const { return m_alpha; }
float get_beta() const { return m_beta; }
float get_gamma() const { return m_gamma; }
matrix3x3<float> get_orthogonal_matrix() const { return m_orthogonal; }
matrix3x3<float> get_fractional_matrix() const { return m_fractional; }
private:
void init();
float m_a, m_b, m_c, m_alpha, m_beta, m_gamma;
matrix3x3<float> m_orthogonal, m_fractional;
};
// --------------------------------------------------------------------
int get_space_group_number(const datablock &db);
int get_space_group_number(std::string_view spacegroup);
int get_space_group_number(std::string_view spacegroup, space_group_name type);
class spacegroup : public std::vector<transformation>
{
public:
spacegroup(const datablock &db)
: spacegroup(get_space_group_number(db))
{
}
spacegroup(std::string_view name)
: spacegroup(get_space_group_number(name))
{
}
spacegroup(std::string_view name, space_group_name type)
: spacegroup(get_space_group_number(name, type))
{
}
spacegroup(int nr);
int get_nr() const { return m_nr; }
std::string get_name() const;
point operator()(const point &pt, const cell &c, sym_op symop) const;
point inverse(const point &pt, const cell &c, sym_op symop) const;
private:
int m_nr;
size_t m_index;
};
// --------------------------------------------------------------------
// A crystal combines a cell and a spacegroup.
class crystal
{
public:
crystal(const datablock &db)
: m_cell(db)
, m_spacegroup(db)
{
}
crystal(const cell &c, const spacegroup &sg)
: m_cell(c)
, m_spacegroup(sg)
{
}
crystal(const crystal &) = default;
crystal(crystal &&) = default;
crystal &operator=(const crystal &) = default;
crystal &operator=(crystal &&) = default;
const cell &get_cell() const { return m_cell; }
const spacegroup &get_spacegroup() const { return m_spacegroup; }
point symmetry_copy(const point &pt, sym_op symop) const
{
return m_spacegroup(pt, m_cell, symop);
}
point inverse_symmetry_copy(const point &pt, sym_op symop) const
{
return m_spacegroup.inverse(pt, m_cell, symop);
}
std::tuple<float,point,sym_op> closest_symmetry_copy(point a, point b) const;
private:
cell m_cell;
spacegroup m_spacegroup;
};
// --------------------------------------------------------------------
// Symmetry operations on points
inline point orthogonal(const point &pt, const cell &c)
{
return c.get_orthogonal_matrix() * pt;
}
inline point fractional(const point &pt, const cell &c)
{
return c.get_fractional_matrix() * pt;
}
// --------------------------------------------------------------------
} // namespace cif

465
include/cif++/text.hpp Normal file
View File

@@ -0,0 +1,465 @@
/*-
* 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
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include "cif++/exports.hpp"
#include <charconv>
#include <cmath>
#include <cstdint>
#include <limits>
#include <set>
#include <sstream>
#include <tuple>
#include <vector>
#if __has_include(<experimental/type_traits>)
#include <experimental/type_traits>
#else
// sub optimal, but replicating the same code is worse
#include <zeep/type-traits.hpp>
#endif
namespace cif
{
// --------------------------------------------------------------------
// some basic utilities: Since we're using ASCII input only, we define for optimisation
// our own case conversion routines.
bool iequals(std::string_view a, std::string_view b);
int icompare(std::string_view a, std::string_view b);
bool iequals(const char *a, const char *b);
int icompare(const char *a, const char *b);
void to_lower(std::string &s);
std::string to_lower_copy(std::string_view s);
void to_upper(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;
if (ni == e)
break;
ai = ni;
ni = std::next(ai);
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.data();
auto e = b;
while (e != s.data() + s.length())
{
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
struct iless
{
bool operator()(const std::string &a, const std::string &b) const
{
return icompare(a, b) < 0;
}
};
typedef std::set<std::string, iless> iset;
// --------------------------------------------------------------------
// This really makes a difference, having our own tolower routines
extern CIFPP_EXPORT const uint8_t kCharToLowerMap[256];
inline char tolower(int ch)
{
return static_cast<char>(kCharToLowerMap[static_cast<uint8_t>(ch)]);
}
// --------------------------------------------------------------------
std::tuple<std::string, std::string> split_tag_name(std::string_view tag);
// --------------------------------------------------------------------
// generate a cif name, mainly used to generate asym_id's
std::string cif_id_for_number(int number);
// --------------------------------------------------------------------
// custom wordwrapping routine
std::vector<std::string> word_wrap(const std::string &text, size_t width);
// --------------------------------------------------------------------
/// std::from_chars for floating point types.
/// These are optional, there's a selected_charconv class below that selects
/// the best option to used based on support by the stl library
/// I.e. that in case of GNU < 12 (or something) the cif implementation will
/// be used, all other cases will use the stl version.
template <typename FloatType, std::enable_if_t<std::is_floating_point_v<FloatType>, int> = 0>
std::from_chars_result from_chars(const char *first, const char *last, FloatType &value)
{
std::from_chars_result result{ first, {} };
enum State
{
IntegerSign,
Integer,
Fraction,
ExponentSign,
Exponent
} state = IntegerSign;
int sign = 1;
unsigned long long vi = 0;
long double f = 1;
int exponent_sign = 1;
int exponent = 0;
bool done = false;
while (not done and result.ec == std::errc())
{
char ch = result.ptr != last ? *result.ptr : 0;
++result.ptr;
switch (state)
{
case IntegerSign:
if (ch == '-')
{
sign = -1;
state = Integer;
}
else if (ch == '+')
state = Integer;
else if (ch >= '0' and ch <= '9')
{
vi = ch - '0';
state = Integer;
}
else if (ch == '.')
state = Fraction;
else
result.ec = std::errc::invalid_argument;
break;
case Integer:
if (ch >= '0' and ch <= '9')
vi = 10 * vi + (ch - '0');
else if (ch == 'e' or ch == 'E')
state = ExponentSign;
else if (ch == '.')
state = Fraction;
else
{
done = true;
--result.ptr;
}
break;
case Fraction:
if (ch >= '0' and ch <= '9')
{
vi = 10 * vi + (ch - '0');
f /= 10;
}
else if (ch == 'e' or ch == 'E')
state = ExponentSign;
else
{
done = true;
--result.ptr;
}
break;
case ExponentSign:
if (ch == '-')
{
exponent_sign = -1;
state = Exponent;
}
else if (ch == '+')
state = Exponent;
else if (ch >= '0' and ch <= '9')
{
exponent = ch - '0';
state = Exponent;
}
else
result.ec = std::errc::invalid_argument;
break;
case Exponent:
if (ch >= '0' and ch <= '9')
exponent = 10 * exponent + (ch - '0');
else
{
done = true;
--result.ptr;
}
break;
}
}
if (result.ec == std::errc())
{
long double v = f * vi * sign;
if (exponent != 0)
v *= std::pow(10, exponent * exponent_sign);
if (std::isnan(v))
result.ec = std::errc::invalid_argument;
else if (std::abs(v) > std::numeric_limits<FloatType>::max())
result.ec = std::errc::result_out_of_range;
value = static_cast<FloatType>(v);
}
return result;
}
enum class chars_format
{
scientific = 1,
fixed = 2,
// hex,
general = fixed | scientific
};
template <typename FloatType, std::enable_if_t<std::is_floating_point_v<FloatType>, int> = 0>
std::to_chars_result to_chars(char *first, char *last, FloatType &value, chars_format fmt)
{
int size = static_cast<int>(last - first);
int r = 0;
switch (fmt)
{
case chars_format::scientific:
if constexpr (std::is_same_v<FloatType, long double>)
r = snprintf(first, last - first, "%le", value);
else
r = snprintf(first, last - first, "%e", value);
break;
case chars_format::fixed:
if constexpr (std::is_same_v<FloatType, long double>)
r = snprintf(first, last - first, "%lf", value);
else
r = snprintf(first, last - first, "%f", value);
break;
case chars_format::general:
if constexpr (std::is_same_v<FloatType, long double>)
r = snprintf(first, last - first, "%lg", value);
else
r = snprintf(first, last - first, "%g", value);
break;
}
std::to_chars_result result;
if (r < 0 or r >= size)
result = { first, std::errc::value_too_large };
else
result = { first + r, std::errc() };
return result;
}
template <typename FloatType, std::enable_if_t<std::is_floating_point_v<FloatType>, int> = 0>
std::to_chars_result to_chars(char *first, char *last, FloatType &value, chars_format fmt, int precision)
{
int size = static_cast<int>(last - first);
int r = 0;
switch (fmt)
{
case chars_format::scientific:
if constexpr (std::is_same_v<FloatType, long double>)
r = snprintf(first, last - first, "%.*le", precision, value);
else
r = snprintf(first, last - first, "%.*e", precision, value);
break;
case chars_format::fixed:
if constexpr (std::is_same_v<FloatType, long double>)
r = snprintf(first, last - first, "%.*lf", precision, value);
else
r = snprintf(first, last - first, "%.*f", precision, value);
break;
case chars_format::general:
if constexpr (std::is_same_v<FloatType, long double>)
r = snprintf(first, last - first, "%.*lg", precision, value);
else
r = snprintf(first, last - first, "%.*g", precision, value);
break;
}
std::to_chars_result result;
if (r < 0 or r >= size)
result = { first, std::errc::value_too_large };
else
result = { first + r, std::errc() };
return result;
}
template <typename T>
struct my_charconv
{
static std::from_chars_result from_chars(const char *a, const char *b, T &d)
{
return cif::from_chars(a, b, d);
}
static std::to_chars_result to_chars(char *first, char *last, T &value, chars_format fmt)
{
return cif::to_chars(first, last, value, fmt);
}
};
template <typename T>
struct std_charconv
{
static std::from_chars_result from_chars(const char *a, const char *b, T &d)
{
return std::from_chars(a, b, d);
}
static std::to_chars_result to_chars(char *first, char *last, T &value, chars_format fmt)
{
return std::to_chars(first, last, value, fmt);
}
};
template <typename T>
using from_chars_function = decltype(std::from_chars(std::declval<const char *>(), std::declval<const char *>(), std::declval<T &>()));
template <typename T>
using selected_charconv = typename std::conditional_t<std::experimental::is_detected_v<from_chars_function, T>, std_charconv<T>, my_charconv<T>>;
} // namespace cif

185
include/cif++/utilities.hpp Normal file
View File

@@ -0,0 +1,185 @@
/*-
* 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
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include "cif++/exports.hpp"
#include <filesystem>
#ifndef STDOUT_FILENO
#define STDOUT_FILENO 1
#endif
#if _MSC_VER
#include <io.h>
#define isatty _isatty
#else
#include <unistd.h>
#endif
#if _MSC_VER
#pragma warning(disable : 4996) // unsafe function or variable (strcpy e.g.)
#pragma warning(disable : 4068) // unknown pragma
#pragma warning(disable : 4100) // unreferenced formal parameter
#pragma warning(disable : 4101) // unreferenced local variable
#define _SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING 1
#endif
namespace cif
{
extern CIFPP_EXPORT int VERBOSE;
// the git 'build' number
std::string get_version_nr();
// std::string get_version_date();
// --------------------------------------------------------------------
// Code helping with terminal i/o
uint32_t get_terminal_width();
// --------------------------------------------------------------------
// Path of the current executable
std::string get_executable_path();
// --------------------------------------------------------------------
// some manipulators to write coloured text to terminals
enum StringColour
{
scBLACK = 0,
scRED,
scGREEN,
scYELLOW,
scBLUE,
scMAGENTA,
scCYAN,
scWHITE,
scNONE = 9
};
template <typename String, typename CharT>
struct ColouredString
{
static_assert(std::is_reference<String>::value or std::is_pointer<String>::value, "String type must be pointer or reference");
ColouredString(String s, StringColour fore, StringColour back, bool bold = true)
: m_s(s)
, m_fore(fore)
, m_back(back)
, m_bold(bold)
{
}
ColouredString &operator=(const ColouredString &) = delete;
String m_s;
StringColour m_fore, m_back;
bool m_bold;
};
template <typename CharT, typename Traits>
std::basic_ostream<CharT, Traits> &operator<<(std::basic_ostream<CharT, Traits> &os, const ColouredString<const CharT *, CharT> &s)
{
if (isatty(STDOUT_FILENO))
{
std::basic_ostringstream<CharT, Traits> ostr;
ostr << "\033[" << (30 + s.m_fore) << ';' << (s.m_bold ? "1" : "22") << ';' << (40 + s.m_back) << 'm'
<< s.m_s
<< "\033[0m";
return os << ostr.str();
}
else
return os << s.m_s;
}
template <typename CharT, typename Traits, typename String>
std::basic_ostream<CharT, Traits> &operator<<(std::basic_ostream<CharT, Traits> &os, const ColouredString<String, CharT> &s)
{
if (isatty(STDOUT_FILENO))
{
std::basic_ostringstream<CharT, Traits> ostr;
ostr << "\033[" << (30 + s.m_fore) << ';' << (s.m_bold ? "1" : "22") << ';' << (40 + s.m_back) << 'm'
<< s.m_s
<< "\033[0m";
return os << ostr.str();
}
else
return os << s.m_s;
}
template <typename CharT>
inline auto coloured(const CharT *s, StringColour fore = scWHITE, StringColour back = scRED, bool bold = true)
{
return ColouredString<const CharT *, CharT>(s, fore, back, bold);
}
template <typename CharT, typename Traits, typename Alloc>
inline auto coloured(const std::basic_string<CharT, Traits, Alloc> &s, StringColour fore = scWHITE, StringColour back = scRED, bool bold = true)
{
return ColouredString<const std::basic_string<CharT, Traits, Alloc>, CharT>(s, fore, back, bold);
}
template <typename CharT, typename Traits, typename Alloc>
inline auto coloured(std::basic_string<CharT, Traits, Alloc> &s, StringColour fore = scWHITE, StringColour back = scRED, bool bold = true)
{
return ColouredString<std::basic_string<CharT, Traits, Alloc>, CharT>(s, fore, back, bold);
}
// --------------------------------------------------------------------
// A progress bar
class progress_bar
{
public:
progress_bar(int64_t inMax, const std::string &inAction);
~progress_bar();
void consumed(int64_t inConsumed); // consumed is relative
void progress(int64_t inProgress); // progress is absolute
void message(const std::string &inMessage);
private:
progress_bar(const progress_bar &) = delete;
progress_bar &operator=(const progress_bar &) = delete;
struct progress_bar_impl *m_impl;
};
// --------------------------------------------------------------------
// Resources
std::unique_ptr<std::istream> load_resource(std::filesystem::path name);
void add_file_resource(const std::string &name, std::filesystem::path dataFile);
void add_data_directory(std::filesystem::path dataDir);
} // namespace cif

243
include/cif++/validate.hpp Normal file
View File

@@ -0,0 +1,243 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2022 NKI/AVL, Netherlands Cancer Institute
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include "cif++/text.hpp"
#include <filesystem>
#include <list>
#include <mutex>
#include <utility>
namespace cif
{
struct category_validator;
// --------------------------------------------------------------------
class validation_error : public std::exception
{
public:
validation_error(const std::string &msg);
validation_error(const std::string &cat, const std::string &item,
const std::string &msg);
const char *what() const noexcept { return m_msg.c_str(); }
std::string m_msg;
};
// --------------------------------------------------------------------
enum class DDL_PrimitiveType
{
Char,
UChar,
Numb
};
DDL_PrimitiveType map_to_primitive_type(std::string_view s);
struct regex_impl;
struct type_validator
{
std::string m_name;
DDL_PrimitiveType m_primitive_type;
regex_impl *m_rx;
type_validator() = delete;
type_validator(std::string_view name, DDL_PrimitiveType type, std::string_view rx);
type_validator(const type_validator &) = delete;
type_validator(type_validator &&rhs)
: m_name(std::move(rhs.m_name))
, m_primitive_type(rhs.m_primitive_type)
{
m_rx = std::exchange(rhs.m_rx, nullptr);
}
type_validator &operator=(const type_validator &) = delete;
type_validator &operator=(type_validator &&rhs)
{
m_name = std::move(rhs.m_name);
m_primitive_type = rhs.m_primitive_type;
m_rx = std::exchange(rhs.m_rx, nullptr);
return *this;
}
~type_validator();
bool operator<(const type_validator &rhs) const
{
return icompare(m_name, rhs.m_name) < 0;
}
int compare(std::string_view a, std::string_view b) const;
};
struct item_validator
{
std::string m_tag;
bool m_mandatory;
const type_validator *m_type;
cif::iset m_enums;
std::string m_default;
bool m_default_is_null;
category_validator *m_category = nullptr;
// ItemLinked is used for non-key links
struct item_link
{
item_validator *m_parent;
std::string m_parent_item;
std::string m_child_item;
};
std::vector<item_link> mLinked;
bool operator<(const item_validator &rhs) const
{
return icompare(m_tag, rhs.m_tag) < 0;
}
bool operator==(const item_validator &rhs) const
{
return iequals(m_tag, rhs.m_tag);
}
void operator()(std::string_view value) const;
};
struct category_validator
{
std::string m_name;
std::vector<std::string> m_keys;
cif::iset m_groups;
cif::iset m_mandatory_fields;
std::set<item_validator> m_item_validators;
bool operator<(const category_validator &rhs) const
{
return icompare(m_name, rhs.m_name) < 0;
}
void addItemValidator(item_validator &&v);
const item_validator *get_validator_for_item(std::string_view tag) const;
const std::set<item_validator> &item_validators() const
{
return m_item_validators;
}
};
struct link_validator
{
int m_link_group_id;
std::string m_parent_category;
std::vector<std::string> m_parent_keys;
std::string m_child_category;
std::vector<std::string> m_child_keys;
std::string m_link_group_label;
};
// --------------------------------------------------------------------
class validator
{
public:
validator(std::string_view name)
: m_name(name)
{
}
~validator() = default;
validator(const validator &rhs) = delete;
validator &operator=(const validator &rhs) = delete;
validator(validator &&rhs) = default;
validator &operator=(validator &&rhs) = default;
friend class dictionary_parser;
void add_type_validator(type_validator &&v);
const type_validator *get_validator_for_type(std::string_view type_code) const;
void add_category_validator(category_validator &&v);
const category_validator *get_validator_for_category(std::string_view category) const;
void add_link_validator(link_validator &&v);
std::vector<const link_validator *> get_links_for_parent(std::string_view category) const;
std::vector<const link_validator *> get_links_for_child(std::string_view category) const;
void report_error(const std::string &msg, bool fatal) const;
const std::string &name() const { return m_name; }
void set_name(const std::string &name) { m_name = name; }
const std::string &version() const { return m_version; }
void version(const std::string &version) { m_version = version; }
private:
// name is fully qualified here:
item_validator *get_validator_for_item(std::string_view name) const;
std::string m_name;
std::string m_version;
bool m_strict = false;
std::set<type_validator> m_type_validators;
std::set<category_validator> m_category_validators;
std::vector<link_validator> m_link_validators;
};
// --------------------------------------------------------------------
class validator_factory
{
public:
static validator_factory &instance()
{
static validator_factory s_instance;
return s_instance;
}
const validator &operator[](std::string_view dictionary_name);
const validator &construct_validator(std::string_view name, std::istream &is);
private:
// --------------------------------------------------------------------
validator_factory() = default;
std::mutex m_mutex;
std::list<validator> m_validators;
};
} // namespace cif

View File

@@ -2,9 +2,12 @@ prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
datalibdir=@datarootdir@/libcifpp
Name: libcif++
Name: libcifpp
Description: C++ library for the manipulation of mmCIF files.
Version: @PACKAGE_VERSION@
Libs: -L${libdir} -lcif++
Cflags: -I${includedir}
Requires: zlib
Libs: -L${libdir} -lcifpp
Cflags: -I${includedir} -pthread

69
regex/CMakeLists.txt Normal file
View File

@@ -0,0 +1,69 @@
# Copyright 2018 Mike Dev
# Copyright 2019 Peter Dimov
# Distributed under the Boost Software License, Version 1.0.
# See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt
# We support CMake 3.5, but prefer 3.16 policies and behavior
cmake_minimum_required(VERSION 3.5...3.16)
project(boost_regex VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES CXX)
add_library(boost_regex INTERFACE)
add_library(Boost::regex ALIAS boost_regex)
target_include_directories(boost_regex INTERFACE include)
option(BOOST_REGEX_STANDALONE "Boost.Regex: Enable Standalone Mode (i.e. no Boost dependencies)")
if(NOT BOOST_REGEX_STANDALONE)
target_link_libraries(boost_regex
INTERFACE
Boost::config
Boost::throw_exception
Boost::predef
Boost::assert
)
else()
target_compile_definitions(boost_regex
INTERFACE BOOST_REGEX_STANDALONE
)
endif()
find_package(ICU COMPONENTS data i18n uc QUIET)
#option(BOOST_REGEX_ENABLE_ICU "Boost.Regex: enable ICU support" ${ICU_FOUND})
if(ICU_FOUND)
add_library(boost_regex_icu INTERFACE)
add_library(Boost::regex_icu ALIAS boost_regex_icu)
target_include_directories(boost_regex_icu INTERFACE include)
if(NOT BOOST_REGEX_STANDALONE)
target_link_libraries(boost_regex_icu
INTERFACE
Boost::config
Boost::throw_exception
Boost::predef
Boost::assert
)
else()
target_compile_definitions(boost_regex_icu
INTERFACE BOOST_REGEX_STANDALONE
)
endif()
find_package(ICU COMPONENTS data i18n uc REQUIRED)
target_link_libraries(boost_regex_icu INTERFACE ICU::data ICU::i18n ICU::uc)
endif()

23
regex/LICENSE_1_0.txt Normal file
View File

@@ -0,0 +1,23 @@
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

47
regex/README.md Normal file
View File

@@ -0,0 +1,47 @@
Boost Regex Library
============================
The Boost Regex library provides regular expression support for C++, this library is the ancestor to std::regex and still goes beyond
and offers some advantages to, the standard version.
The full documentation is available on [boost.org](http://www.boost.org/doc/libs/release/libs/regex/index.html).
## Standalone Mode ##
This library may now be used in "standalone" mode without the rest of the Boost C++ libraries, in order to do this you must either:
* Have a C++17 compiler that supports __has_include, in this case if <boost/config.hpp> is not present then the library will automoatically enter standalone mode. Or:
* Define BOOST_REGEX_STANDALONE when building.
The main difference between the 2 modes, is that when Boost.Config is present the library will automatically configure itself around various compiler defects. In particular in order to use the library with exception support turned off, you will either need a copy of Boost.Config in your include path, or else manually define BOOST_NO_EXCEPTIONS when building.
In any event, to obtain a standalone version of this library, simply download a .zip of the "master" branch of this repository.
## Support, bugs and feature requests ##
Bugs and feature requests can be reported through the [Gitub issue tracker](https://github.com/boostorg/regex/issues)
(see [open issues](https://github.com/boostorg/regex/issues) and
[closed issues](https://github.com/boostorg/regex/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aclosed)).
You can submit your changes through a [pull request](https://github.com/boostorg/regex/pulls).
There is no mailing-list specific to Boost Regex, although you can use the general-purpose Boost [mailing-list](http://lists.boost.org/mailman/listinfo.cgi/boost-users) using the tag [regex].
## Development ##
Clone the whole boost project, which includes the individual Boost projects as submodules ([see boost+git doc](https://github.com/boostorg/boost/wiki/Getting-Started)):
git clone https://github.com/boostorg/boost
cd boost
git submodule update --init
The Boost Regex Library is located in `libs/regex/`.
### Running tests ###
First, make sure you are in `libs/regex/test`.
You can either run all the tests listed in `Jamfile.v2` or run a single test:
../../../b2 <- run all tests
../../../b2 regex_regress <- single test

View File

@@ -0,0 +1,43 @@
/*
*
* Copyright (c) 1998-2002
* John Maddock
*
* Use, modification and distribution are subject to the
* Boost Software License, Version 1.0. (See accompanying file
* LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*
*/
/*
* LOCATION: see http://www.boost.org/libs/regex for most recent version.
* FILE cregex.cpp
* VERSION see <boost/version.hpp>
* DESCRIPTION: Declares POSIX API functions
* + boost::RegEx high level wrapper.
*/
#ifndef BOOST_RE_CREGEX_HPP
#define BOOST_RE_CREGEX_HPP
#ifndef BOOST_REGEX_CONFIG_HPP
#include <boost/regex/config.hpp>
#endif
#ifdef BOOST_REGEX_CXX03
#include <boost/regex/v4/cregex.hpp>
#else
#include <boost/regex/v5/cregex.hpp>
#endif
#endif /* include guard */

100
regex/include/boost/regex.h Normal file
View File

@@ -0,0 +1,100 @@
/*
*
* Copyright (c) 1998-2000
* Dr John Maddock
*
* Use, modification and distribution are subject to the
* Boost Software License, Version 1.0. (See accompanying file
* LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*
*/
/*
* LOCATION: see http://www.boost.org/libs/regex for documentation.
* FILE regex.h
* VERSION 3.12
* DESCRIPTION: Declares POSIX API functions
*/
#ifndef BOOST_RE_REGEX_H
#define BOOST_RE_REGEX_H
#include <boost/cregex.hpp>
/*
* add using declarations to bring POSIX API functions into
* global scope, only if this is C++ (and not C).
*/
#ifdef __cplusplus
using boost::regoff_t;
using boost::regex_tA;
using boost::regmatch_t;
using boost::REG_BASIC;
using boost::REG_EXTENDED;
using boost::REG_ICASE;
using boost::REG_NOSUB;
using boost::REG_NEWLINE;
using boost::REG_NOSPEC;
using boost::REG_PEND;
using boost::REG_DUMP;
using boost::REG_NOCOLLATE;
using boost::REG_ESCAPE_IN_LISTS;
using boost::REG_NEWLINE_ALT;
using boost::REG_PERL;
using boost::REG_AWK;
using boost::REG_GREP;
using boost::REG_EGREP;
using boost::REG_ASSERT;
using boost::REG_INVARG;
using boost::REG_ATOI;
using boost::REG_ITOA;
using boost::REG_NOTBOL;
using boost::REG_NOTEOL;
using boost::REG_STARTEND;
using boost::reg_comp_flags;
using boost::reg_exec_flags;
using boost::regcompA;
using boost::regerrorA;
using boost::regexecA;
using boost::regfreeA;
#ifndef BOOST_NO_WREGEX
using boost::regcompW;
using boost::regerrorW;
using boost::regexecW;
using boost::regfreeW;
using boost::regex_tW;
#endif
using boost::REG_NOERROR;
using boost::REG_NOMATCH;
using boost::REG_BADPAT;
using boost::REG_ECOLLATE;
using boost::REG_ECTYPE;
using boost::REG_EESCAPE;
using boost::REG_ESUBREG;
using boost::REG_EBRACK;
using boost::REG_EPAREN;
using boost::REG_EBRACE;
using boost::REG_BADBR;
using boost::REG_ERANGE;
using boost::REG_ESPACE;
using boost::REG_BADRPT;
using boost::REG_EEND;
using boost::REG_ESIZE;
using boost::REG_ERPAREN;
using boost::REG_EMPTY;
using boost::REG_E_MEMORY;
using boost::REG_E_UNKNOWN;
using boost::reg_errcode_t;
#endif /* __cplusplus */
#endif /* BOOST_RE_REGEX_H */

View File

@@ -0,0 +1,41 @@
/*
*
* Copyright (c) 1998-2002
* John Maddock
*
* Use, modification and distribution are subject to the
* Boost Software License, Version 1.0. (See accompanying file
* LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*
*/
/*
* LOCATION: see http://www.boost.org/libs/regex for documentation.
* FILE regex.cpp
* VERSION see <boost/version.hpp>
* DESCRIPTION: Declares boost::basic_regex<> and associated
* functions and classes. This header is the main
* entry point for the template regex code.
*/
/* start with C compatibility API */
#ifndef BOOST_RE_REGEX_HPP
#define BOOST_RE_REGEX_HPP
#ifndef BOOST_REGEX_CONFIG_HPP
#include <boost/regex/config.hpp>
#endif
#ifdef BOOST_REGEX_CXX03
#include <boost/regex/v4/regex.hpp>
#else
#include <boost/regex/v5/regex.hpp>
#endif
#endif // include

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,480 @@
/*
*
* Copyright (c) 1998-2002
* John Maddock
*
* Use, modification and distribution are subject to the
* Boost Software License, Version 1.0. (See accompanying file
* LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*
*/
/*
* LOCATION: see http://www.boost.org for most recent version.
* FILE config.hpp
* VERSION see <boost/version.hpp>
* DESCRIPTION: regex extended config setup.
*/
#ifndef BOOST_REGEX_CONFIG_HPP
#define BOOST_REGEX_CONFIG_HPP
#if !((__cplusplus >= 201103L) || (defined(_MSC_VER) && (_MSC_VER >= 1600)) || defined(BOOST_REGEX_CXX03))
# define BOOST_REGEX_CXX03
#endif
#if defined(BOOST_REGEX_RECURSIVE) && !defined(BOOST_REGEX_CXX03)
# define BOOST_REGEX_CXX03
#endif
#if defined(__has_include)
#if !defined(BOOST_REGEX_STANDALONE) && !__has_include(<boost/version.hpp>)
#define BOOST_REGEX_STANDALONE
#endif
#endif
/*
* Borland C++ Fix/error check
* this has to go *before* we include any std lib headers:
*/
#if defined(__BORLANDC__) && !defined(__clang__)
# include <boost/regex/config/borland.hpp>
#endif
#ifndef BOOST_REGEX_STANDALONE
#include <boost/version.hpp>
#endif
/*************************************************************************
*
* Asserts:
*
*************************************************************************/
#ifdef BOOST_REGEX_STANDALONE
#include <cassert>
# define BOOST_REGEX_ASSERT(x) assert(x)
#else
#include <boost/assert.hpp>
# define BOOST_REGEX_ASSERT(x) BOOST_ASSERT(x)
#endif
/*****************************************************************************
*
* Include all the headers we need here:
*
****************************************************************************/
#ifdef __cplusplus
# ifndef BOOST_REGEX_USER_CONFIG
# define BOOST_REGEX_USER_CONFIG <boost/regex/user.hpp>
# endif
# include BOOST_REGEX_USER_CONFIG
#ifndef BOOST_REGEX_STANDALONE
# include <boost/config.hpp>
# include <boost/predef.h>
#endif
#else
/*
* C build,
* don't include <boost/config.hpp> because that may
* do C++ specific things in future...
*/
# include <stdlib.h>
# include <stddef.h>
# ifdef _MSC_VER
# define BOOST_MSVC _MSC_VER
# endif
#endif
/****************************************************************************
*
* Legacy support:
*
*******************************************************************************/
#if defined(BOOST_NO_STD_LOCALE) || defined(BOOST_NO_CXX11_HDR_MUTEX) || defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS) \
|| defined(BOOST_NO_CXX11_HDR_ATOMIC) || defined(BOOST_NO_CXX11_ALLOCATOR) || defined(BOOST_NO_CXX11_SMART_PTR) \
|| defined(BOOST_NO_CXX11_STATIC_ASSERT) || defined(BOOST_NO_NOEXCEPT)
#ifndef BOOST_REGEX_CXX03
# define BOOST_REGEX_CXX03
#endif
#endif
/*****************************************************************************
*
* Boilerplate regex config options:
*
****************************************************************************/
/* Obsolete macro, use BOOST_VERSION instead: */
#define BOOST_RE_VERSION 500
/* fix: */
#if defined(_UNICODE) && !defined(UNICODE)
#define UNICODE
#endif
#define BOOST_REGEX_JOIN(X, Y) BOOST_REGEX_DO_JOIN(X, Y)
#define BOOST_REGEX_DO_JOIN(X, Y) BOOST_REGEX_DO_JOIN2(X,Y)
#define BOOST_REGEX_DO_JOIN2(X, Y) X##Y
#ifdef BOOST_FALLTHROUGH
# define BOOST_REGEX_FALLTHROUGH BOOST_FALLTHROUGH
#else
#if defined(__clang__) && (__cplusplus >= 201103L) && defined(__has_warning)
# if __has_feature(cxx_attributes) && __has_warning("-Wimplicit-fallthrough")
# define BOOST_REGEX_FALLTHROUGH [[clang::fallthrough]]
# endif
#endif
#if !defined(BOOST_REGEX_FALLTHROUGH) && defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1800) && (__cplusplus >= 201703)
# define BOOST_REGEX_FALLTHROUGH [[fallthrough]]
#endif
#if !defined(BOOST_REGEX_FALLTHROUGH) && defined(__GNUC__) && (__GNUC__ >= 7)
# define BOOST_REGEX_FALLTHROUGH __attribute__((fallthrough))
#endif
#if !defined(BOOST_REGEX_FALLTHROUGH)
# define BOOST_REGEX_FALLTHROUGH
#endif
#endif
#ifdef BOOST_NORETURN
# define BOOST_REGEX_NORETURN BOOST_NORETURN
#else
# define BOOST_REGEX_NORETURN
#endif
/*
* Define a macro for the namespace that details are placed in, this includes the Boost
* version number to avoid mismatched header and library versions:
*/
#define BOOST_REGEX_DETAIL_NS BOOST_REGEX_JOIN(re_detail_, BOOST_RE_VERSION)
/*
* Fix for gcc prior to 3.4: std::ctype<wchar_t> doesn't allow
* masks to be combined, for example:
* std::use_facet<std::ctype<wchar_t> >.is(std::ctype_base::lower|std::ctype_base::upper, L'a');
* returns *false*.
*/
#if defined(__GLIBCPP__) && defined(BOOST_REGEX_CXX03)
# define BOOST_REGEX_BUGGY_CTYPE_FACET
#endif
/*
* If there isn't good enough wide character support then there will
* be no wide character regular expressions:
*/
#if (defined(BOOST_NO_CWCHAR) || defined(BOOST_NO_CWCTYPE) || defined(BOOST_NO_STD_WSTRING))
# if !defined(BOOST_NO_WREGEX)
# define BOOST_NO_WREGEX
# endif
#else
# if defined(__sgi) && (defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION))
/* STLPort on IRIX is misconfigured: <cwctype> does not compile
* as a temporary fix include <wctype.h> instead and prevent inclusion
* of STLPort version of <cwctype> */
# include <wctype.h>
# define __STLPORT_CWCTYPE
# define _STLP_CWCTYPE
# endif
#if defined(__cplusplus) && defined(BOOST_REGEX_CXX03)
# include <boost/regex/config/cwchar.hpp>
#endif
#endif
/*
* If Win32 support has been disabled for boost in general, then
* it is for regex in particular:
*/
#if defined(BOOST_DISABLE_WIN32) && !defined(BOOST_REGEX_NO_W32)
# define BOOST_REGEX_NO_W32
#endif
/* disable our own file-iterators and mapfiles if we can't
* support them: */
#if defined(_WIN32)
# if defined(BOOST_REGEX_NO_W32) || BOOST_PLAT_WINDOWS_RUNTIME
# define BOOST_REGEX_NO_FILEITER
# endif
#else /* defined(_WIN32) */
# if !defined(BOOST_HAS_DIRENT_H)
# define BOOST_REGEX_NO_FILEITER
# endif
#endif
/* backwards compatibitity: */
#if defined(BOOST_RE_NO_LIB)
# define BOOST_REGEX_NO_LIB
#endif
#if defined(__GNUC__) && !defined(_MSC_VER) && (defined(_WIN32) || defined(__CYGWIN__))
/* gcc on win32 has problems if you include <windows.h>
(sporadically generates bad code). */
# define BOOST_REGEX_NO_W32
#endif
#if defined(__COMO__) && !defined(BOOST_REGEX_NO_W32) && !defined(_MSC_EXTENSIONS)
# define BOOST_REGEX_NO_W32
#endif
#ifdef BOOST_REGEX_STANDALONE
# if defined(_MSC_VER) && !defined(__clang__) && !defined(__GNUC__)
# define BOOST_REGEX_MSVC _MSC_VER
#endif
#elif defined(BOOST_MSVC)
# define BOOST_REGEX_MSVC BOOST_MSVC
#endif
/*****************************************************************************
*
* Set up dll import/export options:
*
****************************************************************************/
#if (defined(BOOST_REGEX_DYN_LINK) || defined(BOOST_ALL_DYN_LINK)) && !defined(BOOST_REGEX_STATIC_LINK) && defined(BOOST_SYMBOL_IMPORT)
# if defined(BOOST_REGEX_SOURCE)
# define BOOST_REGEX_BUILD_DLL
# define BOOST_REGEX_DECL BOOST_SYMBOL_EXPORT
# else
# define BOOST_REGEX_DECL BOOST_SYMBOL_IMPORT
# endif
#else
# define BOOST_REGEX_DECL
#endif
#ifdef BOOST_REGEX_CXX03
#if !defined(BOOST_REGEX_NO_LIB) && !defined(BOOST_REGEX_SOURCE) && !defined(BOOST_ALL_NO_LIB) && defined(__cplusplus)
# define BOOST_LIB_NAME boost_regex
# if defined(BOOST_REGEX_DYN_LINK) || defined(BOOST_ALL_DYN_LINK)
# define BOOST_DYN_LINK
# endif
# ifdef BOOST_REGEX_DIAG
# define BOOST_LIB_DIAGNOSTIC
# endif
# include <boost/config/auto_link.hpp>
#endif
#endif
/*****************************************************************************
*
* Set up function call type:
*
****************************************************************************/
#if defined(_MSC_VER) && defined(_MSC_EXTENSIONS)
#if defined(_DEBUG) || defined(__MSVC_RUNTIME_CHECKS) || defined(_MANAGED) || defined(BOOST_REGEX_NO_FASTCALL)
# define BOOST_REGEX_CALL __cdecl
#else
# define BOOST_REGEX_CALL __fastcall
#endif
# define BOOST_REGEX_CCALL __cdecl
#endif
#if defined(__BORLANDC__) && !defined(BOOST_DISABLE_WIN32)
#if defined(__clang__)
# define BOOST_REGEX_CALL __cdecl
# define BOOST_REGEX_CCALL __cdecl
#else
# define BOOST_REGEX_CALL __fastcall
# define BOOST_REGEX_CCALL __stdcall
#endif
#endif
#ifndef BOOST_REGEX_CALL
# define BOOST_REGEX_CALL
#endif
#ifndef BOOST_REGEX_CCALL
#define BOOST_REGEX_CCALL
#endif
/*****************************************************************************
*
* Set up localisation model:
*
****************************************************************************/
/* backwards compatibility: */
#ifdef BOOST_RE_LOCALE_C
# define BOOST_REGEX_USE_C_LOCALE
#endif
#ifdef BOOST_RE_LOCALE_CPP
# define BOOST_REGEX_USE_CPP_LOCALE
#endif
#if defined(__CYGWIN__)
# define BOOST_REGEX_USE_C_LOCALE
#endif
/* use C++ locale when targeting windows store */
#if BOOST_PLAT_WINDOWS_RUNTIME
# define BOOST_REGEX_USE_CPP_LOCALE
# define BOOST_REGEX_NO_WIN32_LOCALE
#endif
/* Win32 defaults to native Win32 locale: */
#if defined(_WIN32) && \
!defined(BOOST_REGEX_USE_WIN32_LOCALE) && \
!defined(BOOST_REGEX_USE_C_LOCALE) && \
!defined(BOOST_REGEX_USE_CPP_LOCALE) && \
!defined(BOOST_REGEX_NO_W32) && \
!defined(BOOST_REGEX_NO_WIN32_LOCALE)
# define BOOST_REGEX_USE_WIN32_LOCALE
#endif
/* otherwise use C++ locale if supported: */
#if !defined(BOOST_REGEX_USE_WIN32_LOCALE) && !defined(BOOST_REGEX_USE_C_LOCALE) && !defined(BOOST_REGEX_USE_CPP_LOCALE) && !defined(BOOST_NO_STD_LOCALE)
# define BOOST_REGEX_USE_CPP_LOCALE
#endif
/* otherwise use C locale: */
#if !defined(BOOST_REGEX_USE_WIN32_LOCALE) && !defined(BOOST_REGEX_USE_C_LOCALE) && !defined(BOOST_REGEX_USE_CPP_LOCALE)
# define BOOST_REGEX_USE_C_LOCALE
#endif
#ifndef BOOST_REGEX_MAX_STATE_COUNT
# define BOOST_REGEX_MAX_STATE_COUNT 100000000
#endif
/*****************************************************************************
*
* Error Handling for exception free compilers:
*
****************************************************************************/
#ifdef BOOST_NO_EXCEPTIONS
/*
* If there are no exceptions then we must report critical-errors
* the only way we know how; by terminating.
*/
#include <stdexcept>
#include <string>
#include <boost/throw_exception.hpp>
# define BOOST_REGEX_NOEH_ASSERT(x)\
if(0 == (x))\
{\
std::string s("Error: critical regex++ failure in: ");\
s.append(#x);\
std::runtime_error e(s);\
boost::throw_exception(e);\
}
#else
/*
* With exceptions then error handling is taken care of and
* there is no need for these checks:
*/
# define BOOST_REGEX_NOEH_ASSERT(x)
#endif
/*****************************************************************************
*
* Stack protection under MS Windows:
*
****************************************************************************/
#if !defined(BOOST_REGEX_NO_W32) && !defined(BOOST_REGEX_V3)
# if(defined(_WIN32) || defined(_WIN64) || defined(_WINCE)) \
&& !(defined(__GNUC__) || defined(__BORLANDC__) && defined(__clang__)) \
&& !(defined(__BORLANDC__) && (__BORLANDC__ >= 0x600)) \
&& !(defined(__MWERKS__) && (__MWERKS__ <= 0x3003))
# define BOOST_REGEX_HAS_MS_STACK_GUARD
# endif
#elif defined(BOOST_REGEX_HAS_MS_STACK_GUARD)
# undef BOOST_REGEX_HAS_MS_STACK_GUARD
#endif
#if defined(__cplusplus) && defined(BOOST_REGEX_HAS_MS_STACK_GUARD)
namespace boost{
namespace BOOST_REGEX_DETAIL_NS{
BOOST_REGEX_DECL void BOOST_REGEX_CALL reset_stack_guard_page();
}
}
#endif
/*****************************************************************************
*
* Algorithm selection and configuration.
* These options are now obsolete for C++11 and later (regex v5).
*
****************************************************************************/
#if !defined(BOOST_REGEX_RECURSIVE) && !defined(BOOST_REGEX_NON_RECURSIVE)
# if defined(BOOST_REGEX_HAS_MS_STACK_GUARD) && !defined(_STLP_DEBUG) && !defined(__STL_DEBUG) && !(defined(_MSC_VER) && (_MSC_VER >= 1400)) && defined(BOOST_REGEX_CXX03)
# define BOOST_REGEX_RECURSIVE
# else
# define BOOST_REGEX_NON_RECURSIVE
# endif
#endif
#ifdef BOOST_REGEX_NON_RECURSIVE
# ifdef BOOST_REGEX_RECURSIVE
# error "Can't set both BOOST_REGEX_RECURSIVE and BOOST_REGEX_NON_RECURSIVE"
# endif
# ifndef BOOST_REGEX_BLOCKSIZE
# define BOOST_REGEX_BLOCKSIZE 4096
# endif
# if BOOST_REGEX_BLOCKSIZE < 512
# error "BOOST_REGEX_BLOCKSIZE must be at least 512"
# endif
# ifndef BOOST_REGEX_MAX_BLOCKS
# define BOOST_REGEX_MAX_BLOCKS 1024
# endif
# ifdef BOOST_REGEX_HAS_MS_STACK_GUARD
# undef BOOST_REGEX_HAS_MS_STACK_GUARD
# endif
# ifndef BOOST_REGEX_MAX_CACHE_BLOCKS
# define BOOST_REGEX_MAX_CACHE_BLOCKS 16
# endif
#endif
/*****************************************************************************
*
* Diagnostics:
*
****************************************************************************/
#ifdef BOOST_REGEX_CONFIG_INFO
BOOST_REGEX_DECL void BOOST_REGEX_CALL print_regex_library_info();
#endif
#if defined(BOOST_REGEX_DIAG)
# pragma message ("BOOST_REGEX_DECL" BOOST_STRINGIZE(=BOOST_REGEX_DECL))
# pragma message ("BOOST_REGEX_CALL" BOOST_STRINGIZE(=BOOST_REGEX_CALL))
# pragma message ("BOOST_REGEX_CCALL" BOOST_STRINGIZE(=BOOST_REGEX_CCALL))
#ifdef BOOST_REGEX_USE_C_LOCALE
# pragma message ("Using C locale in regex traits class")
#elif BOOST_REGEX_USE_CPP_LOCALE
# pragma message ("Using C++ locale in regex traits class")
#else
# pragma message ("Using Win32 locale in regex traits class")
#endif
#if defined(BOOST_REGEX_DYN_LINK) || defined(BOOST_ALL_DYN_LINK)
# pragma message ("Dynamic linking enabled")
#endif
#if defined(BOOST_REGEX_NO_LIB) || defined(BOOST_ALL_NO_LIB)
# pragma message ("Auto-linking disabled")
#endif
#ifdef BOOST_REGEX_NO_EXTERNAL_TEMPLATES
# pragma message ("Extern templates disabled")
#endif
#endif
#endif

View File

@@ -0,0 +1,72 @@
/*
*
* Copyright (c) 1998-2002
* John Maddock
*
* Use, modification and distribution are subject to the
* Boost Software License, Version 1.0. (See accompanying file
* LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*
*/
/*
* LOCATION: see http://www.boost.org for most recent version.
* FILE boost/regex/config/borland.hpp
* VERSION see <boost/version.hpp>
* DESCRIPTION: regex borland-specific config setup.
*/
#if defined(__BORLANDC__) && !defined(__clang__)
# if (__BORLANDC__ == 0x550) || (__BORLANDC__ == 0x551)
// problems with std::basic_string and dll RTL:
# if defined(_RTLDLL) && defined(_RWSTD_COMPILE_INSTANTIATE)
# ifdef BOOST_REGEX_BUILD_DLL
# error _RWSTD_COMPILE_INSTANTIATE must not be defined when building regex++ as a DLL
# else
# pragma message("Defining _RWSTD_COMPILE_INSTANTIATE when linking to the DLL version of the RTL may produce memory corruption problems in std::basic_string, as a result of separate versions of basic_string's static data in the RTL and you're exe/dll: be warned!!")
# endif
# endif
# ifndef _RTLDLL
// this is harmless for a staic link:
# define _RWSTD_COMPILE_INSTANTIATE
# endif
// external templates cause problems for some reason:
# define BOOST_REGEX_NO_EXTERNAL_TEMPLATES
# endif
# if (__BORLANDC__ <= 0x540) && !defined(BOOST_REGEX_NO_LIB) && !defined(_NO_VCL)
// C++ Builder 4 and earlier, we can't tell whether we should be using
// the VCL runtime or not, do a static link instead:
# define BOOST_REGEX_STATIC_LINK
# endif
//
// VCL support:
// if we're building a console app then there can't be any VCL (can there?)
# if !defined(__CONSOLE__) && !defined(_NO_VCL)
# define BOOST_REGEX_USE_VCL
# endif
//
// if this isn't Win32 then don't automatically select link
// libraries:
//
# ifndef _Windows
# ifndef BOOST_REGEX_NO_LIB
# define BOOST_REGEX_NO_LIB
# endif
# ifndef BOOST_REGEX_STATIC_LINK
# define BOOST_REGEX_STATIC_LINK
# endif
# endif
#if __BORLANDC__ < 0x600
//
// string workarounds:
//
#include <cstring>
#undef strcmp
#undef strcpy
#endif
#endif

View File

@@ -0,0 +1,207 @@
/*
*
* Copyright (c) 1998-2002
* John Maddock
*
* Use, modification and distribution are subject to the
* Boost Software License, Version 1.0. (See accompanying file
* LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*
*/
/*
* LOCATION: see http://www.boost.org for most recent version.
* FILE boost/regex/config/cwchar.hpp
* VERSION see <boost/version.hpp>
* DESCRIPTION: regex wide character string fixes.
*/
#ifndef BOOST_REGEX_CONFIG_CWCHAR_HPP
#define BOOST_REGEX_CONFIG_CWCHAR_HPP
#include <cwchar>
#include <cwctype>
#include <boost/config.hpp>
#if defined(__STD_RWCOMPILER_H__) || defined(_RWSTD_VER)
// apparently this is required for the RW STL on Linux:
#undef iswalnum
#undef iswalpha
#undef iswblank
#undef iswcntrl
#undef iswdigit
#undef iswgraph
#undef iswlower
#undef iswprint
#undef iswprint
#undef iswpunct
#undef iswspace
#undef iswupper
#undef iswxdigit
#undef iswctype
#undef towlower
#undef towupper
#undef towctrans
#undef wctrans
#undef wctype
#endif
namespace std{
#ifndef BOOST_NO_STDC_NAMESPACE
extern "C"{
#endif
#ifdef iswalnum
inline int (iswalnum)(wint_t i)
{ return iswalnum(i); }
#undef iswalnum
#elif defined(BOOST_NO_STDC_NAMESPACE)
using ::iswalnum;
#endif
#ifdef iswalpha
inline int (iswalpha)(wint_t i)
{ return iswalpha(i); }
#undef iswalpha
#elif defined(BOOST_NO_STDC_NAMESPACE)
using ::iswalpha;
#endif
#ifdef iswcntrl
inline int (iswcntrl)(wint_t i)
{ return iswcntrl(i); }
#undef iswcntrl
#elif defined(BOOST_NO_STDC_NAMESPACE)
using ::iswcntrl;
#endif
#ifdef iswdigit
inline int (iswdigit)(wint_t i)
{ return iswdigit(i); }
#undef iswdigit
#elif defined(BOOST_NO_STDC_NAMESPACE)
using ::iswdigit;
#endif
#ifdef iswgraph
inline int (iswgraph)(wint_t i)
{ return iswgraph(i); }
#undef iswgraph
#elif defined(BOOST_NO_STDC_NAMESPACE)
using ::iswgraph;
#endif
#ifdef iswlower
inline int (iswlower)(wint_t i)
{ return iswlower(i); }
#undef iswlower
#elif defined(BOOST_NO_STDC_NAMESPACE)
using ::iswlower;
#endif
#ifdef iswprint
inline int (iswprint)(wint_t i)
{ return iswprint(i); }
#undef iswprint
#elif defined(BOOST_NO_STDC_NAMESPACE)
using ::iswprint;
#endif
#ifdef iswpunct
inline int (iswpunct)(wint_t i)
{ return iswpunct(i); }
#undef iswpunct
#elif defined(BOOST_NO_STDC_NAMESPACE)
using ::iswpunct;
#endif
#ifdef iswspace
inline int (iswspace)(wint_t i)
{ return iswspace(i); }
#undef iswspace
#elif defined(BOOST_NO_STDC_NAMESPACE)
using ::iswspace;
#endif
#ifdef iswupper
inline int (iswupper)(wint_t i)
{ return iswupper(i); }
#undef iswupper
#elif defined(BOOST_NO_STDC_NAMESPACE)
using ::iswupper;
#endif
#ifdef iswxdigit
inline int (iswxdigit)(wint_t i)
{ return iswxdigit(i); }
#undef iswxdigit
#elif defined(BOOST_NO_STDC_NAMESPACE)
using ::iswxdigit;
#endif
#ifdef towlower
inline wint_t (towlower)(wint_t i)
{ return towlower(i); }
#undef towlower
#elif defined(BOOST_NO_STDC_NAMESPACE)
using ::towlower;
#endif
#ifdef towupper
inline wint_t (towupper)(wint_t i)
{ return towupper(i); }
#undef towupper
#elif defined(BOOST_NO_STDC_NAMESPACE)
using :: towupper;
#endif
#ifdef wcscmp
inline int (wcscmp)(const wchar_t *p1, const wchar_t *p2)
{ return wcscmp(p1,p2); }
#undef wcscmp
#elif defined(BOOST_NO_STDC_NAMESPACE)
using ::wcscmp;
#endif
#ifdef wcscoll
inline int (wcscoll)(const wchar_t *p1, const wchar_t *p2)
{ return wcscoll(p1,p2); }
#undef wcscoll
#elif defined(BOOST_NO_STDC_NAMESPACE) && !defined(UNDER_CE)
using ::wcscoll;
#endif
#ifdef wcscpy
inline wchar_t *(wcscpy)(wchar_t *p1, const wchar_t *p2)
{ return wcscpy(p1,p2); }
#undef wcscpy
#elif defined(BOOST_NO_STDC_NAMESPACE)
using ::wcscpy;
#endif
#ifdef wcslen
inline size_t (wcslen)(const wchar_t *p)
{ return wcslen(p); }
#undef wcslen
#elif defined(BOOST_NO_STDC_NAMESPACE)
using ::wcslen;
#endif
#ifdef wcsxfrm
size_t wcsxfrm(wchar_t *p1, const wchar_t *p2, size_t s)
{ return wcsxfrm(p1,p2,s); }
#undef wcsxfrm
#elif defined(BOOST_NO_STDC_NAMESPACE)
using ::wcsxfrm;
#endif
#ifndef BOOST_NO_STDC_NAMESPACE
} // extern "C"
#endif
} // namespace std
#endif

View File

@@ -0,0 +1,30 @@
/*
*
* Copyright (c) 2020
* John Maddock
*
* Use, modification and distribution are subject to the
* Boost Software License, Version 1.0. (See accompanying file
* LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*
*/
/*
* LOCATION: see http://www.boost.org for most recent version.
* FILE icu.hpp
* VERSION see <boost/version.hpp>
* DESCRIPTION: Unicode regular expressions on top of the ICU Library.
*/
#ifndef BOOST_REGEX_ICU_HPP
#define BOOST_REGEX_ICU_HPP
#include <boost/regex/config.hpp>
#ifdef BOOST_REGEX_CXX03
#include <boost/regex/v4/icu.hpp>
#else
#include <boost/regex/v5/icu.hpp>
#endif
#endif

View File

@@ -0,0 +1,186 @@
/*
*
* Copyright (c) 2004
* John Maddock
*
* Use, modification and distribution are subject to the
* Boost Software License, Version 1.0. (See accompanying file
* LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*
*/
/*
* LOCATION: see http://www.boost.org for most recent version.
* FILE mfc.hpp
* VERSION see <boost/version.hpp>
* DESCRIPTION: Overloads and helpers for using MFC/ATL string types with Boost.Regex.
*/
#ifndef BOOST_REGEX_MFC_HPP
#define BOOST_REGEX_MFC_HPP
#include <atlsimpstr.h>
#include <boost/regex.hpp>
namespace boost{
//
// define the types used for TCHAR's:
typedef basic_regex<TCHAR> tregex;
typedef match_results<TCHAR const*> tmatch;
typedef regex_iterator<TCHAR const*> tregex_iterator;
typedef regex_token_iterator<TCHAR const*> tregex_token_iterator;
// Obsolete. Remove
#define SIMPLE_STRING_PARAM class B, bool b
#define SIMPLE_STRING_ARG_LIST B, b
//
// define regex creation functions:
//
template <class B, bool b>
inline basic_regex<B>
make_regex(const ATL::CSimpleStringT<B, b>& s, ::boost::regex_constants::syntax_option_type f = boost::regex_constants::normal)
{
basic_regex<B> result(s.GetString(), s.GetString() + s.GetLength(), f);
return result;
}
//
// regex_match overloads:
//
template <class B, bool b, class A, class T>
inline bool regex_match(const ATL::CSimpleStringT<B, b>& s,
match_results<const B*, A>& what,
const basic_regex<B, T>& e,
boost::regex_constants::match_flag_type f = boost::regex_constants::match_default)
{
return ::boost::regex_match(s.GetString(),
s.GetString() + s.GetLength(),
what,
e,
f);
}
template <class B, bool b, class T>
inline bool regex_match(const ATL::CSimpleStringT<B, b>& s,
const basic_regex<B, T>& e,
boost::regex_constants::match_flag_type f = boost::regex_constants::match_default)
{
return ::boost::regex_match(s.GetString(),
s.GetString() + s.GetLength(),
e,
f);
}
//
// regex_search overloads:
//
template <class B, bool b, class A, class T>
inline bool regex_search(const ATL::CSimpleStringT<B, b>& s,
match_results<const B*, A>& what,
const basic_regex<B, T>& e,
boost::regex_constants::match_flag_type f = boost::regex_constants::match_default)
{
return ::boost::regex_search(s.GetString(),
s.GetString() + s.GetLength(),
what,
e,
f);
}
template <class B, bool b, class T>
inline bool regex_search(const ATL::CSimpleStringT<B, b>& s,
const basic_regex<B, T>& e,
boost::regex_constants::match_flag_type f = boost::regex_constants::match_default)
{
return ::boost::regex_search(s.GetString(),
s.GetString() + s.GetLength(),
e,
f);
}
//
// regex_iterator creation:
//
template <class B, bool b>
inline regex_iterator<B const*>
make_regex_iterator(const ATL::CSimpleStringT<B, b>& s, const basic_regex<B>& e, ::boost::regex_constants::match_flag_type f = boost::regex_constants::match_default)
{
regex_iterator<B const*> result(s.GetString(), s.GetString() + s.GetLength(), e, f);
return result;
}
template <class B, bool b>
inline regex_token_iterator<B const*>
make_regex_token_iterator(const ATL::CSimpleStringT<B, b>& s, const basic_regex<B>& e, int sub = 0, ::boost::regex_constants::match_flag_type f = boost::regex_constants::match_default)
{
regex_token_iterator<B const*> result(s.GetString(), s.GetString() + s.GetLength(), e, sub, f);
return result;
}
template <class B, bool b>
inline regex_token_iterator<B const*>
make_regex_token_iterator(const ATL::CSimpleStringT<B, b>& s, const basic_regex<B>& e, const std::vector<int>& subs, ::boost::regex_constants::match_flag_type f = boost::regex_constants::match_default)
{
regex_token_iterator<B const*> result(s.GetString(), s.GetString() + s.GetLength(), e, subs, f);
return result;
}
template <class B, bool b, std::size_t N>
inline regex_token_iterator<B const*>
make_regex_token_iterator(const ATL::CSimpleStringT<B, b>& s, const basic_regex<B>& e, const int (& subs)[N], ::boost::regex_constants::match_flag_type f = boost::regex_constants::match_default)
{
regex_token_iterator<B const*> result(s.GetString(), s.GetString() + s.GetLength(), e, subs, f);
return result;
}
template <class OutputIterator, class BidirectionalIterator, class traits,
class B, bool b>
OutputIterator regex_replace(OutputIterator out,
BidirectionalIterator first,
BidirectionalIterator last,
const basic_regex<B, traits>& e,
const ATL::CSimpleStringT<B, b>& fmt,
match_flag_type flags = match_default)
{
return ::boost::regex_replace(out, first, last, e, fmt.GetString(), flags);
}
namespace BOOST_REGEX_DETAIL_NS{
template <class B, bool b>
class mfc_string_out_iterator
{
ATL::CSimpleStringT<B, b>* out;
public:
mfc_string_out_iterator(ATL::CSimpleStringT<B, b>& s) : out(&s) {}
mfc_string_out_iterator& operator++() { return *this; }
mfc_string_out_iterator& operator++(int) { return *this; }
mfc_string_out_iterator& operator*() { return *this; }
mfc_string_out_iterator& operator=(B v)
{
out->AppendChar(v);
return *this;
}
typedef std::ptrdiff_t difference_type;
typedef B value_type;
typedef value_type* pointer;
typedef value_type& reference;
typedef std::output_iterator_tag iterator_category;
};
}
template <class traits, class B, bool b>
ATL::CSimpleStringT<B, b> regex_replace(const ATL::CSimpleStringT<B, b>& s,
const basic_regex<B, traits>& e,
const ATL::CSimpleStringT<B, b>& fmt,
match_flag_type flags = match_default)
{
ATL::CSimpleStringT<B, b> result(s.GetManager());
BOOST_REGEX_DETAIL_NS::mfc_string_out_iterator<B, b> i(result);
regex_replace(i, s.GetString(), s.GetString() + s.GetLength(), e, fmt.GetString(), flags);
return result;
}
} // namespace boost.
#endif

View File

@@ -0,0 +1,32 @@
/*
*
* Copyright (c) 1998-2002
* John Maddock
*
* Use, modification and distribution are subject to the
* Boost Software License, Version 1.0. (See accompanying file
* LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*
*/
/*
* LOCATION: see http://www.boost.org for most recent version.
* FILE pattern_except.hpp
* VERSION see <boost/version.hpp>
* DESCRIPTION: Declares pattern-matching exception classes.
*/
#ifndef BOOST_RE_PAT_EXCEPT_HPP
#define BOOST_RE_PAT_EXCEPT_HPP
#ifndef BOOST_REGEX_CONFIG_HPP
#include <boost/regex/config.hpp>
#endif
#ifdef BOOST_REGEX_CXX03
#include <boost/regex/v4/pattern_except.hpp>
#else
#include <boost/regex/v5/pattern_except.hpp>
#endif
#endif

View File

@@ -0,0 +1,29 @@
/*
*
* Copyright (c) 2004
* John Maddock
*
* Use, modification and distribution are subject to the
* Boost Software License, Version 1.0. (See accompanying file
* LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*
*/
/*
* LOCATION: see http://www.boost.org for most recent version.
* FILE object_cache.hpp
* VERSION see <boost/version.hpp>
* DESCRIPTION: Implements a generic object cache.
*/
#ifndef BOOST_REGEX_OBJECT_CACHE_HPP
#define BOOST_REGEX_OBJECT_CACHE_HPP
#include <boost/regex/config.hpp>
#ifdef BOOST_REGEX_CXX03
#include <boost/regex/v4/object_cache.hpp>
#else
#include <boost/regex/v5/object_cache.hpp>
#endif
#endif

View File

@@ -0,0 +1,182 @@
/*
*
* Copyright (c) 2004
* John Maddock
*
* Use, modification and distribution are subject to the
* Boost Software License, Version 1.0. (See accompanying file
* LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*
*/
/*
* LOCATION: see http://www.boost.org for most recent version.
* FILE static_mutex.hpp
* VERSION see <boost/version.hpp>
* DESCRIPTION: Declares static_mutex lock type, there are three different
* implementations: POSIX pthreads, WIN32 threads, and portable,
* these are described in more detail below.
*/
#ifndef BOOST_REGEX_STATIC_MUTEX_HPP
#define BOOST_REGEX_STATIC_MUTEX_HPP
#include <boost/config.hpp>
#include <boost/regex/config.hpp> // dll import/export options.
#ifdef BOOST_HAS_PTHREADS
#include <pthread.h>
#endif
#if defined(BOOST_HAS_PTHREADS) && defined(PTHREAD_MUTEX_INITIALIZER)
//
// pthreads version:
// simple wrap around a pthread_mutex_t initialized with
// PTHREAD_MUTEX_INITIALIZER.
//
namespace boost{
class static_mutex;
#define BOOST_STATIC_MUTEX_INIT { PTHREAD_MUTEX_INITIALIZER, }
class BOOST_REGEX_DECL scoped_static_mutex_lock
{
public:
scoped_static_mutex_lock(static_mutex& mut, bool lk = true);
~scoped_static_mutex_lock();
inline bool locked()const
{
return m_have_lock;
}
inline operator void const*()const
{
return locked() ? this : 0;
}
void lock();
void unlock();
private:
static_mutex& m_mutex;
bool m_have_lock;
};
class static_mutex
{
public:
typedef scoped_static_mutex_lock scoped_lock;
pthread_mutex_t m_mutex;
};
} // namespace boost
#elif defined(BOOST_HAS_WINTHREADS)
//
// Win32 version:
// Use a 32-bit int as a lock, along with a test-and-set
// implementation using InterlockedCompareExchange.
//
#include <boost/cstdint.hpp>
namespace boost{
class BOOST_REGEX_DECL scoped_static_mutex_lock;
class static_mutex
{
public:
typedef scoped_static_mutex_lock scoped_lock;
boost::int32_t m_mutex;
};
#define BOOST_STATIC_MUTEX_INIT { 0, }
class BOOST_REGEX_DECL scoped_static_mutex_lock
{
public:
scoped_static_mutex_lock(static_mutex& mut, bool lk = true);
~scoped_static_mutex_lock();
operator void const*()const
{
return locked() ? this : 0;
}
bool locked()const
{
return m_have_lock;
}
void lock();
void unlock();
private:
static_mutex& m_mutex;
bool m_have_lock;
scoped_static_mutex_lock(const scoped_static_mutex_lock&);
scoped_static_mutex_lock& operator=(const scoped_static_mutex_lock&);
};
} // namespace
#else
//
// Portable version of a static mutex based on Boost.Thread library:
// This has to use a single mutex shared by all instances of static_mutex
// because boost::call_once doesn't alow us to pass instance information
// down to the initialisation proceedure. In fact the initialisation routine
// may need to be called more than once - but only once per instance.
//
// Since this preprocessor path is almost never taken, we hide these header
// dependencies so that build tools don't find them.
//
#define BOOST_REGEX_H1 <boost/thread/once.hpp>
#define BOOST_REGEX_H2 <boost/thread/recursive_mutex.hpp>
#define BOOST_REGEX_H3 <boost/thread/lock_types.hpp>
#include BOOST_REGEX_H1
#include BOOST_REGEX_H2
#include BOOST_REGEX_H3
#undef BOOST_REGEX_H1
#undef BOOST_REGEX_H2
#undef BOOST_REGEX_H3
namespace boost{
class BOOST_REGEX_DECL scoped_static_mutex_lock;
extern "C" BOOST_REGEX_DECL void boost_regex_free_static_mutex();
class BOOST_REGEX_DECL static_mutex
{
public:
typedef scoped_static_mutex_lock scoped_lock;
static void init();
static boost::recursive_mutex* m_pmutex;
static boost::once_flag m_once;
};
#define BOOST_STATIC_MUTEX_INIT { }
class BOOST_REGEX_DECL scoped_static_mutex_lock
{
public:
scoped_static_mutex_lock(static_mutex& mut, bool lk = true);
~scoped_static_mutex_lock();
operator void const*()const;
bool locked()const;
void lock();
void unlock();
private:
boost::unique_lock<boost::recursive_mutex>* m_plock;
bool m_have_lock;
};
inline scoped_static_mutex_lock::operator void const*()const
{
return locked() ? this : 0;
}
inline bool scoped_static_mutex_lock::locked()const
{
return m_have_lock;
}
} // namespace
#endif
#endif

View File

@@ -0,0 +1,32 @@
/*
*
* Copyright (c) 2020
* John Maddock
*
* Use, modification and distribution are subject to the
* Boost Software License, Version 1.0. (See accompanying file
* LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*
*/
/*
* LOCATION: see http://www.boost.org for most recent version.
* FILE unicode_iterator.hpp
* VERSION see <boost/version.hpp>
* DESCRIPTION: Iterator adapters for converting between different Unicode encodings.
*/
#ifndef BOOST_REGEX_PENDING_UNICODE_ITERATOR_HPP
#define BOOST_REGEX_PENDING_UNICODE_ITERATOR_HPP
#include <boost/regex/config.hpp>
#if defined(BOOST_REGEX_CXX03)
#include <boost/regex/v4/unicode_iterator.hpp>
#else
#include <boost/regex/v5/unicode_iterator.hpp>
#endif
#endif // BOOST_REGEX_PENDING_UNICODE_ITERATOR_HPP

View File

@@ -0,0 +1,39 @@
/*
*
* Copyright (c) 1998-2002
* John Maddock
*
* Use, modification and distribution are subject to the
* Boost Software License, Version 1.0. (See accompanying file
* LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*
*/
/*
* LOCATION: see http://www.boost.org for most recent version.
* FILE regex_traits.hpp
* VERSION see <boost/version.hpp>
* DESCRIPTION: Declares regular expression traits classes.
*/
#ifndef BOOST_REGEX_TRAITS_HPP
#define BOOST_REGEX_TRAITS_HPP
#ifndef BOOST_REGEX_CONFIG_HPP
# include <boost/regex/config.hpp>
#endif
# ifndef BOOST_REGEX_TRAITS_HPP_INCLUDED
#ifdef BOOST_REGEX_CXX03
# include <boost/regex/v4/regex_traits.hpp>
#else
# include <boost/regex/v5/regex_traits.hpp>
#endif
# endif
#endif // include

View File

@@ -0,0 +1,95 @@
/*
*
* Copyright (c) 1998-2002
* John Maddock
*
* Use, modification and distribution are subject to the
* Boost Software License, Version 1.0. (See accompanying file
* LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*
*/
/*
* LOCATION: see http://www.boost.org for most recent version.
* FILE user.hpp
* VERSION see <boost/version.hpp>
* DESCRIPTION: User settable options.
*/
// define if you want the regex library to use the C locale
// even on Win32:
// #define BOOST_REGEX_USE_C_LOCALE
// define this is you want the regex library to use the C++
// locale:
// #define BOOST_REGEX_USE_CPP_LOCALE
// define this if the runtime library is a dll, and you
// want BOOST_REGEX_DYN_LINK to set up dll exports/imports
// with __declspec(dllexport)/__declspec(dllimport.)
// #define BOOST_REGEX_HAS_DLL_RUNTIME
// define this if you want to dynamically link to regex,
// if the runtime library is also a dll (Probably Win32 specific,
// and has no effect unless BOOST_REGEX_HAS_DLL_RUNTIME is set):
// #define BOOST_REGEX_DYN_LINK
// define this if you don't want the lib to automatically
// select its link libraries:
// #define BOOST_REGEX_NO_LIB
// define this if templates with switch statements cause problems:
// #define BOOST_REGEX_NO_TEMPLATE_SWITCH_MERGE
// define this to disable Win32 support when available:
// #define BOOST_REGEX_NO_W32
// define this if bool is not a real type:
// #define BOOST_REGEX_NO_BOOL
// define this if no template instances are to be placed in
// the library rather than users object files:
// #define BOOST_REGEX_NO_EXTERNAL_TEMPLATES
// define this if the forward declarations in regex_fwd.hpp
// cause more problems than they are worth:
// #define BOOST_REGEX_NO_FWD
// define this if your compiler supports MS Windows structured
// exception handling.
// #define BOOST_REGEX_HAS_MS_STACK_GUARD
// define this if you want to use the recursive algorithm
// even if BOOST_REGEX_HAS_MS_STACK_GUARD is not defined.
// NOTE: OBSOLETE!!
// #define BOOST_REGEX_RECURSIVE
// define this if you want to use the non-recursive
// algorithm, even if the recursive version would be the default.
// NOTE: OBSOLETE!!
// #define BOOST_REGEX_NON_RECURSIVE
// define this if you want to set the size of the memory blocks
// used by the non-recursive algorithm.
// #define BOOST_REGEX_BLOCKSIZE 4096
// define this if you want to set the maximum number of memory blocks
// used by the non-recursive algorithm.
// #define BOOST_REGEX_MAX_BLOCKS 1024
// define this if you want to set the maximum number of memory blocks
// cached by the non-recursive algorithm: Normally this is 16, but can be
// higher if you have multiple threads all using boost.regex, or lower
// if you don't want boost.regex to cache memory.
// #define BOOST_REGEX_MAX_CACHE_BLOCKS 16
// define this if you want to be able to access extended capture
// information in your sub_match's (caution this will slow things
// down quite a bit).
// #define BOOST_REGEX_MATCH_EXTRA
// define this if you want to enable support for Unicode via ICU.
// #define BOOST_HAS_ICU
// define this if you want regex to use __cdecl calling convensions, even when __fastcall is available:
// #define BOOST_REGEX_NO_FASTCALL

View File

@@ -0,0 +1,734 @@
/*
*
* Copyright (c) 1998-2004 John Maddock
* Copyright 2011 Garmin Ltd. or its subsidiaries
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
*/
/*
* LOCATION: see http://www.boost.org/ for most recent version.
* FILE basic_regex.cpp
* VERSION see <boost/version.hpp>
* DESCRIPTION: Declares template class basic_regex.
*/
#ifndef BOOST_REGEX_V5_BASIC_REGEX_HPP
#define BOOST_REGEX_V5_BASIC_REGEX_HPP
#include <vector>
namespace boost{
#ifdef BOOST_REGEX_MSVC
#pragma warning(push)
#pragma warning(disable : 4251)
#if BOOST_REGEX_MSVC < 1700
# pragma warning(disable : 4231)
#endif
#if BOOST_REGEX_MSVC < 1600
#pragma warning(disable : 4660)
#endif
#if BOOST_REGEX_MSVC < 1910
#pragma warning(disable:4800)
#endif
#endif
namespace BOOST_REGEX_DETAIL_NS{
//
// forward declaration, we will need this one later:
//
template <class charT, class traits>
class basic_regex_parser;
template <class I>
void bubble_down_one(I first, I last)
{
if(first != last)
{
I next = last - 1;
while((next != first) && (*next < *(next-1)))
{
(next-1)->swap(*next);
--next;
}
}
}
static const int hash_value_mask = 1 << (std::numeric_limits<int>::digits - 1);
template <class Iterator>
inline int hash_value_from_capture_name(Iterator i, Iterator j)
{
std::size_t r = 0;
while (i != j)
{
r ^= *i + 0x9e3779b9 + (r << 6) + (r >> 2);
++i;
}
r %= ((std::numeric_limits<int>::max)());
return static_cast<int>(r) | hash_value_mask;
}
class named_subexpressions
{
public:
struct name
{
template <class charT>
name(const charT* i, const charT* j, int idx)
: index(idx)
{
hash = hash_value_from_capture_name(i, j);
}
name(int h, int idx)
: index(idx), hash(h)
{
}
int index;
int hash;
bool operator < (const name& other)const
{
return hash < other.hash;
}
bool operator == (const name& other)const
{
return hash == other.hash;
}
void swap(name& other)
{
std::swap(index, other.index);
std::swap(hash, other.hash);
}
};
typedef std::vector<name>::const_iterator const_iterator;
typedef std::pair<const_iterator, const_iterator> range_type;
named_subexpressions(){}
template <class charT>
void set_name(const charT* i, const charT* j, int index)
{
m_sub_names.push_back(name(i, j, index));
bubble_down_one(m_sub_names.begin(), m_sub_names.end());
}
template <class charT>
int get_id(const charT* i, const charT* j)const
{
name t(i, j, 0);
typename std::vector<name>::const_iterator pos = std::lower_bound(m_sub_names.begin(), m_sub_names.end(), t);
if((pos != m_sub_names.end()) && (*pos == t))
{
return pos->index;
}
return -1;
}
template <class charT>
range_type equal_range(const charT* i, const charT* j)const
{
name t(i, j, 0);
return std::equal_range(m_sub_names.begin(), m_sub_names.end(), t);
}
int get_id(int h)const
{
name t(h, 0);
std::vector<name>::const_iterator pos = std::lower_bound(m_sub_names.begin(), m_sub_names.end(), t);
if((pos != m_sub_names.end()) && (*pos == t))
{
return pos->index;
}
return -1;
}
range_type equal_range(int h)const
{
name t(h, 0);
return std::equal_range(m_sub_names.begin(), m_sub_names.end(), t);
}
private:
std::vector<name> m_sub_names;
};
//
// class regex_data:
// represents the data we wish to expose to the matching algorithms.
//
template <class charT, class traits>
struct regex_data : public named_subexpressions
{
typedef regex_constants::syntax_option_type flag_type;
typedef std::size_t size_type;
regex_data(const ::std::shared_ptr<
::boost::regex_traits_wrapper<traits> >& t)
: m_ptraits(t), m_flags(0), m_status(0), m_expression(0), m_expression_len(0),
m_mark_count(0), m_first_state(0), m_restart_type(0),
m_startmap{ 0 },
m_can_be_null(0), m_word_mask(0), m_has_recursions(false), m_disable_match_any(false) {}
regex_data()
: m_ptraits(new ::boost::regex_traits_wrapper<traits>()), m_flags(0), m_status(0), m_expression(0), m_expression_len(0),
m_mark_count(0), m_first_state(0), m_restart_type(0),
m_startmap{ 0 },
m_can_be_null(0), m_word_mask(0), m_has_recursions(false), m_disable_match_any(false) {}
::std::shared_ptr<
::boost::regex_traits_wrapper<traits>
> m_ptraits; // traits class instance
flag_type m_flags; // flags with which we were compiled
int m_status; // error code (0 implies OK).
const charT* m_expression; // the original expression
std::ptrdiff_t m_expression_len; // the length of the original expression
size_type m_mark_count; // the number of marked sub-expressions
BOOST_REGEX_DETAIL_NS::re_syntax_base* m_first_state; // the first state of the machine
unsigned m_restart_type; // search optimisation type
unsigned char m_startmap[1 << CHAR_BIT]; // which characters can start a match
unsigned int m_can_be_null; // whether we can match a null string
BOOST_REGEX_DETAIL_NS::raw_storage m_data; // the buffer in which our states are constructed
typename traits::char_class_type m_word_mask; // mask used to determine if a character is a word character
std::vector<
std::pair<
std::size_t, std::size_t> > m_subs; // Position of sub-expressions within the *string*.
bool m_has_recursions; // whether we have recursive expressions;
bool m_disable_match_any; // when set we need to disable the match_any flag as it causes different/buggy behaviour.
};
//
// class basic_regex_implementation
// pimpl implementation class for basic_regex.
//
template <class charT, class traits>
class basic_regex_implementation
: public regex_data<charT, traits>
{
public:
typedef regex_constants::syntax_option_type flag_type;
typedef std::ptrdiff_t difference_type;
typedef std::size_t size_type;
typedef typename traits::locale_type locale_type;
typedef const charT* const_iterator;
basic_regex_implementation(){}
basic_regex_implementation(const ::std::shared_ptr<
::boost::regex_traits_wrapper<traits> >& t)
: regex_data<charT, traits>(t) {}
void assign(const charT* arg_first,
const charT* arg_last,
flag_type f)
{
regex_data<charT, traits>* pdat = this;
basic_regex_parser<charT, traits> parser(pdat);
parser.parse(arg_first, arg_last, f);
}
locale_type imbue(locale_type l)
{
return this->m_ptraits->imbue(l);
}
locale_type getloc()const
{
return this->m_ptraits->getloc();
}
std::basic_string<charT> str()const
{
std::basic_string<charT> result;
if(this->m_status == 0)
result = std::basic_string<charT>(this->m_expression, this->m_expression_len);
return result;
}
const_iterator expression()const
{
return this->m_expression;
}
std::pair<const_iterator, const_iterator> subexpression(std::size_t n)const
{
const std::pair<std::size_t, std::size_t>& pi = this->m_subs.at(n);
std::pair<const_iterator, const_iterator> p(expression() + pi.first, expression() + pi.second);
return p;
}
//
// begin, end:
const_iterator begin()const
{
return (this->m_status ? 0 : this->m_expression);
}
const_iterator end()const
{
return (this->m_status ? 0 : this->m_expression + this->m_expression_len);
}
flag_type flags()const
{
return this->m_flags;
}
size_type size()const
{
return this->m_expression_len;
}
int status()const
{
return this->m_status;
}
size_type mark_count()const
{
return this->m_mark_count - 1;
}
const BOOST_REGEX_DETAIL_NS::re_syntax_base* get_first_state()const
{
return this->m_first_state;
}
unsigned get_restart_type()const
{
return this->m_restart_type;
}
const unsigned char* get_map()const
{
return this->m_startmap;
}
const ::boost::regex_traits_wrapper<traits>& get_traits()const
{
return *(this->m_ptraits);
}
bool can_be_null()const
{
return this->m_can_be_null;
}
const regex_data<charT, traits>& get_data()const
{
basic_regex_implementation<charT, traits> const* p = this;
return *static_cast<const regex_data<charT, traits>*>(p);
}
};
} // namespace BOOST_REGEX_DETAIL_NS
//
// class basic_regex:
// represents the compiled
// regular expression:
//
#ifdef BOOST_REGEX_NO_FWD
template <class charT, class traits = regex_traits<charT> >
#else
template <class charT, class traits >
#endif
class basic_regex : public regbase
{
public:
// typedefs:
typedef std::size_t traits_size_type;
typedef typename traits::string_type traits_string_type;
typedef charT char_type;
typedef traits traits_type;
typedef charT value_type;
typedef charT& reference;
typedef const charT& const_reference;
typedef const charT* const_iterator;
typedef const_iterator iterator;
typedef std::ptrdiff_t difference_type;
typedef std::size_t size_type;
typedef regex_constants::syntax_option_type flag_type;
// locale_type
// placeholder for actual locale type used by the
// traits class to localise *this.
typedef typename traits::locale_type locale_type;
public:
explicit basic_regex(){}
explicit basic_regex(const charT* p, flag_type f = regex_constants::normal)
{
assign(p, f);
}
basic_regex(const charT* p1, const charT* p2, flag_type f = regex_constants::normal)
{
assign(p1, p2, f);
}
basic_regex(const charT* p, size_type len, flag_type f)
{
assign(p, len, f);
}
basic_regex(const basic_regex& that)
: m_pimpl(that.m_pimpl) {}
~basic_regex(){}
basic_regex& operator=(const basic_regex& that)
{
return assign(that);
}
basic_regex& operator=(const charT* ptr)
{
return assign(ptr);
}
//
// assign:
basic_regex& assign(const basic_regex& that)
{
m_pimpl = that.m_pimpl;
return *this;
}
basic_regex& assign(const charT* p, flag_type f = regex_constants::normal)
{
return assign(p, p + traits::length(p), f);
}
basic_regex& assign(const charT* p, size_type len, flag_type f)
{
return assign(p, p + len, f);
}
private:
basic_regex& do_assign(const charT* p1,
const charT* p2,
flag_type f);
public:
basic_regex& assign(const charT* p1,
const charT* p2,
flag_type f = regex_constants::normal)
{
return do_assign(p1, p2, f);
}
template <class ST, class SA>
unsigned int set_expression(const std::basic_string<charT, ST, SA>& p, flag_type f = regex_constants::normal)
{
return set_expression(p.data(), p.data() + p.size(), f);
}
template <class ST, class SA>
explicit basic_regex(const std::basic_string<charT, ST, SA>& p, flag_type f = regex_constants::normal)
{
assign(p, f);
}
template <class InputIterator>
basic_regex(InputIterator arg_first, InputIterator arg_last, flag_type f = regex_constants::normal)
{
typedef typename traits::string_type seq_type;
seq_type a(arg_first, arg_last);
if(!a.empty())
assign(static_cast<const charT*>(&*a.begin()), static_cast<const charT*>(&*a.begin() + a.size()), f);
else
assign(static_cast<const charT*>(0), static_cast<const charT*>(0), f);
}
template <class ST, class SA>
basic_regex& operator=(const std::basic_string<charT, ST, SA>& p)
{
return assign(p.data(), p.data() + p.size(), regex_constants::normal);
}
template <class string_traits, class A>
basic_regex& assign(
const std::basic_string<charT, string_traits, A>& s,
flag_type f = regex_constants::normal)
{
return assign(s.data(), s.data() + s.size(), f);
}
template <class InputIterator>
basic_regex& assign(InputIterator arg_first,
InputIterator arg_last,
flag_type f = regex_constants::normal)
{
typedef typename traits::string_type seq_type;
seq_type a(arg_first, arg_last);
if(a.size())
{
const charT* p1 = &*a.begin();
const charT* p2 = &*a.begin() + a.size();
return assign(p1, p2, f);
}
return assign(static_cast<const charT*>(0), static_cast<const charT*>(0), f);
}
//
// locale:
locale_type imbue(locale_type l);
locale_type getloc()const
{
return m_pimpl.get() ? m_pimpl->getloc() : locale_type();
}
//
// getflags:
// retained for backwards compatibility only, "flags"
// is now the preferred name:
flag_type getflags()const
{
return flags();
}
flag_type flags()const
{
return m_pimpl.get() ? m_pimpl->flags() : 0;
}
//
// str:
std::basic_string<charT> str()const
{
return m_pimpl.get() ? m_pimpl->str() : std::basic_string<charT>();
}
//
// begin, end, subexpression:
std::pair<const_iterator, const_iterator> subexpression(std::size_t n)const
{
#ifdef BOOST_REGEX_STANDALONE
if (!m_pimpl.get())
throw std::logic_error("Can't access subexpressions in an invalid regex.");
#else
if(!m_pimpl.get())
boost::throw_exception(std::logic_error("Can't access subexpressions in an invalid regex."));
#endif
return m_pimpl->subexpression(n);
}
const_iterator begin()const
{
return (m_pimpl.get() ? m_pimpl->begin() : 0);
}
const_iterator end()const
{
return (m_pimpl.get() ? m_pimpl->end() : 0);
}
//
// swap:
void swap(basic_regex& that)throw()
{
m_pimpl.swap(that.m_pimpl);
}
//
// size:
size_type size()const
{
return (m_pimpl.get() ? m_pimpl->size() : 0);
}
//
// max_size:
size_type max_size()const
{
return UINT_MAX;
}
//
// empty:
bool empty()const
{
return (m_pimpl.get() ? 0 != m_pimpl->status() : true);
}
size_type mark_count()const
{
return (m_pimpl.get() ? m_pimpl->mark_count() : 0);
}
int status()const
{
return (m_pimpl.get() ? m_pimpl->status() : regex_constants::error_empty);
}
int compare(const basic_regex& that) const
{
if(m_pimpl.get() == that.m_pimpl.get())
return 0;
if(!m_pimpl.get())
return -1;
if(!that.m_pimpl.get())
return 1;
if(status() != that.status())
return status() - that.status();
if(flags() != that.flags())
return flags() - that.flags();
return str().compare(that.str());
}
bool operator==(const basic_regex& e)const
{
return compare(e) == 0;
}
bool operator != (const basic_regex& e)const
{
return compare(e) != 0;
}
bool operator<(const basic_regex& e)const
{
return compare(e) < 0;
}
bool operator>(const basic_regex& e)const
{
return compare(e) > 0;
}
bool operator<=(const basic_regex& e)const
{
return compare(e) <= 0;
}
bool operator>=(const basic_regex& e)const
{
return compare(e) >= 0;
}
//
// The following are deprecated as public interfaces
// but are available for compatibility with earlier versions.
const charT* expression()const
{
return (m_pimpl.get() && !m_pimpl->status() ? m_pimpl->expression() : 0);
}
unsigned int set_expression(const charT* p1, const charT* p2, flag_type f = regex_constants::normal)
{
assign(p1, p2, f | regex_constants::no_except);
return status();
}
unsigned int set_expression(const charT* p, flag_type f = regex_constants::normal)
{
assign(p, f | regex_constants::no_except);
return status();
}
unsigned int error_code()const
{
return status();
}
//
// private access methods:
//
const BOOST_REGEX_DETAIL_NS::re_syntax_base* get_first_state()const
{
BOOST_REGEX_ASSERT(0 != m_pimpl.get());
return m_pimpl->get_first_state();
}
unsigned get_restart_type()const
{
BOOST_REGEX_ASSERT(0 != m_pimpl.get());
return m_pimpl->get_restart_type();
}
const unsigned char* get_map()const
{
BOOST_REGEX_ASSERT(0 != m_pimpl.get());
return m_pimpl->get_map();
}
const ::boost::regex_traits_wrapper<traits>& get_traits()const
{
BOOST_REGEX_ASSERT(0 != m_pimpl.get());
return m_pimpl->get_traits();
}
bool can_be_null()const
{
BOOST_REGEX_ASSERT(0 != m_pimpl.get());
return m_pimpl->can_be_null();
}
const BOOST_REGEX_DETAIL_NS::regex_data<charT, traits>& get_data()const
{
BOOST_REGEX_ASSERT(0 != m_pimpl.get());
return m_pimpl->get_data();
}
std::shared_ptr<BOOST_REGEX_DETAIL_NS::named_subexpressions > get_named_subs()const
{
return m_pimpl;
}
private:
std::shared_ptr<BOOST_REGEX_DETAIL_NS::basic_regex_implementation<charT, traits> > m_pimpl;
};
//
// out of line members;
// these are the only members that mutate the basic_regex object,
// and are designed to provide the strong exception guarantee
// (in the event of a throw, the state of the object remains unchanged).
//
template <class charT, class traits>
basic_regex<charT, traits>& basic_regex<charT, traits>::do_assign(const charT* p1,
const charT* p2,
flag_type f)
{
std::shared_ptr<BOOST_REGEX_DETAIL_NS::basic_regex_implementation<charT, traits> > temp;
if(!m_pimpl.get())
{
temp = std::shared_ptr<BOOST_REGEX_DETAIL_NS::basic_regex_implementation<charT, traits> >(new BOOST_REGEX_DETAIL_NS::basic_regex_implementation<charT, traits>());
}
else
{
temp = std::shared_ptr<BOOST_REGEX_DETAIL_NS::basic_regex_implementation<charT, traits> >(new BOOST_REGEX_DETAIL_NS::basic_regex_implementation<charT, traits>(m_pimpl->m_ptraits));
}
temp->assign(p1, p2, f);
temp.swap(m_pimpl);
return *this;
}
template <class charT, class traits>
typename basic_regex<charT, traits>::locale_type basic_regex<charT, traits>::imbue(locale_type l)
{
std::shared_ptr<BOOST_REGEX_DETAIL_NS::basic_regex_implementation<charT, traits> > temp(new BOOST_REGEX_DETAIL_NS::basic_regex_implementation<charT, traits>());
locale_type result = temp->imbue(l);
temp.swap(m_pimpl);
return result;
}
//
// non-members:
//
template <class charT, class traits>
void swap(basic_regex<charT, traits>& e1, basic_regex<charT, traits>& e2)
{
e1.swap(e2);
}
template <class charT, class traits, class traits2>
std::basic_ostream<charT, traits>&
operator << (std::basic_ostream<charT, traits>& os,
const basic_regex<charT, traits2>& e)
{
return (os << e.str());
}
//
// class reg_expression:
// this is provided for backwards compatibility only,
// it is deprecated, no not use!
//
#ifdef BOOST_REGEX_NO_FWD
template <class charT, class traits = regex_traits<charT> >
#else
template <class charT, class traits >
#endif
class reg_expression : public basic_regex<charT, traits>
{
public:
typedef typename basic_regex<charT, traits>::flag_type flag_type;
typedef typename basic_regex<charT, traits>::size_type size_type;
explicit reg_expression(){}
explicit reg_expression(const charT* p, flag_type f = regex_constants::normal)
: basic_regex<charT, traits>(p, f){}
reg_expression(const charT* p1, const charT* p2, flag_type f = regex_constants::normal)
: basic_regex<charT, traits>(p1, p2, f){}
reg_expression(const charT* p, size_type len, flag_type f)
: basic_regex<charT, traits>(p, len, f){}
reg_expression(const reg_expression& that)
: basic_regex<charT, traits>(that) {}
~reg_expression(){}
reg_expression& operator=(const reg_expression& that)
{
return this->assign(that);
}
template <class ST, class SA>
explicit reg_expression(const std::basic_string<charT, ST, SA>& p, flag_type f = regex_constants::normal)
: basic_regex<charT, traits>(p, f)
{
}
template <class InputIterator>
reg_expression(InputIterator arg_first, InputIterator arg_last, flag_type f = regex_constants::normal)
: basic_regex<charT, traits>(arg_first, arg_last, f)
{
}
template <class ST, class SA>
reg_expression& operator=(const std::basic_string<charT, ST, SA>& p)
{
this->assign(p);
return *this;
}
};
#ifdef BOOST_REGEX_MSVC
#pragma warning (pop)
#endif
} // namespace boost
#endif

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More