mirror of
https://github.com/PDB-REDO/libcifpp.git
synced 2026-06-04 22:14:24 +08:00
Compare commits
1028 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9dc5d11829 | ||
|
|
8565e1b408 | ||
|
|
bfc7133786 | ||
|
|
15a49f1bb4 | ||
|
|
db1dff16fe | ||
|
|
8d7d9d3a31 | ||
|
|
078bf8a559 | ||
|
|
1f314a5e9b | ||
|
|
0adb50ac01 | ||
|
|
d91707cd06 | ||
|
|
c0e7ee4eeb | ||
|
|
c143a7223e | ||
|
|
2c951ba146 | ||
|
|
660aadcd9c | ||
|
|
91d6adb980 | ||
|
|
b79ddd55c5 | ||
|
|
0ca645c634 | ||
|
|
676c0c8dc8 | ||
|
|
5c366ad9b1 | ||
|
|
836aed6ea9 | ||
|
|
50df250415 | ||
|
|
2409fc5b7b | ||
|
|
8a1184a24c | ||
|
|
d2fbc54765 | ||
|
|
1bcb26ba75 | ||
|
|
32f4749d84 | ||
|
|
da12be879a | ||
|
|
94a38ad4e8 | ||
|
|
20ef79a172 | ||
|
|
92bf25476e | ||
|
|
b55e074dd7 | ||
|
|
7b654a837d | ||
|
|
ae9d247d22 | ||
|
|
16b7deafe8 | ||
|
|
f2cfe28458 | ||
|
|
2e8a52949e | ||
|
|
441e142767 | ||
|
|
bf9bdd2aae | ||
|
|
ce14593f0b | ||
|
|
1c02a451e1 | ||
|
|
448855a2d3 | ||
|
|
8ac8e89f2b | ||
|
|
2281f59401 | ||
|
|
4cb0673370 | ||
|
|
76c5706f7c | ||
|
|
2bf4284ff4 | ||
|
|
d9e2fc97f3 | ||
|
|
85dfdf4174 | ||
|
|
1bede3efda | ||
|
|
505f0fdd31 | ||
|
|
eed7ec3a4a | ||
|
|
fdb057e0e2 | ||
|
|
3fddd1a628 | ||
|
|
2440706b87 | ||
|
|
cf628fa95c | ||
|
|
2b0b47d20d | ||
|
|
a8abf2804f | ||
|
|
22d7757949 | ||
|
|
0b0d170c96 | ||
|
|
1e8e9adf62 | ||
|
|
0f03fc31e0 | ||
|
|
518432e0fb | ||
|
|
10ef3464ef | ||
|
|
226abbd577 | ||
|
|
8d66f42ab1 | ||
|
|
0f14d06f9a | ||
|
|
c53be78496 | ||
|
|
a38f31ce48 | ||
|
|
1258bd5047 | ||
|
|
d25cbeb14c | ||
|
|
9b60a07fb6 | ||
|
|
c0dd41ce50 | ||
|
|
4cff92bbcc | ||
|
|
9aa8a223c7 | ||
|
|
fb59adcfdd | ||
|
|
4acca8a3e3 | ||
|
|
c1030d2b08 | ||
|
|
16a185c6c0 | ||
|
|
174e818bd0 | ||
|
|
7f829bf5df | ||
|
|
71908282bb | ||
|
|
db3ae446af | ||
|
|
bc7d291307 | ||
|
|
cfd4702279 | ||
|
|
54eefb546d | ||
|
|
6af0d96a4e | ||
|
|
eb50bee4a3 | ||
|
|
b6143f3652 | ||
|
|
348aa7afb6 | ||
|
|
66912b68cc | ||
|
|
84dd218758 | ||
|
|
106ae38976 | ||
|
|
f1a52245ea | ||
|
|
cea38e5bb2 | ||
|
|
ed5aac358c | ||
|
|
5eb128251e | ||
|
|
cfa46ec954 | ||
|
|
07cc60e264 | ||
|
|
90973dc547 | ||
|
|
12e3d71b00 | ||
|
|
9addc8f873 | ||
|
|
343465cef0 | ||
|
|
bec5159415 | ||
|
|
f8da8360e6 | ||
|
|
fb2ad7b75d | ||
|
|
24aa7a70e5 | ||
|
|
5ade3d6cdd | ||
|
|
0d8e548ffc | ||
|
|
b09650812f | ||
|
|
acc9ad5c08 | ||
|
|
67b6c4bd27 | ||
|
|
7a1d3dbdfa | ||
|
|
4bf10df0c5 | ||
|
|
d84faad109 | ||
|
|
e01ace7ea4 | ||
|
|
e004e1591e | ||
|
|
4613084e1b | ||
|
|
637b795a8f | ||
|
|
4de981a3c0 | ||
|
|
15db026e27 | ||
|
|
d88d520553 | ||
|
|
46cd98ea1d | ||
|
|
d10328d891 | ||
|
|
e418a17256 | ||
|
|
627d3b9df2 | ||
|
|
ba28ade414 | ||
|
|
7c11130357 | ||
|
|
151915beea | ||
|
|
4f9aacb338 | ||
|
|
1f8e491ddc | ||
|
|
05cfa92182 | ||
|
|
e8031aeb49 | ||
|
|
85885406aa | ||
|
|
636f17d78d | ||
|
|
29559a5339 | ||
|
|
19f2fd75c9 | ||
|
|
8a60bae335 | ||
|
|
fa5ff60550 | ||
|
|
f6e0568964 | ||
|
|
fa27a11fea | ||
|
|
19706559cb | ||
|
|
0a06a0a51d | ||
|
|
b045177734 | ||
|
|
7ee5fa8765 | ||
|
|
3e690048a6 | ||
|
|
7ec3bfea9f | ||
|
|
098f3fd496 | ||
|
|
5476eef049 | ||
|
|
33c1eea9a1 | ||
|
|
d3432ed87c | ||
|
|
f05363ea93 | ||
|
|
77389c20a4 | ||
|
|
7c5f1ba85e | ||
|
|
e7c34cc15c | ||
|
|
72fd03a6b2 | ||
|
|
61f464ae4d | ||
|
|
19cdf66f10 | ||
|
|
0c036df6a8 | ||
|
|
4c1b9d83d1 | ||
|
|
b976b4657b | ||
|
|
eba04950d5 | ||
|
|
0c70df27ec | ||
|
|
d83f34722b | ||
|
|
652b6021d3 | ||
|
|
7fe9c87b6e | ||
|
|
9b2ae6d7fd | ||
|
|
8fd5b9a34b | ||
|
|
dffbf52d04 | ||
|
|
57ac5f0112 | ||
|
|
d5a71b0b24 | ||
|
|
d95b7be2e4 | ||
|
|
2f0a23f56a | ||
|
|
13b218f643 | ||
|
|
92a836ecdc | ||
|
|
c88a46f155 | ||
|
|
8882a34984 | ||
|
|
2d4a1731d9 | ||
|
|
be1e3073f1 | ||
|
|
6fe5a04cc0 | ||
|
|
426432885e | ||
|
|
9bc3381814 | ||
|
|
f3a492fd67 | ||
|
|
8cd2aa46b6 | ||
|
|
d638d634ba | ||
|
|
35196789e0 | ||
|
|
e907ce6c29 | ||
|
|
b80bc20d17 | ||
|
|
3a87eaa435 | ||
|
|
143eb57f04 | ||
|
|
6cc550bf18 | ||
|
|
7f5336661b | ||
|
|
e44539ef2c | ||
|
|
a2f5850173 | ||
|
|
283f4883f7 | ||
|
|
ce9842f671 | ||
|
|
b784433fd7 | ||
|
|
8c064e7c0a | ||
|
|
c15a8bd127 | ||
|
|
64e40e7b31 | ||
|
|
06d254e0de | ||
|
|
eaa342ca32 | ||
|
|
782f7c467b | ||
|
|
c45d02cb70 | ||
|
|
5b4c131eea | ||
|
|
bbe71af99e | ||
|
|
49912d019f | ||
|
|
d4758e09d7 | ||
|
|
f0a913cc07 | ||
|
|
8b0b8e3688 | ||
|
|
de4fc8a015 | ||
|
|
bf1e56ec53 | ||
|
|
040b4e4ff9 | ||
|
|
4666ee3145 | ||
|
|
2958c56a92 | ||
|
|
9cff8768ab | ||
|
|
cc671b8006 | ||
|
|
728abe6d0e | ||
|
|
7b8f3f2538 | ||
|
|
98db98f916 | ||
|
|
96a67b23ca | ||
|
|
2c3d7542e5 | ||
|
|
f84d83b723 | ||
|
|
b1837ba029 | ||
|
|
260438fa44 | ||
|
|
23d82beb04 | ||
|
|
19db5d736b | ||
|
|
6946c40657 | ||
|
|
bd3723ee20 | ||
|
|
1f078d4827 | ||
|
|
3c62a38667 | ||
|
|
7ffda74e3d | ||
|
|
560f6debc6 | ||
|
|
ea1ac33de8 | ||
|
|
7ea30237ae | ||
|
|
bc668487e2 | ||
|
|
1769f9864b | ||
|
|
75ffd97802 | ||
|
|
cfd5b7da0f | ||
|
|
26b7d1df26 | ||
|
|
0747929cd6 | ||
|
|
5bcfb102f4 | ||
|
|
908fb1ccea | ||
|
|
af8389baa4 | ||
|
|
24ca1017cd | ||
|
|
85c21aeb01 | ||
|
|
2f249048d9 | ||
|
|
974cb40ab3 | ||
|
|
c01c16ea60 | ||
|
|
bd157c249c | ||
|
|
b0ac33c1b1 | ||
|
|
82e73a9525 | ||
|
|
adc316d671 | ||
|
|
6a0b6b99ac | ||
|
|
08dd9dd5b4 | ||
|
|
557a1c2d00 | ||
|
|
f77bbfedda | ||
|
|
3aa3fe19e2 | ||
|
|
35fcc0493e | ||
|
|
9485bec2fa | ||
|
|
4b759e731c | ||
|
|
7dd6a8a1aa | ||
|
|
96725ae8b9 | ||
|
|
b3a0ded9a8 | ||
|
|
184c491803 | ||
|
|
f944b3ce00 | ||
|
|
2557f41863 | ||
|
|
2b92cee3f7 | ||
|
|
8071768579 | ||
|
|
71c8541b68 | ||
|
|
3d66c77188 | ||
|
|
8701512961 | ||
|
|
b317c780ba | ||
|
|
681aa3bf8b | ||
|
|
a68e053471 | ||
|
|
25a90e3b32 | ||
|
|
2f62759dfe | ||
|
|
cf9ec46ab8 | ||
|
|
ecbef51b10 | ||
|
|
dfff8c9587 | ||
|
|
cc5d52bbf9 | ||
|
|
a9e9f86c93 | ||
|
|
a2c52713b2 | ||
|
|
545aca88d8 | ||
|
|
ac27248784 | ||
|
|
5758bfbaea | ||
|
|
8d3a079774 | ||
|
|
718c138510 | ||
|
|
29aac70e67 | ||
|
|
700575adfe | ||
|
|
9fe6e5df85 | ||
|
|
ce7434a463 | ||
|
|
ad7d876d07 | ||
|
|
0dc19e86fa | ||
|
|
a12acaa5c7 | ||
|
|
ff62efe720 | ||
|
|
2407877184 | ||
|
|
5fde050738 | ||
|
|
a855f88073 | ||
|
|
cfa2acd61d | ||
|
|
d9db2fe2e7 | ||
|
|
15d62cd3b6 | ||
|
|
19a89aeb7e | ||
|
|
677c61c32f | ||
|
|
4dd4f66397 | ||
|
|
04b7828abc | ||
|
|
9c621ecab8 | ||
|
|
ab9c4d9416 | ||
|
|
e5eb62255a | ||
|
|
98ff79432b | ||
|
|
24fa80ba2a | ||
|
|
3999d792ef | ||
|
|
4db3732749 | ||
|
|
07131e8b40 | ||
|
|
39b91e74c9 | ||
|
|
d4bb7ec3bc | ||
|
|
6175b7e359 | ||
|
|
10442d506a | ||
|
|
573a695c3d | ||
|
|
a76bef0d01 | ||
|
|
e20111b566 | ||
|
|
4a1d9c8f75 | ||
|
|
26c86282e3 | ||
|
|
0eaeb1650d | ||
|
|
f4a6533f6b | ||
|
|
df1b6a13e1 | ||
|
|
e8f24f617c | ||
|
|
9454fdc217 | ||
|
|
22543d8fe5 | ||
|
|
60d1dc82e6 | ||
|
|
87486f87ef | ||
|
|
80e7da0f13 | ||
|
|
3745beae66 | ||
|
|
3965840bfa | ||
|
|
a88c6f3d32 | ||
|
|
ed6c6f0026 | ||
|
|
bdda9d72b5 | ||
|
|
fd080e778e | ||
|
|
9f72df2ecd | ||
|
|
617db012f0 | ||
|
|
9d15541237 | ||
|
|
35c99564c6 | ||
|
|
1d8fe334d6 | ||
|
|
d86bb314ac | ||
|
|
0ef8eb59f8 | ||
|
|
b5fe4a9a87 | ||
|
|
11fea31b98 | ||
|
|
f629275ed5 | ||
|
|
a5f6166469 | ||
|
|
501050e591 | ||
|
|
e1b240b2b2 | ||
|
|
3d79278ed7 | ||
|
|
5e0b197a43 | ||
|
|
9c4170d9e2 | ||
|
|
af721eb196 | ||
|
|
788e315f5e | ||
|
|
4a82a8d5a8 | ||
|
|
11019a26f8 | ||
|
|
6f8909dce9 | ||
|
|
5525103aaf | ||
|
|
291ef737b1 | ||
|
|
af125bdd57 | ||
|
|
79089bbb8c | ||
|
|
1f08498d00 | ||
|
|
49ba714a03 | ||
|
|
85fd9296b2 | ||
|
|
1cda14867f | ||
|
|
2d2b26f7dc | ||
|
|
93b33af44a | ||
|
|
eb80490bcd | ||
|
|
ba2b06f5af | ||
|
|
fecc762db1 | ||
|
|
1e406253ab | ||
|
|
6e3b85f43d | ||
|
|
58f1b626e2 | ||
|
|
c104a08e16 | ||
|
|
dd0f6ca1e6 | ||
|
|
f02ea91b51 | ||
|
|
6768a501a3 | ||
|
|
879e15c759 | ||
|
|
89285b4abc | ||
|
|
c584714f91 | ||
|
|
f5016403b7 | ||
|
|
c8f66ae6bb | ||
|
|
858c967e71 | ||
|
|
f9ca5de5bf | ||
|
|
252c3476a1 | ||
|
|
19210df6db | ||
|
|
15c5730749 | ||
|
|
3764adb7ef | ||
|
|
9160adb1cf | ||
|
|
3ebf4338ab | ||
|
|
2eb4b7b39b | ||
|
|
c241e49b48 | ||
|
|
238c881132 | ||
|
|
49dc733536 | ||
|
|
755bd78f60 | ||
|
|
77f80cd51f | ||
|
|
3df6000635 | ||
|
|
5efee2b40d | ||
|
|
f3c2e59184 | ||
|
|
24ab660e6e | ||
|
|
6c0a418068 | ||
|
|
07a180991e | ||
|
|
4732004b67 | ||
|
|
faa9cd0431 | ||
|
|
e0c3c2394d | ||
|
|
2dec584f54 | ||
|
|
5ab2ccae40 | ||
|
|
1017d08626 | ||
|
|
32b1bbd943 | ||
|
|
1abf31ffa5 | ||
|
|
aec60829d2 | ||
|
|
888c3c38c2 | ||
|
|
e2c4648037 | ||
|
|
f7b98c0530 | ||
|
|
d4bd3faa16 | ||
|
|
c4f3b1cd7b | ||
|
|
74add69a83 | ||
|
|
a490b19d24 | ||
|
|
44cfa2c1a2 | ||
|
|
6dd9522b3f | ||
|
|
5e352cb8e4 | ||
|
|
2fad7315b8 | ||
|
|
520759dfe8 | ||
|
|
577b44ae11 | ||
|
|
66f742d6c0 | ||
|
|
7ba9f688c7 | ||
|
|
883f0307a2 | ||
|
|
c9719f873f | ||
|
|
123d25f853 | ||
|
|
56da42db84 | ||
|
|
7f820449ca | ||
|
|
ecb2cf5f11 | ||
|
|
7f27da9b3b | ||
|
|
01eb499c69 | ||
|
|
1ff6f70682 | ||
|
|
ddde996e10 | ||
|
|
1c9212c7e0 | ||
|
|
a568143991 | ||
|
|
2b6f1bd9ee | ||
|
|
2527aa5ea6 | ||
|
|
4c28091ecd | ||
|
|
d49725423e | ||
|
|
fcb4dc61b5 | ||
|
|
b7330c074f | ||
|
|
e8f4123030 | ||
|
|
975057c4c4 | ||
|
|
a0e01668d1 | ||
|
|
2c77491416 | ||
|
|
be19e4a9cb | ||
|
|
61ce91a9d7 | ||
|
|
18f1d07e85 | ||
|
|
b596976194 | ||
|
|
1f6b86d516 | ||
|
|
31499b977d | ||
|
|
f83850e380 | ||
|
|
1a4ccd86fe | ||
|
|
5c3c6fec09 | ||
|
|
f97e742daa | ||
|
|
7f39d401e2 | ||
|
|
af412c284d | ||
|
|
874cd3bae5 | ||
|
|
ea28ebdd13 | ||
|
|
3ba468933f | ||
|
|
45f33e4bea | ||
|
|
021487ed16 | ||
|
|
cb3443ffb1 | ||
|
|
6b2c9dc3e3 | ||
|
|
7513cc1947 | ||
|
|
c98b8ae5c9 | ||
|
|
ab2dd4b75f | ||
|
|
be77316545 | ||
|
|
cdfb0d9497 | ||
|
|
71f7e7c741 | ||
|
|
cff099596e | ||
|
|
e182604455 | ||
|
|
45a7defb7e | ||
|
|
906f6ac1ea | ||
|
|
8d96e513bd | ||
|
|
cdefd063e2 | ||
|
|
8bbcba76cf | ||
|
|
c767e89a5d | ||
|
|
b78a603dca | ||
|
|
18088457d3 | ||
|
|
056697d901 | ||
|
|
2681cfad50 | ||
|
|
8aaa7925a3 | ||
|
|
d4f73e471b | ||
|
|
750be0c4a4 | ||
|
|
0f4a2a26fc | ||
|
|
6adb56341d | ||
|
|
4524357cd3 | ||
|
|
0b05b6f6e3 | ||
|
|
6382170157 | ||
|
|
c2eeb69dcc | ||
|
|
f32261fc59 | ||
|
|
90c967c8c6 | ||
|
|
4ac90128db | ||
|
|
3d71db1bb7 | ||
|
|
5e35ea5168 | ||
|
|
2fc88d52eb | ||
|
|
567b0f3b57 | ||
|
|
8f29386998 | ||
|
|
d2427d57d9 | ||
|
|
14a9499962 | ||
|
|
0fafb80d44 | ||
|
|
b5454f0943 | ||
|
|
b698260d73 | ||
|
|
ccdd1b74a0 | ||
|
|
298fe20a1b | ||
|
|
12a7c45452 | ||
|
|
02a28c2fd6 | ||
|
|
68e182b0bd | ||
|
|
b0ec88f469 | ||
|
|
4feee6ac22 | ||
|
|
ee8a85ec2f | ||
|
|
0245d4a881 | ||
|
|
e8f0058956 | ||
|
|
9c75dbaae0 | ||
|
|
5bd39b598e | ||
|
|
25a43abffd | ||
|
|
9a7ca022e2 | ||
|
|
46fe0d7caf | ||
|
|
0371cec415 | ||
|
|
2b1020cbb9 | ||
|
|
8c3ce2a87d | ||
|
|
d633622e27 | ||
|
|
19b652f615 | ||
|
|
37f7dd0631 | ||
|
|
4c99710fb3 | ||
|
|
59865cdb44 | ||
|
|
c3434507da | ||
|
|
79ecf20b85 | ||
|
|
1de9681bb7 | ||
|
|
345c4778e6 | ||
|
|
0ccb2f88ca | ||
|
|
f7bef8b0e9 | ||
|
|
9da8608f8f | ||
|
|
496cb0b909 | ||
|
|
583cafa91e | ||
|
|
01da665243 | ||
|
|
e900cd1e3d | ||
|
|
a8a838b33e | ||
|
|
072be25335 | ||
|
|
5f50429cdb | ||
|
|
db3fb04172 | ||
|
|
839385c3fb | ||
|
|
d508b7b2df | ||
|
|
b1456b87c0 | ||
|
|
58d2dcaef2 | ||
|
|
a9468d1cbb | ||
|
|
a29e3e8da3 | ||
|
|
dd5df1bb2a | ||
|
|
d5d6f3a7b3 | ||
|
|
9d2f2b3026 | ||
|
|
74717a3047 | ||
|
|
c13ee92f1e | ||
|
|
0ca04bed4f | ||
|
|
89850de660 | ||
|
|
8bb4ebd897 | ||
|
|
6a67208d24 | ||
|
|
139f32c3e8 | ||
|
|
81c0d01944 | ||
|
|
1d2f997efb | ||
|
|
f126b1dac3 | ||
|
|
bbc38262ce | ||
|
|
caeafd3189 | ||
|
|
98e3c47cdf | ||
|
|
390b230cac | ||
|
|
c5c3950c91 | ||
|
|
2aea0b3b1f | ||
|
|
6b16e02b34 | ||
|
|
bb2f81318a | ||
|
|
ec91d0fb22 | ||
|
|
760e23693e | ||
|
|
cfba00ae46 | ||
|
|
dc1cfb60ff | ||
|
|
92148304ee | ||
|
|
9329c0c0f6 | ||
|
|
de3ac001fc | ||
|
|
b1047154a4 | ||
|
|
c361af3792 | ||
|
|
73487fc24b | ||
|
|
73513fd700 | ||
|
|
6b7723eb2a | ||
|
|
7056c15366 | ||
|
|
8539e050ae | ||
|
|
5d4c2641f6 | ||
|
|
bc32071576 | ||
|
|
3b2c57314f | ||
|
|
36351a0608 | ||
|
|
047b454c1d | ||
|
|
3f5e620102 | ||
|
|
851a43ba4b | ||
|
|
47ae50f704 | ||
|
|
33bdd6ae82 | ||
|
|
433021727e | ||
|
|
7f23c84287 | ||
|
|
74bd2585e7 | ||
|
|
ebb27638ff | ||
|
|
3eb7e4c5bf | ||
|
|
112f859b19 | ||
|
|
fd08678ff6 | ||
|
|
2e2fc11fe1 | ||
|
|
d44ed57cf9 | ||
|
|
aa31acb056 | ||
|
|
232003cb2e | ||
|
|
db21dd1659 | ||
|
|
2f3279a5ff | ||
|
|
ab21317156 | ||
|
|
43cb312225 | ||
|
|
ce28cb7a48 | ||
|
|
1e47fa557c | ||
|
|
1ae3cf7b99 | ||
|
|
915d6504a2 | ||
|
|
5e63ca7a82 | ||
|
|
e0777e74c2 | ||
|
|
cf465134fd | ||
|
|
873ac70d18 | ||
|
|
9ca3c50c83 | ||
|
|
cc1c7c39b1 | ||
|
|
2c6222984d | ||
|
|
58d7e17165 | ||
|
|
57618095bf | ||
|
|
492a1ad8ec | ||
|
|
71da0ce345 | ||
|
|
7dc574b534 | ||
|
|
ff8a7a1bfd | ||
|
|
0f963eeab1 | ||
|
|
8f02665e6d | ||
|
|
8604c3ab03 | ||
|
|
7a61129388 | ||
|
|
516db3d8be | ||
|
|
34bdc5056a | ||
|
|
9402fd5cf3 | ||
|
|
a6faa5ce0c | ||
|
|
5735a70e47 | ||
|
|
8f997658d7 | ||
|
|
5069316326 | ||
|
|
143f17fb2a | ||
|
|
900d7fa07a | ||
|
|
a4389542fd | ||
|
|
b7f4e40917 | ||
|
|
a0447ba91c | ||
|
|
17c9d208ad | ||
|
|
e89311fcff | ||
|
|
bab750fa6c | ||
|
|
0caaf23767 | ||
|
|
c5676f1dfb | ||
|
|
86854581f8 | ||
|
|
ef81944826 | ||
|
|
b3b53ebcc0 | ||
|
|
3bc0384100 | ||
|
|
24b1c2ae58 | ||
|
|
c996bfcfaf | ||
|
|
3814635aa0 | ||
|
|
2b6c09cfad | ||
|
|
9ee474081e | ||
|
|
5bab298f74 | ||
|
|
fd42b7f443 | ||
|
|
edcea220f6 | ||
|
|
a92e85f8db | ||
|
|
6fbe8bb192 | ||
|
|
5f45fd9b5b | ||
|
|
46925331c7 | ||
|
|
84123df996 | ||
|
|
641b446195 | ||
|
|
34bbf06793 | ||
|
|
53a88e236b | ||
|
|
c2069a12b4 | ||
|
|
791ab245ca | ||
|
|
43287736bb | ||
|
|
34ee3321d8 | ||
|
|
6e433ae784 | ||
|
|
cd370275da | ||
|
|
7ed0f4c8ae | ||
|
|
ea7d8ce766 | ||
|
|
f12e877251 | ||
|
|
57ce90ce7c | ||
|
|
b61321e360 | ||
|
|
6416056958 | ||
|
|
4fdfd03c04 | ||
|
|
a1d2438341 | ||
|
|
952aa15d6e | ||
|
|
b3e45eb0b6 | ||
|
|
a548b39677 | ||
|
|
d5d96c58e4 | ||
|
|
9b61a06ef1 | ||
|
|
3dbf19ac0b | ||
|
|
7dc999ef39 | ||
|
|
697028b706 | ||
|
|
c260fccdb5 | ||
|
|
d9bf7c941b | ||
|
|
af64151c60 | ||
|
|
da94d65c6b | ||
|
|
d51340000f | ||
|
|
6f93fa3758 | ||
|
|
598f953cc1 | ||
|
|
c39304281d | ||
|
|
5e5e5c21ed | ||
|
|
299e270594 | ||
|
|
bd8a4e3639 | ||
|
|
b3b5d05bfc | ||
|
|
268cefcb51 | ||
|
|
f4e860bc2c | ||
|
|
b65aa46daa | ||
|
|
faef95a84d | ||
|
|
25dfdd2ff6 | ||
|
|
88879a5de9 | ||
|
|
52919f96a7 | ||
|
|
402505098a | ||
|
|
e8d8b8be60 | ||
|
|
5ff7d01bd2 | ||
|
|
3f8849680b | ||
|
|
e450fee020 | ||
|
|
d7c162c71c | ||
|
|
f211fa4b5e | ||
|
|
c3963bc453 | ||
|
|
23bd51ac9c | ||
|
|
9e200b947e | ||
|
|
2e661d5ff4 | ||
|
|
766d5a4d7e | ||
|
|
1f24937e65 | ||
|
|
aba35c3440 | ||
|
|
3a8fd0ebb1 | ||
|
|
69a2d53277 | ||
|
|
0b66d67ef3 | ||
|
|
1f22326db6 | ||
|
|
b4dfdb5515 | ||
|
|
25512340c8 | ||
|
|
d2d322ba30 | ||
|
|
96a26eae4a | ||
|
|
71a46cd10e | ||
|
|
013af6af46 | ||
|
|
1d79a9e915 | ||
|
|
28b4deaf32 | ||
|
|
694d93f50b | ||
|
|
8fed9a1302 | ||
|
|
4fa2d84374 | ||
|
|
0e43b81c34 | ||
|
|
eaf38e6353 | ||
|
|
4012a71f6c | ||
|
|
5a71dbecdc | ||
|
|
6675768ab4 | ||
|
|
63256f09ad | ||
|
|
be54866ca4 | ||
|
|
7329009fff | ||
|
|
bb5d72a40e | ||
|
|
85d68b93eb | ||
|
|
360d970033 | ||
|
|
87d87fe5b0 | ||
|
|
bdfde18728 | ||
|
|
1d0b2b8c6e | ||
|
|
7e91ae334f | ||
|
|
515d16fe79 | ||
|
|
896a8ebbdc | ||
|
|
ae23938aa4 | ||
|
|
4db05c20ae | ||
|
|
8bb0663313 | ||
|
|
83b2c651f1 | ||
|
|
e65a782f45 | ||
|
|
43f418ae67 | ||
|
|
4b4757ee74 | ||
|
|
ac088dd0a4 | ||
|
|
31c86d9c8a | ||
|
|
85b08f9d77 | ||
|
|
d50529c6b9 | ||
|
|
bb9d81616b | ||
|
|
024607002e | ||
|
|
31ce161543 | ||
|
|
359538e170 | ||
|
|
d45ce5060d | ||
|
|
6aebf8408f | ||
|
|
5ce8d87b19 | ||
|
|
f815b8588a | ||
|
|
e812e2e092 | ||
|
|
43eda65dd8 | ||
|
|
3a94384775 | ||
|
|
7c5bf01090 | ||
|
|
3f421f34a2 | ||
|
|
c7f67525ec | ||
|
|
71a78813e1 | ||
|
|
62face74ee | ||
|
|
1cbfbd8f4f | ||
|
|
3928be4939 | ||
|
|
a967154625 | ||
|
|
78dd9a3c02 | ||
|
|
52d6b2eace | ||
|
|
2ef9e6b843 | ||
|
|
48d9d22d70 | ||
|
|
a3d9bc01a0 | ||
|
|
52ea0bc7fc | ||
|
|
ba804abb34 | ||
|
|
6835a9808b | ||
|
|
77fc4080c5 | ||
|
|
599d0cb537 | ||
|
|
59a7ff68e0 | ||
|
|
80bb24f347 | ||
|
|
34c7fd3f54 | ||
|
|
fac1eb915a | ||
|
|
3a84a8e6e8 | ||
|
|
dd02b3633d | ||
|
|
54728d49be | ||
|
|
2afddc23ff | ||
|
|
700c1d408d | ||
|
|
e3297d0de6 | ||
|
|
e4ced4caef | ||
|
|
14e32bed28 | ||
|
|
a3cf3343c9 | ||
|
|
188fa4e59c | ||
|
|
d053492a7c | ||
|
|
8d9f4f007b | ||
|
|
5084e7185a | ||
|
|
11b4c1d399 | ||
|
|
a56b6b136d | ||
|
|
b6e8f79c1a | ||
|
|
eda40b8eb6 | ||
|
|
c0c4be78f2 | ||
|
|
513dbb6bfd | ||
|
|
77e0b3f776 | ||
|
|
a7249eb2ca | ||
|
|
51aebf844a | ||
|
|
38121e20f5 | ||
|
|
dbd826867f | ||
|
|
fe519e71a5 | ||
|
|
072882e005 | ||
|
|
3ab625cb2b | ||
|
|
2583975afd | ||
|
|
9ec0eae41f | ||
|
|
f2449abb79 | ||
|
|
4a5312a648 | ||
|
|
9c636544b3 | ||
|
|
19714ecb0b | ||
|
|
9fbd41aef9 | ||
|
|
c432ac4d7c | ||
|
|
267302429c | ||
|
|
db164a2045 | ||
|
|
9b1e935628 | ||
|
|
f1dfe12c24 | ||
|
|
0bdda4610a | ||
|
|
530d1110d9 | ||
|
|
d170c8da78 | ||
|
|
fe6d7a11ca | ||
|
|
6082b11959 | ||
|
|
01dbe675c8 | ||
|
|
a825cfc687 | ||
|
|
9f81a4ef89 | ||
|
|
c9f37c74b4 | ||
|
|
ffd82dfee0 | ||
|
|
6ef927cfa1 | ||
|
|
13a38fd011 | ||
|
|
f90990507a | ||
|
|
55b1c56647 | ||
|
|
1c009d481d | ||
|
|
42c72958a8 | ||
|
|
13109f767a | ||
|
|
72e6708076 | ||
|
|
aaf25de2d0 | ||
|
|
0cbb927b0f | ||
|
|
59f2387b68 | ||
|
|
6d07611e49 | ||
|
|
f7b12dedc0 | ||
|
|
2cce9e5379 | ||
|
|
5e1fe8211a | ||
|
|
29ebdcf7d2 | ||
|
|
4206f26699 | ||
|
|
dd7a4f1189 | ||
|
|
d1b3f08d5b | ||
|
|
9a7aeed632 | ||
|
|
963d51bbcb | ||
|
|
ef7a6f8f9d | ||
|
|
85aed9fb40 | ||
|
|
603a0eca6b | ||
|
|
cccbfe025d | ||
|
|
778fa86410 | ||
|
|
b4da5aeda3 | ||
|
|
4ddfe65734 | ||
|
|
95d0d55715 | ||
|
|
ec09e7ba57 | ||
|
|
74750a7940 | ||
|
|
0de2ae3673 | ||
|
|
a236547a54 | ||
|
|
8f12d15439 | ||
|
|
535ea566de | ||
|
|
e095d3bf67 | ||
|
|
bb0562ebc1 | ||
|
|
ec4ea697dd | ||
|
|
4918f572b4 | ||
|
|
0119c93aa0 | ||
|
|
03c95609dd | ||
|
|
3650bc9269 | ||
|
|
25e2c38076 | ||
|
|
a265b97058 | ||
|
|
fa7a0de6db | ||
|
|
996710728a | ||
|
|
b5f159c345 | ||
|
|
958d1fb32c | ||
|
|
28620841e0 | ||
|
|
e0d2c1328c | ||
|
|
9a54b6b990 | ||
|
|
e27908b9ee | ||
|
|
63fa06d656 | ||
|
|
9856d0de35 | ||
|
|
a2a1e63e06 | ||
|
|
a83fb55961 | ||
|
|
83965b9a7f | ||
|
|
e5bd42b4c7 | ||
|
|
602c770a45 | ||
|
|
64e2793c51 | ||
|
|
51b6c7eb3f | ||
|
|
1cf8e7b72a | ||
|
|
bc50f86836 | ||
|
|
909a33c01a | ||
|
|
f66bd7fdaa | ||
|
|
7f23427272 | ||
|
|
4f2427e95c | ||
|
|
1546cedb63 | ||
|
|
d3bc435a2e | ||
|
|
4436ad4358 | ||
|
|
5af0296028 | ||
|
|
b450cdf16d | ||
|
|
f96499cdd8 | ||
|
|
274120c9fc | ||
|
|
0d50305679 | ||
|
|
6999b7a12a | ||
|
|
8118c073c4 | ||
|
|
27bda1c6a0 | ||
|
|
7927a7c0dd | ||
|
|
39ead681b0 | ||
|
|
9c05120753 | ||
|
|
91abdc568b | ||
|
|
b1a6180a67 | ||
|
|
a789367ee8 | ||
|
|
61dbb7c137 | ||
|
|
834a3a50f9 | ||
|
|
7a423aecf7 | ||
|
|
91f7f9c238 | ||
|
|
af930b23a1 | ||
|
|
8047cda02d | ||
|
|
773137e852 | ||
|
|
efd96f18b4 | ||
|
|
deeac050f9 | ||
|
|
0ab408e1b3 | ||
|
|
521fafdd32 | ||
|
|
66fa88ec88 | ||
|
|
4738d97948 | ||
|
|
cc2f705a21 | ||
|
|
3d9200f990 | ||
|
|
0af4eca14f | ||
|
|
26dc7eaa08 | ||
|
|
9b5ef7548f | ||
|
|
41b2231ee5 | ||
|
|
4a81e814c1 | ||
|
|
ef6643122f | ||
|
|
00742f65af | ||
|
|
1da97e6ebb | ||
|
|
38a852ca20 | ||
|
|
a5b64ec805 | ||
|
|
6dc402263a | ||
|
|
54b8cb5c85 | ||
|
|
8bf1f01926 | ||
|
|
791d8bd98a | ||
|
|
5b963bf62f | ||
|
|
0dc6531395 | ||
|
|
07617dcdac | ||
|
|
2a2172a9eb | ||
|
|
065ba540b2 | ||
|
|
e19fc4f7b6 | ||
|
|
db5540cfc6 | ||
|
|
8aaf0d8813 | ||
|
|
e53c77cb7f | ||
|
|
1a8d585b9c | ||
|
|
d4de02a229 | ||
|
|
b60face9af | ||
|
|
91f8ac9edd | ||
|
|
6d12375691 | ||
|
|
924d37b603 | ||
|
|
6105c1f6fd | ||
|
|
93a96960f1 | ||
|
|
53091a321a | ||
|
|
eccf6c8855 | ||
|
|
2a2fefa80d | ||
|
|
65f17a7b26 | ||
|
|
d2716b4ea2 | ||
|
|
9af1dabbe6 | ||
|
|
1e4e0638b7 | ||
|
|
724c834656 | ||
|
|
ef4120fd72 | ||
|
|
3a9688089c | ||
|
|
eb4f2f778f | ||
|
|
a793eb4c51 | ||
|
|
6f1a592cc9 | ||
|
|
1242ce1d29 | ||
|
|
7dedb46d08 | ||
|
|
0d18d47775 | ||
|
|
4664c0bbe0 | ||
|
|
4543e34c00 | ||
|
|
b85f340cc7 | ||
|
|
c73e18fc26 | ||
|
|
17034d3bff | ||
|
|
4632a41763 | ||
|
|
16492f6f5b | ||
|
|
4362fd9d6e | ||
|
|
3b44209b15 | ||
|
|
679a15b637 | ||
|
|
b4a52806e6 | ||
|
|
311961e80b | ||
|
|
0e31a9b17f | ||
|
|
d3194f8cc0 | ||
|
|
2a9bb5752a | ||
|
|
821c1ef94f | ||
|
|
ba0e39c0da | ||
|
|
371c2aa876 | ||
|
|
05ec536059 | ||
|
|
b0272a1cd5 | ||
|
|
caf80a0efe | ||
|
|
032138c4d3 | ||
|
|
e0dc9f1c95 | ||
|
|
c5d277fb43 | ||
|
|
d0b7e21c77 | ||
|
|
b1de54f8b1 | ||
|
|
141764edf5 | ||
|
|
00fe32b76f | ||
|
|
bfd74e6f01 | ||
|
|
edf132c4bd | ||
|
|
f3878b3760 | ||
|
|
6c93599687 | ||
|
|
ca881b82b5 |
10
.gitignore
vendored
Normal file
10
.gitignore
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
build/
|
||||
.vscode/
|
||||
.vs/
|
||||
tools/update-libcifpp-data
|
||||
data/components.cif*
|
||||
CMakeSettings.json
|
||||
msvc/
|
||||
src/revision.hpp
|
||||
test/test-create_sugar_?.cif
|
||||
Testing/
|
||||
499
CMakeLists.txt
Normal file
499
CMakeLists.txt
Normal file
@@ -0,0 +1,499 @@
|
||||
# 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(libcifpp VERSION 5.1.2 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(WIN32)
|
||||
if(${CMAKE_SYSTEM_VERSION} GREATER_EQUAL 10) # Windows 10
|
||||
add_definitions(-D _WIN32_WINNT=0x0A00)
|
||||
elseif(${CMAKE_SYSTEM_VERSION} EQUAL 6.3) # Windows 8.1
|
||||
add_definitions(-D _WIN32_WINNT=0x0603)
|
||||
elseif(${CMAKE_SYSTEM_VERSION} EQUAL 6.2) # Windows 8
|
||||
add_definitions(-D _WIN32_WINNT=0x0602)
|
||||
elseif(${CMAKE_SYSTEM_VERSION} EQUAL 6.1) # Windows 7
|
||||
add_definitions(-D _WIN32_WINNT=0x0601)
|
||||
elseif(${CMAKE_SYSTEM_VERSION} EQUAL 6.0) # Windows Vista
|
||||
add_definitions(-D _WIN32_WINNT=0x0600)
|
||||
else() # Windows XP (5.1)
|
||||
add_definitions(-D _WIN32_WINNT=0x0501)
|
||||
endif()
|
||||
|
||||
add_definitions(-DNOMINMAX)
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
# make msvc standards compliant...
|
||||
add_compile_options(/permissive-)
|
||||
|
||||
if(BUILD_SHARED_LIBS)
|
||||
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>DLL")
|
||||
else()
|
||||
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
|
||||
endif()
|
||||
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/ LIB_NAME "LibCIFPP")
|
||||
|
||||
# SymOp data table
|
||||
if(CIFPP_RECREATE_SYMOP_DATA)
|
||||
# The tool to create the table
|
||||
add_executable(symop-map-generator "${PROJECT_SOURCE_DIR}/src/symop-map-generator.cpp")
|
||||
|
||||
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 Eigen3::Eigen ${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()
|
||||
|
||||
file(DOWNLOAD https://ftp.wwpdb.org/pub/pdb/data/monomers/components.cif ${COMPONENTS_CIF} SHOW_PROGRESS)
|
||||
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" OR ${CMAKE_SYSTEM_NAME} STREQUAL "GNU")
|
||||
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)
|
||||
24
LICENSE
Normal file
24
LICENSE
Normal file
@@ -0,0 +1,24 @@
|
||||
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:
|
||||
|
||||
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.
|
||||
108
README.md
Normal file
108
README.md
Normal file
@@ -0,0 +1,108 @@
|
||||
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);
|
||||
}
|
||||
|
||||
// Take the first datablock in the file
|
||||
auto &db = file.front();
|
||||
|
||||
// Use the atom_site category
|
||||
auto &atom_site = db["atom_site"];
|
||||
|
||||
// Count the atoms with atom-id "OXT"
|
||||
auto n = atom_site.count(cif::key("label_atom_id") == "OXT");
|
||||
|
||||
std::cout << "File contains " << atom_site.size() << " atoms of which "
|
||||
<< n << (n == 1 ? " is" : " are") << " OXT" << std::endl
|
||||
<< "residues with an OXT are:" << std::endl;
|
||||
|
||||
// Loop over all atoms with atom-id "OXT" and print out some info.
|
||||
// That info is extracted using structured binding in C++
|
||||
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.4 and clang 9.0
|
||||
have been used as well as MSVC version 2019.
|
||||
|
||||
Other requirements are:
|
||||
|
||||
- [mrc](https://github.com/mhekkel/mrc), a resource compiler that
|
||||
allows including data files into the executable making them easier to
|
||||
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
|
||||
--------
|
||||
|
||||
This library uses [cmake](https://cmake.org). The usual way of building
|
||||
and installing is to create a `build` directory and run cmake there.
|
||||
|
||||
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.
|
||||
152
changelog
Normal file
152
changelog
Normal file
@@ -0,0 +1,152 @@
|
||||
Version 5.1.2
|
||||
- New version string code
|
||||
- Added check for Eigen3 in cifppConfig.cmake
|
||||
|
||||
Version 5.1.1
|
||||
- Added missing include <compare> in symmetry.hpp
|
||||
- Added empty() to matrix
|
||||
- Fix for parsing PDB files with a last line that does not end with
|
||||
a new line character.
|
||||
|
||||
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
62
cmake/FindAtomic.cmake
Normal 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()
|
||||
74
cmake/FindFilesystem.cmake
Normal file
74
cmake/FindFilesystem.cmake
Normal 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()
|
||||
|
||||
395
cmake/VersionString.cmake
Normal file
395
cmake/VersionString.cmake
Normal file
@@ -0,0 +1,395 @@
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
# Copyright (c) 2021-2023 Maarten L. Hekkelman
|
||||
|
||||
# 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.
|
||||
|
||||
# This cmake extension writes out a revision.hpp file in a specified directory.
|
||||
# The file will contain a C++ inline function that can be used to write out
|
||||
# version information.
|
||||
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
|
||||
# We want the revision.hpp file to be updated whenever the status of the
|
||||
# git repository changes. Use the same technique as in GetGitRevisionDescription.cmake
|
||||
# from https://github.com/rpavlik/cmake-modules
|
||||
|
||||
|
||||
#[=======================================================================[.rst:
|
||||
.. command:: write_version_header
|
||||
|
||||
Write a file named revision.hpp containing version info::
|
||||
|
||||
write_version_header(<destdir>
|
||||
[FILE_NAME <file-name>]
|
||||
[LIB_NAME <library-name>]
|
||||
)
|
||||
|
||||
This command will generate the code to write a file name
|
||||
revision.hpp in the directory ``<destdir>``.
|
||||
|
||||
``FILE_NAME``
|
||||
Specify the name of the file to create, default is ``revision.hpp``.
|
||||
|
||||
``LIB_NAME``
|
||||
Specify the library name which will be used as a prefix part for the
|
||||
variables contained in the revision file.
|
||||
#]=======================================================================]
|
||||
|
||||
# First locate a .git file or directory.
|
||||
function(_get_git_dir _start_dir _variable)
|
||||
|
||||
set(cur_dir "${_start_dir}")
|
||||
set(git_dir "${_start_dir}/.git")
|
||||
|
||||
while(NOT EXISTS "${git_dir}")
|
||||
# .git dir not found, search parent directories
|
||||
set(prev_dir "${cur_dir}")
|
||||
get_filename_component(cur_dir "${cur_dir}" DIRECTORY)
|
||||
if(cur_dir STREQUAL prev_dir OR cur_dir STREQUAL ${_start_dir})
|
||||
# we are not in git since we either hit root or
|
||||
# the ${_start_dir} which should be the top
|
||||
set(${_variable} "" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
set(git_dir "${cur_dir}/.git")
|
||||
endwhile()
|
||||
|
||||
set(${_variable} "${git_dir}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# Locate the git refspec hash and load the hash
|
||||
# This code locates the file containing the git refspec/hash
|
||||
# and loads it. Doing it this way assures that each time the git
|
||||
# repository changes the revision.hpp file gets out of date.
|
||||
function(_get_git_hash _data_dir _variable)
|
||||
|
||||
# Be pessimistic
|
||||
set(_variable "" PARENT_SCOPE)
|
||||
|
||||
# Load git package if needed
|
||||
if(NOT GIT_FOUND)
|
||||
find_package(Git QUIET)
|
||||
endif()
|
||||
|
||||
# And fail if not found
|
||||
if(NOT GIT_FOUND)
|
||||
return()
|
||||
endif()
|
||||
|
||||
# Locate the nearest .git file or directory
|
||||
_get_git_dir(${CMAKE_CURRENT_SOURCE_DIR} GIT_DIR)
|
||||
|
||||
# And fail if not found
|
||||
if("${GIT_DIR}" STREQUAL "")
|
||||
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(IS_DIRECTORY ${GIT_DIR})
|
||||
set(HEAD_SOURCE_FILE "${GIT_DIR}/HEAD")
|
||||
else()
|
||||
# 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 not 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)
|
||||
_get_git_dir("${git_worktree_dir}" GIT_DIR)
|
||||
set(HEAD_SOURCE_FILE "${git_worktree_dir}/HEAD")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Fail if the 'head' file was not found
|
||||
if(NOT EXISTS "${HEAD_SOURCE_FILE}")
|
||||
return()
|
||||
endif()
|
||||
|
||||
# Make a copy of the head file
|
||||
set(HEAD_FILE "${_data_dir}/HEAD")
|
||||
configure_file("${HEAD_SOURCE_FILE}" "${HEAD_FILE}" COPYONLY)
|
||||
|
||||
# Now we create a cmake file that will read the contents of this
|
||||
# head file in the appropriate way
|
||||
file(WRITE "${_data_dir}/grab-ref.cmake.in" [[
|
||||
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}" "@VERSION_STRING_DATA@/head-ref" COPYONLY)
|
||||
else()
|
||||
configure_file("@GIT_DIR@/packed-refs" "@VERSION_STRING_DATA@/packed-refs" COPYONLY)
|
||||
file(READ "@VERSION_STRING_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" "@VERSION_STRING_DATA@/head-ref" COPYONLY)
|
||||
endif()
|
||||
|
||||
if(NOT HEAD_HASH)
|
||||
file(READ "@VERSION_STRING_DATA@/head-ref" HEAD_HASH LIMIT 1024)
|
||||
string(STRIP "${HEAD_HASH}" HEAD_HASH)
|
||||
endif()
|
||||
]])
|
||||
|
||||
configure_file("${VERSION_STRING_DATA}/grab-ref.cmake.in"
|
||||
"${VERSION_STRING_DATA}/grab-ref.cmake" @ONLY)
|
||||
|
||||
# Include the aforementioned file, this will define
|
||||
# the HEAD_HASH variable we're looking for
|
||||
include("${VERSION_STRING_DATA}/grab-ref.cmake")
|
||||
|
||||
set(${_variable} "${HEAD_HASH}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# Create a revision file, containing the current git version info, if any
|
||||
function(write_version_header dir)
|
||||
|
||||
set(flags )
|
||||
set(options LIB_NAME FILE_NAME)
|
||||
set(sources )
|
||||
cmake_parse_arguments(VERSION_STRING_OPTION "${flags}" "${options}" "${sources}" ${ARGN})
|
||||
|
||||
# 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()
|
||||
|
||||
if(VERSION_STRING_OPTION_FILE_NAME)
|
||||
set(file_name "${VERSION_STRING_OPTION_FILE_NAME}")
|
||||
else()
|
||||
set(file_name "revision.hpp")
|
||||
endif()
|
||||
|
||||
# Where to store intermediate files
|
||||
set(VERSION_STRING_DATA "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/VersionString")
|
||||
if(NOT EXISTS "${VERSION_STRING_DATA}")
|
||||
file(MAKE_DIRECTORY "${VERSION_STRING_DATA}")
|
||||
endif()
|
||||
|
||||
# Load the git hash using the wizzard-like code above.
|
||||
_get_git_hash("${VERSION_STRING_DATA}" GIT_HASH)
|
||||
|
||||
# If git was found, fetch the git description string
|
||||
if(GIT_HASH)
|
||||
execute_process(
|
||||
COMMAND "${GIT_EXECUTABLE}" describe --dirty --match=build
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
RESULT_VARIABLE res
|
||||
OUTPUT_VARIABLE out
|
||||
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
|
||||
if(res EQUAL 0)
|
||||
set(REVISION_STRING "${out}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Check the revision string, if it matches we fill in the required info
|
||||
if(REVISION_STRING MATCHES "build-([0-9]+)-g([0-9a-f]+)(-dirty)?")
|
||||
set(BUILD_NUMBER ${CMAKE_MATCH_1})
|
||||
if(CMAKE_MATCH_3)
|
||||
set(REVISION_GIT_TAGREF "${CMAKE_MATCH_2}*")
|
||||
else()
|
||||
set(REVISION_GIT_TAGREF "${CMAKE_MATCH_2}")
|
||||
endif()
|
||||
|
||||
string(TIMESTAMP REVISION_DATE_TIME "%Y-%m-%dT%H:%M:%SZ" UTC)
|
||||
else()
|
||||
set(REVISION_GIT_TAGREF "")
|
||||
set(BUILD_NUMBER 0)
|
||||
set(REVISION_DATE_TIME "")
|
||||
endif()
|
||||
|
||||
if(VERSION_STRING_OPTION_LIB_NAME)
|
||||
set(VAR_PREFIX "${VERSION_STRING_OPTION_LIB_NAME}")
|
||||
set(IDENT_PREFIX "${VERSION_STRING_OPTION_LIB_NAME}_")
|
||||
else()
|
||||
set(VAR_PREFIX "")
|
||||
set(IDENT_PREFIX "")
|
||||
endif()
|
||||
|
||||
# And finally, write out the header file
|
||||
file(WRITE "${VERSION_STRING_DATA}/${file_name}.in" [[// This file was generated by VersionString.cmake
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ostream>
|
||||
|
||||
constexpr const char k@VAR_PREFIX@ProjectName[] = "@PROJECT_NAME@";
|
||||
constexpr const char k@VAR_PREFIX@VersionNumber[] = "@PROJECT_VERSION@";
|
||||
constexpr int k@VAR_PREFIX@BuildNumber = @BUILD_NUMBER@;
|
||||
constexpr const char k@VAR_PREFIX@RevisionGitTag[] = "@REVISION_GIT_TAGREF@";
|
||||
constexpr const char k@VAR_PREFIX@RevisionDate[] = "@REVISION_DATE_TIME@";
|
||||
|
||||
#ifndef VERSION_INFO_DEFINED
|
||||
#define VERSION_INFO_DEFINED 1
|
||||
|
||||
namespace version_info_v1
|
||||
{
|
||||
|
||||
class version_info_base
|
||||
{
|
||||
public:
|
||||
|
||||
static void write(std::ostream &os, bool verbose)
|
||||
{
|
||||
auto &s_head = head();
|
||||
if (s_head != nullptr)
|
||||
write(s_head, os, verbose);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
version_info_base(const char *name, const char *version, int build_number, const char *git_tag, const char *revision_date)
|
||||
: m_name(name)
|
||||
, m_version(version)
|
||||
, m_build_number(build_number)
|
||||
, m_git_tag(git_tag)
|
||||
, m_revision_date(revision_date)
|
||||
{
|
||||
auto &s_head = head();
|
||||
m_next = s_head;
|
||||
s_head = this;
|
||||
}
|
||||
|
||||
static void write(const version_info_base *inst, std::ostream &os, bool verbose)
|
||||
{
|
||||
if (inst->m_next)
|
||||
{
|
||||
write(inst->m_next, os, verbose);
|
||||
|
||||
if (not verbose)
|
||||
return;
|
||||
|
||||
os << '-' << std::endl;
|
||||
}
|
||||
|
||||
os << inst->m_name << " version " << inst->m_version << std::endl;
|
||||
|
||||
if (verbose)
|
||||
{
|
||||
if (inst->m_build_number != 0)
|
||||
{
|
||||
os << "build: " << inst->m_build_number << ' ' << inst->m_revision_date << std::endl;
|
||||
if (inst->m_git_tag[0] != 0)
|
||||
os << "git tag: " << inst->m_git_tag << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
using version_info_ptr = version_info_base *;
|
||||
|
||||
static version_info_ptr &head()
|
||||
{
|
||||
static version_info_ptr s_head = nullptr;
|
||||
return s_head;
|
||||
}
|
||||
|
||||
const char *m_name;
|
||||
const char *m_version;
|
||||
int m_build_number;
|
||||
const char *m_git_tag;
|
||||
const char *m_revision_date;
|
||||
version_info_base *m_next = nullptr;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class version_info : public version_info_base
|
||||
{
|
||||
public:
|
||||
using implementation_type = T;
|
||||
|
||||
version_info(const char *name, const char *version, int build_number, const char *git_tag, const char *revision_date)
|
||||
: version_info_base(name, version, build_number, git_tag, revision_date)
|
||||
{
|
||||
}
|
||||
|
||||
struct register_object
|
||||
{
|
||||
register_object()
|
||||
{
|
||||
static implementation_type s_instance;
|
||||
}
|
||||
};
|
||||
|
||||
template<register_object&> struct reference_object;
|
||||
|
||||
static register_object s_registered_object;
|
||||
static reference_object<s_registered_object> s_referenced_object;
|
||||
};
|
||||
|
||||
template<typename T> typename version_info<T>::register_object version_info<T>::s_registered_object;
|
||||
|
||||
}
|
||||
|
||||
inline void write_version_string(std::ostream &os, bool verbose)
|
||||
{
|
||||
version_info_v1::version_info_base::write(os, verbose);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
class version_info_@IDENT_PREFIX@impl : public version_info_v1::version_info<version_info_@IDENT_PREFIX@impl>
|
||||
{
|
||||
public:
|
||||
version_info_@IDENT_PREFIX@impl()
|
||||
: version_info(k@VAR_PREFIX@ProjectName, k@VAR_PREFIX@VersionNumber, k@VAR_PREFIX@BuildNumber, k@VAR_PREFIX@RevisionGitTag, k@VAR_PREFIX@RevisionDate)
|
||||
{
|
||||
}
|
||||
};
|
||||
]])
|
||||
configure_file("${VERSION_STRING_DATA}/${file_name}.in" "${dir}/${file_name}" @ONLY)
|
||||
endfunction()
|
||||
|
||||
20
cmake/cifppConfig.cmake.in
Normal file
20
cmake/cifppConfig.cmake.in
Normal file
@@ -0,0 +1,20 @@
|
||||
@PACKAGE_INIT@
|
||||
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/cifppTargets.cmake")
|
||||
|
||||
# Note that this set_and_check needs te be executed before
|
||||
# find_dependency of Eigen3, otherwise the path is
|
||||
# not found....
|
||||
set_and_check(CIFPP_SHARE_DIR "@PACKAGE_CIFPP_DATA_DIR@")
|
||||
|
||||
include(CMakeFindDependencyMacro)
|
||||
find_dependency(Threads)
|
||||
|
||||
find_dependency(ZLIB REQUIRED)
|
||||
find_dependency(Eigen3 REQUIRED)
|
||||
|
||||
if(MSVC)
|
||||
find_dependency(zeep REQUIRED)
|
||||
endif()
|
||||
|
||||
check_required_components(cifpp)
|
||||
18
cmake/test-rx.cpp
Normal file
18
cmake/test-rx.cpp
Normal 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;
|
||||
}
|
||||
2715
data/ccd-subset.cif
Normal file
2715
data/ccd-subset.cif
Normal file
File diff suppressed because it is too large
Load Diff
BIN
examples/1cbs.cif.gz
Normal file
BIN
examples/1cbs.cif.gz
Normal file
Binary file not shown.
35
examples/example.cpp
Normal file
35
examples/example.cpp
Normal 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
8
examples/makefile
Normal 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
41
include/cif++.hpp
Normal 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"
|
||||
281
include/cif++/atom_type.hpp
Normal file
281
include/cif++/atom_type.hpp
Normal 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, // Hydrogen
|
||||
He = 2, // Helium
|
||||
|
||||
Li = 3, // Lithium
|
||||
Be = 4, // Beryllium
|
||||
B = 5, // Boron
|
||||
C = 6, // Carbon
|
||||
N = 7, // Nitrogen
|
||||
O = 8, // Oxygen
|
||||
F = 9, // Fluorine
|
||||
Ne = 10, // Neon
|
||||
|
||||
Na = 11, // Sodium
|
||||
Mg = 12, // Magnesium
|
||||
Al = 13, // Aluminium
|
||||
Si = 14, // Silicon
|
||||
P = 15, // Phosphorus
|
||||
S = 16, // Sulfur
|
||||
Cl = 17, // Chlorine
|
||||
Ar = 18, // Argon
|
||||
|
||||
K = 19, // Potassium
|
||||
Ca = 20, // Calcium
|
||||
Sc = 21, // Scandium
|
||||
Ti = 22, // Titanium
|
||||
V = 23, // Vanadium
|
||||
Cr = 24, // Chromium
|
||||
Mn = 25, // Manganese
|
||||
Fe = 26, // Iron
|
||||
Co = 27, // Cobalt
|
||||
Ni = 28, // Nickel
|
||||
Cu = 29, // Copper
|
||||
Zn = 30, // Zinc
|
||||
Ga = 31, // Gallium
|
||||
Ge = 32, // Germanium
|
||||
As = 33, // Arsenic
|
||||
Se = 34, // Selenium
|
||||
Br = 35, // Bromine
|
||||
Kr = 36, // Krypton
|
||||
|
||||
Rb = 37, // Rubidium
|
||||
Sr = 38, // Strontium
|
||||
Y = 39, // Yttrium
|
||||
Zr = 40, // Zirconium
|
||||
Nb = 41, // Niobium
|
||||
Mo = 42, // Molybdenum
|
||||
Tc = 43, // Technetium
|
||||
Ru = 44, // Ruthenium
|
||||
Rh = 45, // Rhodium
|
||||
Pd = 46, // Palladium
|
||||
Ag = 47, // Silver
|
||||
Cd = 48, // Cadmium
|
||||
In = 49, // Indium
|
||||
Sn = 50, // Tin
|
||||
Sb = 51, // Antimony
|
||||
Te = 52, // Tellurium
|
||||
I = 53, // Iodine
|
||||
Xe = 54, // Xenon
|
||||
Cs = 55, // Caesium
|
||||
Ba = 56, // Barium
|
||||
La = 57, // Lanthanum
|
||||
|
||||
Hf = 72, // Hafnium
|
||||
Ta = 73, // Tantalum
|
||||
W = 74, // Tungsten
|
||||
Re = 75, // Rhenium
|
||||
Os = 76, // Osmium
|
||||
Ir = 77, // Iridium
|
||||
Pt = 78, // Platinum
|
||||
Au = 79, // Gold
|
||||
Hg = 80, // Mercury
|
||||
Tl = 81, // Thallium
|
||||
Pb = 82, // Lead
|
||||
Bi = 83, // Bismuth
|
||||
Po = 84, // Polonium
|
||||
At = 85, // Astatine
|
||||
Rn = 86, // Radon
|
||||
Fr = 87, // Francium
|
||||
Ra = 88, // Radium
|
||||
Ac = 89, // Actinium
|
||||
|
||||
Rf = 104, // Rutherfordium
|
||||
Db = 105, // Dubnium
|
||||
Sg = 106, // Seaborgium
|
||||
Bh = 107, // Bohrium
|
||||
Hs = 108, // Hassium
|
||||
Mt = 109, // Meitnerium
|
||||
Ds = 110, // Darmstadtium
|
||||
Rg = 111, // Roentgenium
|
||||
Cn = 112, // Copernicium
|
||||
Nh = 113, // Nihonium
|
||||
Fl = 114, // Flerovium
|
||||
Mc = 115, // Moscovium
|
||||
Lv = 116, // Livermorium
|
||||
Ts = 117, // Tennessine
|
||||
Og = 118, // Oganesson
|
||||
|
||||
Ce = 58, // Cerium
|
||||
Pr = 59, // Praseodymium
|
||||
Nd = 60, // Neodymium
|
||||
Pm = 61, // Promethium
|
||||
Sm = 62, // Samarium
|
||||
Eu = 63, // Europium
|
||||
Gd = 64, // Gadolinium
|
||||
Tb = 65, // Terbium
|
||||
Dy = 66, // Dysprosium
|
||||
Ho = 67, // Holmium
|
||||
Er = 68, // Erbium
|
||||
Tm = 69, // Thulium
|
||||
Yb = 70, // Ytterbium
|
||||
Lu = 71, // Lutetium
|
||||
|
||||
Th = 90, // Thorium
|
||||
Pa = 91, // Protactinium
|
||||
U = 92, // Uranium
|
||||
Np = 93, // Neptunium
|
||||
Pu = 94, // Plutonium
|
||||
Am = 95, // Americium
|
||||
Cm = 96, // Curium
|
||||
Bk = 97, // Berkelium
|
||||
Cf = 98, // Californium
|
||||
Es = 99, // Einsteinium
|
||||
Fm = 100, // Fermium
|
||||
Md = 101, // Mendelevium
|
||||
No = 102, // Nobelium
|
||||
Lr = 103, // Lawrencium
|
||||
|
||||
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
766
include/cif++/category.hpp
Normal 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
197
include/cif++/compound.hpp
Normal 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
894
include/cif++/condition.hpp
Normal 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
|
||||
98
include/cif++/datablock.hpp
Normal file
98
include/cif++/datablock.hpp
Normal 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
|
||||
37
include/cif++/dictionary_parser.hpp
Normal file
37
include/cif++/dictionary_parser.hpp
Normal file
@@ -0,0 +1,37 @@
|
||||
/*-
|
||||
* 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++/validate.hpp"
|
||||
|
||||
namespace cif
|
||||
{
|
||||
|
||||
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
123
include/cif++/file.hpp
Normal 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
206
include/cif++/format.hpp
Normal 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
|
||||
48
include/cif++/forward_decl.hpp
Normal file
48
include/cif++/forward_decl.hpp
Normal 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
|
||||
1042
include/cif++/gzio.hpp
Normal file
1042
include/cif++/gzio.hpp
Normal file
File diff suppressed because it is too large
Load Diff
567
include/cif++/item.hpp
Normal file
567
include/cif++/item.hpp
Normal 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
678
include/cif++/iterator.hpp
Normal 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
|
||||
533
include/cif++/matrix.hpp
Normal file
533
include/cif++/matrix.hpp
Normal file
@@ -0,0 +1,533 @@
|
||||
/*-
|
||||
* 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 size_t dim_m() const { return static_cast<const M &>(*this).dim_m(); }
|
||||
constexpr size_t dim_n() const { return static_cast<const M &>(*this).dim_n(); }
|
||||
|
||||
constexpr bool empty() const { return dim_m() == 0 or dim_n() == 0; }
|
||||
|
||||
constexpr auto &operator()(size_t i, size_t j)
|
||||
{
|
||||
return static_cast<M &>(*this).operator()(i, j);
|
||||
}
|
||||
|
||||
constexpr auto operator()(size_t i, size_t j) const
|
||||
{
|
||||
return static_cast<const M &>(*this).operator()(i, j);
|
||||
}
|
||||
|
||||
void swap_row(size_t r1, size_t r2)
|
||||
{
|
||||
for (size_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(size_t c1, size_t c2)
|
||||
{
|
||||
for (size_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 (size_t i = 0; i < m_m; ++i)
|
||||
{
|
||||
for (size_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 (size_t i = 0; i < M; ++i)
|
||||
{
|
||||
for (size_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(size_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 size_t dim_m() const { return m_n; }
|
||||
constexpr size_t dim_n() const { return m_n; }
|
||||
|
||||
constexpr value_type operator()(size_t i, size_t j) const
|
||||
{
|
||||
return i < j
|
||||
? m_data[(j * (j + 1)) / 2 + i]
|
||||
: m_data[(i * (i + 1)) / 2 + j];
|
||||
}
|
||||
|
||||
constexpr value_type &operator()(size_t i, size_t j)
|
||||
{
|
||||
if (i > j)
|
||||
std::swap(i, j);
|
||||
assert(j < m_n);
|
||||
return m_data[(j * (j + 1)) / 2 + i];
|
||||
}
|
||||
|
||||
private:
|
||||
size_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 size_t dim_m() const { return M; }
|
||||
constexpr size_t dim_n() const { return M; }
|
||||
|
||||
constexpr value_type operator()(size_t i, size_t j) const
|
||||
{
|
||||
return i < j
|
||||
? m_data[(j * (j + 1)) / 2 + i]
|
||||
: m_data[(i * (i + 1)) / 2 + j];
|
||||
}
|
||||
|
||||
constexpr value_type &operator()(size_t i, size_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(size_t n)
|
||||
: m_n(n)
|
||||
{
|
||||
}
|
||||
|
||||
constexpr size_t dim_m() const { return m_n; }
|
||||
constexpr size_t dim_n() const { return m_n; }
|
||||
|
||||
constexpr value_type operator()(size_t i, size_t j) const
|
||||
{
|
||||
return static_cast<value_type>(i == j ? 1 : 0);
|
||||
}
|
||||
|
||||
private:
|
||||
size_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 size_t dim_m() const { return m_m1.dim_m(); }
|
||||
constexpr size_t dim_n() const { return m_m1.dim_n(); }
|
||||
|
||||
constexpr auto operator()(size_t i, size_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 size_t dim_m() const { return m_m1.dim_m(); }
|
||||
constexpr size_t dim_n() const { return m_m1.dim_n(); }
|
||||
|
||||
constexpr auto operator()(size_t i, size_t j) const
|
||||
{
|
||||
using value_type = decltype(m_m1(0, 0));
|
||||
|
||||
value_type result = {};
|
||||
|
||||
for (size_t k = 0; k < m_m1.dim_m(); ++k)
|
||||
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 size_t dim_m() const { return m_m.dim_m(); }
|
||||
constexpr size_t dim_n() const { return m_m.dim_n(); }
|
||||
|
||||
constexpr auto operator()(size_t i, size_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 size_t dim_m() const { return m_m.dim_m(); }
|
||||
constexpr size_t dim_n() const { return m_m.dim_n(); }
|
||||
|
||||
constexpr auto operator()(size_t i, size_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
917
include/cif++/model.hpp
Normal 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
253
include/cif++/parser.hpp
Normal 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
|
||||
42
include/cif++/pdb/cif2pdb.hpp
Normal file
42
include/cif++/pdb/cif2pdb.hpp
Normal file
@@ -0,0 +1,42 @@
|
||||
/*-
|
||||
* 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++/datablock.hpp"
|
||||
|
||||
namespace cif::pdb
|
||||
{
|
||||
|
||||
/// \brief Just the HEADER, COMPND, SOURCE and AUTHOR lines
|
||||
void write_header_lines(std::ostream &os, const datablock &data);
|
||||
|
||||
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
60
include/cif++/pdb/io.hpp
Normal 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());
|
||||
}
|
||||
|
||||
}
|
||||
64
include/cif++/pdb/pdb2cif.hpp
Normal file
64
include/cif++/pdb/pdb2cif.hpp
Normal file
@@ -0,0 +1,64 @@
|
||||
/*-
|
||||
* 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++/file.hpp"
|
||||
namespace cif::pdb
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
struct PDBRecord
|
||||
{
|
||||
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();
|
||||
|
||||
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);
|
||||
std::string vF(size_t columnFirst, size_t columnLast);
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
void ReadPDBFile(std::istream &pdbFile, file &cifFile);
|
||||
|
||||
} // namespace pdbx
|
||||
75
include/cif++/pdb/pdb2cif_remark_3.hpp
Normal file
75
include/cif++/pdb/pdb2cif_remark_3.hpp
Normal file
@@ -0,0 +1,75 @@
|
||||
/*-
|
||||
* 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 "pdb2cif.hpp"
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
namespace cif::pdb
|
||||
{
|
||||
|
||||
struct TemplateLine;
|
||||
|
||||
class Remark3Parser
|
||||
{
|
||||
public:
|
||||
virtual ~Remark3Parser() {}
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
virtual void fixup() {}
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
} // namespace pdbx
|
||||
51
include/cif++/pdb/tls.hpp
Normal file
51
include/cif++/pdb/tls.hpp
Normal file
@@ -0,0 +1,51 @@
|
||||
/*-
|
||||
* 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++/datablock.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
namespace cif
|
||||
{
|
||||
|
||||
struct tls_selection;
|
||||
struct tls_residue;
|
||||
|
||||
struct tls_selection
|
||||
{
|
||||
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
|
||||
std::unique_ptr<tls_selection> parse_tls_selection_details(const std::string &program, const std::string &selection);
|
||||
|
||||
} // namespace cif
|
||||
767
include/cif++/point.hpp
Normal file
767
include/cif++/point.hpp
Normal file
@@ -0,0 +1,767 @@
|
||||
/*-
|
||||
* 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 <cstdint>
|
||||
#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
307
include/cif++/row.hpp
Normal 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
|
||||
422
include/cif++/symmetry.hpp
Normal file
422
include/cif++/symmetry.hpp
Normal file
@@ -0,0 +1,422 @@
|
||||
/*-
|
||||
* 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>
|
||||
|
||||
#if defined(__cpp_impl_three_way_comparison)
|
||||
#include <compare>
|
||||
#endif
|
||||
|
||||
/// \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;
|
||||
struct 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
465
include/cif++/text.hpp
Normal 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
|
||||
184
include/cif++/utilities.hpp
Normal file
184
include/cif++/utilities.hpp
Normal file
@@ -0,0 +1,184 @@
|
||||
/*-
|
||||
* 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 _WIN32
|
||||
#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();
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// 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
243
include/cif++/validate.hpp
Normal 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
|
||||
13
libcifpp.pc.in
Normal file
13
libcifpp.pc.in
Normal file
@@ -0,0 +1,13 @@
|
||||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
libdir=@libdir@
|
||||
includedir=@includedir@
|
||||
datalibdir=@datarootdir@/libcifpp
|
||||
|
||||
Name: libcifpp
|
||||
Description: C++ library for the manipulation of mmCIF files.
|
||||
Version: @PACKAGE_VERSION@
|
||||
|
||||
Requires: zlib
|
||||
Libs: -L${libdir} -lcifpp
|
||||
Cflags: -I${includedir} -pthread
|
||||
69
regex/CMakeLists.txt
Normal file
69
regex/CMakeLists.txt
Normal 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
23
regex/LICENSE_1_0.txt
Normal 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
47
regex/README.md
Normal 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
|
||||
|
||||
43
regex/include/boost/cregex.hpp
Normal file
43
regex/include/boost/cregex.hpp
Normal 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
100
regex/include/boost/regex.h
Normal 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 */
|
||||
|
||||
|
||||
|
||||
|
||||
41
regex/include/boost/regex.hpp
Normal file
41
regex/include/boost/regex.hpp
Normal 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
|
||||
|
||||
|
||||
|
||||
|
||||
1134
regex/include/boost/regex/concepts.hpp
Normal file
1134
regex/include/boost/regex/concepts.hpp
Normal file
File diff suppressed because it is too large
Load Diff
480
regex/include/boost/regex/config.hpp
Normal file
480
regex/include/boost/regex/config.hpp
Normal 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
|
||||
|
||||
72
regex/include/boost/regex/config/borland.hpp
Normal file
72
regex/include/boost/regex/config/borland.hpp
Normal 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
|
||||
|
||||
|
||||
207
regex/include/boost/regex/config/cwchar.hpp
Normal file
207
regex/include/boost/regex/config/cwchar.hpp
Normal 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
|
||||
|
||||
30
regex/include/boost/regex/icu.hpp
Normal file
30
regex/include/boost/regex/icu.hpp
Normal 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
|
||||
186
regex/include/boost/regex/mfc.hpp
Normal file
186
regex/include/boost/regex/mfc.hpp
Normal 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
|
||||
32
regex/include/boost/regex/pattern_except.hpp
Normal file
32
regex/include/boost/regex/pattern_except.hpp
Normal 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
|
||||
29
regex/include/boost/regex/pending/object_cache.hpp
Normal file
29
regex/include/boost/regex/pending/object_cache.hpp
Normal 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
|
||||
182
regex/include/boost/regex/pending/static_mutex.hpp
Normal file
182
regex/include/boost/regex/pending/static_mutex.hpp
Normal 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
|
||||
32
regex/include/boost/regex/pending/unicode_iterator.hpp
Normal file
32
regex/include/boost/regex/pending/unicode_iterator.hpp
Normal 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
|
||||
|
||||
39
regex/include/boost/regex/regex_traits.hpp
Normal file
39
regex/include/boost/regex/regex_traits.hpp
Normal 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
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
95
regex/include/boost/regex/user.hpp
Normal file
95
regex/include/boost/regex/user.hpp
Normal 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
|
||||
734
regex/include/boost/regex/v5/basic_regex.hpp
Normal file
734
regex/include/boost/regex/v5/basic_regex.hpp
Normal 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
|
||||
1576
regex/include/boost/regex/v5/basic_regex_creator.hpp
Normal file
1576
regex/include/boost/regex/v5/basic_regex_creator.hpp
Normal file
File diff suppressed because it is too large
Load Diff
3130
regex/include/boost/regex/v5/basic_regex_parser.hpp
Normal file
3130
regex/include/boost/regex/v5/basic_regex_parser.hpp
Normal file
File diff suppressed because it is too large
Load Diff
474
regex/include/boost/regex/v5/c_regex_traits.hpp
Normal file
474
regex/include/boost/regex/v5/c_regex_traits.hpp
Normal file
@@ -0,0 +1,474 @@
|
||||
/*
|
||||
*
|
||||
* 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 c_regex_traits.hpp
|
||||
* VERSION see <boost/version.hpp>
|
||||
* DESCRIPTION: Declares regular expression traits class that wraps the global C locale.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_C_REGEX_TRAITS_HPP_INCLUDED
|
||||
#define BOOST_C_REGEX_TRAITS_HPP_INCLUDED
|
||||
|
||||
#include <boost/regex/config.hpp>
|
||||
#include <boost/regex/v5/regex_workaround.hpp>
|
||||
#include <cctype>
|
||||
|
||||
namespace boost{
|
||||
|
||||
namespace BOOST_REGEX_DETAIL_NS {
|
||||
|
||||
enum
|
||||
{
|
||||
char_class_space = 1 << 0,
|
||||
char_class_print = 1 << 1,
|
||||
char_class_cntrl = 1 << 2,
|
||||
char_class_upper = 1 << 3,
|
||||
char_class_lower = 1 << 4,
|
||||
char_class_alpha = 1 << 5,
|
||||
char_class_digit = 1 << 6,
|
||||
char_class_punct = 1 << 7,
|
||||
char_class_xdigit = 1 << 8,
|
||||
char_class_alnum = char_class_alpha | char_class_digit,
|
||||
char_class_graph = char_class_alnum | char_class_punct,
|
||||
char_class_blank = 1 << 9,
|
||||
char_class_word = 1 << 10,
|
||||
char_class_unicode = 1 << 11,
|
||||
char_class_horizontal = 1 << 12,
|
||||
char_class_vertical = 1 << 13
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template <class charT>
|
||||
struct c_regex_traits;
|
||||
|
||||
template<>
|
||||
struct c_regex_traits<char>
|
||||
{
|
||||
c_regex_traits(){}
|
||||
typedef char char_type;
|
||||
typedef std::size_t size_type;
|
||||
typedef std::string string_type;
|
||||
struct locale_type{};
|
||||
typedef std::uint32_t char_class_type;
|
||||
|
||||
static size_type length(const char_type* p)
|
||||
{
|
||||
return (std::strlen)(p);
|
||||
}
|
||||
|
||||
char translate(char c) const
|
||||
{
|
||||
return c;
|
||||
}
|
||||
char translate_nocase(char c) const
|
||||
{
|
||||
return static_cast<char>((std::tolower)(static_cast<unsigned char>(c)));
|
||||
}
|
||||
|
||||
static string_type transform(const char* p1, const char* p2);
|
||||
static string_type transform_primary(const char* p1, const char* p2);
|
||||
|
||||
static char_class_type lookup_classname(const char* p1, const char* p2);
|
||||
static string_type lookup_collatename(const char* p1, const char* p2);
|
||||
|
||||
static bool isctype(char, char_class_type);
|
||||
static int value(char, int);
|
||||
|
||||
locale_type imbue(locale_type l)
|
||||
{ return l; }
|
||||
locale_type getloc()const
|
||||
{ return locale_type(); }
|
||||
|
||||
private:
|
||||
// this type is not copyable:
|
||||
c_regex_traits(const c_regex_traits&);
|
||||
c_regex_traits& operator=(const c_regex_traits&);
|
||||
};
|
||||
|
||||
#ifndef BOOST_NO_WREGEX
|
||||
template<>
|
||||
struct c_regex_traits<wchar_t>
|
||||
{
|
||||
c_regex_traits(){}
|
||||
typedef wchar_t char_type;
|
||||
typedef std::size_t size_type;
|
||||
typedef std::wstring string_type;
|
||||
struct locale_type{};
|
||||
typedef std::uint32_t char_class_type;
|
||||
|
||||
static size_type length(const char_type* p)
|
||||
{
|
||||
return (std::wcslen)(p);
|
||||
}
|
||||
|
||||
wchar_t translate(wchar_t c) const
|
||||
{
|
||||
return c;
|
||||
}
|
||||
wchar_t translate_nocase(wchar_t c) const
|
||||
{
|
||||
return (std::towlower)(c);
|
||||
}
|
||||
|
||||
static string_type transform(const wchar_t* p1, const wchar_t* p2);
|
||||
static string_type transform_primary(const wchar_t* p1, const wchar_t* p2);
|
||||
|
||||
static char_class_type lookup_classname(const wchar_t* p1, const wchar_t* p2);
|
||||
static string_type lookup_collatename(const wchar_t* p1, const wchar_t* p2);
|
||||
|
||||
static bool isctype(wchar_t, char_class_type);
|
||||
static int value(wchar_t, int);
|
||||
|
||||
locale_type imbue(locale_type l)
|
||||
{ return l; }
|
||||
locale_type getloc()const
|
||||
{ return locale_type(); }
|
||||
|
||||
private:
|
||||
// this type is not copyable:
|
||||
c_regex_traits(const c_regex_traits&);
|
||||
c_regex_traits& operator=(const c_regex_traits&);
|
||||
};
|
||||
|
||||
#endif // BOOST_NO_WREGEX
|
||||
|
||||
inline c_regex_traits<char>::string_type c_regex_traits<char>::transform(const char* p1, const char* p2)
|
||||
{
|
||||
std::string result(10, ' ');
|
||||
std::size_t s = result.size();
|
||||
std::size_t r;
|
||||
std::string src(p1, p2);
|
||||
while (s < (r = std::strxfrm(&*result.begin(), src.c_str(), s)))
|
||||
{
|
||||
#if defined(_CPPLIB_VER)
|
||||
//
|
||||
// A bug in VC11 and 12 causes the program to hang if we pass a null-string
|
||||
// to std::strxfrm, but only for certain locales :-(
|
||||
// Probably effects Intel and Clang or any compiler using the VC std library (Dinkumware).
|
||||
//
|
||||
if (r == INT_MAX)
|
||||
{
|
||||
result.erase();
|
||||
result.insert(result.begin(), static_cast<char>(0));
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
result.append(r - s + 3, ' ');
|
||||
s = result.size();
|
||||
}
|
||||
result.erase(r);
|
||||
return result;
|
||||
}
|
||||
|
||||
inline c_regex_traits<char>::string_type c_regex_traits<char>::transform_primary(const char* p1, const char* p2)
|
||||
{
|
||||
static char s_delim;
|
||||
static const int s_collate_type = ::boost::BOOST_REGEX_DETAIL_NS::find_sort_syntax(static_cast<c_regex_traits<char>*>(0), &s_delim);
|
||||
std::string result;
|
||||
//
|
||||
// What we do here depends upon the format of the sort key returned by
|
||||
// sort key returned by this->transform:
|
||||
//
|
||||
switch (s_collate_type)
|
||||
{
|
||||
case ::boost::BOOST_REGEX_DETAIL_NS::sort_C:
|
||||
case ::boost::BOOST_REGEX_DETAIL_NS::sort_unknown:
|
||||
// the best we can do is translate to lower case, then get a regular sort key:
|
||||
{
|
||||
result.assign(p1, p2);
|
||||
for (std::string::size_type i = 0; i < result.size(); ++i)
|
||||
result[i] = static_cast<char>((std::tolower)(static_cast<unsigned char>(result[i])));
|
||||
result = transform(&*result.begin(), &*result.begin() + result.size());
|
||||
break;
|
||||
}
|
||||
case ::boost::BOOST_REGEX_DETAIL_NS::sort_fixed:
|
||||
{
|
||||
// get a regular sort key, and then truncate it:
|
||||
result = transform(p1, p2);
|
||||
result.erase(s_delim);
|
||||
break;
|
||||
}
|
||||
case ::boost::BOOST_REGEX_DETAIL_NS::sort_delim:
|
||||
// get a regular sort key, and then truncate everything after the delim:
|
||||
result = transform(p1, p2);
|
||||
if ((!result.empty()) && (result[0] == s_delim))
|
||||
break;
|
||||
std::size_t i;
|
||||
for (i = 0; i < result.size(); ++i)
|
||||
{
|
||||
if (result[i] == s_delim)
|
||||
break;
|
||||
}
|
||||
result.erase(i);
|
||||
break;
|
||||
}
|
||||
if (result.empty())
|
||||
result = std::string(1, char(0));
|
||||
return result;
|
||||
}
|
||||
|
||||
inline c_regex_traits<char>::char_class_type c_regex_traits<char>::lookup_classname(const char* p1, const char* p2)
|
||||
{
|
||||
using namespace BOOST_REGEX_DETAIL_NS;
|
||||
static const char_class_type masks[] =
|
||||
{
|
||||
0,
|
||||
char_class_alnum,
|
||||
char_class_alpha,
|
||||
char_class_blank,
|
||||
char_class_cntrl,
|
||||
char_class_digit,
|
||||
char_class_digit,
|
||||
char_class_graph,
|
||||
char_class_horizontal,
|
||||
char_class_lower,
|
||||
char_class_lower,
|
||||
char_class_print,
|
||||
char_class_punct,
|
||||
char_class_space,
|
||||
char_class_space,
|
||||
char_class_upper,
|
||||
char_class_unicode,
|
||||
char_class_upper,
|
||||
char_class_vertical,
|
||||
char_class_alnum | char_class_word,
|
||||
char_class_alnum | char_class_word,
|
||||
char_class_xdigit,
|
||||
};
|
||||
|
||||
int idx = ::boost::BOOST_REGEX_DETAIL_NS::get_default_class_id(p1, p2);
|
||||
if (idx < 0)
|
||||
{
|
||||
std::string s(p1, p2);
|
||||
for (std::string::size_type i = 0; i < s.size(); ++i)
|
||||
s[i] = static_cast<char>((std::tolower)(static_cast<unsigned char>(s[i])));
|
||||
idx = ::boost::BOOST_REGEX_DETAIL_NS::get_default_class_id(&*s.begin(), &*s.begin() + s.size());
|
||||
}
|
||||
BOOST_REGEX_ASSERT(std::size_t(idx) + 1u < sizeof(masks) / sizeof(masks[0]));
|
||||
return masks[idx + 1];
|
||||
}
|
||||
|
||||
inline bool c_regex_traits<char>::isctype(char c, char_class_type mask)
|
||||
{
|
||||
using namespace BOOST_REGEX_DETAIL_NS;
|
||||
return
|
||||
((mask & char_class_space) && (std::isspace)(static_cast<unsigned char>(c)))
|
||||
|| ((mask & char_class_print) && (std::isprint)(static_cast<unsigned char>(c)))
|
||||
|| ((mask & char_class_cntrl) && (std::iscntrl)(static_cast<unsigned char>(c)))
|
||||
|| ((mask & char_class_upper) && (std::isupper)(static_cast<unsigned char>(c)))
|
||||
|| ((mask & char_class_lower) && (std::islower)(static_cast<unsigned char>(c)))
|
||||
|| ((mask & char_class_alpha) && (std::isalpha)(static_cast<unsigned char>(c)))
|
||||
|| ((mask & char_class_digit) && (std::isdigit)(static_cast<unsigned char>(c)))
|
||||
|| ((mask & char_class_punct) && (std::ispunct)(static_cast<unsigned char>(c)))
|
||||
|| ((mask & char_class_xdigit) && (std::isxdigit)(static_cast<unsigned char>(c)))
|
||||
|| ((mask & char_class_blank) && (std::isspace)(static_cast<unsigned char>(c)) && !::boost::BOOST_REGEX_DETAIL_NS::is_separator(c))
|
||||
|| ((mask & char_class_word) && (c == '_'))
|
||||
|| ((mask & char_class_vertical) && (::boost::BOOST_REGEX_DETAIL_NS::is_separator(c) || (c == '\v')))
|
||||
|| ((mask & char_class_horizontal) && (std::isspace)(static_cast<unsigned char>(c)) && !::boost::BOOST_REGEX_DETAIL_NS::is_separator(c) && (c != '\v'));
|
||||
}
|
||||
|
||||
inline c_regex_traits<char>::string_type c_regex_traits<char>::lookup_collatename(const char* p1, const char* p2)
|
||||
{
|
||||
std::string s(p1, p2);
|
||||
s = ::boost::BOOST_REGEX_DETAIL_NS::lookup_default_collate_name(s);
|
||||
if (s.empty() && (p2 - p1 == 1))
|
||||
s.append(1, *p1);
|
||||
return s;
|
||||
}
|
||||
|
||||
inline int c_regex_traits<char>::value(char c, int radix)
|
||||
{
|
||||
char b[2] = { c, '\0', };
|
||||
char* ep;
|
||||
int result = std::strtol(b, &ep, radix);
|
||||
if (ep == b)
|
||||
return -1;
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifndef BOOST_NO_WREGEX
|
||||
|
||||
inline c_regex_traits<wchar_t>::string_type c_regex_traits<wchar_t>::transform(const wchar_t* p1, const wchar_t* p2)
|
||||
{
|
||||
std::size_t r;
|
||||
std::size_t s = 10;
|
||||
std::wstring src(p1, p2);
|
||||
std::wstring result(s, L' ');
|
||||
while (s < (r = std::wcsxfrm(&*result.begin(), src.c_str(), s)))
|
||||
{
|
||||
#if defined(_CPPLIB_VER)
|
||||
//
|
||||
// A bug in VC11 and 12 causes the program to hang if we pass a null-string
|
||||
// to std::strxfrm, but only for certain locales :-(
|
||||
// Probably effects Intel and Clang or any compiler using the VC std library (Dinkumware).
|
||||
//
|
||||
if (r == INT_MAX)
|
||||
{
|
||||
result.erase();
|
||||
result.insert(result.begin(), static_cast<wchar_t>(0));
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
result.append(r - s + 3, L' ');
|
||||
s = result.size();
|
||||
}
|
||||
result.erase(r);
|
||||
return result;
|
||||
}
|
||||
|
||||
inline c_regex_traits<wchar_t>::string_type c_regex_traits<wchar_t>::transform_primary(const wchar_t* p1, const wchar_t* p2)
|
||||
{
|
||||
static wchar_t s_delim;
|
||||
static const int s_collate_type = ::boost::BOOST_REGEX_DETAIL_NS::find_sort_syntax(static_cast<const c_regex_traits<wchar_t>*>(0), &s_delim);
|
||||
std::wstring result;
|
||||
//
|
||||
// What we do here depends upon the format of the sort key returned by
|
||||
// sort key returned by this->transform:
|
||||
//
|
||||
switch (s_collate_type)
|
||||
{
|
||||
case ::boost::BOOST_REGEX_DETAIL_NS::sort_C:
|
||||
case ::boost::BOOST_REGEX_DETAIL_NS::sort_unknown:
|
||||
// the best we can do is translate to lower case, then get a regular sort key:
|
||||
{
|
||||
result.assign(p1, p2);
|
||||
for (std::wstring::size_type i = 0; i < result.size(); ++i)
|
||||
result[i] = (std::towlower)(result[i]);
|
||||
result = c_regex_traits<wchar_t>::transform(&*result.begin(), &*result.begin() + result.size());
|
||||
break;
|
||||
}
|
||||
case ::boost::BOOST_REGEX_DETAIL_NS::sort_fixed:
|
||||
{
|
||||
// get a regular sort key, and then truncate it:
|
||||
result = c_regex_traits<wchar_t>::transform(&*result.begin(), &*result.begin() + result.size());
|
||||
result.erase(s_delim);
|
||||
break;
|
||||
}
|
||||
case ::boost::BOOST_REGEX_DETAIL_NS::sort_delim:
|
||||
// get a regular sort key, and then truncate everything after the delim:
|
||||
result = c_regex_traits<wchar_t>::transform(&*result.begin(), &*result.begin() + result.size());
|
||||
if ((!result.empty()) && (result[0] == s_delim))
|
||||
break;
|
||||
std::size_t i;
|
||||
for (i = 0; i < result.size(); ++i)
|
||||
{
|
||||
if (result[i] == s_delim)
|
||||
break;
|
||||
}
|
||||
result.erase(i);
|
||||
break;
|
||||
}
|
||||
if (result.empty())
|
||||
result = std::wstring(1, char(0));
|
||||
return result;
|
||||
}
|
||||
|
||||
inline c_regex_traits<wchar_t>::char_class_type c_regex_traits<wchar_t>::lookup_classname(const wchar_t* p1, const wchar_t* p2)
|
||||
{
|
||||
using namespace BOOST_REGEX_DETAIL_NS;
|
||||
static const char_class_type masks[] =
|
||||
{
|
||||
0,
|
||||
char_class_alnum,
|
||||
char_class_alpha,
|
||||
char_class_blank,
|
||||
char_class_cntrl,
|
||||
char_class_digit,
|
||||
char_class_digit,
|
||||
char_class_graph,
|
||||
char_class_horizontal,
|
||||
char_class_lower,
|
||||
char_class_lower,
|
||||
char_class_print,
|
||||
char_class_punct,
|
||||
char_class_space,
|
||||
char_class_space,
|
||||
char_class_upper,
|
||||
char_class_unicode,
|
||||
char_class_upper,
|
||||
char_class_vertical,
|
||||
char_class_alnum | char_class_word,
|
||||
char_class_alnum | char_class_word,
|
||||
char_class_xdigit,
|
||||
};
|
||||
|
||||
int idx = ::boost::BOOST_REGEX_DETAIL_NS::get_default_class_id(p1, p2);
|
||||
if (idx < 0)
|
||||
{
|
||||
std::wstring s(p1, p2);
|
||||
for (std::wstring::size_type i = 0; i < s.size(); ++i)
|
||||
s[i] = (std::towlower)(s[i]);
|
||||
idx = ::boost::BOOST_REGEX_DETAIL_NS::get_default_class_id(&*s.begin(), &*s.begin() + s.size());
|
||||
}
|
||||
BOOST_REGEX_ASSERT(idx + 1 < static_cast<int>(sizeof(masks) / sizeof(masks[0])));
|
||||
return masks[idx + 1];
|
||||
}
|
||||
|
||||
inline bool c_regex_traits<wchar_t>::isctype(wchar_t c, char_class_type mask)
|
||||
{
|
||||
using namespace BOOST_REGEX_DETAIL_NS;
|
||||
return
|
||||
((mask & char_class_space) && (std::iswspace)(c))
|
||||
|| ((mask & char_class_print) && (std::iswprint)(c))
|
||||
|| ((mask & char_class_cntrl) && (std::iswcntrl)(c))
|
||||
|| ((mask & char_class_upper) && (std::iswupper)(c))
|
||||
|| ((mask & char_class_lower) && (std::iswlower)(c))
|
||||
|| ((mask & char_class_alpha) && (std::iswalpha)(c))
|
||||
|| ((mask & char_class_digit) && (std::iswdigit)(c))
|
||||
|| ((mask & char_class_punct) && (std::iswpunct)(c))
|
||||
|| ((mask & char_class_xdigit) && (std::iswxdigit)(c))
|
||||
|| ((mask & char_class_blank) && (std::iswspace)(c) && !::boost::BOOST_REGEX_DETAIL_NS::is_separator(c))
|
||||
|| ((mask & char_class_word) && (c == '_'))
|
||||
|| ((mask & char_class_unicode) && (c & ~static_cast<wchar_t>(0xff)))
|
||||
|| ((mask & char_class_vertical) && (::boost::BOOST_REGEX_DETAIL_NS::is_separator(c) || (c == L'\v')))
|
||||
|| ((mask & char_class_horizontal) && (std::iswspace)(c) && !::boost::BOOST_REGEX_DETAIL_NS::is_separator(c) && (c != L'\v'));
|
||||
}
|
||||
|
||||
inline c_regex_traits<wchar_t>::string_type c_regex_traits<wchar_t>::lookup_collatename(const wchar_t* p1, const wchar_t* p2)
|
||||
{
|
||||
std::string name;
|
||||
// Usual msvc warning suppression does not work here with std::string template constructor.... use a workaround instead:
|
||||
for (const wchar_t* pos = p1; pos != p2; ++pos)
|
||||
name.push_back((char)*pos);
|
||||
name = ::boost::BOOST_REGEX_DETAIL_NS::lookup_default_collate_name(name);
|
||||
if (!name.empty())
|
||||
return string_type(name.begin(), name.end());
|
||||
if (p2 - p1 == 1)
|
||||
return string_type(1, *p1);
|
||||
return string_type();
|
||||
}
|
||||
|
||||
inline int c_regex_traits<wchar_t>::value(wchar_t c, int radix)
|
||||
{
|
||||
#ifdef BOOST_BORLANDC
|
||||
// workaround for broken wcstol:
|
||||
if ((std::iswxdigit)(c) == 0)
|
||||
return -1;
|
||||
#endif
|
||||
wchar_t b[2] = { c, '\0', };
|
||||
wchar_t* ep;
|
||||
int result = std::wcstol(b, &ep, radix);
|
||||
if (ep == b)
|
||||
return -1;
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
59
regex/include/boost/regex/v5/char_regex_traits.hpp
Normal file
59
regex/include/boost/regex/v5/char_regex_traits.hpp
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 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 char_regex_traits.cpp
|
||||
* VERSION see <boost/version.hpp>
|
||||
* DESCRIPTION: Declares deprecated traits classes char_regex_traits<>.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef BOOST_REGEX_V5_CHAR_REGEX_TRAITS_HPP
|
||||
#define BOOST_REGEX_V5_CHAR_REGEX_TRAITS_HPP
|
||||
|
||||
namespace boost{
|
||||
|
||||
namespace deprecated{
|
||||
//
|
||||
// class char_regex_traits_i
|
||||
// provides case insensitive traits classes (deprecated):
|
||||
template <class charT>
|
||||
class char_regex_traits_i : public regex_traits<charT> {};
|
||||
|
||||
template<>
|
||||
class char_regex_traits_i<char> : public regex_traits<char>
|
||||
{
|
||||
public:
|
||||
typedef char char_type;
|
||||
typedef unsigned char uchar_type;
|
||||
typedef unsigned int size_type;
|
||||
typedef regex_traits<char> base_type;
|
||||
|
||||
};
|
||||
|
||||
#ifndef BOOST_NO_WREGEX
|
||||
template<>
|
||||
class char_regex_traits_i<wchar_t> : public regex_traits<wchar_t>
|
||||
{
|
||||
public:
|
||||
typedef wchar_t char_type;
|
||||
typedef unsigned short uchar_type;
|
||||
typedef unsigned int size_type;
|
||||
typedef regex_traits<wchar_t> base_type;
|
||||
|
||||
};
|
||||
#endif
|
||||
} // namespace deprecated
|
||||
} // namespace boost
|
||||
|
||||
#endif // include
|
||||
|
||||
1040
regex/include/boost/regex/v5/cpp_regex_traits.hpp
Normal file
1040
regex/include/boost/regex/v5/cpp_regex_traits.hpp
Normal file
File diff suppressed because it is too large
Load Diff
195
regex/include/boost/regex/v5/cregex.hpp
Normal file
195
regex/include/boost/regex/v5/cregex.hpp
Normal file
@@ -0,0 +1,195 @@
|
||||
/*
|
||||
*
|
||||
* 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 cregex.cpp
|
||||
* VERSION see <boost/version.hpp>
|
||||
* DESCRIPTION: Declares POSIX API functions
|
||||
* + boost::RegEx high level wrapper.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_RE_CREGEX_HPP_INCLUDED
|
||||
#define BOOST_RE_CREGEX_HPP_INCLUDED
|
||||
|
||||
#ifndef BOOST_REGEX_CONFIG_HPP
|
||||
#include <boost/regex/config.hpp>
|
||||
#endif
|
||||
#include <boost/regex/v5/match_flags.hpp>
|
||||
#include <boost/regex/v5/error_type.hpp>
|
||||
|
||||
#ifndef BOOST_REGEX_STANDALONE
|
||||
#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
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <cstddef>
|
||||
#else
|
||||
#include <stddef.h>
|
||||
#endif
|
||||
|
||||
/* include these defs only for POSIX compatablity */
|
||||
#ifdef __cplusplus
|
||||
namespace boost{
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus)
|
||||
typedef std::ptrdiff_t regoff_t;
|
||||
typedef std::size_t regsize_t;
|
||||
#else
|
||||
typedef ptrdiff_t regoff_t;
|
||||
typedef size_t regsize_t;
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned int re_magic;
|
||||
#ifdef __cplusplus
|
||||
std::size_t re_nsub; /* number of parenthesized subexpressions */
|
||||
#else
|
||||
size_t re_nsub;
|
||||
#endif
|
||||
const char* re_endp; /* end pointer for REG_PEND */
|
||||
void* guts; /* none of your business :-) */
|
||||
match_flag_type eflags; /* none of your business :-) */
|
||||
} regex_tA;
|
||||
|
||||
#ifndef BOOST_NO_WREGEX
|
||||
typedef struct
|
||||
{
|
||||
unsigned int re_magic;
|
||||
#ifdef __cplusplus
|
||||
std::size_t re_nsub; /* number of parenthesized subexpressions */
|
||||
#else
|
||||
size_t re_nsub;
|
||||
#endif
|
||||
const wchar_t* re_endp; /* end pointer for REG_PEND */
|
||||
void* guts; /* none of your business :-) */
|
||||
match_flag_type eflags; /* none of your business :-) */
|
||||
} regex_tW;
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
regoff_t rm_so; /* start of match */
|
||||
regoff_t rm_eo; /* end of match */
|
||||
} regmatch_t;
|
||||
|
||||
/* regcomp() flags */
|
||||
typedef enum{
|
||||
REG_BASIC = 0000,
|
||||
REG_EXTENDED = 0001,
|
||||
REG_ICASE = 0002,
|
||||
REG_NOSUB = 0004,
|
||||
REG_NEWLINE = 0010,
|
||||
REG_NOSPEC = 0020,
|
||||
REG_PEND = 0040,
|
||||
REG_DUMP = 0200,
|
||||
REG_NOCOLLATE = 0400,
|
||||
REG_ESCAPE_IN_LISTS = 01000,
|
||||
REG_NEWLINE_ALT = 02000,
|
||||
REG_PERLEX = 04000,
|
||||
|
||||
REG_PERL = REG_EXTENDED | REG_NOCOLLATE | REG_ESCAPE_IN_LISTS | REG_PERLEX,
|
||||
REG_AWK = REG_EXTENDED | REG_ESCAPE_IN_LISTS,
|
||||
REG_GREP = REG_BASIC | REG_NEWLINE_ALT,
|
||||
REG_EGREP = REG_EXTENDED | REG_NEWLINE_ALT,
|
||||
|
||||
REG_ASSERT = 15,
|
||||
REG_INVARG = 16,
|
||||
REG_ATOI = 255, /* convert name to number (!) */
|
||||
REG_ITOA = 0400 /* convert number to name (!) */
|
||||
} reg_comp_flags;
|
||||
|
||||
/* regexec() flags */
|
||||
typedef enum{
|
||||
REG_NOTBOL = 00001,
|
||||
REG_NOTEOL = 00002,
|
||||
REG_STARTEND = 00004
|
||||
} reg_exec_flags;
|
||||
|
||||
/*
|
||||
* POSIX error codes:
|
||||
*/
|
||||
typedef unsigned reg_error_t;
|
||||
typedef reg_error_t reg_errcode_t; /* backwards compatibility */
|
||||
|
||||
static const reg_error_t REG_NOERROR = 0; /* Success. */
|
||||
static const reg_error_t REG_NOMATCH = 1; /* Didn't find a match (for regexec). */
|
||||
|
||||
/* POSIX regcomp return error codes. (In the order listed in the
|
||||
standard.) */
|
||||
static const reg_error_t REG_BADPAT = 2; /* Invalid pattern. */
|
||||
static const reg_error_t REG_ECOLLATE = 3; /* Undefined collating element. */
|
||||
static const reg_error_t REG_ECTYPE = 4; /* Invalid character class name. */
|
||||
static const reg_error_t REG_EESCAPE = 5; /* Trailing backslash. */
|
||||
static const reg_error_t REG_ESUBREG = 6; /* Invalid back reference. */
|
||||
static const reg_error_t REG_EBRACK = 7; /* Unmatched left bracket. */
|
||||
static const reg_error_t REG_EPAREN = 8; /* Parenthesis imbalance. */
|
||||
static const reg_error_t REG_EBRACE = 9; /* Unmatched \{. */
|
||||
static const reg_error_t REG_BADBR = 10; /* Invalid contents of \{\}. */
|
||||
static const reg_error_t REG_ERANGE = 11; /* Invalid range end. */
|
||||
static const reg_error_t REG_ESPACE = 12; /* Ran out of memory. */
|
||||
static const reg_error_t REG_BADRPT = 13; /* No preceding re for repetition op. */
|
||||
static const reg_error_t REG_EEND = 14; /* unexpected end of expression */
|
||||
static const reg_error_t REG_ESIZE = 15; /* expression too big */
|
||||
static const reg_error_t REG_ERPAREN = 8; /* = REG_EPAREN : unmatched right parenthesis */
|
||||
static const reg_error_t REG_EMPTY = 17; /* empty expression */
|
||||
static const reg_error_t REG_E_MEMORY = 15; /* = REG_ESIZE : out of memory */
|
||||
static const reg_error_t REG_ECOMPLEXITY = 18; /* complexity too high */
|
||||
static const reg_error_t REG_ESTACK = 19; /* out of stack space */
|
||||
static const reg_error_t REG_E_PERL = 20; /* Perl (?...) error */
|
||||
static const reg_error_t REG_E_UNKNOWN = 21; /* unknown error */
|
||||
static const reg_error_t REG_ENOSYS = 21; /* = REG_E_UNKNOWN : Reserved. */
|
||||
|
||||
BOOST_REGEX_DECL int BOOST_REGEX_CCALL regcompA(regex_tA*, const char*, int);
|
||||
BOOST_REGEX_DECL regsize_t BOOST_REGEX_CCALL regerrorA(int, const regex_tA*, char*, regsize_t);
|
||||
BOOST_REGEX_DECL int BOOST_REGEX_CCALL regexecA(const regex_tA*, const char*, regsize_t, regmatch_t*, int);
|
||||
BOOST_REGEX_DECL void BOOST_REGEX_CCALL regfreeA(regex_tA*);
|
||||
|
||||
#ifndef BOOST_NO_WREGEX
|
||||
BOOST_REGEX_DECL int BOOST_REGEX_CCALL regcompW(regex_tW*, const wchar_t*, int);
|
||||
BOOST_REGEX_DECL regsize_t BOOST_REGEX_CCALL regerrorW(int, const regex_tW*, wchar_t*, regsize_t);
|
||||
BOOST_REGEX_DECL int BOOST_REGEX_CCALL regexecW(const regex_tW*, const wchar_t*, regsize_t, regmatch_t*, int);
|
||||
BOOST_REGEX_DECL void BOOST_REGEX_CCALL regfreeW(regex_tW*);
|
||||
#endif
|
||||
|
||||
#ifdef UNICODE
|
||||
#define regcomp regcompW
|
||||
#define regerror regerrorW
|
||||
#define regexec regexecW
|
||||
#define regfree regfreeW
|
||||
#define regex_t regex_tW
|
||||
#else
|
||||
#define regcomp regcompA
|
||||
#define regerror regerrorA
|
||||
#define regexec regexecA
|
||||
#define regfree regfreeA
|
||||
#define regex_t regex_tA
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
} /* namespace */
|
||||
#endif
|
||||
|
||||
#endif /* include guard */
|
||||
|
||||
59
regex/include/boost/regex/v5/error_type.hpp
Normal file
59
regex/include/boost/regex/v5/error_type.hpp
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 2003-2005
|
||||
* 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 error_type.hpp
|
||||
* VERSION see <boost/version.hpp>
|
||||
* DESCRIPTION: Declares regular expression error type enumerator.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_REGEX_ERROR_TYPE_HPP
|
||||
#define BOOST_REGEX_ERROR_TYPE_HPP
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace boost{
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace regex_constants{
|
||||
|
||||
enum error_type{
|
||||
|
||||
error_ok = 0, /* not used */
|
||||
error_no_match = 1, /* not used */
|
||||
error_bad_pattern = 2,
|
||||
error_collate = 3,
|
||||
error_ctype = 4,
|
||||
error_escape = 5,
|
||||
error_backref = 6,
|
||||
error_brack = 7,
|
||||
error_paren = 8,
|
||||
error_brace = 9,
|
||||
error_badbrace = 10,
|
||||
error_range = 11,
|
||||
error_space = 12,
|
||||
error_badrepeat = 13,
|
||||
error_end = 14, /* not used */
|
||||
error_size = 15,
|
||||
error_right_paren = 16, /* not used */
|
||||
error_empty = 17,
|
||||
error_complexity = 18,
|
||||
error_stack = 19,
|
||||
error_perl_extension = 20,
|
||||
error_unknown = 21
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif
|
||||
1402
regex/include/boost/regex/v5/icu.hpp
Normal file
1402
regex/include/boost/regex/v5/icu.hpp
Normal file
File diff suppressed because it is too large
Load Diff
84
regex/include/boost/regex/v5/iterator_category.hpp
Normal file
84
regex/include/boost/regex/v5/iterator_category.hpp
Normal file
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 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_match.hpp
|
||||
* VERSION see <boost/version.hpp>
|
||||
* DESCRIPTION: Iterator traits for selecting an iterator type as
|
||||
* an integral constant expression.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef BOOST_REGEX_ITERATOR_CATEGORY_HPP
|
||||
#define BOOST_REGEX_ITERATOR_CATEGORY_HPP
|
||||
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost{
|
||||
namespace detail{
|
||||
|
||||
template <class I>
|
||||
struct is_random_imp
|
||||
{
|
||||
private:
|
||||
typedef typename std::iterator_traits<I>::iterator_category cat;
|
||||
public:
|
||||
static const bool value = (std::is_convertible<cat*, std::random_access_iterator_tag*>::value);
|
||||
};
|
||||
|
||||
template <class I>
|
||||
struct is_random_pointer_imp
|
||||
{
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
template <bool is_pointer_type>
|
||||
struct is_random_imp_selector
|
||||
{
|
||||
template <class I>
|
||||
struct rebind
|
||||
{
|
||||
typedef is_random_imp<I> type;
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct is_random_imp_selector<true>
|
||||
{
|
||||
template <class I>
|
||||
struct rebind
|
||||
{
|
||||
typedef is_random_pointer_imp<I> type;
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template <class I>
|
||||
struct is_random_access_iterator
|
||||
{
|
||||
private:
|
||||
typedef detail::is_random_imp_selector< std::is_pointer<I>::value> selector;
|
||||
typedef typename selector::template rebind<I> bound_type;
|
||||
typedef typename bound_type::type answer;
|
||||
public:
|
||||
static const bool value = answer::value;
|
||||
};
|
||||
|
||||
template <class I>
|
||||
const bool is_random_access_iterator<I>::value;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
32
regex/include/boost/regex/v5/iterator_traits.hpp
Normal file
32
regex/include/boost/regex/v5/iterator_traits.hpp
Normal 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 iterator_traits.cpp
|
||||
* VERSION see <boost/version.hpp>
|
||||
* DESCRIPTION: Declares iterator traits workarounds.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_REGEX_V5_ITERATOR_TRAITS_HPP
|
||||
#define BOOST_REGEX_V5_ITERATOR_TRAITS_HPP
|
||||
|
||||
namespace boost{
|
||||
namespace BOOST_REGEX_DETAIL_NS{
|
||||
|
||||
template <class T>
|
||||
struct regex_iterator_traits : public std::iterator_traits<T> {};
|
||||
|
||||
} // namespace BOOST_REGEX_DETAIL_NS
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
|
||||
156
regex/include/boost/regex/v5/match_flags.hpp
Normal file
156
regex/include/boost/regex/v5/match_flags.hpp
Normal file
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
*
|
||||
* 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 match_flags.hpp
|
||||
* VERSION see <boost/version.hpp>
|
||||
* DESCRIPTION: Declares match_flags type.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_REGEX_V5_MATCH_FLAGS
|
||||
#define BOOST_REGEX_V5_MATCH_FLAGS
|
||||
|
||||
#ifdef __cplusplus
|
||||
# include <cstdint>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace boost{
|
||||
namespace regex_constants{
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_REGEX_MSVC
|
||||
#pragma warning(push)
|
||||
#if BOOST_REGEX_MSVC >= 1800
|
||||
#pragma warning(disable : 26812)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
typedef enum _match_flags
|
||||
{
|
||||
match_default = 0,
|
||||
match_not_bol = 1, /* first is not start of line */
|
||||
match_not_eol = match_not_bol << 1, /* last is not end of line */
|
||||
match_not_bob = match_not_eol << 1, /* first is not start of buffer */
|
||||
match_not_eob = match_not_bob << 1, /* last is not end of buffer */
|
||||
match_not_bow = match_not_eob << 1, /* first is not start of word */
|
||||
match_not_eow = match_not_bow << 1, /* last is not end of word */
|
||||
match_not_dot_newline = match_not_eow << 1, /* \n is not matched by '.' */
|
||||
match_not_dot_null = match_not_dot_newline << 1, /* '\0' is not matched by '.' */
|
||||
match_prev_avail = match_not_dot_null << 1, /* *--first is a valid expression */
|
||||
match_init = match_prev_avail << 1, /* internal use */
|
||||
match_any = match_init << 1, /* don't care what we match */
|
||||
match_not_null = match_any << 1, /* string can't be null */
|
||||
match_continuous = match_not_null << 1, /* each grep match must continue from */
|
||||
/* uninterrupted from the previous one */
|
||||
match_partial = match_continuous << 1, /* find partial matches */
|
||||
|
||||
match_stop = match_partial << 1, /* stop after first match (grep) V3 only */
|
||||
match_not_initial_null = match_stop, /* don't match initial null, V4 only */
|
||||
match_all = match_stop << 1, /* must find the whole of input even if match_any is set */
|
||||
match_perl = match_all << 1, /* Use perl matching rules */
|
||||
match_posix = match_perl << 1, /* Use POSIX matching rules */
|
||||
match_nosubs = match_posix << 1, /* don't trap marked subs */
|
||||
match_extra = match_nosubs << 1, /* include full capture information for repeated captures */
|
||||
match_single_line = match_extra << 1, /* treat text as single line and ignore any \n's when matching ^ and $. */
|
||||
match_unused1 = match_single_line << 1, /* unused */
|
||||
match_unused2 = match_unused1 << 1, /* unused */
|
||||
match_unused3 = match_unused2 << 1, /* unused */
|
||||
match_max = match_unused3,
|
||||
|
||||
format_perl = 0, /* perl style replacement */
|
||||
format_default = 0, /* ditto. */
|
||||
format_sed = match_max << 1, /* sed style replacement. */
|
||||
format_all = format_sed << 1, /* enable all extensions to syntax. */
|
||||
format_no_copy = format_all << 1, /* don't copy non-matching segments. */
|
||||
format_first_only = format_no_copy << 1, /* Only replace first occurrence. */
|
||||
format_is_if = format_first_only << 1, /* internal use only. */
|
||||
format_literal = format_is_if << 1, /* treat string as a literal */
|
||||
|
||||
match_not_any = match_not_bol | match_not_eol | match_not_bob
|
||||
| match_not_eob | match_not_bow | match_not_eow | match_not_dot_newline
|
||||
| match_not_dot_null | match_prev_avail | match_init | match_not_null
|
||||
| match_continuous | match_partial | match_stop | match_not_initial_null
|
||||
| match_stop | match_all | match_perl | match_posix | match_nosubs
|
||||
| match_extra | match_single_line | match_unused1 | match_unused2
|
||||
| match_unused3 | match_max | format_perl | format_default | format_sed
|
||||
| format_all | format_no_copy | format_first_only | format_is_if
|
||||
| format_literal
|
||||
|
||||
|
||||
} match_flags;
|
||||
|
||||
typedef match_flags match_flag_type;
|
||||
|
||||
#ifdef __cplusplus
|
||||
inline match_flags operator&(match_flags m1, match_flags m2)
|
||||
{ return static_cast<match_flags>(static_cast<std::int32_t>(m1) & static_cast<std::int32_t>(m2)); }
|
||||
inline match_flags operator|(match_flags m1, match_flags m2)
|
||||
{ return static_cast<match_flags>(static_cast<std::int32_t>(m1) | static_cast<std::int32_t>(m2)); }
|
||||
inline match_flags operator^(match_flags m1, match_flags m2)
|
||||
{ return static_cast<match_flags>(static_cast<std::int32_t>(m1) ^ static_cast<std::int32_t>(m2)); }
|
||||
inline match_flags operator~(match_flags m1)
|
||||
{ return static_cast<match_flags>(~static_cast<std::int32_t>(m1)); }
|
||||
inline match_flags& operator&=(match_flags& m1, match_flags m2)
|
||||
{ m1 = m1&m2; return m1; }
|
||||
inline match_flags& operator|=(match_flags& m1, match_flags m2)
|
||||
{ m1 = m1|m2; return m1; }
|
||||
inline match_flags& operator^=(match_flags& m1, match_flags m2)
|
||||
{ m1 = m1^m2; return m1; }
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* namespace regex_constants */
|
||||
/*
|
||||
* import names into boost for backwards compatibility:
|
||||
*/
|
||||
using regex_constants::match_flag_type;
|
||||
using regex_constants::match_default;
|
||||
using regex_constants::match_not_bol;
|
||||
using regex_constants::match_not_eol;
|
||||
using regex_constants::match_not_bob;
|
||||
using regex_constants::match_not_eob;
|
||||
using regex_constants::match_not_bow;
|
||||
using regex_constants::match_not_eow;
|
||||
using regex_constants::match_not_dot_newline;
|
||||
using regex_constants::match_not_dot_null;
|
||||
using regex_constants::match_prev_avail;
|
||||
/* using regex_constants::match_init; */
|
||||
using regex_constants::match_any;
|
||||
using regex_constants::match_not_null;
|
||||
using regex_constants::match_continuous;
|
||||
using regex_constants::match_partial;
|
||||
/*using regex_constants::match_stop; */
|
||||
using regex_constants::match_all;
|
||||
using regex_constants::match_perl;
|
||||
using regex_constants::match_posix;
|
||||
using regex_constants::match_nosubs;
|
||||
using regex_constants::match_extra;
|
||||
using regex_constants::match_single_line;
|
||||
/*using regex_constants::match_max; */
|
||||
using regex_constants::format_all;
|
||||
using regex_constants::format_sed;
|
||||
using regex_constants::format_perl;
|
||||
using regex_constants::format_default;
|
||||
using regex_constants::format_no_copy;
|
||||
using regex_constants::format_first_only;
|
||||
/*using regex_constants::format_is_if;*/
|
||||
|
||||
#ifdef BOOST_REGEX_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
|
||||
} /* namespace boost */
|
||||
#endif /* __cplusplus */
|
||||
#endif /* include guard */
|
||||
|
||||
667
regex/include/boost/regex/v5/match_results.hpp
Normal file
667
regex/include/boost/regex/v5/match_results.hpp
Normal file
@@ -0,0 +1,667 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 1998-2009
|
||||
* 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 match_results.cpp
|
||||
* VERSION see <boost/version.hpp>
|
||||
* DESCRIPTION: Declares template class match_results.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_REGEX_V5_MATCH_RESULTS_HPP
|
||||
#define BOOST_REGEX_V5_MATCH_RESULTS_HPP
|
||||
|
||||
namespace boost{
|
||||
#ifdef BOOST_REGEX_MSVC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4251 4459)
|
||||
#if BOOST_REGEX_MSVC < 1700
|
||||
# pragma warning(disable : 4231)
|
||||
#endif
|
||||
# if BOOST_REGEX_MSVC < 1600
|
||||
# pragma warning(disable : 4660)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
namespace BOOST_REGEX_DETAIL_NS{
|
||||
|
||||
class named_subexpressions;
|
||||
|
||||
}
|
||||
|
||||
template <class BidiIterator, class Allocator>
|
||||
class match_results
|
||||
{
|
||||
private:
|
||||
typedef std::vector<sub_match<BidiIterator>, Allocator> vector_type;
|
||||
public:
|
||||
typedef sub_match<BidiIterator> value_type;
|
||||
typedef typename std::allocator_traits<Allocator>::value_type const & const_reference;
|
||||
typedef const_reference reference;
|
||||
typedef typename vector_type::const_iterator const_iterator;
|
||||
typedef const_iterator iterator;
|
||||
typedef typename std::iterator_traits<
|
||||
BidiIterator>::difference_type difference_type;
|
||||
typedef typename std::allocator_traits<Allocator>::size_type size_type;
|
||||
typedef Allocator allocator_type;
|
||||
typedef typename std::iterator_traits<
|
||||
BidiIterator>::value_type char_type;
|
||||
typedef std::basic_string<char_type> string_type;
|
||||
typedef BOOST_REGEX_DETAIL_NS::named_subexpressions named_sub_type;
|
||||
|
||||
// construct/copy/destroy:
|
||||
explicit match_results(const Allocator& a = Allocator())
|
||||
: m_subs(a), m_base(), m_null(), m_last_closed_paren(0), m_is_singular(true) {}
|
||||
//
|
||||
// IMPORTANT: in the code below, the crazy looking checks around m_is_singular are
|
||||
// all required because it is illegal to copy a singular iterator.
|
||||
// See https://svn.boost.org/trac/boost/ticket/3632.
|
||||
//
|
||||
match_results(const match_results& m)
|
||||
: m_subs(m.m_subs), m_base(), m_null(), m_named_subs(m.m_named_subs), m_last_closed_paren(m.m_last_closed_paren), m_is_singular(m.m_is_singular)
|
||||
{
|
||||
if(!m_is_singular)
|
||||
{
|
||||
m_base = m.m_base;
|
||||
m_null = m.m_null;
|
||||
}
|
||||
}
|
||||
match_results& operator=(const match_results& m)
|
||||
{
|
||||
m_subs = m.m_subs;
|
||||
m_named_subs = m.m_named_subs;
|
||||
m_last_closed_paren = m.m_last_closed_paren;
|
||||
m_is_singular = m.m_is_singular;
|
||||
if(!m_is_singular)
|
||||
{
|
||||
m_base = m.m_base;
|
||||
m_null = m.m_null;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
~match_results(){}
|
||||
|
||||
// size:
|
||||
size_type size() const
|
||||
{ return empty() ? 0 : m_subs.size() - 2; }
|
||||
size_type max_size() const
|
||||
{ return m_subs.max_size(); }
|
||||
bool empty() const
|
||||
{ return m_subs.size() < 2; }
|
||||
// element access:
|
||||
difference_type length(int sub = 0) const
|
||||
{
|
||||
if(m_is_singular)
|
||||
raise_logic_error();
|
||||
sub += 2;
|
||||
if((sub < (int)m_subs.size()) && (sub > 0))
|
||||
return m_subs[sub].length();
|
||||
return 0;
|
||||
}
|
||||
difference_type length(const char_type* sub) const
|
||||
{
|
||||
if(m_is_singular)
|
||||
raise_logic_error();
|
||||
const char_type* sub_end = sub;
|
||||
while(*sub_end) ++sub_end;
|
||||
return length(named_subexpression_index(sub, sub_end));
|
||||
}
|
||||
template <class charT>
|
||||
difference_type length(const charT* sub) const
|
||||
{
|
||||
if(m_is_singular)
|
||||
raise_logic_error();
|
||||
const charT* sub_end = sub;
|
||||
while(*sub_end) ++sub_end;
|
||||
return length(named_subexpression_index(sub, sub_end));
|
||||
}
|
||||
template <class charT, class Traits, class A>
|
||||
difference_type length(const std::basic_string<charT, Traits, A>& sub) const
|
||||
{
|
||||
return length(sub.c_str());
|
||||
}
|
||||
difference_type position(size_type sub = 0) const
|
||||
{
|
||||
if(m_is_singular)
|
||||
raise_logic_error();
|
||||
sub += 2;
|
||||
if(sub < m_subs.size())
|
||||
{
|
||||
const sub_match<BidiIterator>& s = m_subs[sub];
|
||||
if(s.matched || (sub == 2))
|
||||
{
|
||||
return std::distance((BidiIterator)(m_base), (BidiIterator)(s.first));
|
||||
}
|
||||
}
|
||||
return ~static_cast<difference_type>(0);
|
||||
}
|
||||
difference_type position(const char_type* sub) const
|
||||
{
|
||||
const char_type* sub_end = sub;
|
||||
while(*sub_end) ++sub_end;
|
||||
return position(named_subexpression_index(sub, sub_end));
|
||||
}
|
||||
template <class charT>
|
||||
difference_type position(const charT* sub) const
|
||||
{
|
||||
const charT* sub_end = sub;
|
||||
while(*sub_end) ++sub_end;
|
||||
return position(named_subexpression_index(sub, sub_end));
|
||||
}
|
||||
template <class charT, class Traits, class A>
|
||||
difference_type position(const std::basic_string<charT, Traits, A>& sub) const
|
||||
{
|
||||
return position(sub.c_str());
|
||||
}
|
||||
string_type str(int sub = 0) const
|
||||
{
|
||||
if(m_is_singular)
|
||||
raise_logic_error();
|
||||
sub += 2;
|
||||
string_type result;
|
||||
if(sub < (int)m_subs.size() && (sub > 0))
|
||||
{
|
||||
const sub_match<BidiIterator>& s = m_subs[sub];
|
||||
if(s.matched)
|
||||
{
|
||||
result = s.str();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
string_type str(const char_type* sub) const
|
||||
{
|
||||
return (*this)[sub].str();
|
||||
}
|
||||
template <class Traits, class A>
|
||||
string_type str(const std::basic_string<char_type, Traits, A>& sub) const
|
||||
{
|
||||
return (*this)[sub].str();
|
||||
}
|
||||
template <class charT>
|
||||
string_type str(const charT* sub) const
|
||||
{
|
||||
return (*this)[sub].str();
|
||||
}
|
||||
template <class charT, class Traits, class A>
|
||||
string_type str(const std::basic_string<charT, Traits, A>& sub) const
|
||||
{
|
||||
return (*this)[sub].str();
|
||||
}
|
||||
const_reference operator[](int sub) const
|
||||
{
|
||||
if(m_is_singular && m_subs.empty())
|
||||
raise_logic_error();
|
||||
sub += 2;
|
||||
if(sub < (int)m_subs.size() && (sub >= 0))
|
||||
{
|
||||
return m_subs[sub];
|
||||
}
|
||||
return m_null;
|
||||
}
|
||||
//
|
||||
// Named sub-expressions:
|
||||
//
|
||||
const_reference named_subexpression(const char_type* i, const char_type* j) const
|
||||
{
|
||||
//
|
||||
// Scan for the leftmost *matched* subexpression with the specified named:
|
||||
//
|
||||
if(m_is_singular)
|
||||
raise_logic_error();
|
||||
BOOST_REGEX_DETAIL_NS::named_subexpressions::range_type r = m_named_subs->equal_range(i, j);
|
||||
while((r.first != r.second) && ((*this)[r.first->index].matched == false))
|
||||
++r.first;
|
||||
return r.first != r.second ? (*this)[r.first->index] : m_null;
|
||||
}
|
||||
template <class charT>
|
||||
const_reference named_subexpression(const charT* i, const charT* j) const
|
||||
{
|
||||
static_assert(sizeof(charT) <= sizeof(char_type), "Failed internal logic");
|
||||
if(i == j)
|
||||
return m_null;
|
||||
std::vector<char_type> s;
|
||||
while(i != j)
|
||||
s.insert(s.end(), *i++);
|
||||
return named_subexpression(&*s.begin(), &*s.begin() + s.size());
|
||||
}
|
||||
int named_subexpression_index(const char_type* i, const char_type* j) const
|
||||
{
|
||||
//
|
||||
// Scan for the leftmost *matched* subexpression with the specified named.
|
||||
// If none found then return the leftmost expression with that name,
|
||||
// otherwise an invalid index:
|
||||
//
|
||||
if(m_is_singular)
|
||||
raise_logic_error();
|
||||
BOOST_REGEX_DETAIL_NS::named_subexpressions::range_type s, r;
|
||||
s = r = m_named_subs->equal_range(i, j);
|
||||
while((r.first != r.second) && ((*this)[r.first->index].matched == false))
|
||||
++r.first;
|
||||
if(r.first == r.second)
|
||||
r = s;
|
||||
return r.first != r.second ? r.first->index : -20;
|
||||
}
|
||||
template <class charT>
|
||||
int named_subexpression_index(const charT* i, const charT* j) const
|
||||
{
|
||||
static_assert(sizeof(charT) <= sizeof(char_type), "Failed internal logic");
|
||||
if(i == j)
|
||||
return -20;
|
||||
std::vector<char_type> s;
|
||||
while(i != j)
|
||||
s.insert(s.end(), *i++);
|
||||
return named_subexpression_index(&*s.begin(), &*s.begin() + s.size());
|
||||
}
|
||||
template <class Traits, class A>
|
||||
const_reference operator[](const std::basic_string<char_type, Traits, A>& s) const
|
||||
{
|
||||
return named_subexpression(s.c_str(), s.c_str() + s.size());
|
||||
}
|
||||
const_reference operator[](const char_type* p) const
|
||||
{
|
||||
const char_type* e = p;
|
||||
while(*e) ++e;
|
||||
return named_subexpression(p, e);
|
||||
}
|
||||
|
||||
template <class charT>
|
||||
const_reference operator[](const charT* p) const
|
||||
{
|
||||
static_assert(sizeof(charT) <= sizeof(char_type), "Failed internal logic");
|
||||
if(*p == 0)
|
||||
return m_null;
|
||||
std::vector<char_type> s;
|
||||
while(*p)
|
||||
s.insert(s.end(), *p++);
|
||||
return named_subexpression(&*s.begin(), &*s.begin() + s.size());
|
||||
}
|
||||
template <class charT, class Traits, class A>
|
||||
const_reference operator[](const std::basic_string<charT, Traits, A>& ns) const
|
||||
{
|
||||
static_assert(sizeof(charT) <= sizeof(char_type), "Failed internal logic");
|
||||
if(ns.empty())
|
||||
return m_null;
|
||||
std::vector<char_type> s;
|
||||
for(unsigned i = 0; i < ns.size(); ++i)
|
||||
s.insert(s.end(), ns[i]);
|
||||
return named_subexpression(&*s.begin(), &*s.begin() + s.size());
|
||||
}
|
||||
|
||||
const_reference prefix() const
|
||||
{
|
||||
if(m_is_singular)
|
||||
raise_logic_error();
|
||||
return (*this)[-1];
|
||||
}
|
||||
|
||||
const_reference suffix() const
|
||||
{
|
||||
if(m_is_singular)
|
||||
raise_logic_error();
|
||||
return (*this)[-2];
|
||||
}
|
||||
const_iterator begin() const
|
||||
{
|
||||
return (m_subs.size() > 2) ? (m_subs.begin() + 2) : m_subs.end();
|
||||
}
|
||||
const_iterator end() const
|
||||
{
|
||||
return m_subs.end();
|
||||
}
|
||||
// format:
|
||||
template <class OutputIterator, class Functor>
|
||||
OutputIterator format(OutputIterator out,
|
||||
Functor fmt,
|
||||
match_flag_type flags = format_default) const
|
||||
{
|
||||
if(m_is_singular)
|
||||
raise_logic_error();
|
||||
typedef typename BOOST_REGEX_DETAIL_NS::compute_functor_type<Functor, match_results<BidiIterator, Allocator>, OutputIterator>::type F;
|
||||
F func(fmt);
|
||||
return func(*this, out, flags);
|
||||
}
|
||||
template <class Functor>
|
||||
string_type format(Functor fmt, match_flag_type flags = format_default) const
|
||||
{
|
||||
if(m_is_singular)
|
||||
raise_logic_error();
|
||||
std::basic_string<char_type> result;
|
||||
BOOST_REGEX_DETAIL_NS::string_out_iterator<std::basic_string<char_type> > i(result);
|
||||
|
||||
typedef typename BOOST_REGEX_DETAIL_NS::compute_functor_type<Functor, match_results<BidiIterator, Allocator>, BOOST_REGEX_DETAIL_NS::string_out_iterator<std::basic_string<char_type> > >::type F;
|
||||
F func(fmt);
|
||||
|
||||
func(*this, i, flags);
|
||||
return result;
|
||||
}
|
||||
// format with locale:
|
||||
template <class OutputIterator, class Functor, class RegexT>
|
||||
OutputIterator format(OutputIterator out,
|
||||
Functor fmt,
|
||||
match_flag_type flags,
|
||||
const RegexT& re) const
|
||||
{
|
||||
if(m_is_singular)
|
||||
raise_logic_error();
|
||||
typedef ::boost::regex_traits_wrapper<typename RegexT::traits_type> traits_type;
|
||||
typedef typename BOOST_REGEX_DETAIL_NS::compute_functor_type<Functor, match_results<BidiIterator, Allocator>, OutputIterator, traits_type>::type F;
|
||||
F func(fmt);
|
||||
return func(*this, out, flags, re.get_traits());
|
||||
}
|
||||
template <class RegexT, class Functor>
|
||||
string_type format(Functor fmt,
|
||||
match_flag_type flags,
|
||||
const RegexT& re) const
|
||||
{
|
||||
if(m_is_singular)
|
||||
raise_logic_error();
|
||||
typedef ::boost::regex_traits_wrapper<typename RegexT::traits_type> traits_type;
|
||||
std::basic_string<char_type> result;
|
||||
BOOST_REGEX_DETAIL_NS::string_out_iterator<std::basic_string<char_type> > i(result);
|
||||
|
||||
typedef typename BOOST_REGEX_DETAIL_NS::compute_functor_type<Functor, match_results<BidiIterator, Allocator>, BOOST_REGEX_DETAIL_NS::string_out_iterator<std::basic_string<char_type> >, traits_type >::type F;
|
||||
F func(fmt);
|
||||
|
||||
func(*this, i, flags, re.get_traits());
|
||||
return result;
|
||||
}
|
||||
|
||||
const_reference get_last_closed_paren()const
|
||||
{
|
||||
if(m_is_singular)
|
||||
raise_logic_error();
|
||||
return m_last_closed_paren == 0 ? m_null : (*this)[m_last_closed_paren];
|
||||
}
|
||||
|
||||
allocator_type get_allocator() const
|
||||
{
|
||||
return m_subs.get_allocator();
|
||||
}
|
||||
void swap(match_results& that)
|
||||
{
|
||||
std::swap(m_subs, that.m_subs);
|
||||
std::swap(m_named_subs, that.m_named_subs);
|
||||
std::swap(m_last_closed_paren, that.m_last_closed_paren);
|
||||
if(m_is_singular)
|
||||
{
|
||||
if(!that.m_is_singular)
|
||||
{
|
||||
m_base = that.m_base;
|
||||
m_null = that.m_null;
|
||||
}
|
||||
}
|
||||
else if(that.m_is_singular)
|
||||
{
|
||||
that.m_base = m_base;
|
||||
that.m_null = m_null;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::swap(m_base, that.m_base);
|
||||
std::swap(m_null, that.m_null);
|
||||
}
|
||||
std::swap(m_is_singular, that.m_is_singular);
|
||||
}
|
||||
bool operator==(const match_results& that)const
|
||||
{
|
||||
if(m_is_singular)
|
||||
{
|
||||
return that.m_is_singular;
|
||||
}
|
||||
else if(that.m_is_singular)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return (m_subs == that.m_subs) && (m_base == that.m_base) && (m_last_closed_paren == that.m_last_closed_paren);
|
||||
}
|
||||
bool operator!=(const match_results& that)const
|
||||
{ return !(*this == that); }
|
||||
|
||||
#ifdef BOOST_REGEX_MATCH_EXTRA
|
||||
typedef typename sub_match<BidiIterator>::capture_sequence_type capture_sequence_type;
|
||||
|
||||
const capture_sequence_type& captures(int i)const
|
||||
{
|
||||
if(m_is_singular)
|
||||
raise_logic_error();
|
||||
return (*this)[i].captures();
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
// private access functions:
|
||||
void set_second(BidiIterator i)
|
||||
{
|
||||
BOOST_REGEX_ASSERT(m_subs.size() > 2);
|
||||
m_subs[2].second = i;
|
||||
m_subs[2].matched = true;
|
||||
m_subs[0].first = i;
|
||||
m_subs[0].matched = (m_subs[0].first != m_subs[0].second);
|
||||
m_null.first = i;
|
||||
m_null.second = i;
|
||||
m_null.matched = false;
|
||||
m_is_singular = false;
|
||||
}
|
||||
|
||||
void set_second(BidiIterator i, size_type pos, bool m = true, bool escape_k = false)
|
||||
{
|
||||
if(pos)
|
||||
m_last_closed_paren = static_cast<int>(pos);
|
||||
pos += 2;
|
||||
BOOST_REGEX_ASSERT(m_subs.size() > pos);
|
||||
m_subs[pos].second = i;
|
||||
m_subs[pos].matched = m;
|
||||
if((pos == 2) && !escape_k)
|
||||
{
|
||||
m_subs[0].first = i;
|
||||
m_subs[0].matched = (m_subs[0].first != m_subs[0].second);
|
||||
m_null.first = i;
|
||||
m_null.second = i;
|
||||
m_null.matched = false;
|
||||
m_is_singular = false;
|
||||
}
|
||||
}
|
||||
void set_size(size_type n, BidiIterator i, BidiIterator j)
|
||||
{
|
||||
value_type v(j);
|
||||
size_type len = m_subs.size();
|
||||
if(len > n + 2)
|
||||
{
|
||||
m_subs.erase(m_subs.begin()+n+2, m_subs.end());
|
||||
std::fill(m_subs.begin(), m_subs.end(), v);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::fill(m_subs.begin(), m_subs.end(), v);
|
||||
if(n+2 != len)
|
||||
m_subs.insert(m_subs.end(), n+2-len, v);
|
||||
}
|
||||
m_subs[1].first = i;
|
||||
m_last_closed_paren = 0;
|
||||
}
|
||||
void set_base(BidiIterator pos)
|
||||
{
|
||||
m_base = pos;
|
||||
}
|
||||
BidiIterator base()const
|
||||
{
|
||||
return m_base;
|
||||
}
|
||||
void set_first(BidiIterator i)
|
||||
{
|
||||
BOOST_REGEX_ASSERT(m_subs.size() > 2);
|
||||
// set up prefix:
|
||||
m_subs[1].second = i;
|
||||
m_subs[1].matched = (m_subs[1].first != i);
|
||||
// set up $0:
|
||||
m_subs[2].first = i;
|
||||
// zero out everything else:
|
||||
for(size_type n = 3; n < m_subs.size(); ++n)
|
||||
{
|
||||
m_subs[n].first = m_subs[n].second = m_subs[0].second;
|
||||
m_subs[n].matched = false;
|
||||
}
|
||||
}
|
||||
void set_first(BidiIterator i, size_type pos, bool escape_k = false)
|
||||
{
|
||||
BOOST_REGEX_ASSERT(pos+2 < m_subs.size());
|
||||
if(pos || escape_k)
|
||||
{
|
||||
m_subs[pos+2].first = i;
|
||||
if(escape_k)
|
||||
{
|
||||
m_subs[1].second = i;
|
||||
m_subs[1].matched = (m_subs[1].first != m_subs[1].second);
|
||||
}
|
||||
}
|
||||
else
|
||||
set_first(i);
|
||||
}
|
||||
void maybe_assign(const match_results<BidiIterator, Allocator>& m);
|
||||
|
||||
void set_named_subs(std::shared_ptr<named_sub_type> subs)
|
||||
{
|
||||
m_named_subs = subs;
|
||||
}
|
||||
|
||||
private:
|
||||
//
|
||||
// Error handler called when an uninitialized match_results is accessed:
|
||||
//
|
||||
static void raise_logic_error()
|
||||
{
|
||||
std::logic_error e("Attempt to access an uninitialized boost::match_results<> class.");
|
||||
#ifndef BOOST_REGEX_STANDALONE
|
||||
boost::throw_exception(e);
|
||||
#else
|
||||
throw e;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
vector_type m_subs; // subexpressions
|
||||
BidiIterator m_base; // where the search started from
|
||||
sub_match<BidiIterator> m_null; // a null match
|
||||
std::shared_ptr<named_sub_type> m_named_subs; // Shared copy of named subs in the regex object
|
||||
int m_last_closed_paren; // Last ) to be seen - used for formatting
|
||||
bool m_is_singular; // True if our stored iterators are singular
|
||||
};
|
||||
|
||||
template <class BidiIterator, class Allocator>
|
||||
void match_results<BidiIterator, Allocator>::maybe_assign(const match_results<BidiIterator, Allocator>& m)
|
||||
{
|
||||
if(m_is_singular)
|
||||
{
|
||||
*this = m;
|
||||
return;
|
||||
}
|
||||
const_iterator p1, p2;
|
||||
p1 = begin();
|
||||
p2 = m.begin();
|
||||
//
|
||||
// Distances are measured from the start of *this* match, unless this isn't
|
||||
// a valid match in which case we use the start of the whole sequence. Note that
|
||||
// no subsequent match-candidate can ever be to the left of the first match found.
|
||||
// This ensures that when we are using bidirectional iterators, that distances
|
||||
// measured are as short as possible, and therefore as efficient as possible
|
||||
// to compute. Finally note that we don't use the "matched" data member to test
|
||||
// whether a sub-expression is a valid match, because partial matches set this
|
||||
// to false for sub-expression 0.
|
||||
//
|
||||
BidiIterator l_end = this->suffix().second;
|
||||
BidiIterator l_base = (p1->first == l_end) ? this->prefix().first : (*this)[0].first;
|
||||
difference_type len1 = 0;
|
||||
difference_type len2 = 0;
|
||||
difference_type base1 = 0;
|
||||
difference_type base2 = 0;
|
||||
std::size_t i;
|
||||
for(i = 0; i < size(); ++i, ++p1, ++p2)
|
||||
{
|
||||
//
|
||||
// Leftmost takes priority over longest; handle special cases
|
||||
// where distances need not be computed first (an optimisation
|
||||
// for bidirectional iterators: ensure that we don't accidently
|
||||
// compute the length of the whole sequence, as this can be really
|
||||
// expensive).
|
||||
//
|
||||
if(p1->first == l_end)
|
||||
{
|
||||
if(p2->first != l_end)
|
||||
{
|
||||
// p2 must be better than p1, and no need to calculate
|
||||
// actual distances:
|
||||
base1 = 1;
|
||||
base2 = 0;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// *p1 and *p2 are either unmatched or match end-of sequence,
|
||||
// either way no need to calculate distances:
|
||||
if((p1->matched == false) && (p2->matched == true))
|
||||
break;
|
||||
if((p1->matched == true) && (p2->matched == false))
|
||||
return;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if(p2->first == l_end)
|
||||
{
|
||||
// p1 better than p2, and no need to calculate distances:
|
||||
return;
|
||||
}
|
||||
base1 = std::distance(l_base, p1->first);
|
||||
base2 = std::distance(l_base, p2->first);
|
||||
BOOST_REGEX_ASSERT(base1 >= 0);
|
||||
BOOST_REGEX_ASSERT(base2 >= 0);
|
||||
if(base1 < base2) return;
|
||||
if(base2 < base1) break;
|
||||
|
||||
len1 = std::distance((BidiIterator)p1->first, (BidiIterator)p1->second);
|
||||
len2 = std::distance((BidiIterator)p2->first, (BidiIterator)p2->second);
|
||||
BOOST_REGEX_ASSERT(len1 >= 0);
|
||||
BOOST_REGEX_ASSERT(len2 >= 0);
|
||||
if((len1 != len2) || ((p1->matched == false) && (p2->matched == true)))
|
||||
break;
|
||||
if((p1->matched == true) && (p2->matched == false))
|
||||
return;
|
||||
}
|
||||
if(i == size())
|
||||
return;
|
||||
if(base2 < base1)
|
||||
*this = m;
|
||||
else if((len2 > len1) || ((p1->matched == false) && (p2->matched == true)) )
|
||||
*this = m;
|
||||
}
|
||||
|
||||
template <class BidiIterator, class Allocator>
|
||||
void swap(match_results<BidiIterator, Allocator>& a, match_results<BidiIterator, Allocator>& b)
|
||||
{
|
||||
a.swap(b);
|
||||
}
|
||||
|
||||
template <class charT, class traits, class BidiIterator, class Allocator>
|
||||
std::basic_ostream<charT, traits>&
|
||||
operator << (std::basic_ostream<charT, traits>& os,
|
||||
const match_results<BidiIterator, Allocator>& s)
|
||||
{
|
||||
return (os << s.str());
|
||||
}
|
||||
|
||||
#ifdef BOOST_REGEX_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
173
regex/include/boost/regex/v5/mem_block_cache.hpp
Normal file
173
regex/include/boost/regex/v5/mem_block_cache.hpp
Normal file
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* Copyright (c) 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 mem_block_cache.hpp
|
||||
* VERSION see <boost/version.hpp>
|
||||
* DESCRIPTION: memory block cache used by the non-recursive matcher.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_REGEX_V5_MEM_BLOCK_CACHE_HPP
|
||||
#define BOOST_REGEX_V5_MEM_BLOCK_CACHE_HPP
|
||||
|
||||
#include <new>
|
||||
#ifdef BOOST_HAS_THREADS
|
||||
#include <mutex>
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_NO_CXX11_HDR_ATOMIC
|
||||
#include <atomic>
|
||||
#if ATOMIC_POINTER_LOCK_FREE == 2
|
||||
#define BOOST_REGEX_MEM_BLOCK_CACHE_LOCK_FREE
|
||||
#define BOOST_REGEX_ATOMIC_POINTER std::atomic
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace boost{
|
||||
namespace BOOST_REGEX_DETAIL_NS{
|
||||
|
||||
#if BOOST_REGEX_MAX_CACHE_BLOCKS != 0
|
||||
#ifdef BOOST_REGEX_MEM_BLOCK_CACHE_LOCK_FREE /* lock free implementation */
|
||||
struct mem_block_cache
|
||||
{
|
||||
std::atomic<void*> cache[BOOST_REGEX_MAX_CACHE_BLOCKS];
|
||||
|
||||
~mem_block_cache()
|
||||
{
|
||||
for (size_t i = 0;i < BOOST_REGEX_MAX_CACHE_BLOCKS; ++i) {
|
||||
if (cache[i].load()) ::operator delete(cache[i].load());
|
||||
}
|
||||
}
|
||||
void* get()
|
||||
{
|
||||
for (size_t i = 0;i < BOOST_REGEX_MAX_CACHE_BLOCKS; ++i) {
|
||||
void* p = cache[i].load();
|
||||
if (p != NULL) {
|
||||
if (cache[i].compare_exchange_strong(p, NULL)) return p;
|
||||
}
|
||||
}
|
||||
return ::operator new(BOOST_REGEX_BLOCKSIZE);
|
||||
}
|
||||
void put(void* ptr)
|
||||
{
|
||||
for (size_t i = 0;i < BOOST_REGEX_MAX_CACHE_BLOCKS; ++i) {
|
||||
void* p = cache[i].load();
|
||||
if (p == NULL) {
|
||||
if (cache[i].compare_exchange_strong(p, ptr)) return;
|
||||
}
|
||||
}
|
||||
::operator delete(ptr);
|
||||
}
|
||||
|
||||
static mem_block_cache& instance()
|
||||
{
|
||||
static mem_block_cache block_cache = { { {nullptr} } };
|
||||
return block_cache;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#else /* lock-based implementation */
|
||||
|
||||
|
||||
struct mem_block_node
|
||||
{
|
||||
mem_block_node* next;
|
||||
};
|
||||
|
||||
struct mem_block_cache
|
||||
{
|
||||
// this member has to be statically initialsed:
|
||||
mem_block_node* next { nullptr };
|
||||
unsigned cached_blocks { 0 };
|
||||
#ifdef BOOST_HAS_THREADS
|
||||
std::mutex mut;
|
||||
#endif
|
||||
|
||||
~mem_block_cache()
|
||||
{
|
||||
while(next)
|
||||
{
|
||||
mem_block_node* old = next;
|
||||
next = next->next;
|
||||
::operator delete(old);
|
||||
}
|
||||
}
|
||||
void* get()
|
||||
{
|
||||
#ifdef BOOST_HAS_THREADS
|
||||
std::lock_guard<std::mutex> g(mut);
|
||||
#endif
|
||||
if(next)
|
||||
{
|
||||
mem_block_node* result = next;
|
||||
next = next->next;
|
||||
--cached_blocks;
|
||||
return result;
|
||||
}
|
||||
return ::operator new(BOOST_REGEX_BLOCKSIZE);
|
||||
}
|
||||
void put(void* p)
|
||||
{
|
||||
#ifdef BOOST_HAS_THREADS
|
||||
std::lock_guard<std::mutex> g(mut);
|
||||
#endif
|
||||
if(cached_blocks >= BOOST_REGEX_MAX_CACHE_BLOCKS)
|
||||
{
|
||||
::operator delete(p);
|
||||
}
|
||||
else
|
||||
{
|
||||
mem_block_node* old = static_cast<mem_block_node*>(p);
|
||||
old->next = next;
|
||||
next = old;
|
||||
++cached_blocks;
|
||||
}
|
||||
}
|
||||
static mem_block_cache& instance()
|
||||
{
|
||||
static mem_block_cache block_cache;
|
||||
return block_cache;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if BOOST_REGEX_MAX_CACHE_BLOCKS == 0
|
||||
|
||||
inline void* get_mem_block()
|
||||
{
|
||||
return ::operator new(BOOST_REGEX_BLOCKSIZE);
|
||||
}
|
||||
|
||||
inline void put_mem_block(void* p)
|
||||
{
|
||||
::operator delete(p);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
inline void* get_mem_block()
|
||||
{
|
||||
return mem_block_cache::instance().get();
|
||||
}
|
||||
|
||||
inline void put_mem_block(void* p)
|
||||
{
|
||||
mem_block_cache::instance().put(p);
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
|
||||
160
regex/include/boost/regex/v5/object_cache.hpp
Normal file
160
regex/include/boost/regex/v5/object_cache.hpp
Normal file
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
*
|
||||
* 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>
|
||||
#include <memory>
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#ifdef BOOST_HAS_THREADS
|
||||
#include <mutex>
|
||||
#endif
|
||||
|
||||
namespace boost{
|
||||
|
||||
template <class Key, class Object>
|
||||
class object_cache
|
||||
{
|
||||
public:
|
||||
typedef std::pair< ::std::shared_ptr<Object const>, Key const*> value_type;
|
||||
typedef std::list<value_type> list_type;
|
||||
typedef typename list_type::iterator list_iterator;
|
||||
typedef std::map<Key, list_iterator> map_type;
|
||||
typedef typename map_type::iterator map_iterator;
|
||||
typedef typename list_type::size_type size_type;
|
||||
static std::shared_ptr<Object const> get(const Key& k, size_type l_max_cache_size);
|
||||
|
||||
private:
|
||||
static std::shared_ptr<Object const> do_get(const Key& k, size_type l_max_cache_size);
|
||||
|
||||
struct data
|
||||
{
|
||||
list_type cont;
|
||||
map_type index;
|
||||
};
|
||||
|
||||
// Needed by compilers not implementing the resolution to DR45. For reference,
|
||||
// see http://www.open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html#45.
|
||||
friend struct data;
|
||||
};
|
||||
|
||||
#ifdef BOOST_REGEX_MSVC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4702)
|
||||
#endif
|
||||
template <class Key, class Object>
|
||||
std::shared_ptr<Object const> object_cache<Key, Object>::get(const Key& k, size_type l_max_cache_size)
|
||||
{
|
||||
#ifdef BOOST_HAS_THREADS
|
||||
static std::mutex mut;
|
||||
std::lock_guard<std::mutex> l(mut);
|
||||
return do_get(k, l_max_cache_size);
|
||||
#else
|
||||
return do_get(k, l_max_cache_size);
|
||||
#endif
|
||||
}
|
||||
#ifdef BOOST_REGEX_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
template <class Key, class Object>
|
||||
std::shared_ptr<Object const> object_cache<Key, Object>::do_get(const Key& k, size_type l_max_cache_size)
|
||||
{
|
||||
typedef typename object_cache<Key, Object>::data object_data;
|
||||
typedef typename map_type::size_type map_size_type;
|
||||
static object_data s_data;
|
||||
|
||||
//
|
||||
// see if the object is already in the cache:
|
||||
//
|
||||
map_iterator mpos = s_data.index.find(k);
|
||||
if(mpos != s_data.index.end())
|
||||
{
|
||||
//
|
||||
// Eureka!
|
||||
// We have a cached item, bump it up the list and return it:
|
||||
//
|
||||
if(--(s_data.cont.end()) != mpos->second)
|
||||
{
|
||||
// splice out the item we want to move:
|
||||
list_type temp;
|
||||
temp.splice(temp.end(), s_data.cont, mpos->second);
|
||||
// and now place it at the end of the list:
|
||||
s_data.cont.splice(s_data.cont.end(), temp, temp.begin());
|
||||
BOOST_REGEX_ASSERT(*(s_data.cont.back().second) == k);
|
||||
// update index with new position:
|
||||
mpos->second = --(s_data.cont.end());
|
||||
BOOST_REGEX_ASSERT(&(mpos->first) == mpos->second->second);
|
||||
BOOST_REGEX_ASSERT(&(mpos->first) == s_data.cont.back().second);
|
||||
}
|
||||
return s_data.cont.back().first;
|
||||
}
|
||||
//
|
||||
// if we get here then the item is not in the cache,
|
||||
// so create it:
|
||||
//
|
||||
std::shared_ptr<Object const> result(new Object(k));
|
||||
//
|
||||
// Add it to the list, and index it:
|
||||
//
|
||||
s_data.cont.push_back(value_type(result, static_cast<Key const*>(0)));
|
||||
s_data.index.insert(std::make_pair(k, --(s_data.cont.end())));
|
||||
s_data.cont.back().second = &(s_data.index.find(k)->first);
|
||||
map_size_type s = s_data.index.size();
|
||||
BOOST_REGEX_ASSERT(s_data.index[k]->first.get() == result.get());
|
||||
BOOST_REGEX_ASSERT(&(s_data.index.find(k)->first) == s_data.cont.back().second);
|
||||
BOOST_REGEX_ASSERT(s_data.index.find(k)->first == k);
|
||||
if(s > l_max_cache_size)
|
||||
{
|
||||
//
|
||||
// We have too many items in the list, so we need to start
|
||||
// popping them off the back of the list, but only if they're
|
||||
// being held uniquely by us:
|
||||
//
|
||||
list_iterator pos = s_data.cont.begin();
|
||||
list_iterator last = s_data.cont.end();
|
||||
while((pos != last) && (s > l_max_cache_size))
|
||||
{
|
||||
if(pos->first.use_count() == 1)
|
||||
{
|
||||
list_iterator condemmed(pos);
|
||||
++pos;
|
||||
// now remove the items from our containers,
|
||||
// then order has to be as follows:
|
||||
BOOST_REGEX_ASSERT(s_data.index.find(*(condemmed->second)) != s_data.index.end());
|
||||
s_data.index.erase(*(condemmed->second));
|
||||
s_data.cont.erase(condemmed);
|
||||
--s;
|
||||
}
|
||||
else
|
||||
++pos;
|
||||
}
|
||||
BOOST_REGEX_ASSERT(s_data.index[k]->first.get() == result.get());
|
||||
BOOST_REGEX_ASSERT(&(s_data.index.find(k)->first) == s_data.cont.back().second);
|
||||
BOOST_REGEX_ASSERT(s_data.index.find(k)->first == k);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
106
regex/include/boost/regex/v5/pattern_except.hpp
Normal file
106
regex/include/boost/regex/v5/pattern_except.hpp
Normal file
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
*
|
||||
* 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_V5_PAT_EXCEPT_HPP
|
||||
#define BOOST_RE_V5_PAT_EXCEPT_HPP
|
||||
|
||||
#ifndef BOOST_REGEX_CONFIG_HPP
|
||||
#include <boost/regex/config.hpp>
|
||||
#endif
|
||||
|
||||
#include <cstddef>
|
||||
#include <stdexcept>
|
||||
#include <boost/regex/v5/error_type.hpp>
|
||||
#include <boost/regex/v5/regex_traits_defaults.hpp>
|
||||
|
||||
namespace boost{
|
||||
|
||||
#ifdef BOOST_REGEX_MSVC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4275)
|
||||
#if BOOST_REGEX_MSVC >= 1800
|
||||
#pragma warning(disable : 26812 4459)
|
||||
#endif
|
||||
#endif
|
||||
class regex_error : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
explicit regex_error(const std::string& s, regex_constants::error_type err = regex_constants::error_unknown, std::ptrdiff_t pos = 0)
|
||||
: std::runtime_error(s)
|
||||
, m_error_code(err)
|
||||
, m_position(pos)
|
||||
{
|
||||
}
|
||||
explicit regex_error(regex_constants::error_type err)
|
||||
: std::runtime_error(::boost::BOOST_REGEX_DETAIL_NS::get_default_error_string(err))
|
||||
, m_error_code(err)
|
||||
, m_position(0)
|
||||
{
|
||||
}
|
||||
~regex_error() noexcept override {}
|
||||
regex_constants::error_type code()const
|
||||
{ return m_error_code; }
|
||||
std::ptrdiff_t position()const
|
||||
{ return m_position; }
|
||||
void raise()const
|
||||
{
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
#ifndef BOOST_REGEX_STANDALONE
|
||||
::boost::throw_exception(*this);
|
||||
#else
|
||||
throw* this;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
private:
|
||||
regex_constants::error_type m_error_code;
|
||||
std::ptrdiff_t m_position;
|
||||
};
|
||||
|
||||
typedef regex_error bad_pattern;
|
||||
typedef regex_error bad_expression;
|
||||
|
||||
namespace BOOST_REGEX_DETAIL_NS{
|
||||
|
||||
template <class E>
|
||||
inline void raise_runtime_error(const E& ex)
|
||||
{
|
||||
#ifndef BOOST_REGEX_STANDALONE
|
||||
::boost::throw_exception(ex);
|
||||
#else
|
||||
throw ex;
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class traits>
|
||||
void raise_error(const traits& t, regex_constants::error_type code)
|
||||
{
|
||||
(void)t; // warning suppression
|
||||
regex_error e(t.error_string(code), code, 0);
|
||||
::boost::BOOST_REGEX_DETAIL_NS::raise_runtime_error(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#ifdef BOOST_REGEX_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
576
regex/include/boost/regex/v5/perl_matcher.hpp
Normal file
576
regex/include/boost/regex/v5/perl_matcher.hpp
Normal file
@@ -0,0 +1,576 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 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)
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BOOST_REGEX_MATCHER_HPP
|
||||
#define BOOST_REGEX_MATCHER_HPP
|
||||
|
||||
#include <boost/regex/v5/iterator_category.hpp>
|
||||
|
||||
#ifdef BOOST_REGEX_MSVC
|
||||
# pragma warning(push)
|
||||
#pragma warning(disable : 4251 4459)
|
||||
#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{
|
||||
namespace BOOST_REGEX_DETAIL_NS{
|
||||
|
||||
//
|
||||
// error checking API:
|
||||
//
|
||||
inline void verify_options(boost::regex_constants::syntax_option_type, match_flag_type mf)
|
||||
{
|
||||
//
|
||||
// can't mix match_extra with POSIX matching rules:
|
||||
//
|
||||
if ((mf & match_extra) && (mf & match_posix))
|
||||
{
|
||||
std::logic_error msg("Usage Error: Can't mix regular expression captures with POSIX matching rules");
|
||||
#ifndef BOOST_REGEX_STANDALONE
|
||||
throw_exception(msg);
|
||||
#else
|
||||
throw msg;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
//
|
||||
// function can_start:
|
||||
//
|
||||
template <class charT>
|
||||
inline bool can_start(charT c, const unsigned char* map, unsigned char mask)
|
||||
{
|
||||
return ((c < static_cast<charT>(0)) ? true : ((c >= static_cast<charT>(1 << CHAR_BIT)) ? true : map[c] & mask));
|
||||
}
|
||||
inline bool can_start(char c, const unsigned char* map, unsigned char mask)
|
||||
{
|
||||
return map[(unsigned char)c] & mask;
|
||||
}
|
||||
inline bool can_start(signed char c, const unsigned char* map, unsigned char mask)
|
||||
{
|
||||
return map[(unsigned char)c] & mask;
|
||||
}
|
||||
inline bool can_start(unsigned char c, const unsigned char* map, unsigned char mask)
|
||||
{
|
||||
return map[c] & mask;
|
||||
}
|
||||
inline bool can_start(unsigned short c, const unsigned char* map, unsigned char mask)
|
||||
{
|
||||
return ((c >= (1 << CHAR_BIT)) ? true : map[c] & mask);
|
||||
}
|
||||
#if defined(WCHAR_MIN) && (WCHAR_MIN == 0) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
|
||||
inline bool can_start(wchar_t c, const unsigned char* map, unsigned char mask)
|
||||
{
|
||||
return ((c >= static_cast<wchar_t>(1u << CHAR_BIT)) ? true : map[c] & mask);
|
||||
}
|
||||
#endif
|
||||
#if !defined(BOOST_NO_INTRINSIC_WCHAR_T)
|
||||
inline bool can_start(unsigned int c, const unsigned char* map, unsigned char mask)
|
||||
{
|
||||
return (((c >= static_cast<unsigned int>(1u << CHAR_BIT)) ? true : map[c] & mask));
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class C, class T, class A>
|
||||
inline int string_compare(const std::basic_string<C,T,A>& s, const C* p)
|
||||
{
|
||||
if(0 == *p)
|
||||
{
|
||||
if(s.empty() || ((s.size() == 1) && (s[0] == 0)))
|
||||
return 0;
|
||||
}
|
||||
return s.compare(p);
|
||||
}
|
||||
template <class Seq, class C>
|
||||
inline int string_compare(const Seq& s, const C* p)
|
||||
{
|
||||
std::size_t i = 0;
|
||||
while((i < s.size()) && (p[i] == s[i]))
|
||||
{
|
||||
++i;
|
||||
}
|
||||
return (i == s.size()) ? -(int)p[i] : (int)s[i] - (int)p[i];
|
||||
}
|
||||
# define STR_COMP(s,p) string_compare(s,p)
|
||||
|
||||
template<class charT>
|
||||
inline const charT* re_skip_past_null(const charT* p)
|
||||
{
|
||||
while (*p != static_cast<charT>(0)) ++p;
|
||||
return ++p;
|
||||
}
|
||||
|
||||
template <class iterator, class charT, class traits_type, class char_classT>
|
||||
iterator re_is_set_member(iterator next,
|
||||
iterator last,
|
||||
const re_set_long<char_classT>* set_,
|
||||
const regex_data<charT, traits_type>& e, bool icase)
|
||||
{
|
||||
const charT* p = reinterpret_cast<const charT*>(set_+1);
|
||||
iterator ptr;
|
||||
unsigned int i;
|
||||
//bool icase = e.m_flags & regex_constants::icase;
|
||||
|
||||
if(next == last) return next;
|
||||
|
||||
typedef typename traits_type::string_type traits_string_type;
|
||||
const ::boost::regex_traits_wrapper<traits_type>& traits_inst = *(e.m_ptraits);
|
||||
|
||||
// dwa 9/13/00 suppress incorrect MSVC warning - it claims this is never
|
||||
// referenced
|
||||
(void)traits_inst;
|
||||
|
||||
// try and match a single character, could be a multi-character
|
||||
// collating element...
|
||||
for(i = 0; i < set_->csingles; ++i)
|
||||
{
|
||||
ptr = next;
|
||||
if(*p == static_cast<charT>(0))
|
||||
{
|
||||
// treat null string as special case:
|
||||
if(traits_inst.translate(*ptr, icase))
|
||||
{
|
||||
++p;
|
||||
continue;
|
||||
}
|
||||
return set_->isnot ? next : (ptr == next) ? ++next : ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
while(*p && (ptr != last))
|
||||
{
|
||||
if(traits_inst.translate(*ptr, icase) != *p)
|
||||
break;
|
||||
++p;
|
||||
++ptr;
|
||||
}
|
||||
|
||||
if(*p == static_cast<charT>(0)) // if null we've matched
|
||||
return set_->isnot ? next : (ptr == next) ? ++next : ptr;
|
||||
|
||||
p = re_skip_past_null(p); // skip null
|
||||
}
|
||||
}
|
||||
|
||||
charT col = traits_inst.translate(*next, icase);
|
||||
|
||||
|
||||
if(set_->cranges || set_->cequivalents)
|
||||
{
|
||||
traits_string_type s1;
|
||||
//
|
||||
// try and match a range, NB only a single character can match
|
||||
if(set_->cranges)
|
||||
{
|
||||
if((e.m_flags & regex_constants::collate) == 0)
|
||||
s1.assign(1, col);
|
||||
else
|
||||
{
|
||||
charT a[2] = { col, charT(0), };
|
||||
s1 = traits_inst.transform(a, a + 1);
|
||||
}
|
||||
for(i = 0; i < set_->cranges; ++i)
|
||||
{
|
||||
if(STR_COMP(s1, p) >= 0)
|
||||
{
|
||||
do{ ++p; }while(*p);
|
||||
++p;
|
||||
if(STR_COMP(s1, p) <= 0)
|
||||
return set_->isnot ? next : ++next;
|
||||
}
|
||||
else
|
||||
{
|
||||
// skip first string
|
||||
do{ ++p; }while(*p);
|
||||
++p;
|
||||
}
|
||||
// skip second string
|
||||
do{ ++p; }while(*p);
|
||||
++p;
|
||||
}
|
||||
}
|
||||
//
|
||||
// try and match an equivalence class, NB only a single character can match
|
||||
if(set_->cequivalents)
|
||||
{
|
||||
charT a[2] = { col, charT(0), };
|
||||
s1 = traits_inst.transform_primary(a, a +1);
|
||||
for(i = 0; i < set_->cequivalents; ++i)
|
||||
{
|
||||
if(STR_COMP(s1, p) == 0)
|
||||
return set_->isnot ? next : ++next;
|
||||
// skip string
|
||||
do{ ++p; }while(*p);
|
||||
++p;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(traits_inst.isctype(col, set_->cclasses) == true)
|
||||
return set_->isnot ? next : ++next;
|
||||
if((set_->cnclasses != 0) && (traits_inst.isctype(col, set_->cnclasses) == false))
|
||||
return set_->isnot ? next : ++next;
|
||||
return set_->isnot ? ++next : next;
|
||||
}
|
||||
|
||||
template <class BidiIterator>
|
||||
class repeater_count
|
||||
{
|
||||
repeater_count** stack;
|
||||
repeater_count* next;
|
||||
int state_id;
|
||||
std::size_t count; // the number of iterations so far
|
||||
BidiIterator start_pos; // where the last repeat started
|
||||
|
||||
repeater_count* unwind_until(int n, repeater_count* p, int current_recursion_id)
|
||||
{
|
||||
while(p && (p->state_id != n))
|
||||
{
|
||||
if(-2 - current_recursion_id == p->state_id)
|
||||
return 0;
|
||||
p = p->next;
|
||||
if(p && (p->state_id < 0))
|
||||
{
|
||||
p = unwind_until(p->state_id, p, current_recursion_id);
|
||||
if(!p)
|
||||
return p;
|
||||
p = p->next;
|
||||
}
|
||||
}
|
||||
return p;
|
||||
}
|
||||
public:
|
||||
repeater_count(repeater_count** s) : stack(s), next(0), state_id(-1), count(0), start_pos() {}
|
||||
|
||||
repeater_count(int i, repeater_count** s, BidiIterator start, int current_recursion_id)
|
||||
: start_pos(start)
|
||||
{
|
||||
state_id = i;
|
||||
stack = s;
|
||||
next = *stack;
|
||||
*stack = this;
|
||||
if((state_id > next->state_id) && (next->state_id >= 0))
|
||||
count = 0;
|
||||
else
|
||||
{
|
||||
repeater_count* p = next;
|
||||
p = unwind_until(state_id, p, current_recursion_id);
|
||||
if(p)
|
||||
{
|
||||
count = p->count;
|
||||
start_pos = p->start_pos;
|
||||
}
|
||||
else
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
~repeater_count()
|
||||
{
|
||||
if(next)
|
||||
*stack = next;
|
||||
}
|
||||
std::size_t get_count() { return count; }
|
||||
int get_id() { return state_id; }
|
||||
std::size_t operator++() { return ++count; }
|
||||
bool check_null_repeat(const BidiIterator& pos, std::size_t max)
|
||||
{
|
||||
// this is called when we are about to start a new repeat,
|
||||
// if the last one was NULL move our count to max,
|
||||
// otherwise save the current position.
|
||||
bool result = (count == 0) ? false : (pos == start_pos);
|
||||
if(result)
|
||||
count = max;
|
||||
else
|
||||
start_pos = pos;
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
struct saved_state;
|
||||
|
||||
enum saved_state_type
|
||||
{
|
||||
saved_type_end = 0,
|
||||
saved_type_paren = 1,
|
||||
saved_type_recurse = 2,
|
||||
saved_type_assertion = 3,
|
||||
saved_state_alt = 4,
|
||||
saved_state_repeater_count = 5,
|
||||
saved_state_extra_block = 6,
|
||||
saved_state_greedy_single_repeat = 7,
|
||||
saved_state_rep_slow_dot = 8,
|
||||
saved_state_rep_fast_dot = 9,
|
||||
saved_state_rep_char = 10,
|
||||
saved_state_rep_short_set = 11,
|
||||
saved_state_rep_long_set = 12,
|
||||
saved_state_non_greedy_long_repeat = 13,
|
||||
saved_state_count = 14
|
||||
};
|
||||
|
||||
#ifdef BOOST_REGEX_MSVC
|
||||
# pragma warning(push)
|
||||
#if BOOST_REGEX_MSVC >= 1800
|
||||
#pragma warning(disable:26495)
|
||||
#endif
|
||||
#endif
|
||||
template <class Results>
|
||||
struct recursion_info
|
||||
{
|
||||
typedef typename Results::value_type value_type;
|
||||
typedef typename value_type::iterator iterator;
|
||||
int idx;
|
||||
const re_syntax_base* preturn_address;
|
||||
Results results;
|
||||
repeater_count<iterator>* repeater_stack;
|
||||
iterator location_of_start;
|
||||
};
|
||||
#ifdef BOOST_REGEX_MSVC
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
template <class BidiIterator, class Allocator, class traits>
|
||||
class perl_matcher
|
||||
{
|
||||
public:
|
||||
typedef typename traits::char_type char_type;
|
||||
typedef perl_matcher<BidiIterator, Allocator, traits> self_type;
|
||||
typedef bool (self_type::*matcher_proc_type)();
|
||||
typedef std::size_t traits_size_type;
|
||||
typedef typename is_byte<char_type>::width_type width_type;
|
||||
typedef typename std::iterator_traits<BidiIterator>::difference_type difference_type;
|
||||
typedef match_results<BidiIterator, Allocator> results_type;
|
||||
|
||||
perl_matcher(BidiIterator first, BidiIterator end,
|
||||
match_results<BidiIterator, Allocator>& what,
|
||||
const basic_regex<char_type, traits>& e,
|
||||
match_flag_type f,
|
||||
BidiIterator l_base)
|
||||
: m_result(what), base(first), last(end),
|
||||
position(first), backstop(l_base), re(e), traits_inst(e.get_traits()),
|
||||
m_independent(false), next_count(&rep_obj), rep_obj(&next_count)
|
||||
, m_recursions(0)
|
||||
{
|
||||
construct_init(e, f);
|
||||
}
|
||||
|
||||
bool match();
|
||||
bool find();
|
||||
|
||||
void setf(match_flag_type f)
|
||||
{ m_match_flags |= f; }
|
||||
void unsetf(match_flag_type f)
|
||||
{ m_match_flags &= ~f; }
|
||||
|
||||
private:
|
||||
void construct_init(const basic_regex<char_type, traits>& e, match_flag_type f);
|
||||
|
||||
bool find_imp();
|
||||
bool match_imp();
|
||||
void estimate_max_state_count(std::random_access_iterator_tag*);
|
||||
void estimate_max_state_count(void*);
|
||||
bool match_prefix();
|
||||
bool match_all_states();
|
||||
|
||||
// match procs, stored in s_match_vtable:
|
||||
bool match_startmark();
|
||||
bool match_endmark();
|
||||
bool match_literal();
|
||||
bool match_start_line();
|
||||
bool match_end_line();
|
||||
bool match_wild();
|
||||
bool match_match();
|
||||
bool match_word_boundary();
|
||||
bool match_within_word();
|
||||
bool match_word_start();
|
||||
bool match_word_end();
|
||||
bool match_buffer_start();
|
||||
bool match_buffer_end();
|
||||
bool match_backref();
|
||||
bool match_long_set();
|
||||
bool match_set();
|
||||
bool match_jump();
|
||||
bool match_alt();
|
||||
bool match_rep();
|
||||
bool match_combining();
|
||||
bool match_soft_buffer_end();
|
||||
bool match_restart_continue();
|
||||
bool match_long_set_repeat();
|
||||
bool match_set_repeat();
|
||||
bool match_char_repeat();
|
||||
bool match_dot_repeat_fast();
|
||||
bool match_dot_repeat_slow();
|
||||
bool match_dot_repeat_dispatch()
|
||||
{
|
||||
return ::boost::is_random_access_iterator<BidiIterator>::value ? match_dot_repeat_fast() : match_dot_repeat_slow();
|
||||
}
|
||||
bool match_backstep();
|
||||
bool match_assert_backref();
|
||||
bool match_toggle_case();
|
||||
bool match_recursion();
|
||||
bool match_fail();
|
||||
bool match_accept();
|
||||
bool match_commit();
|
||||
bool match_then();
|
||||
bool skip_until_paren(int index, bool match = true);
|
||||
|
||||
// find procs stored in s_find_vtable:
|
||||
bool find_restart_any();
|
||||
bool find_restart_word();
|
||||
bool find_restart_line();
|
||||
bool find_restart_buf();
|
||||
bool find_restart_lit();
|
||||
|
||||
private:
|
||||
// final result structure to be filled in:
|
||||
match_results<BidiIterator, Allocator>& m_result;
|
||||
// temporary result for POSIX matches:
|
||||
std::unique_ptr<match_results<BidiIterator, Allocator> > m_temp_match;
|
||||
// pointer to actual result structure to fill in:
|
||||
match_results<BidiIterator, Allocator>* m_presult;
|
||||
// start of sequence being searched:
|
||||
BidiIterator base;
|
||||
// end of sequence being searched:
|
||||
BidiIterator last;
|
||||
// current character being examined:
|
||||
BidiIterator position;
|
||||
// where to restart next search after failed match attempt:
|
||||
BidiIterator restart;
|
||||
// where the current search started from, acts as base for $` during grep:
|
||||
BidiIterator search_base;
|
||||
// how far we can go back when matching lookbehind:
|
||||
BidiIterator backstop;
|
||||
// the expression being examined:
|
||||
const basic_regex<char_type, traits>& re;
|
||||
// the expression's traits class:
|
||||
const ::boost::regex_traits_wrapper<traits>& traits_inst;
|
||||
// the next state in the machine being matched:
|
||||
const re_syntax_base* pstate;
|
||||
// matching flags in use:
|
||||
match_flag_type m_match_flags;
|
||||
// how many states we have examined so far:
|
||||
std::ptrdiff_t state_count;
|
||||
// max number of states to examine before giving up:
|
||||
std::ptrdiff_t max_state_count;
|
||||
// whether we should ignore case or not:
|
||||
bool icase;
|
||||
// set to true when (position == last), indicates that we may have a partial match:
|
||||
bool m_has_partial_match;
|
||||
// set to true whenever we get a match:
|
||||
bool m_has_found_match;
|
||||
// set to true whenever we're inside an independent sub-expression:
|
||||
bool m_independent;
|
||||
// the current repeat being examined:
|
||||
repeater_count<BidiIterator>* next_count;
|
||||
// the first repeat being examined (top of linked list):
|
||||
repeater_count<BidiIterator> rep_obj;
|
||||
// the mask to pass when matching word boundaries:
|
||||
typename traits::char_class_type m_word_mask;
|
||||
// the bitmask to use when determining whether a match_any matches a newline or not:
|
||||
unsigned char match_any_mask;
|
||||
// recursion information:
|
||||
std::vector<recursion_info<results_type> > recursion_stack;
|
||||
//
|
||||
// additional members for non-recursive version:
|
||||
//
|
||||
typedef bool (self_type::*unwind_proc_type)(bool);
|
||||
|
||||
void extend_stack();
|
||||
bool unwind(bool);
|
||||
bool unwind_end(bool);
|
||||
bool unwind_paren(bool);
|
||||
bool unwind_recursion_stopper(bool);
|
||||
bool unwind_assertion(bool);
|
||||
bool unwind_alt(bool);
|
||||
bool unwind_repeater_counter(bool);
|
||||
bool unwind_extra_block(bool);
|
||||
bool unwind_greedy_single_repeat(bool);
|
||||
bool unwind_slow_dot_repeat(bool);
|
||||
bool unwind_fast_dot_repeat(bool);
|
||||
bool unwind_char_repeat(bool);
|
||||
bool unwind_short_set_repeat(bool);
|
||||
bool unwind_long_set_repeat(bool);
|
||||
bool unwind_non_greedy_repeat(bool);
|
||||
bool unwind_recursion(bool);
|
||||
bool unwind_recursion_pop(bool);
|
||||
bool unwind_commit(bool);
|
||||
bool unwind_then(bool);
|
||||
bool unwind_case(bool);
|
||||
void destroy_single_repeat();
|
||||
void push_matched_paren(int index, const sub_match<BidiIterator>& sub);
|
||||
void push_recursion_stopper();
|
||||
void push_assertion(const re_syntax_base* ps, bool positive);
|
||||
void push_alt(const re_syntax_base* ps);
|
||||
void push_repeater_count(int i, repeater_count<BidiIterator>** s);
|
||||
void push_single_repeat(std::size_t c, const re_repeat* r, BidiIterator last_position, int state_id);
|
||||
void push_non_greedy_repeat(const re_syntax_base* ps);
|
||||
void push_recursion(int idx, const re_syntax_base* p, results_type* presults, results_type* presults2);
|
||||
void push_recursion_pop();
|
||||
void push_case_change(bool);
|
||||
|
||||
// pointer to base of stack:
|
||||
saved_state* m_stack_base;
|
||||
// pointer to current stack position:
|
||||
saved_state* m_backup_state;
|
||||
// how many memory blocks have we used up?:
|
||||
unsigned used_block_count;
|
||||
// determines what value to return when unwinding from recursion,
|
||||
// allows for mixed recursive/non-recursive algorithm:
|
||||
bool m_recursive_result;
|
||||
// We have unwound to a lookahead/lookbehind, used by COMMIT/PRUNE/SKIP:
|
||||
bool m_unwound_lookahead;
|
||||
// We have unwound to an alternative, used by THEN:
|
||||
bool m_unwound_alt;
|
||||
// We are unwinding a commit - used by independent subs to determine whether to stop there or carry on unwinding:
|
||||
//bool m_unwind_commit;
|
||||
// Recursion limit:
|
||||
unsigned m_recursions;
|
||||
|
||||
#ifdef BOOST_REGEX_MSVC
|
||||
# pragma warning(push)
|
||||
#if BOOST_REGEX_MSVC >= 1800
|
||||
#pragma warning(disable:26495)
|
||||
#endif
|
||||
#endif
|
||||
// these operations aren't allowed, so are declared private,
|
||||
// bodies are provided to keep explicit-instantiation requests happy:
|
||||
perl_matcher& operator=(const perl_matcher&)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
perl_matcher(const perl_matcher& that)
|
||||
: m_result(that.m_result), re(that.re), traits_inst(that.traits_inst), rep_obj(0) {}
|
||||
#ifdef BOOST_REGEX_MSVC
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace BOOST_REGEX_DETAIL_NS
|
||||
|
||||
#ifdef BOOST_REGEX_MSVC
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
} // namespace boost
|
||||
|
||||
//
|
||||
// include the implementation of perl_matcher:
|
||||
//
|
||||
#include <boost/regex/v5/perl_matcher_non_recursive.hpp>
|
||||
// this one has to be last:
|
||||
#include <boost/regex/v5/perl_matcher_common.hpp>
|
||||
|
||||
#endif
|
||||
921
regex/include/boost/regex/v5/perl_matcher_common.hpp
Normal file
921
regex/include/boost/regex/v5/perl_matcher_common.hpp
Normal file
@@ -0,0 +1,921 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 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 perl_matcher_common.cpp
|
||||
* VERSION see <boost/version.hpp>
|
||||
* DESCRIPTION: Definitions of perl_matcher member functions that are
|
||||
* common to both the recursive and non-recursive versions.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_REGEX_V5_PERL_MATCHER_COMMON_HPP
|
||||
#define BOOST_REGEX_V5_PERL_MATCHER_COMMON_HPP
|
||||
|
||||
#ifdef BOOST_REGEX_MSVC
|
||||
# pragma warning(push)
|
||||
#pragma warning(disable:4459)
|
||||
#if BOOST_REGEX_MSVC < 1910
|
||||
#pragma warning(disable:4800)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace boost{
|
||||
namespace BOOST_REGEX_DETAIL_NS{
|
||||
|
||||
#ifdef BOOST_REGEX_MSVC
|
||||
# pragma warning(push)
|
||||
#pragma warning(disable:26812)
|
||||
#endif
|
||||
template <class BidiIterator, class Allocator, class traits>
|
||||
void perl_matcher<BidiIterator, Allocator, traits>::construct_init(const basic_regex<char_type, traits>& e, match_flag_type f)
|
||||
{
|
||||
typedef typename std::iterator_traits<BidiIterator>::iterator_category category;
|
||||
typedef typename basic_regex<char_type, traits>::flag_type expression_flag_type;
|
||||
|
||||
if(e.empty())
|
||||
{
|
||||
// precondition failure: e is not a valid regex.
|
||||
std::invalid_argument ex("Invalid regular expression object");
|
||||
#ifndef BOOST_REGEX_STANDALONE
|
||||
boost::throw_exception(ex);
|
||||
#else
|
||||
throw e;
|
||||
#endif
|
||||
}
|
||||
pstate = 0;
|
||||
m_match_flags = f;
|
||||
estimate_max_state_count(static_cast<category*>(0));
|
||||
expression_flag_type re_f = re.flags();
|
||||
icase = re_f & regex_constants::icase;
|
||||
if(!(m_match_flags & (match_perl|match_posix)))
|
||||
{
|
||||
if((re_f & (regbase::main_option_type|regbase::no_perl_ex)) == 0)
|
||||
m_match_flags |= match_perl;
|
||||
else if((re_f & (regbase::main_option_type|regbase::emacs_ex)) == (regbase::basic_syntax_group|regbase::emacs_ex))
|
||||
m_match_flags |= match_perl;
|
||||
else if((re_f & (regbase::main_option_type|regbase::literal)) == (regbase::literal))
|
||||
m_match_flags |= match_perl;
|
||||
else
|
||||
m_match_flags |= match_posix;
|
||||
}
|
||||
if(m_match_flags & match_posix)
|
||||
{
|
||||
m_temp_match.reset(new match_results<BidiIterator, Allocator>());
|
||||
m_presult = m_temp_match.get();
|
||||
}
|
||||
else
|
||||
m_presult = &m_result;
|
||||
m_stack_base = 0;
|
||||
m_backup_state = 0;
|
||||
// find the value to use for matching word boundaries:
|
||||
m_word_mask = re.get_data().m_word_mask;
|
||||
// find bitmask to use for matching '.':
|
||||
match_any_mask = static_cast<unsigned char>((f & match_not_dot_newline) ? BOOST_REGEX_DETAIL_NS::test_not_newline : BOOST_REGEX_DETAIL_NS::test_newline);
|
||||
// Disable match_any if requested in the state machine:
|
||||
if(e.get_data().m_disable_match_any)
|
||||
m_match_flags &= regex_constants::match_not_any;
|
||||
}
|
||||
#ifdef BOOST_REGEX_MSVC
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
template <class BidiIterator, class Allocator, class traits>
|
||||
void perl_matcher<BidiIterator, Allocator, traits>::estimate_max_state_count(std::random_access_iterator_tag*)
|
||||
{
|
||||
//
|
||||
// How many states should we allow our machine to visit before giving up?
|
||||
// This is a heuristic: it takes the greater of O(N^2) and O(NS^2)
|
||||
// where N is the length of the string, and S is the number of states
|
||||
// in the machine. It's tempting to up this to O(N^2S) or even O(N^2S^2)
|
||||
// but these take unreasonably amounts of time to bale out in pathological
|
||||
// cases.
|
||||
//
|
||||
// Calculate NS^2 first:
|
||||
//
|
||||
static const std::ptrdiff_t k = 100000;
|
||||
std::ptrdiff_t dist = std::distance(base, last);
|
||||
if(dist == 0)
|
||||
dist = 1;
|
||||
std::ptrdiff_t states = re.size();
|
||||
if(states == 0)
|
||||
states = 1;
|
||||
if ((std::numeric_limits<std::ptrdiff_t>::max)() / states < states)
|
||||
{
|
||||
max_state_count = (std::min)((std::ptrdiff_t)BOOST_REGEX_MAX_STATE_COUNT, (std::numeric_limits<std::ptrdiff_t>::max)() - 2);
|
||||
return;
|
||||
}
|
||||
states *= states;
|
||||
if((std::numeric_limits<std::ptrdiff_t>::max)() / dist < states)
|
||||
{
|
||||
max_state_count = (std::min)((std::ptrdiff_t)BOOST_REGEX_MAX_STATE_COUNT, (std::numeric_limits<std::ptrdiff_t>::max)() - 2);
|
||||
return;
|
||||
}
|
||||
states *= dist;
|
||||
if((std::numeric_limits<std::ptrdiff_t>::max)() - k < states)
|
||||
{
|
||||
max_state_count = (std::min)((std::ptrdiff_t)BOOST_REGEX_MAX_STATE_COUNT, (std::numeric_limits<std::ptrdiff_t>::max)() - 2);
|
||||
return;
|
||||
}
|
||||
states += k;
|
||||
|
||||
max_state_count = states;
|
||||
|
||||
//
|
||||
// Now calculate N^2:
|
||||
//
|
||||
states = dist;
|
||||
if((std::numeric_limits<std::ptrdiff_t>::max)() / dist < states)
|
||||
{
|
||||
max_state_count = (std::min)((std::ptrdiff_t)BOOST_REGEX_MAX_STATE_COUNT, (std::numeric_limits<std::ptrdiff_t>::max)() - 2);
|
||||
return;
|
||||
}
|
||||
states *= dist;
|
||||
if((std::numeric_limits<std::ptrdiff_t>::max)() - k < states)
|
||||
{
|
||||
max_state_count = (std::min)((std::ptrdiff_t)BOOST_REGEX_MAX_STATE_COUNT, (std::numeric_limits<std::ptrdiff_t>::max)() - 2);
|
||||
return;
|
||||
}
|
||||
states += k;
|
||||
//
|
||||
// N^2 can be a very large number indeed, to prevent things getting out
|
||||
// of control, cap the max states:
|
||||
//
|
||||
if(states > BOOST_REGEX_MAX_STATE_COUNT)
|
||||
states = BOOST_REGEX_MAX_STATE_COUNT;
|
||||
//
|
||||
// If (the possibly capped) N^2 is larger than our first estimate,
|
||||
// use this instead:
|
||||
//
|
||||
if(states > max_state_count)
|
||||
max_state_count = states;
|
||||
}
|
||||
|
||||
template <class BidiIterator, class Allocator, class traits>
|
||||
inline void perl_matcher<BidiIterator, Allocator, traits>::estimate_max_state_count(void*)
|
||||
{
|
||||
// we don't know how long the sequence is:
|
||||
max_state_count = BOOST_REGEX_MAX_STATE_COUNT;
|
||||
}
|
||||
|
||||
template <class BidiIterator, class Allocator, class traits>
|
||||
inline bool perl_matcher<BidiIterator, Allocator, traits>::match()
|
||||
{
|
||||
return match_imp();
|
||||
}
|
||||
|
||||
template <class BidiIterator, class Allocator, class traits>
|
||||
bool perl_matcher<BidiIterator, Allocator, traits>::match_imp()
|
||||
{
|
||||
// initialise our stack if we are non-recursive:
|
||||
save_state_init init(&m_stack_base, &m_backup_state);
|
||||
used_block_count = BOOST_REGEX_MAX_BLOCKS;
|
||||
#if !defined(BOOST_NO_EXCEPTIONS)
|
||||
try{
|
||||
#endif
|
||||
|
||||
// reset our state machine:
|
||||
position = base;
|
||||
search_base = base;
|
||||
state_count = 0;
|
||||
m_match_flags |= regex_constants::match_all;
|
||||
m_presult->set_size((m_match_flags & match_nosubs) ? 1u : static_cast<typename results_type::size_type>(1u + re.mark_count()), search_base, last);
|
||||
m_presult->set_base(base);
|
||||
m_presult->set_named_subs(this->re.get_named_subs());
|
||||
if(m_match_flags & match_posix)
|
||||
m_result = *m_presult;
|
||||
verify_options(re.flags(), m_match_flags);
|
||||
if(0 == match_prefix())
|
||||
return false;
|
||||
return (m_result[0].second == last) && (m_result[0].first == base);
|
||||
|
||||
#if !defined(BOOST_NO_EXCEPTIONS)
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
// unwind all pushed states, apart from anything else this
|
||||
// ensures that all the states are correctly destructed
|
||||
// not just the memory freed.
|
||||
while(unwind(true)){}
|
||||
throw;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class BidiIterator, class Allocator, class traits>
|
||||
inline bool perl_matcher<BidiIterator, Allocator, traits>::find()
|
||||
{
|
||||
return find_imp();
|
||||
}
|
||||
|
||||
template <class BidiIterator, class Allocator, class traits>
|
||||
bool perl_matcher<BidiIterator, Allocator, traits>::find_imp()
|
||||
{
|
||||
static matcher_proc_type const s_find_vtable[7] =
|
||||
{
|
||||
&perl_matcher<BidiIterator, Allocator, traits>::find_restart_any,
|
||||
&perl_matcher<BidiIterator, Allocator, traits>::find_restart_word,
|
||||
&perl_matcher<BidiIterator, Allocator, traits>::find_restart_line,
|
||||
&perl_matcher<BidiIterator, Allocator, traits>::find_restart_buf,
|
||||
&perl_matcher<BidiIterator, Allocator, traits>::match_prefix,
|
||||
&perl_matcher<BidiIterator, Allocator, traits>::find_restart_lit,
|
||||
&perl_matcher<BidiIterator, Allocator, traits>::find_restart_lit,
|
||||
};
|
||||
|
||||
// initialise our stack if we are non-recursive:
|
||||
save_state_init init(&m_stack_base, &m_backup_state);
|
||||
used_block_count = BOOST_REGEX_MAX_BLOCKS;
|
||||
#if !defined(BOOST_NO_EXCEPTIONS)
|
||||
try{
|
||||
#endif
|
||||
|
||||
state_count = 0;
|
||||
if((m_match_flags & regex_constants::match_init) == 0)
|
||||
{
|
||||
// reset our state machine:
|
||||
search_base = position = base;
|
||||
pstate = re.get_first_state();
|
||||
m_presult->set_size((m_match_flags & match_nosubs) ? 1u : static_cast<typename results_type::size_type>(1u + re.mark_count()), base, last);
|
||||
m_presult->set_base(base);
|
||||
m_presult->set_named_subs(this->re.get_named_subs());
|
||||
m_match_flags |= regex_constants::match_init;
|
||||
}
|
||||
else
|
||||
{
|
||||
// start again:
|
||||
search_base = position = m_result[0].second;
|
||||
// If last match was null and match_not_null was not set then increment
|
||||
// our start position, otherwise we go into an infinite loop:
|
||||
if(((m_match_flags & match_not_null) == 0) && (m_result.length() == 0))
|
||||
{
|
||||
if(position == last)
|
||||
return false;
|
||||
else
|
||||
++position;
|
||||
}
|
||||
// reset $` start:
|
||||
m_presult->set_size((m_match_flags & match_nosubs) ? 1u : static_cast<typename results_type::size_type>(1u + re.mark_count()), search_base, last);
|
||||
//if((base != search_base) && (base == backstop))
|
||||
// m_match_flags |= match_prev_avail;
|
||||
}
|
||||
if(m_match_flags & match_posix)
|
||||
{
|
||||
m_result.set_size(static_cast<typename results_type::size_type>(1u + re.mark_count()), base, last);
|
||||
m_result.set_base(base);
|
||||
}
|
||||
|
||||
verify_options(re.flags(), m_match_flags);
|
||||
// find out what kind of expression we have:
|
||||
unsigned type = (m_match_flags & match_continuous) ?
|
||||
static_cast<unsigned int>(regbase::restart_continue)
|
||||
: static_cast<unsigned int>(re.get_restart_type());
|
||||
|
||||
// call the appropriate search routine:
|
||||
matcher_proc_type proc = s_find_vtable[type];
|
||||
return (this->*proc)();
|
||||
|
||||
#if !defined(BOOST_NO_EXCEPTIONS)
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
// unwind all pushed states, apart from anything else this
|
||||
// ensures that all the states are correctly destructed
|
||||
// not just the memory freed.
|
||||
while(unwind(true)){}
|
||||
throw;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class BidiIterator, class Allocator, class traits>
|
||||
bool perl_matcher<BidiIterator, Allocator, traits>::match_prefix()
|
||||
{
|
||||
m_has_partial_match = false;
|
||||
m_has_found_match = false;
|
||||
pstate = re.get_first_state();
|
||||
m_presult->set_first(position);
|
||||
restart = position;
|
||||
match_all_states();
|
||||
if(!m_has_found_match && m_has_partial_match && (m_match_flags & match_partial))
|
||||
{
|
||||
m_has_found_match = true;
|
||||
m_presult->set_second(last, 0, false);
|
||||
position = last;
|
||||
if((m_match_flags & match_posix) == match_posix)
|
||||
{
|
||||
m_result.maybe_assign(*m_presult);
|
||||
}
|
||||
}
|
||||
#ifdef BOOST_REGEX_MATCH_EXTRA
|
||||
if(m_has_found_match && (match_extra & m_match_flags))
|
||||
{
|
||||
//
|
||||
// we have a match, reverse the capture information:
|
||||
//
|
||||
for(unsigned i = 0; i < m_presult->size(); ++i)
|
||||
{
|
||||
typename sub_match<BidiIterator>::capture_sequence_type & seq = ((*m_presult)[i]).get_captures();
|
||||
std::reverse(seq.begin(), seq.end());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if(!m_has_found_match)
|
||||
position = restart; // reset search postion
|
||||
return m_has_found_match;
|
||||
}
|
||||
|
||||
template <class BidiIterator, class Allocator, class traits>
|
||||
bool perl_matcher<BidiIterator, Allocator, traits>::match_literal()
|
||||
{
|
||||
unsigned int len = static_cast<const re_literal*>(pstate)->length;
|
||||
const char_type* what = reinterpret_cast<const char_type*>(static_cast<const re_literal*>(pstate) + 1);
|
||||
//
|
||||
// compare string with what we stored in
|
||||
// our records:
|
||||
for(unsigned int i = 0; i < len; ++i, ++position)
|
||||
{
|
||||
if((position == last) || (traits_inst.translate(*position, icase) != what[i]))
|
||||
return false;
|
||||
}
|
||||
pstate = pstate->next.p;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class BidiIterator, class Allocator, class traits>
|
||||
bool perl_matcher<BidiIterator, Allocator, traits>::match_start_line()
|
||||
{
|
||||
if(position == backstop)
|
||||
{
|
||||
if((m_match_flags & match_prev_avail) == 0)
|
||||
{
|
||||
if((m_match_flags & match_not_bol) == 0)
|
||||
{
|
||||
pstate = pstate->next.p;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if(m_match_flags & match_single_line)
|
||||
return false;
|
||||
|
||||
// check the previous value character:
|
||||
BidiIterator t(position);
|
||||
--t;
|
||||
if(position != last)
|
||||
{
|
||||
if(is_separator(*t) && !((*t == static_cast<char_type>('\r')) && (*position == static_cast<char_type>('\n'))) )
|
||||
{
|
||||
pstate = pstate->next.p;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if(is_separator(*t))
|
||||
{
|
||||
pstate = pstate->next.p;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class BidiIterator, class Allocator, class traits>
|
||||
bool perl_matcher<BidiIterator, Allocator, traits>::match_end_line()
|
||||
{
|
||||
if(position != last)
|
||||
{
|
||||
if(m_match_flags & match_single_line)
|
||||
return false;
|
||||
// we're not yet at the end so *first is always valid:
|
||||
if(is_separator(*position))
|
||||
{
|
||||
if((position != backstop) || (m_match_flags & match_prev_avail))
|
||||
{
|
||||
// check that we're not in the middle of \r\n sequence
|
||||
BidiIterator t(position);
|
||||
--t;
|
||||
if((*t == static_cast<char_type>('\r')) && (*position == static_cast<char_type>('\n')))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
pstate = pstate->next.p;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if((m_match_flags & match_not_eol) == 0)
|
||||
{
|
||||
pstate = pstate->next.p;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class BidiIterator, class Allocator, class traits>
|
||||
bool perl_matcher<BidiIterator, Allocator, traits>::match_wild()
|
||||
{
|
||||
if(position == last)
|
||||
return false;
|
||||
if(is_separator(*position) && ((match_any_mask & static_cast<const re_dot*>(pstate)->mask) == 0))
|
||||
return false;
|
||||
if((*position == char_type(0)) && (m_match_flags & match_not_dot_null))
|
||||
return false;
|
||||
pstate = pstate->next.p;
|
||||
++position;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class BidiIterator, class Allocator, class traits>
|
||||
bool perl_matcher<BidiIterator, Allocator, traits>::match_word_boundary()
|
||||
{
|
||||
bool b; // indcates whether next character is a word character
|
||||
if(position != last)
|
||||
{
|
||||
// prev and this character must be opposites:
|
||||
b = traits_inst.isctype(*position, m_word_mask);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_match_flags & match_not_eow)
|
||||
return false;
|
||||
b = false;
|
||||
}
|
||||
if((position == backstop) && ((m_match_flags & match_prev_avail) == 0))
|
||||
{
|
||||
if(m_match_flags & match_not_bow)
|
||||
return false;
|
||||
else
|
||||
b ^= false;
|
||||
}
|
||||
else
|
||||
{
|
||||
--position;
|
||||
b ^= traits_inst.isctype(*position, m_word_mask);
|
||||
++position;
|
||||
}
|
||||
if(b)
|
||||
{
|
||||
pstate = pstate->next.p;
|
||||
return true;
|
||||
}
|
||||
return false; // no match if we get to here...
|
||||
}
|
||||
|
||||
template <class BidiIterator, class Allocator, class traits>
|
||||
bool perl_matcher<BidiIterator, Allocator, traits>::match_within_word()
|
||||
{
|
||||
bool b = !match_word_boundary();
|
||||
if(b)
|
||||
pstate = pstate->next.p;
|
||||
return b;
|
||||
/*
|
||||
if(position == last)
|
||||
return false;
|
||||
// both prev and this character must be m_word_mask:
|
||||
bool prev = traits_inst.isctype(*position, m_word_mask);
|
||||
{
|
||||
bool b;
|
||||
if((position == backstop) && ((m_match_flags & match_prev_avail) == 0))
|
||||
return false;
|
||||
else
|
||||
{
|
||||
--position;
|
||||
b = traits_inst.isctype(*position, m_word_mask);
|
||||
++position;
|
||||
}
|
||||
if(b == prev)
|
||||
{
|
||||
pstate = pstate->next.p;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
*/
|
||||
}
|
||||
|
||||
template <class BidiIterator, class Allocator, class traits>
|
||||
bool perl_matcher<BidiIterator, Allocator, traits>::match_word_start()
|
||||
{
|
||||
if(position == last)
|
||||
return false; // can't be starting a word if we're already at the end of input
|
||||
if(!traits_inst.isctype(*position, m_word_mask))
|
||||
return false; // next character isn't a word character
|
||||
if((position == backstop) && ((m_match_flags & match_prev_avail) == 0))
|
||||
{
|
||||
if(m_match_flags & match_not_bow)
|
||||
return false; // no previous input
|
||||
}
|
||||
else
|
||||
{
|
||||
// otherwise inside buffer:
|
||||
BidiIterator t(position);
|
||||
--t;
|
||||
if(traits_inst.isctype(*t, m_word_mask))
|
||||
return false; // previous character not non-word
|
||||
}
|
||||
// OK we have a match:
|
||||
pstate = pstate->next.p;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class BidiIterator, class Allocator, class traits>
|
||||
bool perl_matcher<BidiIterator, Allocator, traits>::match_word_end()
|
||||
{
|
||||
if((position == backstop) && ((m_match_flags & match_prev_avail) == 0))
|
||||
return false; // start of buffer can't be end of word
|
||||
BidiIterator t(position);
|
||||
--t;
|
||||
if(traits_inst.isctype(*t, m_word_mask) == false)
|
||||
return false; // previous character wasn't a word character
|
||||
|
||||
if(position == last)
|
||||
{
|
||||
if(m_match_flags & match_not_eow)
|
||||
return false; // end of buffer but not end of word
|
||||
}
|
||||
else
|
||||
{
|
||||
// otherwise inside buffer:
|
||||
if(traits_inst.isctype(*position, m_word_mask))
|
||||
return false; // next character is a word character
|
||||
}
|
||||
pstate = pstate->next.p;
|
||||
return true; // if we fall through to here then we've succeeded
|
||||
}
|
||||
|
||||
template <class BidiIterator, class Allocator, class traits>
|
||||
bool perl_matcher<BidiIterator, Allocator, traits>::match_buffer_start()
|
||||
{
|
||||
if((position != backstop) || (m_match_flags & match_not_bob))
|
||||
return false;
|
||||
// OK match:
|
||||
pstate = pstate->next.p;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class BidiIterator, class Allocator, class traits>
|
||||
bool perl_matcher<BidiIterator, Allocator, traits>::match_buffer_end()
|
||||
{
|
||||
if((position != last) || (m_match_flags & match_not_eob))
|
||||
return false;
|
||||
// OK match:
|
||||
pstate = pstate->next.p;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class BidiIterator, class Allocator, class traits>
|
||||
bool perl_matcher<BidiIterator, Allocator, traits>::match_backref()
|
||||
{
|
||||
//
|
||||
// Compare with what we previously matched.
|
||||
// Note that this succeeds if the backref did not partisipate
|
||||
// in the match, this is in line with ECMAScript, but not Perl
|
||||
// or PCRE.
|
||||
//
|
||||
int index = static_cast<const re_brace*>(pstate)->index;
|
||||
if(index >= hash_value_mask)
|
||||
{
|
||||
named_subexpressions::range_type r = re.get_data().equal_range(index);
|
||||
BOOST_REGEX_ASSERT(r.first != r.second);
|
||||
do
|
||||
{
|
||||
index = r.first->index;
|
||||
++r.first;
|
||||
}while((r.first != r.second) && ((*m_presult)[index].matched != true));
|
||||
}
|
||||
|
||||
if((m_match_flags & match_perl) && !(*m_presult)[index].matched)
|
||||
return false;
|
||||
|
||||
BidiIterator i = (*m_presult)[index].first;
|
||||
BidiIterator j = (*m_presult)[index].second;
|
||||
while(i != j)
|
||||
{
|
||||
if((position == last) || (traits_inst.translate(*position, icase) != traits_inst.translate(*i, icase)))
|
||||
return false;
|
||||
++i;
|
||||
++position;
|
||||
}
|
||||
pstate = pstate->next.p;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class BidiIterator, class Allocator, class traits>
|
||||
bool perl_matcher<BidiIterator, Allocator, traits>::match_long_set()
|
||||
{
|
||||
typedef typename traits::char_class_type char_class_type;
|
||||
// let the traits class do the work:
|
||||
if(position == last)
|
||||
return false;
|
||||
BidiIterator t = re_is_set_member(position, last, static_cast<const re_set_long<char_class_type>*>(pstate), re.get_data(), icase);
|
||||
if(t != position)
|
||||
{
|
||||
pstate = pstate->next.p;
|
||||
position = t;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class BidiIterator, class Allocator, class traits>
|
||||
bool perl_matcher<BidiIterator, Allocator, traits>::match_set()
|
||||
{
|
||||
if(position == last)
|
||||
return false;
|
||||
if(static_cast<const re_set*>(pstate)->_map[static_cast<unsigned char>(traits_inst.translate(*position, icase))])
|
||||
{
|
||||
pstate = pstate->next.p;
|
||||
++position;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class BidiIterator, class Allocator, class traits>
|
||||
bool perl_matcher<BidiIterator, Allocator, traits>::match_jump()
|
||||
{
|
||||
pstate = static_cast<const re_jump*>(pstate)->alt.p;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class BidiIterator, class Allocator, class traits>
|
||||
bool perl_matcher<BidiIterator, Allocator, traits>::match_combining()
|
||||
{
|
||||
if(position == last)
|
||||
return false;
|
||||
if(is_combining(traits_inst.translate(*position, icase)))
|
||||
return false;
|
||||
++position;
|
||||
while((position != last) && is_combining(traits_inst.translate(*position, icase)))
|
||||
++position;
|
||||
pstate = pstate->next.p;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class BidiIterator, class Allocator, class traits>
|
||||
bool perl_matcher<BidiIterator, Allocator, traits>::match_soft_buffer_end()
|
||||
{
|
||||
if(m_match_flags & match_not_eob)
|
||||
return false;
|
||||
BidiIterator p(position);
|
||||
while((p != last) && is_separator(traits_inst.translate(*p, icase)))++p;
|
||||
if(p != last)
|
||||
return false;
|
||||
pstate = pstate->next.p;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class BidiIterator, class Allocator, class traits>
|
||||
bool perl_matcher<BidiIterator, Allocator, traits>::match_restart_continue()
|
||||
{
|
||||
if(position == search_base)
|
||||
{
|
||||
pstate = pstate->next.p;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class BidiIterator, class Allocator, class traits>
|
||||
bool perl_matcher<BidiIterator, Allocator, traits>::match_backstep()
|
||||
{
|
||||
#ifdef BOOST_REGEX_MSVC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4127)
|
||||
#endif
|
||||
if( ::boost::is_random_access_iterator<BidiIterator>::value)
|
||||
{
|
||||
std::ptrdiff_t maxlen = std::distance(backstop, position);
|
||||
if(maxlen < static_cast<const re_brace*>(pstate)->index)
|
||||
return false;
|
||||
std::advance(position, -static_cast<const re_brace*>(pstate)->index);
|
||||
}
|
||||
else
|
||||
{
|
||||
int c = static_cast<const re_brace*>(pstate)->index;
|
||||
while(c--)
|
||||
{
|
||||
if(position == backstop)
|
||||
return false;
|
||||
--position;
|
||||
}
|
||||
}
|
||||
pstate = pstate->next.p;
|
||||
return true;
|
||||
#ifdef BOOST_REGEX_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class BidiIterator, class Allocator, class traits>
|
||||
inline bool perl_matcher<BidiIterator, Allocator, traits>::match_assert_backref()
|
||||
{
|
||||
// return true if marked sub-expression N has been matched:
|
||||
int index = static_cast<const re_brace*>(pstate)->index;
|
||||
bool result = false;
|
||||
if(index == 9999)
|
||||
{
|
||||
// Magic value for a (DEFINE) block:
|
||||
return false;
|
||||
}
|
||||
else if(index > 0)
|
||||
{
|
||||
// Have we matched subexpression "index"?
|
||||
// Check if index is a hash value:
|
||||
if(index >= hash_value_mask)
|
||||
{
|
||||
named_subexpressions::range_type r = re.get_data().equal_range(index);
|
||||
while(r.first != r.second)
|
||||
{
|
||||
if((*m_presult)[r.first->index].matched)
|
||||
{
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
++r.first;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = (*m_presult)[index].matched;
|
||||
}
|
||||
pstate = pstate->next.p;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Have we recursed into subexpression "index"?
|
||||
// If index == 0 then check for any recursion at all, otherwise for recursion to -index-1.
|
||||
int idx = -(index+1);
|
||||
if(idx >= hash_value_mask)
|
||||
{
|
||||
named_subexpressions::range_type r = re.get_data().equal_range(idx);
|
||||
int stack_index = recursion_stack.empty() ? -1 : recursion_stack.back().idx;
|
||||
while(r.first != r.second)
|
||||
{
|
||||
result |= (stack_index == r.first->index);
|
||||
if(result)break;
|
||||
++r.first;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = !recursion_stack.empty() && ((recursion_stack.back().idx == idx) || (index == 0));
|
||||
}
|
||||
pstate = pstate->next.p;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class BidiIterator, class Allocator, class traits>
|
||||
bool perl_matcher<BidiIterator, Allocator, traits>::match_fail()
|
||||
{
|
||||
// Just force a backtrack:
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class BidiIterator, class Allocator, class traits>
|
||||
bool perl_matcher<BidiIterator, Allocator, traits>::match_accept()
|
||||
{
|
||||
if(!recursion_stack.empty())
|
||||
{
|
||||
return skip_until_paren(recursion_stack.back().idx);
|
||||
}
|
||||
else
|
||||
{
|
||||
return skip_until_paren(INT_MAX);
|
||||
}
|
||||
}
|
||||
|
||||
template <class BidiIterator, class Allocator, class traits>
|
||||
bool perl_matcher<BidiIterator, Allocator, traits>::find_restart_any()
|
||||
{
|
||||
#ifdef BOOST_REGEX_MSVC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4127)
|
||||
#endif
|
||||
const unsigned char* _map = re.get_map();
|
||||
while(true)
|
||||
{
|
||||
// skip everything we can't match:
|
||||
while((position != last) && !can_start(*position, _map, (unsigned char)mask_any) )
|
||||
++position;
|
||||
if(position == last)
|
||||
{
|
||||
// run out of characters, try a null match if possible:
|
||||
if(re.can_be_null())
|
||||
return match_prefix();
|
||||
break;
|
||||
}
|
||||
// now try and obtain a match:
|
||||
if(match_prefix())
|
||||
return true;
|
||||
if(position == last)
|
||||
return false;
|
||||
++position;
|
||||
}
|
||||
return false;
|
||||
#ifdef BOOST_REGEX_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class BidiIterator, class Allocator, class traits>
|
||||
bool perl_matcher<BidiIterator, Allocator, traits>::find_restart_word()
|
||||
{
|
||||
#ifdef BOOST_REGEX_MSVC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4127)
|
||||
#endif
|
||||
// do search optimised for word starts:
|
||||
const unsigned char* _map = re.get_map();
|
||||
if((m_match_flags & match_prev_avail) || (position != base))
|
||||
--position;
|
||||
else if(match_prefix())
|
||||
return true;
|
||||
do
|
||||
{
|
||||
while((position != last) && traits_inst.isctype(*position, m_word_mask))
|
||||
++position;
|
||||
while((position != last) && !traits_inst.isctype(*position, m_word_mask))
|
||||
++position;
|
||||
if(position == last)
|
||||
break;
|
||||
|
||||
if(can_start(*position, _map, (unsigned char)mask_any) )
|
||||
{
|
||||
if(match_prefix())
|
||||
return true;
|
||||
}
|
||||
if(position == last)
|
||||
break;
|
||||
} while(true);
|
||||
return false;
|
||||
#ifdef BOOST_REGEX_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class BidiIterator, class Allocator, class traits>
|
||||
bool perl_matcher<BidiIterator, Allocator, traits>::find_restart_line()
|
||||
{
|
||||
// do search optimised for line starts:
|
||||
const unsigned char* _map = re.get_map();
|
||||
if(match_prefix())
|
||||
return true;
|
||||
while(position != last)
|
||||
{
|
||||
while((position != last) && !is_separator(*position))
|
||||
++position;
|
||||
if(position == last)
|
||||
return false;
|
||||
++position;
|
||||
if(position == last)
|
||||
{
|
||||
if(re.can_be_null() && match_prefix())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
if( can_start(*position, _map, (unsigned char)mask_any) )
|
||||
{
|
||||
if(match_prefix())
|
||||
return true;
|
||||
}
|
||||
if(position == last)
|
||||
return false;
|
||||
//++position;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class BidiIterator, class Allocator, class traits>
|
||||
bool perl_matcher<BidiIterator, Allocator, traits>::find_restart_buf()
|
||||
{
|
||||
if((position == base) && ((m_match_flags & match_not_bob) == 0))
|
||||
return match_prefix();
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class BidiIterator, class Allocator, class traits>
|
||||
bool perl_matcher<BidiIterator, Allocator, traits>::find_restart_lit()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace BOOST_REGEX_DETAIL_NS
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#ifdef BOOST_REGEX_MSVC
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
1874
regex/include/boost/regex/v5/perl_matcher_non_recursive.hpp
Normal file
1874
regex/include/boost/regex/v5/perl_matcher_non_recursive.hpp
Normal file
File diff suppressed because it is too large
Load Diff
120
regex/include/boost/regex/v5/primary_transform.hpp
Normal file
120
regex/include/boost/regex/v5/primary_transform.hpp
Normal file
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
*
|
||||
* 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: primary_transform.hpp
|
||||
* VERSION: see <boost/version.hpp>
|
||||
* DESCRIPTION: Heuristically determines the sort string format in use
|
||||
* by the current locale.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_REGEX_PRIMARY_TRANSFORM
|
||||
#define BOOST_REGEX_PRIMARY_TRANSFORM
|
||||
|
||||
namespace boost{
|
||||
namespace BOOST_REGEX_DETAIL_NS{
|
||||
|
||||
|
||||
enum{
|
||||
sort_C,
|
||||
sort_fixed,
|
||||
sort_delim,
|
||||
sort_unknown
|
||||
};
|
||||
|
||||
template <class S, class charT>
|
||||
unsigned count_chars(const S& s, charT c)
|
||||
{
|
||||
//
|
||||
// Count how many occurrences of character c occur
|
||||
// in string s: if c is a delimeter between collation
|
||||
// fields, then this should be the same value for all
|
||||
// sort keys:
|
||||
//
|
||||
unsigned int count = 0;
|
||||
for(unsigned pos = 0; pos < s.size(); ++pos)
|
||||
{
|
||||
if(s[pos] == c) ++count;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
template <class traits, class charT>
|
||||
unsigned find_sort_syntax(const traits* pt, charT* delim)
|
||||
{
|
||||
//
|
||||
// compare 'a' with 'A' to see how similar they are,
|
||||
// should really use a-accute but we can't portably do that,
|
||||
//
|
||||
typedef typename traits::string_type string_type;
|
||||
typedef typename traits::char_type char_type;
|
||||
|
||||
// Suppress incorrect warning for MSVC
|
||||
(void)pt;
|
||||
|
||||
char_type a[2] = {'a', '\0', };
|
||||
string_type sa(pt->transform(a, a+1));
|
||||
if(sa == a)
|
||||
{
|
||||
*delim = 0;
|
||||
return sort_C;
|
||||
}
|
||||
char_type A[2] = { 'A', '\0', };
|
||||
string_type sA(pt->transform(A, A+1));
|
||||
char_type c[2] = { ';', '\0', };
|
||||
string_type sc(pt->transform(c, c+1));
|
||||
|
||||
int pos = 0;
|
||||
while((pos <= static_cast<int>(sa.size())) && (pos <= static_cast<int>(sA.size())) && (sa[pos] == sA[pos])) ++pos;
|
||||
--pos;
|
||||
if(pos < 0)
|
||||
{
|
||||
*delim = 0;
|
||||
return sort_unknown;
|
||||
}
|
||||
//
|
||||
// at this point sa[pos] is either the end of a fixed width field
|
||||
// or the character that acts as a delimiter:
|
||||
//
|
||||
charT maybe_delim = sa[pos];
|
||||
if((pos != 0) && (count_chars(sa, maybe_delim) == count_chars(sA, maybe_delim)) && (count_chars(sa, maybe_delim) == count_chars(sc, maybe_delim)))
|
||||
{
|
||||
*delim = maybe_delim;
|
||||
return sort_delim;
|
||||
}
|
||||
//
|
||||
// OK doen't look like a delimiter, try for fixed width field:
|
||||
//
|
||||
if((sa.size() == sA.size()) && (sa.size() == sc.size()))
|
||||
{
|
||||
// note assumes that the fixed width field is less than
|
||||
// (numeric_limits<charT>::max)(), should be true for all types
|
||||
// I can't imagine 127 character fields...
|
||||
*delim = static_cast<charT>(++pos);
|
||||
return sort_fixed;
|
||||
}
|
||||
//
|
||||
// don't know what it is:
|
||||
//
|
||||
*delim = 0;
|
||||
return sort_unknown;
|
||||
}
|
||||
|
||||
|
||||
} // namespace BOOST_REGEX_DETAIL_NS
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
158
regex/include/boost/regex/v5/regbase.hpp
Normal file
158
regex/include/boost/regex/v5/regbase.hpp
Normal file
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
*
|
||||
* 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 regbase.cpp
|
||||
* VERSION see <boost/version.hpp>
|
||||
* DESCRIPTION: Declares class regbase.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_REGEX_V5_REGBASE_HPP
|
||||
#define BOOST_REGEX_V5_REGBASE_HPP
|
||||
|
||||
namespace boost{
|
||||
//
|
||||
// class regbase
|
||||
// handles error codes and flags
|
||||
//
|
||||
class regbase
|
||||
{
|
||||
public:
|
||||
enum flag_type_
|
||||
{
|
||||
//
|
||||
// Divide the flags up into logical groups:
|
||||
// bits 0-7 indicate main synatx type.
|
||||
// bits 8-15 indicate syntax subtype.
|
||||
// bits 16-31 indicate options that are common to all
|
||||
// regex syntaxes.
|
||||
// In all cases the default is 0.
|
||||
//
|
||||
// Main synatx group:
|
||||
//
|
||||
perl_syntax_group = 0, // default
|
||||
basic_syntax_group = 1, // POSIX basic
|
||||
literal = 2, // all characters are literals
|
||||
main_option_type = literal | basic_syntax_group | perl_syntax_group, // everything!
|
||||
//
|
||||
// options specific to perl group:
|
||||
//
|
||||
no_bk_refs = 1 << 8, // \d not allowed
|
||||
no_perl_ex = 1 << 9, // disable perl extensions
|
||||
no_mod_m = 1 << 10, // disable Perl m modifier
|
||||
mod_x = 1 << 11, // Perl x modifier
|
||||
mod_s = 1 << 12, // force s modifier on (overrides match_not_dot_newline)
|
||||
no_mod_s = 1 << 13, // force s modifier off (overrides match_not_dot_newline)
|
||||
|
||||
//
|
||||
// options specific to basic group:
|
||||
//
|
||||
no_char_classes = 1 << 8, // [[:CLASS:]] not allowed
|
||||
no_intervals = 1 << 9, // {x,y} not allowed
|
||||
bk_plus_qm = 1 << 10, // uses \+ and \?
|
||||
bk_vbar = 1 << 11, // use \| for alternatives
|
||||
emacs_ex = 1 << 12, // enables emacs extensions
|
||||
|
||||
//
|
||||
// options common to all groups:
|
||||
//
|
||||
no_escape_in_lists = 1 << 16, // '\' not special inside [...]
|
||||
newline_alt = 1 << 17, // \n is the same as |
|
||||
no_except = 1 << 18, // no exception on error
|
||||
failbit = 1 << 19, // error flag
|
||||
icase = 1 << 20, // characters are matched regardless of case
|
||||
nocollate = 0, // don't use locale specific collation (deprecated)
|
||||
collate = 1 << 21, // use locale specific collation
|
||||
nosubs = 1 << 22, // don't mark sub-expressions
|
||||
save_subexpression_location = 1 << 23, // save subexpression locations
|
||||
no_empty_expressions = 1 << 24, // no empty expressions allowed
|
||||
optimize = 0, // not really supported
|
||||
|
||||
|
||||
|
||||
basic = basic_syntax_group | collate | no_escape_in_lists,
|
||||
extended = no_bk_refs | collate | no_perl_ex | no_escape_in_lists,
|
||||
normal = 0,
|
||||
emacs = basic_syntax_group | collate | emacs_ex | bk_vbar,
|
||||
awk = no_bk_refs | collate | no_perl_ex,
|
||||
grep = basic | newline_alt,
|
||||
egrep = extended | newline_alt,
|
||||
sed = basic,
|
||||
perl = normal,
|
||||
ECMAScript = normal,
|
||||
JavaScript = normal,
|
||||
JScript = normal
|
||||
};
|
||||
typedef unsigned int flag_type;
|
||||
|
||||
enum restart_info
|
||||
{
|
||||
restart_any = 0,
|
||||
restart_word = 1,
|
||||
restart_line = 2,
|
||||
restart_buf = 3,
|
||||
restart_continue = 4,
|
||||
restart_lit = 5,
|
||||
restart_fixed_lit = 6,
|
||||
restart_count = 7
|
||||
};
|
||||
};
|
||||
|
||||
//
|
||||
// provide std lib proposal compatible constants:
|
||||
//
|
||||
namespace regex_constants{
|
||||
|
||||
enum flag_type_
|
||||
{
|
||||
|
||||
no_except = ::boost::regbase::no_except,
|
||||
failbit = ::boost::regbase::failbit,
|
||||
literal = ::boost::regbase::literal,
|
||||
icase = ::boost::regbase::icase,
|
||||
nocollate = ::boost::regbase::nocollate,
|
||||
collate = ::boost::regbase::collate,
|
||||
nosubs = ::boost::regbase::nosubs,
|
||||
optimize = ::boost::regbase::optimize,
|
||||
bk_plus_qm = ::boost::regbase::bk_plus_qm,
|
||||
bk_vbar = ::boost::regbase::bk_vbar,
|
||||
no_intervals = ::boost::regbase::no_intervals,
|
||||
no_char_classes = ::boost::regbase::no_char_classes,
|
||||
no_escape_in_lists = ::boost::regbase::no_escape_in_lists,
|
||||
no_mod_m = ::boost::regbase::no_mod_m,
|
||||
mod_x = ::boost::regbase::mod_x,
|
||||
mod_s = ::boost::regbase::mod_s,
|
||||
no_mod_s = ::boost::regbase::no_mod_s,
|
||||
save_subexpression_location = ::boost::regbase::save_subexpression_location,
|
||||
no_empty_expressions = ::boost::regbase::no_empty_expressions,
|
||||
|
||||
basic = ::boost::regbase::basic,
|
||||
extended = ::boost::regbase::extended,
|
||||
normal = ::boost::regbase::normal,
|
||||
emacs = ::boost::regbase::emacs,
|
||||
awk = ::boost::regbase::awk,
|
||||
grep = ::boost::regbase::grep,
|
||||
egrep = ::boost::regbase::egrep,
|
||||
sed = basic,
|
||||
perl = normal,
|
||||
ECMAScript = normal,
|
||||
JavaScript = normal,
|
||||
JScript = normal
|
||||
};
|
||||
typedef ::boost::regbase::flag_type syntax_option_type;
|
||||
|
||||
} // namespace regex_constants
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
|
||||
106
regex/include/boost/regex/v5/regex.hpp
Normal file
106
regex/include/boost/regex/v5/regex.hpp
Normal file
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
*
|
||||
* 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.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.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_RE_REGEX_HPP_INCLUDED
|
||||
#define BOOST_RE_REGEX_HPP_INCLUDED
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
// what follows is all C++ don't include in C builds!!
|
||||
|
||||
#include <boost/regex/config.hpp>
|
||||
#include <boost/regex/v5/regex_workaround.hpp>
|
||||
#include <boost/regex_fwd.hpp>
|
||||
#include <boost/regex/regex_traits.hpp>
|
||||
#include <boost/regex/v5/error_type.hpp>
|
||||
#include <boost/regex/v5/match_flags.hpp>
|
||||
#include <boost/regex/v5/regex_raw_buffer.hpp>
|
||||
#include <boost/regex/pattern_except.hpp>
|
||||
#include <boost/regex/v5/char_regex_traits.hpp>
|
||||
#include <boost/regex/v5/states.hpp>
|
||||
#include <boost/regex/v5/regbase.hpp>
|
||||
#include <boost/regex/v5/basic_regex.hpp>
|
||||
#include <boost/regex/v5/basic_regex_creator.hpp>
|
||||
#include <boost/regex/v5/basic_regex_parser.hpp>
|
||||
#include <boost/regex/v5/sub_match.hpp>
|
||||
#include <boost/regex/v5/regex_format.hpp>
|
||||
#include <boost/regex/v5/match_results.hpp>
|
||||
#include <boost/regex/v5/perl_matcher.hpp>
|
||||
|
||||
namespace boost{
|
||||
#ifdef BOOST_REGEX_NO_FWD
|
||||
typedef basic_regex<char, regex_traits<char> > regex;
|
||||
#ifndef BOOST_NO_WREGEX
|
||||
typedef basic_regex<wchar_t, regex_traits<wchar_t> > wregex;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
typedef match_results<const char*> cmatch;
|
||||
typedef match_results<std::string::const_iterator> smatch;
|
||||
#ifndef BOOST_NO_WREGEX
|
||||
typedef match_results<const wchar_t*> wcmatch;
|
||||
typedef match_results<std::wstring::const_iterator> wsmatch;
|
||||
#endif
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/regex/v5/regex_match.hpp>
|
||||
#include <boost/regex/v5/regex_search.hpp>
|
||||
#include <boost/regex/v5/regex_iterator.hpp>
|
||||
#include <boost/regex/v5/regex_token_iterator.hpp>
|
||||
#include <boost/regex/v5/regex_grep.hpp>
|
||||
#include <boost/regex/v5/regex_replace.hpp>
|
||||
#include <boost/regex/v5/regex_merge.hpp>
|
||||
#include <boost/regex/v5/regex_split.hpp>
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // include
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
1124
regex/include/boost/regex/v5/regex_format.hpp
Normal file
1124
regex/include/boost/regex/v5/regex_format.hpp
Normal file
File diff suppressed because it is too large
Load Diff
73
regex/include/boost/regex/v5/regex_fwd.hpp
Normal file
73
regex/include/boost/regex/v5/regex_fwd.hpp
Normal file
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
*
|
||||
* 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_fwd.cpp
|
||||
* VERSION see <boost/version.hpp>
|
||||
* DESCRIPTION: Forward declares boost::basic_regex<> and
|
||||
* associated typedefs.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_REGEX_FWD_HPP_INCLUDED
|
||||
#define BOOST_REGEX_FWD_HPP_INCLUDED
|
||||
|
||||
#ifndef BOOST_REGEX_CONFIG_HPP
|
||||
#include <boost/regex/config.hpp>
|
||||
#endif
|
||||
|
||||
//
|
||||
// define BOOST_REGEX_NO_FWD if this
|
||||
// header doesn't work!
|
||||
//
|
||||
#ifdef BOOST_REGEX_NO_FWD
|
||||
# ifndef BOOST_RE_REGEX_HPP
|
||||
# include <boost/regex.hpp>
|
||||
# endif
|
||||
#else
|
||||
|
||||
namespace boost{
|
||||
|
||||
template <class charT>
|
||||
class cpp_regex_traits;
|
||||
template <class charT>
|
||||
struct c_regex_traits;
|
||||
template <class charT>
|
||||
class w32_regex_traits;
|
||||
|
||||
#ifdef BOOST_REGEX_USE_WIN32_LOCALE
|
||||
template <class charT, class implementationT = w32_regex_traits<charT> >
|
||||
struct regex_traits;
|
||||
#elif defined(BOOST_REGEX_USE_CPP_LOCALE)
|
||||
template <class charT, class implementationT = cpp_regex_traits<charT> >
|
||||
struct regex_traits;
|
||||
#else
|
||||
template <class charT, class implementationT = c_regex_traits<charT> >
|
||||
struct regex_traits;
|
||||
#endif
|
||||
|
||||
template <class charT, class traits = regex_traits<charT> >
|
||||
class basic_regex;
|
||||
|
||||
typedef basic_regex<char, regex_traits<char> > regex;
|
||||
#ifndef BOOST_NO_WREGEX
|
||||
typedef basic_regex<wchar_t, regex_traits<wchar_t> > wregex;
|
||||
#endif
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_REGEX_NO_FWD
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
98
regex/include/boost/regex/v5/regex_grep.hpp
Normal file
98
regex/include/boost/regex/v5/regex_grep.hpp
Normal file
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
*
|
||||
* 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_grep.hpp
|
||||
* VERSION see <boost/version.hpp>
|
||||
* DESCRIPTION: Provides regex_grep implementation.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_REGEX_V5_REGEX_GREP_HPP
|
||||
#define BOOST_REGEX_V5_REGEX_GREP_HPP
|
||||
|
||||
|
||||
namespace boost{
|
||||
|
||||
//
|
||||
// regex_grep:
|
||||
// find all non-overlapping matches within the sequence first last:
|
||||
//
|
||||
template <class Predicate, class BidiIterator, class charT, class traits>
|
||||
inline unsigned int regex_grep(Predicate foo,
|
||||
BidiIterator first,
|
||||
BidiIterator last,
|
||||
const basic_regex<charT, traits>& e,
|
||||
match_flag_type flags = match_default)
|
||||
{
|
||||
if(e.flags() & regex_constants::failbit)
|
||||
return false;
|
||||
|
||||
typedef typename match_results<BidiIterator>::allocator_type match_allocator_type;
|
||||
|
||||
match_results<BidiIterator> m;
|
||||
BOOST_REGEX_DETAIL_NS::perl_matcher<BidiIterator, match_allocator_type, traits> matcher(first, last, m, e, flags, first);
|
||||
unsigned int count = 0;
|
||||
while(matcher.find())
|
||||
{
|
||||
++count;
|
||||
if(0 == foo(m))
|
||||
return count; // caller doesn't want to go on
|
||||
if(m[0].second == last)
|
||||
return count; // we've reached the end, don't try and find an extra null match.
|
||||
if(m.length() == 0)
|
||||
{
|
||||
if(m[0].second == last)
|
||||
return count;
|
||||
// we found a NULL-match, now try to find
|
||||
// a non-NULL one at the same position:
|
||||
match_results<BidiIterator, match_allocator_type> m2(m);
|
||||
matcher.setf(match_not_null | match_continuous);
|
||||
if(matcher.find())
|
||||
{
|
||||
++count;
|
||||
if(0 == foo(m))
|
||||
return count;
|
||||
}
|
||||
else
|
||||
{
|
||||
// reset match back to where it was:
|
||||
m = m2;
|
||||
}
|
||||
matcher.unsetf((match_not_null | match_continuous) & ~flags);
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
//
|
||||
// regex_grep convenience interfaces:
|
||||
//
|
||||
template <class Predicate, class charT, class traits>
|
||||
inline unsigned int regex_grep(Predicate foo, const charT* str,
|
||||
const basic_regex<charT, traits>& e,
|
||||
match_flag_type flags = match_default)
|
||||
{
|
||||
return regex_grep(foo, str, str + traits::length(str), e, flags);
|
||||
}
|
||||
|
||||
template <class Predicate, class ST, class SA, class charT, class traits>
|
||||
inline unsigned int regex_grep(Predicate foo, const std::basic_string<charT, ST, SA>& s,
|
||||
const basic_regex<charT, traits>& e,
|
||||
match_flag_type flags = match_default)
|
||||
{
|
||||
return regex_grep(foo, s.begin(), s.end(), e, flags);
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_REGEX_V5_REGEX_GREP_HPP
|
||||
|
||||
173
regex/include/boost/regex/v5/regex_iterator.hpp
Normal file
173
regex/include/boost/regex/v5/regex_iterator.hpp
Normal file
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 2003
|
||||
* 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_iterator.hpp
|
||||
* VERSION see <boost/version.hpp>
|
||||
* DESCRIPTION: Provides regex_iterator implementation.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_REGEX_V5_REGEX_ITERATOR_HPP
|
||||
#define BOOST_REGEX_V5_REGEX_ITERATOR_HPP
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace boost{
|
||||
|
||||
template <class BidirectionalIterator,
|
||||
class charT,
|
||||
class traits>
|
||||
class regex_iterator_implementation
|
||||
{
|
||||
typedef basic_regex<charT, traits> regex_type;
|
||||
|
||||
match_results<BidirectionalIterator> what; // current match
|
||||
BidirectionalIterator base; // start of sequence
|
||||
BidirectionalIterator end; // end of sequence
|
||||
const regex_type re; // the expression
|
||||
match_flag_type flags; // flags for matching
|
||||
|
||||
public:
|
||||
regex_iterator_implementation(const regex_type* p, BidirectionalIterator last, match_flag_type f)
|
||||
: base(), end(last), re(*p), flags(f){}
|
||||
regex_iterator_implementation(const regex_iterator_implementation& other)
|
||||
:what(other.what), base(other.base), end(other.end), re(other.re), flags(other.flags){}
|
||||
bool init(BidirectionalIterator first)
|
||||
{
|
||||
base = first;
|
||||
return regex_search(first, end, what, re, flags);
|
||||
}
|
||||
bool compare(const regex_iterator_implementation& that)
|
||||
{
|
||||
if(this == &that) return true;
|
||||
return (&re.get_data() == &that.re.get_data()) && (end == that.end) && (flags == that.flags) && (what[0].first == that.what[0].first) && (what[0].second == that.what[0].second);
|
||||
}
|
||||
const match_results<BidirectionalIterator>& get()
|
||||
{ return what; }
|
||||
bool next()
|
||||
{
|
||||
//if(what.prefix().first != what[0].second)
|
||||
// flags |= match_prev_avail;
|
||||
BidirectionalIterator next_start = what[0].second;
|
||||
match_flag_type f(flags);
|
||||
if(!what.length() || (f & regex_constants::match_posix))
|
||||
f |= regex_constants::match_not_initial_null;
|
||||
//if(base != next_start)
|
||||
// f |= regex_constants::match_not_bob;
|
||||
bool result = regex_search(next_start, end, what, re, f, base);
|
||||
if(result)
|
||||
what.set_base(base);
|
||||
return result;
|
||||
}
|
||||
private:
|
||||
regex_iterator_implementation& operator=(const regex_iterator_implementation&);
|
||||
};
|
||||
|
||||
template <class BidirectionalIterator,
|
||||
class charT = typename std::iterator_traits<BidirectionalIterator>::value_type,
|
||||
class traits = regex_traits<charT> >
|
||||
class regex_iterator
|
||||
{
|
||||
private:
|
||||
typedef regex_iterator_implementation<BidirectionalIterator, charT, traits> impl;
|
||||
typedef std::shared_ptr<impl> pimpl;
|
||||
public:
|
||||
typedef basic_regex<charT, traits> regex_type;
|
||||
typedef match_results<BidirectionalIterator> value_type;
|
||||
typedef typename std::iterator_traits<BidirectionalIterator>::difference_type
|
||||
difference_type;
|
||||
typedef const value_type* pointer;
|
||||
typedef const value_type& reference;
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
|
||||
regex_iterator(){}
|
||||
regex_iterator(BidirectionalIterator a, BidirectionalIterator b,
|
||||
const regex_type& re,
|
||||
match_flag_type m = match_default)
|
||||
: pdata(new impl(&re, b, m))
|
||||
{
|
||||
if(!pdata->init(a))
|
||||
{
|
||||
pdata.reset();
|
||||
}
|
||||
}
|
||||
regex_iterator(const regex_iterator& that)
|
||||
: pdata(that.pdata) {}
|
||||
regex_iterator& operator=(const regex_iterator& that)
|
||||
{
|
||||
pdata = that.pdata;
|
||||
return *this;
|
||||
}
|
||||
bool operator==(const regex_iterator& that)const
|
||||
{
|
||||
if((pdata.get() == 0) || (that.pdata.get() == 0))
|
||||
return pdata.get() == that.pdata.get();
|
||||
return pdata->compare(*(that.pdata.get()));
|
||||
}
|
||||
bool operator!=(const regex_iterator& that)const
|
||||
{ return !(*this == that); }
|
||||
const value_type& operator*()const
|
||||
{ return pdata->get(); }
|
||||
const value_type* operator->()const
|
||||
{ return &(pdata->get()); }
|
||||
regex_iterator& operator++()
|
||||
{
|
||||
cow();
|
||||
if(0 == pdata->next())
|
||||
{
|
||||
pdata.reset();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
regex_iterator operator++(int)
|
||||
{
|
||||
regex_iterator result(*this);
|
||||
++(*this);
|
||||
return result;
|
||||
}
|
||||
private:
|
||||
|
||||
pimpl pdata;
|
||||
|
||||
void cow()
|
||||
{
|
||||
// copy-on-write
|
||||
if(pdata.get() && (pdata.use_count() > 1))
|
||||
{
|
||||
pdata.reset(new impl(*(pdata.get())));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
typedef regex_iterator<const char*> cregex_iterator;
|
||||
typedef regex_iterator<std::string::const_iterator> sregex_iterator;
|
||||
#ifndef BOOST_NO_WREGEX
|
||||
typedef regex_iterator<const wchar_t*> wcregex_iterator;
|
||||
typedef regex_iterator<std::wstring::const_iterator> wsregex_iterator;
|
||||
#endif
|
||||
|
||||
// make_regex_iterator:
|
||||
template <class charT, class traits>
|
||||
inline regex_iterator<const charT*, charT, traits> make_regex_iterator(const charT* p, const basic_regex<charT, traits>& e, regex_constants::match_flag_type m = regex_constants::match_default)
|
||||
{
|
||||
return regex_iterator<const charT*, charT, traits>(p, p+traits::length(p), e, m);
|
||||
}
|
||||
template <class charT, class traits, class ST, class SA>
|
||||
inline regex_iterator<typename std::basic_string<charT, ST, SA>::const_iterator, charT, traits> make_regex_iterator(const std::basic_string<charT, ST, SA>& p, const basic_regex<charT, traits>& e, regex_constants::match_flag_type m = regex_constants::match_default)
|
||||
{
|
||||
return regex_iterator<typename std::basic_string<charT, ST, SA>::const_iterator, charT, traits>(p.begin(), p.end(), e, m);
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_REGEX_V5_REGEX_ITERATOR_HPP
|
||||
|
||||
92
regex/include/boost/regex/v5/regex_match.hpp
Normal file
92
regex/include/boost/regex/v5/regex_match.hpp
Normal file
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
*
|
||||
* 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_match.hpp
|
||||
* VERSION see <boost/version.hpp>
|
||||
* DESCRIPTION: Regular expression matching algorithms.
|
||||
* Note this is an internal header file included
|
||||
* by regex.hpp, do not include on its own.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef BOOST_REGEX_MATCH_HPP
|
||||
#define BOOST_REGEX_MATCH_HPP
|
||||
|
||||
namespace boost{
|
||||
|
||||
//
|
||||
// proc regex_match
|
||||
// returns true if the specified regular expression matches
|
||||
// the whole of the input. Fills in what matched in m.
|
||||
//
|
||||
template <class BidiIterator, class Allocator, class charT, class traits>
|
||||
bool regex_match(BidiIterator first, BidiIterator last,
|
||||
match_results<BidiIterator, Allocator>& m,
|
||||
const basic_regex<charT, traits>& e,
|
||||
match_flag_type flags = match_default)
|
||||
{
|
||||
BOOST_REGEX_DETAIL_NS::perl_matcher<BidiIterator, Allocator, traits> matcher(first, last, m, e, flags, first);
|
||||
return matcher.match();
|
||||
}
|
||||
template <class iterator, class charT, class traits>
|
||||
bool regex_match(iterator first, iterator last,
|
||||
const basic_regex<charT, traits>& e,
|
||||
match_flag_type flags = match_default)
|
||||
{
|
||||
match_results<iterator> m;
|
||||
return regex_match(first, last, m, e, flags | regex_constants::match_any);
|
||||
}
|
||||
//
|
||||
// query_match convenience interfaces:
|
||||
//
|
||||
template <class charT, class Allocator, class traits>
|
||||
inline bool regex_match(const charT* str,
|
||||
match_results<const charT*, Allocator>& m,
|
||||
const basic_regex<charT, traits>& e,
|
||||
match_flag_type flags = match_default)
|
||||
{
|
||||
return regex_match(str, str + traits::length(str), m, e, flags);
|
||||
}
|
||||
|
||||
template <class ST, class SA, class Allocator, class charT, class traits>
|
||||
inline bool regex_match(const std::basic_string<charT, ST, SA>& s,
|
||||
match_results<typename std::basic_string<charT, ST, SA>::const_iterator, Allocator>& m,
|
||||
const basic_regex<charT, traits>& e,
|
||||
match_flag_type flags = match_default)
|
||||
{
|
||||
return regex_match(s.begin(), s.end(), m, e, flags);
|
||||
}
|
||||
template <class charT, class traits>
|
||||
inline bool regex_match(const charT* str,
|
||||
const basic_regex<charT, traits>& e,
|
||||
match_flag_type flags = match_default)
|
||||
{
|
||||
match_results<const charT*> m;
|
||||
return regex_match(str, str + traits::length(str), m, e, flags | regex_constants::match_any);
|
||||
}
|
||||
|
||||
template <class ST, class SA, class charT, class traits>
|
||||
inline bool regex_match(const std::basic_string<charT, ST, SA>& s,
|
||||
const basic_regex<charT, traits>& e,
|
||||
match_flag_type flags = match_default)
|
||||
{
|
||||
typedef typename std::basic_string<charT, ST, SA>::const_iterator iterator;
|
||||
match_results<iterator> m;
|
||||
return regex_match(s.begin(), s.end(), m, e, flags | regex_constants::match_any);
|
||||
}
|
||||
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_REGEX_MATCH_HPP
|
||||
|
||||
71
regex/include/boost/regex/v5/regex_merge.hpp
Normal file
71
regex/include/boost/regex/v5/regex_merge.hpp
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
*
|
||||
* 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_format.hpp
|
||||
* VERSION see <boost/version.hpp>
|
||||
* DESCRIPTION: Provides formatting output routines for search and replace
|
||||
* operations. Note this is an internal header file included
|
||||
* by regex.hpp, do not include on its own.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_REGEX_V5_REGEX_MERGE_HPP
|
||||
#define BOOST_REGEX_V5_REGEX_MERGE_HPP
|
||||
|
||||
|
||||
namespace boost{
|
||||
|
||||
template <class OutputIterator, class Iterator, class traits, class charT>
|
||||
inline OutputIterator regex_merge(OutputIterator out,
|
||||
Iterator first,
|
||||
Iterator last,
|
||||
const basic_regex<charT, traits>& e,
|
||||
const charT* fmt,
|
||||
match_flag_type flags = match_default)
|
||||
{
|
||||
return regex_replace(out, first, last, e, fmt, flags);
|
||||
}
|
||||
|
||||
template <class OutputIterator, class Iterator, class traits, class charT>
|
||||
inline OutputIterator regex_merge(OutputIterator out,
|
||||
Iterator first,
|
||||
Iterator last,
|
||||
const basic_regex<charT, traits>& e,
|
||||
const std::basic_string<charT>& fmt,
|
||||
match_flag_type flags = match_default)
|
||||
{
|
||||
return regex_merge(out, first, last, e, fmt.c_str(), flags);
|
||||
}
|
||||
|
||||
template <class traits, class charT>
|
||||
inline std::basic_string<charT> regex_merge(const std::basic_string<charT>& s,
|
||||
const basic_regex<charT, traits>& e,
|
||||
const charT* fmt,
|
||||
match_flag_type flags = match_default)
|
||||
{
|
||||
return regex_replace(s, e, fmt, flags);
|
||||
}
|
||||
|
||||
template <class traits, class charT>
|
||||
inline std::basic_string<charT> regex_merge(const std::basic_string<charT>& s,
|
||||
const basic_regex<charT, traits>& e,
|
||||
const std::basic_string<charT>& fmt,
|
||||
match_flag_type flags = match_default)
|
||||
{
|
||||
return regex_replace(s, e, fmt, flags);
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_REGEX_V5_REGEX_MERGE_HPP
|
||||
|
||||
|
||||
213
regex/include/boost/regex/v5/regex_raw_buffer.hpp
Normal file
213
regex/include/boost/regex/v5/regex_raw_buffer.hpp
Normal file
@@ -0,0 +1,213 @@
|
||||
/*
|
||||
*
|
||||
* 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_raw_buffer.hpp
|
||||
* VERSION see <boost/version.hpp>
|
||||
* DESCRIPTION: Raw character buffer for regex code.
|
||||
* Note this is an internal header file included
|
||||
* by regex.hpp, do not include on its own.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_REGEX_RAW_BUFFER_HPP
|
||||
#define BOOST_REGEX_RAW_BUFFER_HPP
|
||||
|
||||
#ifndef BOOST_REGEX_CONFIG_HPP
|
||||
#include <boost/regex/config.hpp>
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
|
||||
namespace boost{
|
||||
namespace BOOST_REGEX_DETAIL_NS{
|
||||
|
||||
struct empty_padding{};
|
||||
|
||||
union padding
|
||||
{
|
||||
void* p;
|
||||
unsigned int i;
|
||||
};
|
||||
|
||||
template <int N>
|
||||
struct padding3
|
||||
{
|
||||
enum{
|
||||
padding_size = 8,
|
||||
padding_mask = 7
|
||||
};
|
||||
};
|
||||
|
||||
template<>
|
||||
struct padding3<2>
|
||||
{
|
||||
enum{
|
||||
padding_size = 2,
|
||||
padding_mask = 1
|
||||
};
|
||||
};
|
||||
|
||||
template<>
|
||||
struct padding3<4>
|
||||
{
|
||||
enum{
|
||||
padding_size = 4,
|
||||
padding_mask = 3
|
||||
};
|
||||
};
|
||||
|
||||
template<>
|
||||
struct padding3<8>
|
||||
{
|
||||
enum{
|
||||
padding_size = 8,
|
||||
padding_mask = 7
|
||||
};
|
||||
};
|
||||
|
||||
template<>
|
||||
struct padding3<16>
|
||||
{
|
||||
enum{
|
||||
padding_size = 16,
|
||||
padding_mask = 15
|
||||
};
|
||||
};
|
||||
|
||||
enum{
|
||||
padding_size = padding3<sizeof(padding)>::padding_size,
|
||||
padding_mask = padding3<sizeof(padding)>::padding_mask
|
||||
};
|
||||
|
||||
//
|
||||
// class raw_storage
|
||||
// basically this is a simplified vector<unsigned char>
|
||||
// this is used by basic_regex for expression storage
|
||||
//
|
||||
|
||||
class raw_storage
|
||||
{
|
||||
public:
|
||||
typedef std::size_t size_type;
|
||||
typedef unsigned char* pointer;
|
||||
private:
|
||||
pointer last, start, end;
|
||||
public:
|
||||
|
||||
raw_storage();
|
||||
raw_storage(size_type n);
|
||||
|
||||
~raw_storage()
|
||||
{
|
||||
::operator delete(start);
|
||||
}
|
||||
|
||||
void resize(size_type n)
|
||||
{
|
||||
size_type newsize = start ? last - start : 1024;
|
||||
while (newsize < n)
|
||||
newsize *= 2;
|
||||
size_type datasize = end - start;
|
||||
// extend newsize to WORD/DWORD boundary:
|
||||
newsize = (newsize + padding_mask) & ~(padding_mask);
|
||||
|
||||
// allocate and copy data:
|
||||
pointer ptr = static_cast<pointer>(::operator new(newsize));
|
||||
BOOST_REGEX_NOEH_ASSERT(ptr)
|
||||
if (start)
|
||||
std::memcpy(ptr, start, datasize);
|
||||
|
||||
// get rid of old buffer:
|
||||
::operator delete(start);
|
||||
|
||||
// and set up pointers:
|
||||
start = ptr;
|
||||
end = ptr + datasize;
|
||||
last = ptr + newsize;
|
||||
}
|
||||
|
||||
void* extend(size_type n)
|
||||
{
|
||||
if(size_type(last - end) < n)
|
||||
resize(n + (end - start));
|
||||
pointer result = end;
|
||||
end += n;
|
||||
return result;
|
||||
}
|
||||
|
||||
void* insert(size_type pos, size_type n)
|
||||
{
|
||||
BOOST_REGEX_ASSERT(pos <= size_type(end - start));
|
||||
if (size_type(last - end) < n)
|
||||
resize(n + (end - start));
|
||||
void* result = start + pos;
|
||||
std::memmove(start + pos + n, start + pos, (end - start) - pos);
|
||||
end += n;
|
||||
return result;
|
||||
}
|
||||
|
||||
size_type size()
|
||||
{
|
||||
return size_type(end - start);
|
||||
}
|
||||
|
||||
size_type capacity()
|
||||
{
|
||||
return size_type(last - start);
|
||||
}
|
||||
|
||||
void* data()const
|
||||
{
|
||||
return start;
|
||||
}
|
||||
|
||||
size_type index(void* ptr)
|
||||
{
|
||||
return size_type(static_cast<pointer>(ptr) - static_cast<pointer>(data()));
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
end = start;
|
||||
}
|
||||
|
||||
void align()
|
||||
{
|
||||
// move end up to a boundary:
|
||||
end = start + (((end - start) + padding_mask) & ~padding_mask);
|
||||
}
|
||||
void swap(raw_storage& that)
|
||||
{
|
||||
std::swap(start, that.start);
|
||||
std::swap(end, that.end);
|
||||
std::swap(last, that.last);
|
||||
}
|
||||
};
|
||||
|
||||
inline raw_storage::raw_storage()
|
||||
{
|
||||
last = start = end = 0;
|
||||
}
|
||||
|
||||
inline raw_storage::raw_storage(size_type n)
|
||||
{
|
||||
start = end = static_cast<pointer>(::operator new(n));
|
||||
BOOST_REGEX_NOEH_ASSERT(start)
|
||||
last = start + n;
|
||||
}
|
||||
|
||||
} // namespace BOOST_REGEX_DETAIL_NS
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
|
||||
77
regex/include/boost/regex/v5/regex_replace.hpp
Normal file
77
regex/include/boost/regex/v5/regex_replace.hpp
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 1998-2009
|
||||
* 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_format.hpp
|
||||
* VERSION see <boost/version.hpp>
|
||||
* DESCRIPTION: Provides formatting output routines for search and replace
|
||||
* operations. Note this is an internal header file included
|
||||
* by regex.hpp, do not include on its own.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_REGEX_V5_REGEX_REPLACE_HPP
|
||||
#define BOOST_REGEX_V5_REGEX_REPLACE_HPP
|
||||
|
||||
|
||||
namespace boost{
|
||||
|
||||
template <class OutputIterator, class BidirectionalIterator, class traits, class charT, class Formatter>
|
||||
OutputIterator regex_replace(OutputIterator out,
|
||||
BidirectionalIterator first,
|
||||
BidirectionalIterator last,
|
||||
const basic_regex<charT, traits>& e,
|
||||
Formatter fmt,
|
||||
match_flag_type flags = match_default)
|
||||
{
|
||||
regex_iterator<BidirectionalIterator, charT, traits> i(first, last, e, flags);
|
||||
regex_iterator<BidirectionalIterator, charT, traits> j;
|
||||
if(i == j)
|
||||
{
|
||||
if(!(flags & regex_constants::format_no_copy))
|
||||
out = BOOST_REGEX_DETAIL_NS::copy(first, last, out);
|
||||
}
|
||||
else
|
||||
{
|
||||
BidirectionalIterator last_m(first);
|
||||
while(i != j)
|
||||
{
|
||||
if(!(flags & regex_constants::format_no_copy))
|
||||
out = BOOST_REGEX_DETAIL_NS::copy(i->prefix().first, i->prefix().second, out);
|
||||
out = i->format(out, fmt, flags, e);
|
||||
last_m = (*i)[0].second;
|
||||
if(flags & regex_constants::format_first_only)
|
||||
break;
|
||||
++i;
|
||||
}
|
||||
if(!(flags & regex_constants::format_no_copy))
|
||||
out = BOOST_REGEX_DETAIL_NS::copy(last_m, last, out);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
template <class traits, class charT, class Formatter>
|
||||
std::basic_string<charT> regex_replace(const std::basic_string<charT>& s,
|
||||
const basic_regex<charT, traits>& e,
|
||||
Formatter fmt,
|
||||
match_flag_type flags = match_default)
|
||||
{
|
||||
std::basic_string<charT> result;
|
||||
BOOST_REGEX_DETAIL_NS::string_out_iterator<std::basic_string<charT> > i(result);
|
||||
regex_replace(i, s.begin(), s.end(), e, fmt, flags);
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_REGEX_V5_REGEX_REPLACE_HPP
|
||||
|
||||
|
||||
103
regex/include/boost/regex/v5/regex_search.hpp
Normal file
103
regex/include/boost/regex/v5/regex_search.hpp
Normal file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
*
|
||||
* 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_search.hpp
|
||||
* VERSION see <boost/version.hpp>
|
||||
* DESCRIPTION: Provides regex_search implementation.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_REGEX_V5_REGEX_SEARCH_HPP
|
||||
#define BOOST_REGEX_V5_REGEX_SEARCH_HPP
|
||||
|
||||
|
||||
namespace boost{
|
||||
|
||||
template <class BidiIterator, class Allocator, class charT, class traits>
|
||||
bool regex_search(BidiIterator first, BidiIterator last,
|
||||
match_results<BidiIterator, Allocator>& m,
|
||||
const basic_regex<charT, traits>& e,
|
||||
match_flag_type flags = match_default)
|
||||
{
|
||||
return regex_search(first, last, m, e, flags, first);
|
||||
}
|
||||
|
||||
template <class BidiIterator, class Allocator, class charT, class traits>
|
||||
bool regex_search(BidiIterator first, BidiIterator last,
|
||||
match_results<BidiIterator, Allocator>& m,
|
||||
const basic_regex<charT, traits>& e,
|
||||
match_flag_type flags,
|
||||
BidiIterator base)
|
||||
{
|
||||
if(e.flags() & regex_constants::failbit)
|
||||
return false;
|
||||
|
||||
BOOST_REGEX_DETAIL_NS::perl_matcher<BidiIterator, Allocator, traits> matcher(first, last, m, e, flags, base);
|
||||
return matcher.find();
|
||||
}
|
||||
|
||||
//
|
||||
// regex_search convenience interfaces:
|
||||
//
|
||||
template <class charT, class Allocator, class traits>
|
||||
inline bool regex_search(const charT* str,
|
||||
match_results<const charT*, Allocator>& m,
|
||||
const basic_regex<charT, traits>& e,
|
||||
match_flag_type flags = match_default)
|
||||
{
|
||||
return regex_search(str, str + traits::length(str), m, e, flags);
|
||||
}
|
||||
|
||||
template <class ST, class SA, class Allocator, class charT, class traits>
|
||||
inline bool regex_search(const std::basic_string<charT, ST, SA>& s,
|
||||
match_results<typename std::basic_string<charT, ST, SA>::const_iterator, Allocator>& m,
|
||||
const basic_regex<charT, traits>& e,
|
||||
match_flag_type flags = match_default)
|
||||
{
|
||||
return regex_search(s.begin(), s.end(), m, e, flags);
|
||||
}
|
||||
|
||||
template <class BidiIterator, class charT, class traits>
|
||||
bool regex_search(BidiIterator first, BidiIterator last,
|
||||
const basic_regex<charT, traits>& e,
|
||||
match_flag_type flags = match_default)
|
||||
{
|
||||
if(e.flags() & regex_constants::failbit)
|
||||
return false;
|
||||
|
||||
match_results<BidiIterator> m;
|
||||
typedef typename match_results<BidiIterator>::allocator_type match_alloc_type;
|
||||
BOOST_REGEX_DETAIL_NS::perl_matcher<BidiIterator, match_alloc_type, traits> matcher(first, last, m, e, flags | regex_constants::match_any, first);
|
||||
return matcher.find();
|
||||
}
|
||||
|
||||
template <class charT, class traits>
|
||||
inline bool regex_search(const charT* str,
|
||||
const basic_regex<charT, traits>& e,
|
||||
match_flag_type flags = match_default)
|
||||
{
|
||||
return regex_search(str, str + traits::length(str), e, flags);
|
||||
}
|
||||
|
||||
template <class ST, class SA, class charT, class traits>
|
||||
inline bool regex_search(const std::basic_string<charT, ST, SA>& s,
|
||||
const basic_regex<charT, traits>& e,
|
||||
match_flag_type flags = match_default)
|
||||
{
|
||||
return regex_search(s.begin(), s.end(), e, flags);
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_REGEX_V5_REGEX_SEARCH_HPP
|
||||
|
||||
|
||||
152
regex/include/boost/regex/v5/regex_split.hpp
Normal file
152
regex/include/boost/regex/v5/regex_split.hpp
Normal file
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
*
|
||||
* 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_split.hpp
|
||||
* VERSION see <boost/version.hpp>
|
||||
* DESCRIPTION: Implements regex_split and associated functions.
|
||||
* Note this is an internal header file included
|
||||
* by regex.hpp, do not include on its own.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_REGEX_SPLIT_HPP
|
||||
#define BOOST_REGEX_SPLIT_HPP
|
||||
|
||||
namespace boost{
|
||||
|
||||
#ifdef BOOST_REGEX_MSVC
|
||||
# pragma warning(push)
|
||||
#if BOOST_REGEX_MSVC < 1910
|
||||
#pragma warning(disable:4800)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace BOOST_REGEX_DETAIL_NS{
|
||||
|
||||
template <class charT>
|
||||
const basic_regex<charT>& get_default_expression(charT)
|
||||
{
|
||||
static const charT expression_text[4] = { '\\', 's', '+', '\00', };
|
||||
static const basic_regex<charT> e(expression_text);
|
||||
return e;
|
||||
}
|
||||
|
||||
template <class OutputIterator, class charT, class Traits1, class Alloc1>
|
||||
class split_pred
|
||||
{
|
||||
typedef std::basic_string<charT, Traits1, Alloc1> string_type;
|
||||
typedef typename string_type::const_iterator iterator_type;
|
||||
iterator_type* p_last;
|
||||
OutputIterator* p_out;
|
||||
std::size_t* p_max;
|
||||
std::size_t initial_max;
|
||||
public:
|
||||
split_pred(iterator_type* a, OutputIterator* b, std::size_t* c)
|
||||
: p_last(a), p_out(b), p_max(c), initial_max(*c) {}
|
||||
|
||||
bool operator()(const match_results<iterator_type>& what);
|
||||
};
|
||||
|
||||
template <class OutputIterator, class charT, class Traits1, class Alloc1>
|
||||
bool split_pred<OutputIterator, charT, Traits1, Alloc1>::operator()
|
||||
(const match_results<iterator_type>& what)
|
||||
{
|
||||
*p_last = what[0].second;
|
||||
if(what.size() > 1)
|
||||
{
|
||||
// output sub-expressions only:
|
||||
for(unsigned i = 1; i < what.size(); ++i)
|
||||
{
|
||||
*(*p_out) = what.str(i);
|
||||
++(*p_out);
|
||||
if(0 == --*p_max) return false;
|
||||
}
|
||||
return *p_max != 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// output $` only if it's not-null or not at the start of the input:
|
||||
const sub_match<iterator_type>& sub = what[-1];
|
||||
if((sub.first != sub.second) || (*p_max != initial_max))
|
||||
{
|
||||
*(*p_out) = sub.str();
|
||||
++(*p_out);
|
||||
return --*p_max;
|
||||
}
|
||||
}
|
||||
//
|
||||
// initial null, do nothing:
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace BOOST_REGEX_DETAIL_NS
|
||||
|
||||
template <class OutputIterator, class charT, class Traits1, class Alloc1, class Traits2>
|
||||
std::size_t regex_split(OutputIterator out,
|
||||
std::basic_string<charT, Traits1, Alloc1>& s,
|
||||
const basic_regex<charT, Traits2>& e,
|
||||
match_flag_type flags,
|
||||
std::size_t max_split)
|
||||
{
|
||||
typedef typename std::basic_string<charT, Traits1, Alloc1>::const_iterator ci_t;
|
||||
//typedef typename match_results<ci_t>::allocator_type match_allocator;
|
||||
ci_t last = s.begin();
|
||||
std::size_t init_size = max_split;
|
||||
BOOST_REGEX_DETAIL_NS::split_pred<OutputIterator, charT, Traits1, Alloc1> pred(&last, &out, &max_split);
|
||||
ci_t i, j;
|
||||
i = s.begin();
|
||||
j = s.end();
|
||||
regex_grep(pred, i, j, e, flags);
|
||||
//
|
||||
// if there is still input left, do a final push as long as max_split
|
||||
// is not exhausted, and we're not splitting sub-expressions rather
|
||||
// than whitespace:
|
||||
if(max_split && (last != s.end()) && (e.mark_count() == 0))
|
||||
{
|
||||
*out = std::basic_string<charT, Traits1, Alloc1>((ci_t)last, (ci_t)s.end());
|
||||
++out;
|
||||
last = s.end();
|
||||
--max_split;
|
||||
}
|
||||
//
|
||||
// delete from the string everything that has been processed so far:
|
||||
s.erase(0, last - s.begin());
|
||||
//
|
||||
// return the number of new records pushed:
|
||||
return init_size - max_split;
|
||||
}
|
||||
|
||||
template <class OutputIterator, class charT, class Traits1, class Alloc1, class Traits2>
|
||||
inline std::size_t regex_split(OutputIterator out,
|
||||
std::basic_string<charT, Traits1, Alloc1>& s,
|
||||
const basic_regex<charT, Traits2>& e,
|
||||
match_flag_type flags = match_default)
|
||||
{
|
||||
return regex_split(out, s, e, flags, UINT_MAX);
|
||||
}
|
||||
|
||||
template <class OutputIterator, class charT, class Traits1, class Alloc1>
|
||||
inline std::size_t regex_split(OutputIterator out,
|
||||
std::basic_string<charT, Traits1, Alloc1>& s)
|
||||
{
|
||||
return regex_split(out, s, BOOST_REGEX_DETAIL_NS::get_default_expression(charT(0)), match_default, UINT_MAX);
|
||||
}
|
||||
|
||||
#ifdef BOOST_REGEX_MSVC
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
255
regex/include/boost/regex/v5/regex_token_iterator.hpp
Normal file
255
regex/include/boost/regex/v5/regex_token_iterator.hpp
Normal file
@@ -0,0 +1,255 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 2003
|
||||
* 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_token_iterator.hpp
|
||||
* VERSION see <boost/version.hpp>
|
||||
* DESCRIPTION: Provides regex_token_iterator implementation.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_REGEX_V5_REGEX_TOKEN_ITERATOR_HPP
|
||||
#define BOOST_REGEX_V5_REGEX_TOKEN_ITERATOR_HPP
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace boost{
|
||||
|
||||
template <class BidirectionalIterator,
|
||||
class charT,
|
||||
class traits>
|
||||
class regex_token_iterator_implementation
|
||||
{
|
||||
typedef basic_regex<charT, traits> regex_type;
|
||||
typedef sub_match<BidirectionalIterator> value_type;
|
||||
|
||||
match_results<BidirectionalIterator> what; // current match
|
||||
BidirectionalIterator base; // start of search area
|
||||
BidirectionalIterator end; // end of search area
|
||||
const regex_type re; // the expression
|
||||
match_flag_type flags; // match flags
|
||||
value_type result; // the current string result
|
||||
int N; // the current sub-expression being enumerated
|
||||
std::vector<int> subs; // the sub-expressions to enumerate
|
||||
|
||||
public:
|
||||
regex_token_iterator_implementation(const regex_type* p, BidirectionalIterator last, int sub, match_flag_type f)
|
||||
: end(last), re(*p), flags(f), N(0){ subs.push_back(sub); }
|
||||
regex_token_iterator_implementation(const regex_type* p, BidirectionalIterator last, const std::vector<int>& v, match_flag_type f)
|
||||
: end(last), re(*p), flags(f), N(0), subs(v){}
|
||||
template <std::size_t CN>
|
||||
regex_token_iterator_implementation(const regex_type* p, BidirectionalIterator last, const int (&submatches)[CN], match_flag_type f)
|
||||
: end(last), re(*p), flags(f), N(0)
|
||||
{
|
||||
for(std::size_t i = 0; i < CN; ++i)
|
||||
{
|
||||
subs.push_back(submatches[i]);
|
||||
}
|
||||
}
|
||||
regex_token_iterator_implementation(const regex_token_iterator_implementation& other) = default;
|
||||
bool init(BidirectionalIterator first)
|
||||
{
|
||||
N = 0;
|
||||
base = first;
|
||||
if(regex_search(first, end, what, re, flags, base) == true)
|
||||
{
|
||||
N = 0;
|
||||
result = ((subs[N] == -1) ? what.prefix() : what[(int)subs[N]]);
|
||||
return true;
|
||||
}
|
||||
else if((subs[N] == -1) && (first != end))
|
||||
{
|
||||
result.first = first;
|
||||
result.second = end;
|
||||
result.matched = (first != end);
|
||||
N = -1;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool compare(const regex_token_iterator_implementation& that)
|
||||
{
|
||||
if(this == &that) return true;
|
||||
return (&re.get_data() == &that.re.get_data())
|
||||
&& (end == that.end)
|
||||
&& (flags == that.flags)
|
||||
&& (N == that.N)
|
||||
&& (what[0].first == that.what[0].first)
|
||||
&& (what[0].second == that.what[0].second);
|
||||
}
|
||||
const value_type& get()
|
||||
{ return result; }
|
||||
bool next()
|
||||
{
|
||||
if(N == -1)
|
||||
return false;
|
||||
if(N+1 < (int)subs.size())
|
||||
{
|
||||
++N;
|
||||
result =((subs[N] == -1) ? what.prefix() : what[subs[N]]);
|
||||
return true;
|
||||
}
|
||||
//if(what.prefix().first != what[0].second)
|
||||
// flags |= /*match_prev_avail |*/ regex_constants::match_not_bob;
|
||||
BidirectionalIterator last_end(what[0].second);
|
||||
if(regex_search(last_end, end, what, re, ((what[0].first == what[0].second) ? flags | regex_constants::match_not_initial_null : flags), base))
|
||||
{
|
||||
N =0;
|
||||
result =((subs[N] == -1) ? what.prefix() : what[subs[N]]);
|
||||
return true;
|
||||
}
|
||||
else if((last_end != end) && (subs[0] == -1))
|
||||
{
|
||||
N =-1;
|
||||
result.first = last_end;
|
||||
result.second = end;
|
||||
result.matched = (last_end != end);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
private:
|
||||
regex_token_iterator_implementation& operator=(const regex_token_iterator_implementation&);
|
||||
};
|
||||
|
||||
template <class BidirectionalIterator,
|
||||
class charT = typename std::iterator_traits<BidirectionalIterator>::value_type,
|
||||
class traits = regex_traits<charT> >
|
||||
class regex_token_iterator
|
||||
{
|
||||
private:
|
||||
typedef regex_token_iterator_implementation<BidirectionalIterator, charT, traits> impl;
|
||||
typedef std::shared_ptr<impl> pimpl;
|
||||
public:
|
||||
typedef basic_regex<charT, traits> regex_type;
|
||||
typedef sub_match<BidirectionalIterator> value_type;
|
||||
typedef typename std::iterator_traits<BidirectionalIterator>::difference_type
|
||||
difference_type;
|
||||
typedef const value_type* pointer;
|
||||
typedef const value_type& reference;
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
|
||||
regex_token_iterator(){}
|
||||
regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, const regex_type& re,
|
||||
int submatch = 0, match_flag_type m = match_default)
|
||||
: pdata(new impl(&re, b, submatch, m))
|
||||
{
|
||||
if(!pdata->init(a))
|
||||
pdata.reset();
|
||||
}
|
||||
regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, const regex_type& re,
|
||||
const std::vector<int>& submatches, match_flag_type m = match_default)
|
||||
: pdata(new impl(&re, b, submatches, m))
|
||||
{
|
||||
if(!pdata->init(a))
|
||||
pdata.reset();
|
||||
}
|
||||
template <std::size_t N>
|
||||
regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, const regex_type& re,
|
||||
const int (&submatches)[N], match_flag_type m = match_default)
|
||||
: pdata(new impl(&re, b, submatches, m))
|
||||
{
|
||||
if(!pdata->init(a))
|
||||
pdata.reset();
|
||||
}
|
||||
regex_token_iterator(const regex_token_iterator& that)
|
||||
: pdata(that.pdata) {}
|
||||
regex_token_iterator& operator=(const regex_token_iterator& that)
|
||||
{
|
||||
pdata = that.pdata;
|
||||
return *this;
|
||||
}
|
||||
bool operator==(const regex_token_iterator& that)const
|
||||
{
|
||||
if((pdata.get() == 0) || (that.pdata.get() == 0))
|
||||
return pdata.get() == that.pdata.get();
|
||||
return pdata->compare(*(that.pdata.get()));
|
||||
}
|
||||
bool operator!=(const regex_token_iterator& that)const
|
||||
{ return !(*this == that); }
|
||||
const value_type& operator*()const
|
||||
{ return pdata->get(); }
|
||||
const value_type* operator->()const
|
||||
{ return &(pdata->get()); }
|
||||
regex_token_iterator& operator++()
|
||||
{
|
||||
cow();
|
||||
if(0 == pdata->next())
|
||||
{
|
||||
pdata.reset();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
regex_token_iterator operator++(int)
|
||||
{
|
||||
regex_token_iterator result(*this);
|
||||
++(*this);
|
||||
return result;
|
||||
}
|
||||
private:
|
||||
|
||||
pimpl pdata;
|
||||
|
||||
void cow()
|
||||
{
|
||||
// copy-on-write
|
||||
if(pdata.get() && (pdata.use_count() > 1))
|
||||
{
|
||||
pdata.reset(new impl(*(pdata.get())));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
typedef regex_token_iterator<const char*> cregex_token_iterator;
|
||||
typedef regex_token_iterator<std::string::const_iterator> sregex_token_iterator;
|
||||
#ifndef BOOST_NO_WREGEX
|
||||
typedef regex_token_iterator<const wchar_t*> wcregex_token_iterator;
|
||||
typedef regex_token_iterator<std::wstring::const_iterator> wsregex_token_iterator;
|
||||
#endif
|
||||
|
||||
template <class charT, class traits>
|
||||
inline regex_token_iterator<const charT*, charT, traits> make_regex_token_iterator(const charT* p, const basic_regex<charT, traits>& e, int submatch = 0, regex_constants::match_flag_type m = regex_constants::match_default)
|
||||
{
|
||||
return regex_token_iterator<const charT*, charT, traits>(p, p+traits::length(p), e, submatch, m);
|
||||
}
|
||||
template <class charT, class traits, class ST, class SA>
|
||||
inline regex_token_iterator<typename std::basic_string<charT, ST, SA>::const_iterator, charT, traits> make_regex_token_iterator(const std::basic_string<charT, ST, SA>& p, const basic_regex<charT, traits>& e, int submatch = 0, regex_constants::match_flag_type m = regex_constants::match_default)
|
||||
{
|
||||
return regex_token_iterator<typename std::basic_string<charT, ST, SA>::const_iterator, charT, traits>(p.begin(), p.end(), e, submatch, m);
|
||||
}
|
||||
template <class charT, class traits, std::size_t N>
|
||||
inline regex_token_iterator<const charT*, charT, traits> make_regex_token_iterator(const charT* p, const basic_regex<charT, traits>& e, const int (&submatch)[N], regex_constants::match_flag_type m = regex_constants::match_default)
|
||||
{
|
||||
return regex_token_iterator<const charT*, charT, traits>(p, p+traits::length(p), e, submatch, m);
|
||||
}
|
||||
template <class charT, class traits, class ST, class SA, std::size_t N>
|
||||
inline regex_token_iterator<typename std::basic_string<charT, ST, SA>::const_iterator, charT, traits> make_regex_token_iterator(const std::basic_string<charT, ST, SA>& p, const basic_regex<charT, traits>& e, const int (&submatch)[N], regex_constants::match_flag_type m = regex_constants::match_default)
|
||||
{
|
||||
return regex_token_iterator<typename std::basic_string<charT, ST, SA>::const_iterator, charT, traits>(p.begin(), p.end(), e, submatch, m);
|
||||
}
|
||||
template <class charT, class traits>
|
||||
inline regex_token_iterator<const charT*, charT, traits> make_regex_token_iterator(const charT* p, const basic_regex<charT, traits>& e, const std::vector<int>& submatch, regex_constants::match_flag_type m = regex_constants::match_default)
|
||||
{
|
||||
return regex_token_iterator<const charT*, charT, traits>(p, p+traits::length(p), e, submatch, m);
|
||||
}
|
||||
template <class charT, class traits, class ST, class SA>
|
||||
inline regex_token_iterator<typename std::basic_string<charT, ST, SA>::const_iterator, charT, traits> make_regex_token_iterator(const std::basic_string<charT, ST, SA>& p, const basic_regex<charT, traits>& e, const std::vector<int>& submatch, regex_constants::match_flag_type m = regex_constants::match_default)
|
||||
{
|
||||
return regex_token_iterator<typename std::basic_string<charT, ST, SA>::const_iterator, charT, traits>(p.begin(), p.end(), e, submatch, m);
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_REGEX_V5_REGEX_TOKEN_ITERATOR_HPP
|
||||
|
||||
|
||||
|
||||
|
||||
130
regex/include/boost/regex/v5/regex_traits.hpp
Normal file
130
regex/include/boost/regex/v5/regex_traits.hpp
Normal file
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 2003
|
||||
* 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_INCLUDED
|
||||
#define BOOST_REGEX_TRAITS_HPP_INCLUDED
|
||||
|
||||
#include <boost/regex/config.hpp>
|
||||
#include <boost/regex/v5/regex_workaround.hpp>
|
||||
#include <boost/regex/v5/syntax_type.hpp>
|
||||
#include <boost/regex/v5/error_type.hpp>
|
||||
#include <boost/regex/v5/regex_traits_defaults.hpp>
|
||||
#include <boost/regex/v5/cpp_regex_traits.hpp>
|
||||
#include <boost/regex/v5/c_regex_traits.hpp>
|
||||
#if defined(_WIN32) && !defined(BOOST_REGEX_NO_W32)
|
||||
# include <boost/regex/v5/w32_regex_traits.hpp>
|
||||
#endif
|
||||
#include <boost/regex_fwd.hpp>
|
||||
|
||||
namespace boost{
|
||||
|
||||
template <class charT, class implementationT >
|
||||
struct regex_traits : public implementationT
|
||||
{
|
||||
regex_traits() : implementationT() {}
|
||||
};
|
||||
|
||||
//
|
||||
// class regex_traits_wrapper.
|
||||
// this is what our implementation will actually store;
|
||||
// it provides default implementations of the "optional"
|
||||
// interfaces that we support, in addition to the
|
||||
// required "standard" ones:
|
||||
//
|
||||
namespace BOOST_REGEX_DETAIL_NS{
|
||||
|
||||
template <class T>
|
||||
struct has_boost_extensions_tag
|
||||
{
|
||||
template <class U>
|
||||
static double checker(U*, typename U::boost_extensions_tag* = nullptr);
|
||||
static char checker(...);
|
||||
static T* get();
|
||||
|
||||
static const bool value = sizeof(checker(get())) > 1;
|
||||
};
|
||||
|
||||
|
||||
template <class BaseT>
|
||||
struct default_wrapper : public BaseT
|
||||
{
|
||||
typedef typename BaseT::char_type char_type;
|
||||
std::string error_string(::boost::regex_constants::error_type e)const
|
||||
{
|
||||
return ::boost::BOOST_REGEX_DETAIL_NS::get_default_error_string(e);
|
||||
}
|
||||
::boost::regex_constants::syntax_type syntax_type(char_type c)const
|
||||
{
|
||||
return (char_type(c & 0x7f) == c) ? get_default_syntax_type(static_cast<char>(c)) : ::boost::regex_constants::syntax_char;
|
||||
}
|
||||
::boost::regex_constants::escape_syntax_type escape_syntax_type(char_type c)const
|
||||
{
|
||||
return (char_type(c & 0x7f) == c) ? get_default_escape_syntax_type(static_cast<char>(c)) : ::boost::regex_constants::escape_type_identity;
|
||||
}
|
||||
std::intmax_t toi(const char_type*& p1, const char_type* p2, int radix)const
|
||||
{
|
||||
return ::boost::BOOST_REGEX_DETAIL_NS::global_toi(p1, p2, radix, *this);
|
||||
}
|
||||
char_type translate(char_type c, bool icase)const
|
||||
{
|
||||
return (icase ? this->translate_nocase(c) : this->translate(c));
|
||||
}
|
||||
char_type translate(char_type c)const
|
||||
{
|
||||
return BaseT::translate(c);
|
||||
}
|
||||
char_type tolower(char_type c)const
|
||||
{
|
||||
return ::boost::BOOST_REGEX_DETAIL_NS::global_lower(c);
|
||||
}
|
||||
char_type toupper(char_type c)const
|
||||
{
|
||||
return ::boost::BOOST_REGEX_DETAIL_NS::global_upper(c);
|
||||
}
|
||||
};
|
||||
|
||||
template <class BaseT, bool has_extensions>
|
||||
struct compute_wrapper_base
|
||||
{
|
||||
typedef BaseT type;
|
||||
};
|
||||
template <class BaseT>
|
||||
struct compute_wrapper_base<BaseT, false>
|
||||
{
|
||||
typedef default_wrapper<BaseT> type;
|
||||
};
|
||||
|
||||
} // namespace BOOST_REGEX_DETAIL_NS
|
||||
|
||||
template <class BaseT>
|
||||
struct regex_traits_wrapper
|
||||
: public ::boost::BOOST_REGEX_DETAIL_NS::compute_wrapper_base<
|
||||
BaseT,
|
||||
::boost::BOOST_REGEX_DETAIL_NS::has_boost_extensions_tag<BaseT>::value
|
||||
>::type
|
||||
{
|
||||
regex_traits_wrapper(){}
|
||||
private:
|
||||
regex_traits_wrapper(const regex_traits_wrapper&);
|
||||
regex_traits_wrapper& operator=(const regex_traits_wrapper&);
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // include
|
||||
|
||||
996
regex/include/boost/regex/v5/regex_traits_defaults.hpp
Normal file
996
regex/include/boost/regex/v5/regex_traits_defaults.hpp
Normal file
@@ -0,0 +1,996 @@
|
||||
/*
|
||||
*
|
||||
* 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 regex_traits_defaults.hpp
|
||||
* VERSION see <boost/version.hpp>
|
||||
* DESCRIPTION: Declares API's for access to regex_traits default properties.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_REGEX_TRAITS_DEFAULTS_HPP_INCLUDED
|
||||
#define BOOST_REGEX_TRAITS_DEFAULTS_HPP_INCLUDED
|
||||
|
||||
#include <boost/regex/config.hpp>
|
||||
|
||||
#include <boost/regex/v5/syntax_type.hpp>
|
||||
#include <boost/regex/v5/error_type.hpp>
|
||||
#include <boost/regex/v5/regex_workaround.hpp>
|
||||
#include <type_traits>
|
||||
#include <cstdint>
|
||||
#include <cctype>
|
||||
#include <locale>
|
||||
#include <cwctype>
|
||||
#include <limits>
|
||||
|
||||
namespace boost{ namespace BOOST_REGEX_DETAIL_NS{
|
||||
|
||||
|
||||
//
|
||||
// helpers to suppress warnings:
|
||||
//
|
||||
template <class charT>
|
||||
inline bool is_extended(charT c)
|
||||
{
|
||||
typedef typename std::make_unsigned<charT>::type unsigned_type;
|
||||
return (sizeof(charT) > 1) && (static_cast<unsigned_type>(c) >= 256u);
|
||||
}
|
||||
inline bool is_extended(char)
|
||||
{ return false; }
|
||||
|
||||
inline const char* get_default_syntax(regex_constants::syntax_type n)
|
||||
{
|
||||
// if the user hasn't supplied a message catalog, then this supplies
|
||||
// default "messages" for us to load in the range 1-100.
|
||||
const char* messages[] = {
|
||||
"",
|
||||
"(",
|
||||
")",
|
||||
"$",
|
||||
"^",
|
||||
".",
|
||||
"*",
|
||||
"+",
|
||||
"?",
|
||||
"[",
|
||||
"]",
|
||||
"|",
|
||||
"\\",
|
||||
"#",
|
||||
"-",
|
||||
"{",
|
||||
"}",
|
||||
"0123456789",
|
||||
"b",
|
||||
"B",
|
||||
"<",
|
||||
">",
|
||||
"",
|
||||
"",
|
||||
"A`",
|
||||
"z'",
|
||||
"\n",
|
||||
",",
|
||||
"a",
|
||||
"f",
|
||||
"n",
|
||||
"r",
|
||||
"t",
|
||||
"v",
|
||||
"x",
|
||||
"c",
|
||||
":",
|
||||
"=",
|
||||
"e",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"E",
|
||||
"Q",
|
||||
"X",
|
||||
"C",
|
||||
"Z",
|
||||
"G",
|
||||
"!",
|
||||
"p",
|
||||
"P",
|
||||
"N",
|
||||
"gk",
|
||||
"K",
|
||||
"R",
|
||||
};
|
||||
|
||||
return ((n >= (sizeof(messages) / sizeof(messages[1]))) ? "" : messages[n]);
|
||||
}
|
||||
|
||||
inline const char* get_default_error_string(regex_constants::error_type n)
|
||||
{
|
||||
static const char* const s_default_error_messages[] = {
|
||||
"Success", /* REG_NOERROR 0 error_ok */
|
||||
"No match", /* REG_NOMATCH 1 error_no_match */
|
||||
"Invalid regular expression.", /* REG_BADPAT 2 error_bad_pattern */
|
||||
"Invalid collation character.", /* REG_ECOLLATE 3 error_collate */
|
||||
"Invalid character class name, collating name, or character range.", /* REG_ECTYPE 4 error_ctype */
|
||||
"Invalid or unterminated escape sequence.", /* REG_EESCAPE 5 error_escape */
|
||||
"Invalid back reference: specified capturing group does not exist.", /* REG_ESUBREG 6 error_backref */
|
||||
"Unmatched [ or [^ in character class declaration.", /* REG_EBRACK 7 error_brack */
|
||||
"Unmatched marking parenthesis ( or \\(.", /* REG_EPAREN 8 error_paren */
|
||||
"Unmatched quantified repeat operator { or \\{.", /* REG_EBRACE 9 error_brace */
|
||||
"Invalid content of repeat range.", /* REG_BADBR 10 error_badbrace */
|
||||
"Invalid range end in character class", /* REG_ERANGE 11 error_range */
|
||||
"Out of memory.", /* REG_ESPACE 12 error_space NOT USED */
|
||||
"Invalid preceding regular expression prior to repetition operator.", /* REG_BADRPT 13 error_badrepeat */
|
||||
"Premature end of regular expression", /* REG_EEND 14 error_end NOT USED */
|
||||
"Regular expression is too large.", /* REG_ESIZE 15 error_size NOT USED */
|
||||
"Unmatched ) or \\)", /* REG_ERPAREN 16 error_right_paren NOT USED */
|
||||
"Empty regular expression.", /* REG_EMPTY 17 error_empty */
|
||||
"The complexity of matching the regular expression exceeded predefined bounds. "
|
||||
"Try refactoring the regular expression to make each choice made by the state machine unambiguous. "
|
||||
"This exception is thrown to prevent \"eternal\" matches that take an "
|
||||
"indefinite period time to locate.", /* REG_ECOMPLEXITY 18 error_complexity */
|
||||
"Ran out of stack space trying to match the regular expression.", /* REG_ESTACK 19 error_stack */
|
||||
"Invalid or unterminated Perl (?...) sequence.", /* REG_E_PERL 20 error_perl */
|
||||
"Unknown error.", /* REG_E_UNKNOWN 21 error_unknown */
|
||||
};
|
||||
|
||||
return (n > ::boost::regex_constants::error_unknown) ? s_default_error_messages[::boost::regex_constants::error_unknown] : s_default_error_messages[n];
|
||||
}
|
||||
|
||||
inline regex_constants::syntax_type get_default_syntax_type(char c)
|
||||
{
|
||||
//
|
||||
// char_syntax determines how the compiler treats a given character
|
||||
// in a regular expression.
|
||||
//
|
||||
static regex_constants::syntax_type char_syntax[] = {
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_newline, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /* */ // 32
|
||||
regex_constants::syntax_not, /*!*/
|
||||
regex_constants::syntax_char, /*"*/
|
||||
regex_constants::syntax_hash, /*#*/
|
||||
regex_constants::syntax_dollar, /*$*/
|
||||
regex_constants::syntax_char, /*%*/
|
||||
regex_constants::syntax_char, /*&*/
|
||||
regex_constants::escape_type_end_buffer, /*'*/
|
||||
regex_constants::syntax_open_mark, /*(*/
|
||||
regex_constants::syntax_close_mark, /*)*/
|
||||
regex_constants::syntax_star, /***/
|
||||
regex_constants::syntax_plus, /*+*/
|
||||
regex_constants::syntax_comma, /*,*/
|
||||
regex_constants::syntax_dash, /*-*/
|
||||
regex_constants::syntax_dot, /*.*/
|
||||
regex_constants::syntax_char, /*/*/
|
||||
regex_constants::syntax_digit, /*0*/
|
||||
regex_constants::syntax_digit, /*1*/
|
||||
regex_constants::syntax_digit, /*2*/
|
||||
regex_constants::syntax_digit, /*3*/
|
||||
regex_constants::syntax_digit, /*4*/
|
||||
regex_constants::syntax_digit, /*5*/
|
||||
regex_constants::syntax_digit, /*6*/
|
||||
regex_constants::syntax_digit, /*7*/
|
||||
regex_constants::syntax_digit, /*8*/
|
||||
regex_constants::syntax_digit, /*9*/
|
||||
regex_constants::syntax_colon, /*:*/
|
||||
regex_constants::syntax_char, /*;*/
|
||||
regex_constants::escape_type_left_word, /*<*/
|
||||
regex_constants::syntax_equal, /*=*/
|
||||
regex_constants::escape_type_right_word, /*>*/
|
||||
regex_constants::syntax_question, /*?*/
|
||||
regex_constants::syntax_char, /*@*/
|
||||
regex_constants::syntax_char, /*A*/
|
||||
regex_constants::syntax_char, /*B*/
|
||||
regex_constants::syntax_char, /*C*/
|
||||
regex_constants::syntax_char, /*D*/
|
||||
regex_constants::syntax_char, /*E*/
|
||||
regex_constants::syntax_char, /*F*/
|
||||
regex_constants::syntax_char, /*G*/
|
||||
regex_constants::syntax_char, /*H*/
|
||||
regex_constants::syntax_char, /*I*/
|
||||
regex_constants::syntax_char, /*J*/
|
||||
regex_constants::syntax_char, /*K*/
|
||||
regex_constants::syntax_char, /*L*/
|
||||
regex_constants::syntax_char, /*M*/
|
||||
regex_constants::syntax_char, /*N*/
|
||||
regex_constants::syntax_char, /*O*/
|
||||
regex_constants::syntax_char, /*P*/
|
||||
regex_constants::syntax_char, /*Q*/
|
||||
regex_constants::syntax_char, /*R*/
|
||||
regex_constants::syntax_char, /*S*/
|
||||
regex_constants::syntax_char, /*T*/
|
||||
regex_constants::syntax_char, /*U*/
|
||||
regex_constants::syntax_char, /*V*/
|
||||
regex_constants::syntax_char, /*W*/
|
||||
regex_constants::syntax_char, /*X*/
|
||||
regex_constants::syntax_char, /*Y*/
|
||||
regex_constants::syntax_char, /*Z*/
|
||||
regex_constants::syntax_open_set, /*[*/
|
||||
regex_constants::syntax_escape, /*\*/
|
||||
regex_constants::syntax_close_set, /*]*/
|
||||
regex_constants::syntax_caret, /*^*/
|
||||
regex_constants::syntax_char, /*_*/
|
||||
regex_constants::syntax_char, /*`*/
|
||||
regex_constants::syntax_char, /*a*/
|
||||
regex_constants::syntax_char, /*b*/
|
||||
regex_constants::syntax_char, /*c*/
|
||||
regex_constants::syntax_char, /*d*/
|
||||
regex_constants::syntax_char, /*e*/
|
||||
regex_constants::syntax_char, /*f*/
|
||||
regex_constants::syntax_char, /*g*/
|
||||
regex_constants::syntax_char, /*h*/
|
||||
regex_constants::syntax_char, /*i*/
|
||||
regex_constants::syntax_char, /*j*/
|
||||
regex_constants::syntax_char, /*k*/
|
||||
regex_constants::syntax_char, /*l*/
|
||||
regex_constants::syntax_char, /*m*/
|
||||
regex_constants::syntax_char, /*n*/
|
||||
regex_constants::syntax_char, /*o*/
|
||||
regex_constants::syntax_char, /*p*/
|
||||
regex_constants::syntax_char, /*q*/
|
||||
regex_constants::syntax_char, /*r*/
|
||||
regex_constants::syntax_char, /*s*/
|
||||
regex_constants::syntax_char, /*t*/
|
||||
regex_constants::syntax_char, /*u*/
|
||||
regex_constants::syntax_char, /*v*/
|
||||
regex_constants::syntax_char, /*w*/
|
||||
regex_constants::syntax_char, /*x*/
|
||||
regex_constants::syntax_char, /*y*/
|
||||
regex_constants::syntax_char, /*z*/
|
||||
regex_constants::syntax_open_brace, /*{*/
|
||||
regex_constants::syntax_or, /*|*/
|
||||
regex_constants::syntax_close_brace, /*}*/
|
||||
regex_constants::syntax_char, /*~*/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
regex_constants::syntax_char, /**/
|
||||
};
|
||||
|
||||
return char_syntax[(unsigned char)c];
|
||||
}
|
||||
|
||||
inline regex_constants::escape_syntax_type get_default_escape_syntax_type(char c)
|
||||
{
|
||||
//
|
||||
// char_syntax determines how the compiler treats a given character
|
||||
// in a regular expression.
|
||||
//
|
||||
static regex_constants::escape_syntax_type char_syntax[] = {
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /* */ // 32
|
||||
regex_constants::escape_type_identity, /*!*/
|
||||
regex_constants::escape_type_identity, /*"*/
|
||||
regex_constants::escape_type_identity, /*#*/
|
||||
regex_constants::escape_type_identity, /*$*/
|
||||
regex_constants::escape_type_identity, /*%*/
|
||||
regex_constants::escape_type_identity, /*&*/
|
||||
regex_constants::escape_type_end_buffer, /*'*/
|
||||
regex_constants::syntax_open_mark, /*(*/
|
||||
regex_constants::syntax_close_mark, /*)*/
|
||||
regex_constants::escape_type_identity, /***/
|
||||
regex_constants::syntax_plus, /*+*/
|
||||
regex_constants::escape_type_identity, /*,*/
|
||||
regex_constants::escape_type_identity, /*-*/
|
||||
regex_constants::escape_type_identity, /*.*/
|
||||
regex_constants::escape_type_identity, /*/*/
|
||||
regex_constants::escape_type_decimal, /*0*/
|
||||
regex_constants::escape_type_backref, /*1*/
|
||||
regex_constants::escape_type_backref, /*2*/
|
||||
regex_constants::escape_type_backref, /*3*/
|
||||
regex_constants::escape_type_backref, /*4*/
|
||||
regex_constants::escape_type_backref, /*5*/
|
||||
regex_constants::escape_type_backref, /*6*/
|
||||
regex_constants::escape_type_backref, /*7*/
|
||||
regex_constants::escape_type_backref, /*8*/
|
||||
regex_constants::escape_type_backref, /*9*/
|
||||
regex_constants::escape_type_identity, /*:*/
|
||||
regex_constants::escape_type_identity, /*;*/
|
||||
regex_constants::escape_type_left_word, /*<*/
|
||||
regex_constants::escape_type_identity, /*=*/
|
||||
regex_constants::escape_type_right_word, /*>*/
|
||||
regex_constants::syntax_question, /*?*/
|
||||
regex_constants::escape_type_identity, /*@*/
|
||||
regex_constants::escape_type_start_buffer, /*A*/
|
||||
regex_constants::escape_type_not_word_assert, /*B*/
|
||||
regex_constants::escape_type_C, /*C*/
|
||||
regex_constants::escape_type_not_class, /*D*/
|
||||
regex_constants::escape_type_E, /*E*/
|
||||
regex_constants::escape_type_not_class, /*F*/
|
||||
regex_constants::escape_type_G, /*G*/
|
||||
regex_constants::escape_type_not_class, /*H*/
|
||||
regex_constants::escape_type_not_class, /*I*/
|
||||
regex_constants::escape_type_not_class, /*J*/
|
||||
regex_constants::escape_type_reset_start_mark, /*K*/
|
||||
regex_constants::escape_type_not_class, /*L*/
|
||||
regex_constants::escape_type_not_class, /*M*/
|
||||
regex_constants::escape_type_named_char, /*N*/
|
||||
regex_constants::escape_type_not_class, /*O*/
|
||||
regex_constants::escape_type_not_property, /*P*/
|
||||
regex_constants::escape_type_Q, /*Q*/
|
||||
regex_constants::escape_type_line_ending, /*R*/
|
||||
regex_constants::escape_type_not_class, /*S*/
|
||||
regex_constants::escape_type_not_class, /*T*/
|
||||
regex_constants::escape_type_not_class, /*U*/
|
||||
regex_constants::escape_type_not_class, /*V*/
|
||||
regex_constants::escape_type_not_class, /*W*/
|
||||
regex_constants::escape_type_X, /*X*/
|
||||
regex_constants::escape_type_not_class, /*Y*/
|
||||
regex_constants::escape_type_Z, /*Z*/
|
||||
regex_constants::escape_type_identity, /*[*/
|
||||
regex_constants::escape_type_identity, /*\*/
|
||||
regex_constants::escape_type_identity, /*]*/
|
||||
regex_constants::escape_type_identity, /*^*/
|
||||
regex_constants::escape_type_identity, /*_*/
|
||||
regex_constants::escape_type_start_buffer, /*`*/
|
||||
regex_constants::escape_type_control_a, /*a*/
|
||||
regex_constants::escape_type_word_assert, /*b*/
|
||||
regex_constants::escape_type_ascii_control, /*c*/
|
||||
regex_constants::escape_type_class, /*d*/
|
||||
regex_constants::escape_type_e, /*e*/
|
||||
regex_constants::escape_type_control_f, /*f*/
|
||||
regex_constants::escape_type_extended_backref, /*g*/
|
||||
regex_constants::escape_type_class, /*h*/
|
||||
regex_constants::escape_type_class, /*i*/
|
||||
regex_constants::escape_type_class, /*j*/
|
||||
regex_constants::escape_type_extended_backref, /*k*/
|
||||
regex_constants::escape_type_class, /*l*/
|
||||
regex_constants::escape_type_class, /*m*/
|
||||
regex_constants::escape_type_control_n, /*n*/
|
||||
regex_constants::escape_type_class, /*o*/
|
||||
regex_constants::escape_type_property, /*p*/
|
||||
regex_constants::escape_type_class, /*q*/
|
||||
regex_constants::escape_type_control_r, /*r*/
|
||||
regex_constants::escape_type_class, /*s*/
|
||||
regex_constants::escape_type_control_t, /*t*/
|
||||
regex_constants::escape_type_class, /*u*/
|
||||
regex_constants::escape_type_control_v, /*v*/
|
||||
regex_constants::escape_type_class, /*w*/
|
||||
regex_constants::escape_type_hex, /*x*/
|
||||
regex_constants::escape_type_class, /*y*/
|
||||
regex_constants::escape_type_end_buffer, /*z*/
|
||||
regex_constants::syntax_open_brace, /*{*/
|
||||
regex_constants::syntax_or, /*|*/
|
||||
regex_constants::syntax_close_brace, /*}*/
|
||||
regex_constants::escape_type_identity, /*~*/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
regex_constants::escape_type_identity, /**/
|
||||
};
|
||||
|
||||
return char_syntax[(unsigned char)c];
|
||||
}
|
||||
|
||||
// is charT c a combining character?
|
||||
inline bool is_combining_implementation(std::uint_least16_t c)
|
||||
{
|
||||
const std::uint_least16_t combining_ranges[] = { 0x0300, 0x0361,
|
||||
0x0483, 0x0486,
|
||||
0x0903, 0x0903,
|
||||
0x093E, 0x0940,
|
||||
0x0949, 0x094C,
|
||||
0x0982, 0x0983,
|
||||
0x09BE, 0x09C0,
|
||||
0x09C7, 0x09CC,
|
||||
0x09D7, 0x09D7,
|
||||
0x0A3E, 0x0A40,
|
||||
0x0A83, 0x0A83,
|
||||
0x0ABE, 0x0AC0,
|
||||
0x0AC9, 0x0ACC,
|
||||
0x0B02, 0x0B03,
|
||||
0x0B3E, 0x0B3E,
|
||||
0x0B40, 0x0B40,
|
||||
0x0B47, 0x0B4C,
|
||||
0x0B57, 0x0B57,
|
||||
0x0B83, 0x0B83,
|
||||
0x0BBE, 0x0BBF,
|
||||
0x0BC1, 0x0BCC,
|
||||
0x0BD7, 0x0BD7,
|
||||
0x0C01, 0x0C03,
|
||||
0x0C41, 0x0C44,
|
||||
0x0C82, 0x0C83,
|
||||
0x0CBE, 0x0CBE,
|
||||
0x0CC0, 0x0CC4,
|
||||
0x0CC7, 0x0CCB,
|
||||
0x0CD5, 0x0CD6,
|
||||
0x0D02, 0x0D03,
|
||||
0x0D3E, 0x0D40,
|
||||
0x0D46, 0x0D4C,
|
||||
0x0D57, 0x0D57,
|
||||
0x0F7F, 0x0F7F,
|
||||
0x20D0, 0x20E1,
|
||||
0x3099, 0x309A,
|
||||
0xFE20, 0xFE23,
|
||||
0xffff, 0xffff, };
|
||||
|
||||
const std::uint_least16_t* p = combining_ranges + 1;
|
||||
while (*p < c) p += 2;
|
||||
--p;
|
||||
if ((c >= *p) && (c <= *(p + 1)))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class charT>
|
||||
inline bool is_combining(charT c)
|
||||
{
|
||||
return (c <= static_cast<charT>(0)) ? false : ((c >= static_cast<charT>((std::numeric_limits<uint_least16_t>::max)())) ? false : is_combining_implementation(static_cast<unsigned short>(c)));
|
||||
}
|
||||
template <>
|
||||
inline bool is_combining<char>(char)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
template <>
|
||||
inline bool is_combining<signed char>(signed char)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
template <>
|
||||
inline bool is_combining<unsigned char>(unsigned char)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#ifdef _MSC_VER
|
||||
template<>
|
||||
inline bool is_combining<wchar_t>(wchar_t c)
|
||||
{
|
||||
return is_combining_implementation(static_cast<unsigned short>(c));
|
||||
}
|
||||
#elif !defined(__DECCXX) && !defined(__osf__) && !defined(__OSF__) && defined(WCHAR_MIN) && (WCHAR_MIN == 0) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
|
||||
#if defined(WCHAR_MAX) && (WCHAR_MAX <= USHRT_MAX)
|
||||
template<>
|
||||
inline bool is_combining<wchar_t>(wchar_t c)
|
||||
{
|
||||
return is_combining_implementation(static_cast<unsigned short>(c));
|
||||
}
|
||||
#else
|
||||
template<>
|
||||
inline bool is_combining<wchar_t>(wchar_t c)
|
||||
{
|
||||
return (c >= (std::numeric_limits<uint_least16_t>::max)()) ? false : is_combining_implementation(static_cast<unsigned short>(c));
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//
|
||||
// is a charT c a line separator?
|
||||
//
|
||||
template <class charT>
|
||||
inline bool is_separator(charT c)
|
||||
{
|
||||
return BOOST_REGEX_MAKE_BOOL(
|
||||
(c == static_cast<charT>('\n'))
|
||||
|| (c == static_cast<charT>('\r'))
|
||||
|| (c == static_cast<charT>('\f'))
|
||||
|| (static_cast<std::uint16_t>(c) == 0x2028u)
|
||||
|| (static_cast<std::uint16_t>(c) == 0x2029u)
|
||||
|| (static_cast<std::uint16_t>(c) == 0x85u));
|
||||
}
|
||||
template <>
|
||||
inline bool is_separator<char>(char c)
|
||||
{
|
||||
return BOOST_REGEX_MAKE_BOOL((c == '\n') || (c == '\r') || (c == '\f'));
|
||||
}
|
||||
|
||||
//
|
||||
// get a default collating element:
|
||||
//
|
||||
inline std::string lookup_default_collate_name(const std::string& name)
|
||||
{
|
||||
//
|
||||
// these are the POSIX collating names:
|
||||
//
|
||||
static const char* def_coll_names[] = {
|
||||
"NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "alert", "backspace", "tab", "newline",
|
||||
"vertical-tab", "form-feed", "carriage-return", "SO", "SI", "DLE", "DC1", "DC2", "DC3", "DC4", "NAK",
|
||||
"SYN", "ETB", "CAN", "EM", "SUB", "ESC", "IS4", "IS3", "IS2", "IS1", "space", "exclamation-mark",
|
||||
"quotation-mark", "number-sign", "dollar-sign", "percent-sign", "ampersand", "apostrophe",
|
||||
"left-parenthesis", "right-parenthesis", "asterisk", "plus-sign", "comma", "hyphen",
|
||||
"period", "slash", "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine",
|
||||
"colon", "semicolon", "less-than-sign", "equals-sign", "greater-than-sign",
|
||||
"question-mark", "commercial-at", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P",
|
||||
"Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "left-square-bracket", "backslash",
|
||||
"right-square-bracket", "circumflex", "underscore", "grave-accent", "a", "b", "c", "d", "e", "f",
|
||||
"g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "left-curly-bracket",
|
||||
"vertical-line", "right-curly-bracket", "tilde", "DEL", "",
|
||||
};
|
||||
|
||||
// these multi-character collating elements
|
||||
// should keep most Western-European locales
|
||||
// happy - we should really localise these a
|
||||
// little more - but this will have to do for
|
||||
// now:
|
||||
|
||||
static const char* def_multi_coll[] = {
|
||||
"ae",
|
||||
"Ae",
|
||||
"AE",
|
||||
"ch",
|
||||
"Ch",
|
||||
"CH",
|
||||
"ll",
|
||||
"Ll",
|
||||
"LL",
|
||||
"ss",
|
||||
"Ss",
|
||||
"SS",
|
||||
"nj",
|
||||
"Nj",
|
||||
"NJ",
|
||||
"dz",
|
||||
"Dz",
|
||||
"DZ",
|
||||
"lj",
|
||||
"Lj",
|
||||
"LJ",
|
||||
"",
|
||||
};
|
||||
|
||||
unsigned int i = 0;
|
||||
while (*def_coll_names[i])
|
||||
{
|
||||
if (def_coll_names[i] == name)
|
||||
{
|
||||
return std::string(1, char(i));
|
||||
}
|
||||
++i;
|
||||
}
|
||||
i = 0;
|
||||
while (*def_multi_coll[i])
|
||||
{
|
||||
if (def_multi_coll[i] == name)
|
||||
{
|
||||
return def_multi_coll[i];
|
||||
}
|
||||
++i;
|
||||
}
|
||||
return std::string();
|
||||
}
|
||||
|
||||
//
|
||||
// get the state_id of a character classification, the individual
|
||||
// traits classes then transform that state_id into a bitmask:
|
||||
//
|
||||
template <class charT>
|
||||
struct character_pointer_range
|
||||
{
|
||||
const charT* p1;
|
||||
const charT* p2;
|
||||
|
||||
bool operator < (const character_pointer_range& r)const
|
||||
{
|
||||
return std::lexicographical_compare(p1, p2, r.p1, r.p2);
|
||||
}
|
||||
bool operator == (const character_pointer_range& r)const
|
||||
{
|
||||
// Not only do we check that the ranges are of equal size before
|
||||
// calling std::equal, but there is no other algorithm available:
|
||||
// not even a non-standard MS one. So forward to unchecked_equal
|
||||
// in the MS case.
|
||||
#ifdef __cpp_lib_robust_nonmodifying_seq_ops
|
||||
return std::equal(p1, p2, r.p1, r.p2);
|
||||
#elif defined(BOOST_REGEX_MSVC)
|
||||
if (((p2 - p1) != (r.p2 - r.p1)))
|
||||
return false;
|
||||
const charT* with = r.p1;
|
||||
const charT* pos = p1;
|
||||
while (pos != p2)
|
||||
if (*pos++ != *with++) return false;
|
||||
return true;
|
||||
|
||||
#else
|
||||
return ((p2 - p1) == (r.p2 - r.p1)) && std::equal(p1, p2, r.p1);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
template <class charT>
|
||||
int get_default_class_id(const charT* p1, const charT* p2)
|
||||
{
|
||||
static const charT data[73] = {
|
||||
'a', 'l', 'n', 'u', 'm',
|
||||
'a', 'l', 'p', 'h', 'a',
|
||||
'b', 'l', 'a', 'n', 'k',
|
||||
'c', 'n', 't', 'r', 'l',
|
||||
'd', 'i', 'g', 'i', 't',
|
||||
'g', 'r', 'a', 'p', 'h',
|
||||
'l', 'o', 'w', 'e', 'r',
|
||||
'p', 'r', 'i', 'n', 't',
|
||||
'p', 'u', 'n', 'c', 't',
|
||||
's', 'p', 'a', 'c', 'e',
|
||||
'u', 'n', 'i', 'c', 'o', 'd', 'e',
|
||||
'u', 'p', 'p', 'e', 'r',
|
||||
'v',
|
||||
'w', 'o', 'r', 'd',
|
||||
'x', 'd', 'i', 'g', 'i', 't',
|
||||
};
|
||||
|
||||
static const character_pointer_range<charT> ranges[21] =
|
||||
{
|
||||
{data+0, data+5,}, // alnum
|
||||
{data+5, data+10,}, // alpha
|
||||
{data+10, data+15,}, // blank
|
||||
{data+15, data+20,}, // cntrl
|
||||
{data+20, data+21,}, // d
|
||||
{data+20, data+25,}, // digit
|
||||
{data+25, data+30,}, // graph
|
||||
{data+29, data+30,}, // h
|
||||
{data+30, data+31,}, // l
|
||||
{data+30, data+35,}, // lower
|
||||
{data+35, data+40,}, // print
|
||||
{data+40, data+45,}, // punct
|
||||
{data+45, data+46,}, // s
|
||||
{data+45, data+50,}, // space
|
||||
{data+57, data+58,}, // u
|
||||
{data+50, data+57,}, // unicode
|
||||
{data+57, data+62,}, // upper
|
||||
{data+62, data+63,}, // v
|
||||
{data+63, data+64,}, // w
|
||||
{data+63, data+67,}, // word
|
||||
{data+67, data+73,}, // xdigit
|
||||
};
|
||||
const character_pointer_range<charT>* ranges_begin = ranges;
|
||||
const character_pointer_range<charT>* ranges_end = ranges + (sizeof(ranges)/sizeof(ranges[0]));
|
||||
|
||||
character_pointer_range<charT> t = { p1, p2, };
|
||||
const character_pointer_range<charT>* p = std::lower_bound(ranges_begin, ranges_end, t);
|
||||
if((p != ranges_end) && (t == *p))
|
||||
return static_cast<int>(p - ranges);
|
||||
return -1;
|
||||
}
|
||||
|
||||
//
|
||||
// helper functions:
|
||||
//
|
||||
template <class charT>
|
||||
std::ptrdiff_t global_length(const charT* p)
|
||||
{
|
||||
std::ptrdiff_t n = 0;
|
||||
while(*p)
|
||||
{
|
||||
++p;
|
||||
++n;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
template<>
|
||||
inline std::ptrdiff_t global_length<char>(const char* p)
|
||||
{
|
||||
return (std::strlen)(p);
|
||||
}
|
||||
#ifndef BOOST_NO_WREGEX
|
||||
template<>
|
||||
inline std::ptrdiff_t global_length<wchar_t>(const wchar_t* p)
|
||||
{
|
||||
return (std::ptrdiff_t)(std::wcslen)(p);
|
||||
}
|
||||
#endif
|
||||
template <class charT>
|
||||
inline charT global_lower(charT c)
|
||||
{
|
||||
return c;
|
||||
}
|
||||
template <class charT>
|
||||
inline charT global_upper(charT c)
|
||||
{
|
||||
return c;
|
||||
}
|
||||
|
||||
inline char do_global_lower(char c)
|
||||
{
|
||||
return static_cast<char>((std::tolower)((unsigned char)c));
|
||||
}
|
||||
|
||||
inline char do_global_upper(char c)
|
||||
{
|
||||
return static_cast<char>((std::toupper)((unsigned char)c));
|
||||
}
|
||||
#ifndef BOOST_NO_WREGEX
|
||||
inline wchar_t do_global_lower(wchar_t c)
|
||||
{
|
||||
return (std::towlower)(c);
|
||||
}
|
||||
|
||||
inline wchar_t do_global_upper(wchar_t c)
|
||||
{
|
||||
return (std::towupper)(c);
|
||||
}
|
||||
#endif
|
||||
//
|
||||
// This sucks: declare template specialisations of global_lower/global_upper
|
||||
// that just forward to the non-template implementation functions. We do
|
||||
// this because there is one compiler (Compaq Tru64 C++) that doesn't seem
|
||||
// to differentiate between templates and non-template overloads....
|
||||
// what's more, the primary template, plus all overloads have to be
|
||||
// defined in the same translation unit (if one is inline they all must be)
|
||||
// otherwise the "local template instantiation" compiler option can pick
|
||||
// the wrong instantiation when linking:
|
||||
//
|
||||
template<> inline char global_lower<char>(char c) { return do_global_lower(c); }
|
||||
template<> inline char global_upper<char>(char c) { return do_global_upper(c); }
|
||||
#ifndef BOOST_NO_WREGEX
|
||||
template<> inline wchar_t global_lower<wchar_t>(wchar_t c) { return do_global_lower(c); }
|
||||
template<> inline wchar_t global_upper<wchar_t>(wchar_t c) { return do_global_upper(c); }
|
||||
#endif
|
||||
|
||||
template <class charT>
|
||||
int global_value(charT c)
|
||||
{
|
||||
static const charT zero = '0';
|
||||
static const charT nine = '9';
|
||||
static const charT a = 'a';
|
||||
static const charT f = 'f';
|
||||
static const charT A = 'A';
|
||||
static const charT F = 'F';
|
||||
|
||||
if(c > f) return -1;
|
||||
if(c >= a) return 10 + (c - a);
|
||||
if(c > F) return -1;
|
||||
if(c >= A) return 10 + (c - A);
|
||||
if(c > nine) return -1;
|
||||
if(c >= zero) return c - zero;
|
||||
return -1;
|
||||
}
|
||||
template <class charT, class traits>
|
||||
std::intmax_t global_toi(const charT*& p1, const charT* p2, int radix, const traits& t)
|
||||
{
|
||||
(void)t; // warning suppression
|
||||
std::intmax_t limit = (std::numeric_limits<std::intmax_t>::max)() / radix;
|
||||
std::intmax_t next_value = t.value(*p1, radix);
|
||||
if((p1 == p2) || (next_value < 0) || (next_value >= radix))
|
||||
return -1;
|
||||
std::intmax_t result = 0;
|
||||
while(p1 != p2)
|
||||
{
|
||||
next_value = t.value(*p1, radix);
|
||||
if((next_value < 0) || (next_value >= radix))
|
||||
break;
|
||||
result *= radix;
|
||||
result += next_value;
|
||||
++p1;
|
||||
if (result > limit)
|
||||
return -1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class charT>
|
||||
inline typename std::enable_if<(sizeof(charT) > 1), const charT*>::type get_escape_R_string()
|
||||
{
|
||||
#ifdef BOOST_REGEX_MSVC
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable:4309 4245)
|
||||
#endif
|
||||
static const charT e1[] = { '(', '?', '-', 'x', ':', '(', '?', '>', '\x0D', '\x0A', '?',
|
||||
'|', '[', '\x0A', '\x0B', '\x0C', static_cast<charT>(0x85), static_cast<charT>(0x2028),
|
||||
static_cast<charT>(0x2029), ']', ')', ')', '\0' };
|
||||
static const charT e2[] = { '(', '?', '-', 'x', ':', '(', '?', '>', '\x0D', '\x0A', '?',
|
||||
'|', '[', '\x0A', '\x0B', '\x0C', static_cast<charT>(0x85), ']', ')', ')', '\0' };
|
||||
|
||||
charT c = static_cast<charT>(0x2029u);
|
||||
bool b = (static_cast<unsigned>(c) == 0x2029u);
|
||||
|
||||
return (b ? e1 : e2);
|
||||
#ifdef BOOST_REGEX_MSVC
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class charT>
|
||||
inline typename std::enable_if<(sizeof(charT) == 1), const charT*>::type get_escape_R_string()
|
||||
{
|
||||
#ifdef BOOST_REGEX_MSVC
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable:4309 4245)
|
||||
#endif
|
||||
static const charT e2[] = {
|
||||
static_cast<charT>('('),
|
||||
static_cast<charT>('?'),
|
||||
static_cast<charT>('-'),
|
||||
static_cast<charT>('x'),
|
||||
static_cast<charT>(':'),
|
||||
static_cast<charT>('('),
|
||||
static_cast<charT>('?'),
|
||||
static_cast<charT>('>'),
|
||||
static_cast<charT>('\x0D'),
|
||||
static_cast<charT>('\x0A'),
|
||||
static_cast<charT>('?'),
|
||||
static_cast<charT>('|'),
|
||||
static_cast<charT>('['),
|
||||
static_cast<charT>('\x0A'),
|
||||
static_cast<charT>('\x0B'),
|
||||
static_cast<charT>('\x0C'),
|
||||
static_cast<charT>('\x85'),
|
||||
static_cast<charT>(']'),
|
||||
static_cast<charT>(')'),
|
||||
static_cast<charT>(')'),
|
||||
static_cast<charT>('\0')
|
||||
};
|
||||
return e2;
|
||||
#ifdef BOOST_REGEX_MSVC
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
}
|
||||
|
||||
} // BOOST_REGEX_DETAIL_NS
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
159
regex/include/boost/regex/v5/regex_workaround.hpp
Normal file
159
regex/include/boost/regex/v5/regex_workaround.hpp
Normal file
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 1998-2005
|
||||
* 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_workarounds.cpp
|
||||
* VERSION see <boost/version.hpp>
|
||||
* DESCRIPTION: Declares Misc workarounds.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_REGEX_WORKAROUND_HPP
|
||||
#define BOOST_REGEX_WORKAROUND_HPP
|
||||
|
||||
#include <boost/regex/config.hpp>
|
||||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
#include <cstring>
|
||||
|
||||
#ifndef BOOST_REGEX_STANDALONE
|
||||
#include <boost/detail/workaround.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_REGEX_NO_BOOL
|
||||
# define BOOST_REGEX_MAKE_BOOL(x) static_cast<bool>((x) ? true : false)
|
||||
#else
|
||||
# define BOOST_REGEX_MAKE_BOOL(x) static_cast<bool>(x)
|
||||
#endif
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* helper functions pointer_construct/pointer_destroy:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace boost{ namespace BOOST_REGEX_DETAIL_NS{
|
||||
|
||||
#ifdef BOOST_REGEX_MSVC
|
||||
#pragma warning (push)
|
||||
#pragma warning (disable : 4100)
|
||||
#endif
|
||||
|
||||
template <class T>
|
||||
inline void pointer_destroy(T* p)
|
||||
{ p->~T(); (void)p; }
|
||||
|
||||
#ifdef BOOST_REGEX_MSVC
|
||||
#pragma warning (pop)
|
||||
#endif
|
||||
|
||||
template <class T>
|
||||
inline void pointer_construct(T* p, const T& t)
|
||||
{ new (p) T(t); }
|
||||
|
||||
}} // namespaces
|
||||
#endif
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* helper function copy:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(BOOST_WORKAROUND)
|
||||
#if BOOST_WORKAROUND(BOOST_REGEX_MSVC, >= 1400) && defined(__STDC_WANT_SECURE_LIB__) && __STDC_WANT_SECURE_LIB__
|
||||
#define BOOST_REGEX_HAS_STRCPY_S
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace boost{ namespace BOOST_REGEX_DETAIL_NS{
|
||||
|
||||
#if defined(BOOST_REGEX_MSVC) && (BOOST_REGEX_MSVC < 1910)
|
||||
//
|
||||
// MSVC 10 will either emit warnings or else refuse to compile
|
||||
// code that makes perfectly legitimate use of std::copy, when
|
||||
// the OutputIterator type is a user-defined class (apparently all user
|
||||
// defined iterators are "unsafe"). What's more Microsoft have removed their
|
||||
// non-standard "unchecked" versions, even though they are still in the MS
|
||||
// documentation!! Work around this as best we can:
|
||||
//
|
||||
template<class InputIterator, class OutputIterator>
|
||||
inline OutputIterator copy(
|
||||
InputIterator first,
|
||||
InputIterator last,
|
||||
OutputIterator dest
|
||||
)
|
||||
{
|
||||
while (first != last)
|
||||
*dest++ = *first++;
|
||||
return dest;
|
||||
}
|
||||
#else
|
||||
using std::copy;
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(BOOST_REGEX_HAS_STRCPY_S)
|
||||
|
||||
// use safe versions of strcpy etc:
|
||||
using ::strcpy_s;
|
||||
using ::strcat_s;
|
||||
#else
|
||||
inline std::size_t strcpy_s(
|
||||
char *strDestination,
|
||||
std::size_t sizeInBytes,
|
||||
const char *strSource
|
||||
)
|
||||
{
|
||||
std::size_t lenSourceWithNull = std::strlen(strSource) + 1;
|
||||
if (lenSourceWithNull > sizeInBytes)
|
||||
return 1;
|
||||
std::memcpy(strDestination, strSource, lenSourceWithNull);
|
||||
return 0;
|
||||
}
|
||||
inline std::size_t strcat_s(
|
||||
char *strDestination,
|
||||
std::size_t sizeInBytes,
|
||||
const char *strSource
|
||||
)
|
||||
{
|
||||
std::size_t lenSourceWithNull = std::strlen(strSource) + 1;
|
||||
std::size_t lenDestination = std::strlen(strDestination);
|
||||
if (lenSourceWithNull + lenDestination > sizeInBytes)
|
||||
return 1;
|
||||
std::memcpy(strDestination + lenDestination, strSource, lenSourceWithNull);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
inline void overflow_error_if_not_zero(std::size_t i)
|
||||
{
|
||||
if(i)
|
||||
{
|
||||
std::overflow_error e("String buffer too small");
|
||||
#ifndef BOOST_REGEX_STANDALONE
|
||||
boost::throw_exception(e);
|
||||
#else
|
||||
throw e;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
}} // namespaces
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // include guard
|
||||
|
||||
299
regex/include/boost/regex/v5/states.hpp
Normal file
299
regex/include/boost/regex/v5/states.hpp
Normal file
@@ -0,0 +1,299 @@
|
||||
/*
|
||||
*
|
||||
* 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 states.cpp
|
||||
* VERSION see <boost/version.hpp>
|
||||
* DESCRIPTION: Declares internal state machine structures.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_REGEX_V5_STATES_HPP
|
||||
#define BOOST_REGEX_V5_STATES_HPP
|
||||
|
||||
namespace boost{
|
||||
namespace BOOST_REGEX_DETAIL_NS{
|
||||
|
||||
/*** mask_type *******************************************************
|
||||
Whenever we have a choice of two alternatives, we use an array of bytes
|
||||
to indicate which of the two alternatives it is possible to take for any
|
||||
given input character. If mask_take is set, then we can take the next
|
||||
state, and if mask_skip is set then we can take the alternative.
|
||||
***********************************************************************/
|
||||
enum mask_type
|
||||
{
|
||||
mask_take = 1,
|
||||
mask_skip = 2,
|
||||
mask_init = 4,
|
||||
mask_any = mask_skip | mask_take,
|
||||
mask_all = mask_any
|
||||
};
|
||||
|
||||
/*** helpers **********************************************************
|
||||
These helpers let us use function overload resolution to detect whether
|
||||
we have narrow or wide character strings:
|
||||
***********************************************************************/
|
||||
struct _narrow_type{};
|
||||
struct _wide_type{};
|
||||
template <class charT> struct is_byte;
|
||||
template<> struct is_byte<char> { typedef _narrow_type width_type; };
|
||||
template<> struct is_byte<unsigned char>{ typedef _narrow_type width_type; };
|
||||
template<> struct is_byte<signed char> { typedef _narrow_type width_type; };
|
||||
template <class charT> struct is_byte { typedef _wide_type width_type; };
|
||||
|
||||
/*** enum syntax_element_type ******************************************
|
||||
Every record in the state machine falls into one of the following types:
|
||||
***********************************************************************/
|
||||
enum syntax_element_type
|
||||
{
|
||||
// start of a marked sub-expression, or perl-style (?...) extension
|
||||
syntax_element_startmark = 0,
|
||||
// end of a marked sub-expression, or perl-style (?...) extension
|
||||
syntax_element_endmark = syntax_element_startmark + 1,
|
||||
// any sequence of literal characters
|
||||
syntax_element_literal = syntax_element_endmark + 1,
|
||||
// start of line assertion: ^
|
||||
syntax_element_start_line = syntax_element_literal + 1,
|
||||
// end of line assertion $
|
||||
syntax_element_end_line = syntax_element_start_line + 1,
|
||||
// match any character: .
|
||||
syntax_element_wild = syntax_element_end_line + 1,
|
||||
// end of expression: we have a match when we get here
|
||||
syntax_element_match = syntax_element_wild + 1,
|
||||
// perl style word boundary: \b
|
||||
syntax_element_word_boundary = syntax_element_match + 1,
|
||||
// perl style within word boundary: \B
|
||||
syntax_element_within_word = syntax_element_word_boundary + 1,
|
||||
// start of word assertion: \<
|
||||
syntax_element_word_start = syntax_element_within_word + 1,
|
||||
// end of word assertion: \>
|
||||
syntax_element_word_end = syntax_element_word_start + 1,
|
||||
// start of buffer assertion: \`
|
||||
syntax_element_buffer_start = syntax_element_word_end + 1,
|
||||
// end of buffer assertion: \'
|
||||
syntax_element_buffer_end = syntax_element_buffer_start + 1,
|
||||
// backreference to previously matched sub-expression
|
||||
syntax_element_backref = syntax_element_buffer_end + 1,
|
||||
// either a wide character set [..] or one with multicharacter collating elements:
|
||||
syntax_element_long_set = syntax_element_backref + 1,
|
||||
// narrow character set: [...]
|
||||
syntax_element_set = syntax_element_long_set + 1,
|
||||
// jump to a new state in the machine:
|
||||
syntax_element_jump = syntax_element_set + 1,
|
||||
// choose between two production states:
|
||||
syntax_element_alt = syntax_element_jump + 1,
|
||||
// a repeat
|
||||
syntax_element_rep = syntax_element_alt + 1,
|
||||
// match a combining character sequence
|
||||
syntax_element_combining = syntax_element_rep + 1,
|
||||
// perl style soft buffer end: \z
|
||||
syntax_element_soft_buffer_end = syntax_element_combining + 1,
|
||||
// perl style continuation: \G
|
||||
syntax_element_restart_continue = syntax_element_soft_buffer_end + 1,
|
||||
// single character repeats:
|
||||
syntax_element_dot_rep = syntax_element_restart_continue + 1,
|
||||
syntax_element_char_rep = syntax_element_dot_rep + 1,
|
||||
syntax_element_short_set_rep = syntax_element_char_rep + 1,
|
||||
syntax_element_long_set_rep = syntax_element_short_set_rep + 1,
|
||||
// a backstep for lookbehind repeats:
|
||||
syntax_element_backstep = syntax_element_long_set_rep + 1,
|
||||
// an assertion that a mark was matched:
|
||||
syntax_element_assert_backref = syntax_element_backstep + 1,
|
||||
syntax_element_toggle_case = syntax_element_assert_backref + 1,
|
||||
// a recursive expression:
|
||||
syntax_element_recurse = syntax_element_toggle_case + 1,
|
||||
// Verbs:
|
||||
syntax_element_fail = syntax_element_recurse + 1,
|
||||
syntax_element_accept = syntax_element_fail + 1,
|
||||
syntax_element_commit = syntax_element_accept + 1,
|
||||
syntax_element_then = syntax_element_commit + 1
|
||||
};
|
||||
|
||||
#ifdef BOOST_REGEX_DEBUG
|
||||
// dwa 09/26/00 - This is needed to suppress warnings about an ambiguous conversion
|
||||
std::ostream& operator<<(std::ostream&, syntax_element_type);
|
||||
#endif
|
||||
|
||||
struct re_syntax_base;
|
||||
|
||||
/*** union offset_type ************************************************
|
||||
Points to another state in the machine. During machine construction
|
||||
we use integral offsets, but these are converted to pointers before
|
||||
execution of the machine.
|
||||
***********************************************************************/
|
||||
union offset_type
|
||||
{
|
||||
re_syntax_base* p;
|
||||
std::ptrdiff_t i;
|
||||
};
|
||||
|
||||
/*** struct re_syntax_base ********************************************
|
||||
Base class for all states in the machine.
|
||||
***********************************************************************/
|
||||
struct re_syntax_base
|
||||
{
|
||||
syntax_element_type type; // what kind of state this is
|
||||
offset_type next; // next state in the machine
|
||||
};
|
||||
|
||||
/*** struct re_brace **************************************************
|
||||
A marked parenthesis.
|
||||
***********************************************************************/
|
||||
struct re_brace : public re_syntax_base
|
||||
{
|
||||
// The index to match, can be zero (don't mark the sub-expression)
|
||||
// or negative (for perl style (?...) extensions):
|
||||
int index;
|
||||
bool icase;
|
||||
};
|
||||
|
||||
/*** struct re_dot **************************************************
|
||||
Match anything.
|
||||
***********************************************************************/
|
||||
enum
|
||||
{
|
||||
dont_care = 1,
|
||||
force_not_newline = 0,
|
||||
force_newline = 2,
|
||||
|
||||
test_not_newline = 2,
|
||||
test_newline = 3
|
||||
};
|
||||
struct re_dot : public re_syntax_base
|
||||
{
|
||||
unsigned char mask;
|
||||
};
|
||||
|
||||
/*** struct re_literal ************************************************
|
||||
A string of literals, following this structure will be an
|
||||
array of characters: charT[length]
|
||||
***********************************************************************/
|
||||
struct re_literal : public re_syntax_base
|
||||
{
|
||||
unsigned int length;
|
||||
};
|
||||
|
||||
/*** struct re_case ************************************************
|
||||
Indicates whether we are moving to a case insensive block or not
|
||||
***********************************************************************/
|
||||
struct re_case : public re_syntax_base
|
||||
{
|
||||
bool icase;
|
||||
};
|
||||
|
||||
/*** struct re_set_long ***********************************************
|
||||
A wide character set of characters, following this structure will be
|
||||
an array of type charT:
|
||||
First csingles null-terminated strings
|
||||
Then 2 * cranges NULL terminated strings
|
||||
Then cequivalents NULL terminated strings
|
||||
***********************************************************************/
|
||||
template <class mask_type>
|
||||
struct re_set_long : public re_syntax_base
|
||||
{
|
||||
unsigned int csingles, cranges, cequivalents;
|
||||
mask_type cclasses;
|
||||
mask_type cnclasses;
|
||||
bool isnot;
|
||||
bool singleton;
|
||||
};
|
||||
|
||||
/*** struct re_set ****************************************************
|
||||
A set of narrow-characters, matches any of _map which is none-zero
|
||||
***********************************************************************/
|
||||
struct re_set : public re_syntax_base
|
||||
{
|
||||
unsigned char _map[1 << CHAR_BIT];
|
||||
};
|
||||
|
||||
/*** struct re_jump ***************************************************
|
||||
Jump to a new location in the machine (not next).
|
||||
***********************************************************************/
|
||||
struct re_jump : public re_syntax_base
|
||||
{
|
||||
offset_type alt; // location to jump to
|
||||
};
|
||||
|
||||
/*** struct re_alt ***************************************************
|
||||
Jump to a new location in the machine (possibly next).
|
||||
***********************************************************************/
|
||||
struct re_alt : public re_jump
|
||||
{
|
||||
unsigned char _map[1 << CHAR_BIT]; // which characters can take the jump
|
||||
unsigned int can_be_null; // true if we match a NULL string
|
||||
};
|
||||
|
||||
/*** struct re_repeat *************************************************
|
||||
Repeat a section of the machine
|
||||
***********************************************************************/
|
||||
struct re_repeat : public re_alt
|
||||
{
|
||||
std::size_t min, max; // min and max allowable repeats
|
||||
int state_id; // Unique identifier for this repeat
|
||||
bool leading; // True if this repeat is at the start of the machine (lets us optimize some searches)
|
||||
bool greedy; // True if this is a greedy repeat
|
||||
};
|
||||
|
||||
/*** struct re_recurse ************************************************
|
||||
Recurse to a particular subexpression.
|
||||
**********************************************************************/
|
||||
struct re_recurse : public re_jump
|
||||
{
|
||||
int state_id; // identifier of first nested repeat within the recursion.
|
||||
};
|
||||
|
||||
/*** struct re_commit *************************************************
|
||||
Used for the PRUNE, SKIP and COMMIT verbs which basically differ only in what happens
|
||||
if no match is found and we start searching forward.
|
||||
**********************************************************************/
|
||||
enum commit_type
|
||||
{
|
||||
commit_prune,
|
||||
commit_skip,
|
||||
commit_commit
|
||||
};
|
||||
struct re_commit : public re_syntax_base
|
||||
{
|
||||
commit_type action;
|
||||
};
|
||||
|
||||
/*** enum re_jump_size_type *******************************************
|
||||
Provides compiled size of re_jump structure (allowing for trailing alignment).
|
||||
We provide this so we know how manybytes to insert when constructing the machine
|
||||
(The value of padding_mask is defined in regex_raw_buffer.hpp).
|
||||
***********************************************************************/
|
||||
enum re_jump_size_type
|
||||
{
|
||||
re_jump_size = (sizeof(re_jump) + padding_mask) & ~(padding_mask),
|
||||
re_repeater_size = (sizeof(re_repeat) + padding_mask) & ~(padding_mask),
|
||||
re_alt_size = (sizeof(re_alt) + padding_mask) & ~(padding_mask)
|
||||
};
|
||||
|
||||
/*** proc re_is_set_member *********************************************
|
||||
Forward declaration: we'll need this one later...
|
||||
***********************************************************************/
|
||||
|
||||
template<class charT, class traits>
|
||||
struct regex_data;
|
||||
|
||||
template <class iterator, class charT, class traits_type, class char_classT>
|
||||
iterator re_is_set_member(iterator next,
|
||||
iterator last,
|
||||
const re_set_long<char_classT>* set_,
|
||||
const regex_data<charT, traits_type>& e, bool icase);
|
||||
|
||||
} // namespace BOOST_REGEX_DETAIL_NS
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
382
regex/include/boost/regex/v5/sub_match.hpp
Normal file
382
regex/include/boost/regex/v5/sub_match.hpp
Normal file
@@ -0,0 +1,382 @@
|
||||
/*
|
||||
*
|
||||
* 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 sub_match.cpp
|
||||
* VERSION see <boost/version.hpp>
|
||||
* DESCRIPTION: Declares template class sub_match.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_REGEX_V5_SUB_MATCH_HPP
|
||||
#define BOOST_REGEX_V5_SUB_MATCH_HPP
|
||||
|
||||
namespace boost{
|
||||
|
||||
template <class BidiIterator>
|
||||
struct sub_match : public std::pair<BidiIterator, BidiIterator>
|
||||
{
|
||||
typedef typename std::iterator_traits<BidiIterator>::value_type value_type;
|
||||
typedef typename std::iterator_traits<BidiIterator>::difference_type difference_type;
|
||||
typedef BidiIterator iterator_type;
|
||||
typedef BidiIterator iterator;
|
||||
typedef BidiIterator const_iterator;
|
||||
|
||||
bool matched;
|
||||
|
||||
sub_match() : std::pair<BidiIterator, BidiIterator>(), matched(false) {}
|
||||
sub_match(BidiIterator i) : std::pair<BidiIterator, BidiIterator>(i, i), matched(false) {}
|
||||
template <class T, class A>
|
||||
operator std::basic_string<value_type, T, A> ()const
|
||||
{
|
||||
return matched ? std::basic_string<value_type, T, A>(this->first, this->second) : std::basic_string<value_type, T, A>();
|
||||
}
|
||||
difference_type length()const
|
||||
{
|
||||
difference_type n = matched ? std::distance((BidiIterator)this->first, (BidiIterator)this->second) : 0;
|
||||
return n;
|
||||
}
|
||||
std::basic_string<value_type> str()const
|
||||
{
|
||||
std::basic_string<value_type> result;
|
||||
if(matched)
|
||||
{
|
||||
std::size_t len = std::distance((BidiIterator)this->first, (BidiIterator)this->second);
|
||||
result.reserve(len);
|
||||
BidiIterator i = this->first;
|
||||
while(i != this->second)
|
||||
{
|
||||
result.append(1, *i);
|
||||
++i;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
int compare(const sub_match& s)const
|
||||
{
|
||||
if(matched != s.matched)
|
||||
return static_cast<int>(matched) - static_cast<int>(s.matched);
|
||||
return str().compare(s.str());
|
||||
}
|
||||
int compare(const std::basic_string<value_type>& s)const
|
||||
{
|
||||
return str().compare(s);
|
||||
}
|
||||
int compare(const value_type* p)const
|
||||
{
|
||||
return str().compare(p);
|
||||
}
|
||||
|
||||
bool operator==(const sub_match& that)const
|
||||
{ return compare(that) == 0; }
|
||||
bool operator !=(const sub_match& that)const
|
||||
{ return compare(that) != 0; }
|
||||
bool operator<(const sub_match& that)const
|
||||
{ return compare(that) < 0; }
|
||||
bool operator>(const sub_match& that)const
|
||||
{ return compare(that) > 0; }
|
||||
bool operator<=(const sub_match& that)const
|
||||
{ return compare(that) <= 0; }
|
||||
bool operator>=(const sub_match& that)const
|
||||
{ return compare(that) >= 0; }
|
||||
|
||||
#ifdef BOOST_REGEX_MATCH_EXTRA
|
||||
typedef std::vector<sub_match<BidiIterator> > capture_sequence_type;
|
||||
|
||||
const capture_sequence_type& captures()const
|
||||
{
|
||||
if(!m_captures)
|
||||
m_captures.reset(new capture_sequence_type());
|
||||
return *m_captures;
|
||||
}
|
||||
//
|
||||
// Private implementation API: DO NOT USE!
|
||||
//
|
||||
capture_sequence_type& get_captures()const
|
||||
{
|
||||
if(!m_captures)
|
||||
m_captures.reset(new capture_sequence_type());
|
||||
return *m_captures;
|
||||
}
|
||||
|
||||
private:
|
||||
mutable std::unique_ptr<capture_sequence_type> m_captures;
|
||||
public:
|
||||
|
||||
#endif
|
||||
sub_match(const sub_match& that, bool
|
||||
#ifdef BOOST_REGEX_MATCH_EXTRA
|
||||
deep_copy
|
||||
#endif
|
||||
= true
|
||||
)
|
||||
: std::pair<BidiIterator, BidiIterator>(that),
|
||||
matched(that.matched)
|
||||
{
|
||||
#ifdef BOOST_REGEX_MATCH_EXTRA
|
||||
if(that.m_captures)
|
||||
if(deep_copy)
|
||||
m_captures.reset(new capture_sequence_type(*(that.m_captures)));
|
||||
#endif
|
||||
}
|
||||
sub_match& operator=(const sub_match& that)
|
||||
{
|
||||
this->first = that.first;
|
||||
this->second = that.second;
|
||||
matched = that.matched;
|
||||
#ifdef BOOST_REGEX_MATCH_EXTRA
|
||||
if(that.m_captures)
|
||||
get_captures() = *(that.m_captures);
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
//
|
||||
// Make this type a range, for both Boost.Range, and C++11:
|
||||
//
|
||||
BidiIterator begin()const { return this->first; }
|
||||
BidiIterator end()const { return this->second; }
|
||||
};
|
||||
|
||||
typedef sub_match<const char*> csub_match;
|
||||
typedef sub_match<std::string::const_iterator> ssub_match;
|
||||
#ifndef BOOST_NO_WREGEX
|
||||
typedef sub_match<const wchar_t*> wcsub_match;
|
||||
typedef sub_match<std::wstring::const_iterator> wssub_match;
|
||||
#endif
|
||||
|
||||
// comparison to std::basic_string<> part 1:
|
||||
template <class RandomAccessIterator, class traits, class Allocator>
|
||||
inline bool operator == (const std::basic_string<typename std::iterator_traits<RandomAccessIterator>::value_type, traits, Allocator>& s,
|
||||
const sub_match<RandomAccessIterator>& m)
|
||||
{ return s.compare(m.str()) == 0; }
|
||||
template <class RandomAccessIterator, class traits, class Allocator>
|
||||
inline bool operator != (const std::basic_string<typename std::iterator_traits<RandomAccessIterator>::value_type, traits, Allocator>& s,
|
||||
const sub_match<RandomAccessIterator>& m)
|
||||
{ return s.compare(m.str()) != 0; }
|
||||
template <class RandomAccessIterator, class traits, class Allocator>
|
||||
inline bool operator < (const std::basic_string<typename std::iterator_traits<RandomAccessIterator>::value_type, traits, Allocator>& s,
|
||||
const sub_match<RandomAccessIterator>& m)
|
||||
{ return s.compare(m.str()) < 0; }
|
||||
template <class RandomAccessIterator, class traits, class Allocator>
|
||||
inline bool operator <= (const std::basic_string<typename std::iterator_traits<RandomAccessIterator>::value_type, traits, Allocator>& s,
|
||||
const sub_match<RandomAccessIterator>& m)
|
||||
{ return s.compare(m.str()) <= 0; }
|
||||
template <class RandomAccessIterator, class traits, class Allocator>
|
||||
inline bool operator >= (const std::basic_string<typename std::iterator_traits<RandomAccessIterator>::value_type, traits, Allocator>& s,
|
||||
const sub_match<RandomAccessIterator>& m)
|
||||
{ return s.compare(m.str()) >= 0; }
|
||||
template <class RandomAccessIterator, class traits, class Allocator>
|
||||
inline bool operator > (const std::basic_string<typename std::iterator_traits<RandomAccessIterator>::value_type, traits, Allocator>& s,
|
||||
const sub_match<RandomAccessIterator>& m)
|
||||
{ return s.compare(m.str()) > 0; }
|
||||
// comparison to std::basic_string<> part 2:
|
||||
template <class RandomAccessIterator, class traits, class Allocator>
|
||||
inline bool operator == (const sub_match<RandomAccessIterator>& m,
|
||||
const std::basic_string<typename std::iterator_traits<RandomAccessIterator>::value_type, traits, Allocator>& s)
|
||||
{ return m.str().compare(s) == 0; }
|
||||
template <class RandomAccessIterator, class traits, class Allocator>
|
||||
inline bool operator != (const sub_match<RandomAccessIterator>& m,
|
||||
const std::basic_string<typename std::iterator_traits<RandomAccessIterator>::value_type, traits, Allocator>& s)
|
||||
{ return m.str().compare(s) != 0; }
|
||||
template <class RandomAccessIterator, class traits, class Allocator>
|
||||
inline bool operator < (const sub_match<RandomAccessIterator>& m,
|
||||
const std::basic_string<typename std::iterator_traits<RandomAccessIterator>::value_type, traits, Allocator>& s)
|
||||
{ return m.str().compare(s) < 0; }
|
||||
template <class RandomAccessIterator, class traits, class Allocator>
|
||||
inline bool operator > (const sub_match<RandomAccessIterator>& m,
|
||||
const std::basic_string<typename std::iterator_traits<RandomAccessIterator>::value_type, traits, Allocator>& s)
|
||||
{ return m.str().compare(s) > 0; }
|
||||
template <class RandomAccessIterator, class traits, class Allocator>
|
||||
inline bool operator <= (const sub_match<RandomAccessIterator>& m,
|
||||
const std::basic_string<typename std::iterator_traits<RandomAccessIterator>::value_type, traits, Allocator>& s)
|
||||
{ return m.str().compare(s) <= 0; }
|
||||
template <class RandomAccessIterator, class traits, class Allocator>
|
||||
inline bool operator >= (const sub_match<RandomAccessIterator>& m,
|
||||
const std::basic_string<typename std::iterator_traits<RandomAccessIterator>::value_type, traits, Allocator>& s)
|
||||
{ return m.str().compare(s) >= 0; }
|
||||
// comparison to const charT* part 1:
|
||||
template <class RandomAccessIterator>
|
||||
inline bool operator == (const sub_match<RandomAccessIterator>& m,
|
||||
typename std::iterator_traits<RandomAccessIterator>::value_type const* s)
|
||||
{ return m.str().compare(s) == 0; }
|
||||
template <class RandomAccessIterator>
|
||||
inline bool operator != (const sub_match<RandomAccessIterator>& m,
|
||||
typename std::iterator_traits<RandomAccessIterator>::value_type const* s)
|
||||
{ return m.str().compare(s) != 0; }
|
||||
template <class RandomAccessIterator>
|
||||
inline bool operator > (const sub_match<RandomAccessIterator>& m,
|
||||
typename std::iterator_traits<RandomAccessIterator>::value_type const* s)
|
||||
{ return m.str().compare(s) > 0; }
|
||||
template <class RandomAccessIterator>
|
||||
inline bool operator < (const sub_match<RandomAccessIterator>& m,
|
||||
typename std::iterator_traits<RandomAccessIterator>::value_type const* s)
|
||||
{ return m.str().compare(s) < 0; }
|
||||
template <class RandomAccessIterator>
|
||||
inline bool operator >= (const sub_match<RandomAccessIterator>& m,
|
||||
typename std::iterator_traits<RandomAccessIterator>::value_type const* s)
|
||||
{ return m.str().compare(s) >= 0; }
|
||||
template <class RandomAccessIterator>
|
||||
inline bool operator <= (const sub_match<RandomAccessIterator>& m,
|
||||
typename std::iterator_traits<RandomAccessIterator>::value_type const* s)
|
||||
{ return m.str().compare(s) <= 0; }
|
||||
// comparison to const charT* part 2:
|
||||
template <class RandomAccessIterator>
|
||||
inline bool operator == (typename std::iterator_traits<RandomAccessIterator>::value_type const* s,
|
||||
const sub_match<RandomAccessIterator>& m)
|
||||
{ return m.str().compare(s) == 0; }
|
||||
template <class RandomAccessIterator>
|
||||
inline bool operator != (typename std::iterator_traits<RandomAccessIterator>::value_type const* s,
|
||||
const sub_match<RandomAccessIterator>& m)
|
||||
{ return m.str().compare(s) != 0; }
|
||||
template <class RandomAccessIterator>
|
||||
inline bool operator < (typename std::iterator_traits<RandomAccessIterator>::value_type const* s,
|
||||
const sub_match<RandomAccessIterator>& m)
|
||||
{ return m.str().compare(s) > 0; }
|
||||
template <class RandomAccessIterator>
|
||||
inline bool operator > (typename std::iterator_traits<RandomAccessIterator>::value_type const* s,
|
||||
const sub_match<RandomAccessIterator>& m)
|
||||
{ return m.str().compare(s) < 0; }
|
||||
template <class RandomAccessIterator>
|
||||
inline bool operator <= (typename std::iterator_traits<RandomAccessIterator>::value_type const* s,
|
||||
const sub_match<RandomAccessIterator>& m)
|
||||
{ return m.str().compare(s) >= 0; }
|
||||
template <class RandomAccessIterator>
|
||||
inline bool operator >= (typename std::iterator_traits<RandomAccessIterator>::value_type const* s,
|
||||
const sub_match<RandomAccessIterator>& m)
|
||||
{ return m.str().compare(s) <= 0; }
|
||||
|
||||
// comparison to const charT& part 1:
|
||||
template <class RandomAccessIterator>
|
||||
inline bool operator == (const sub_match<RandomAccessIterator>& m,
|
||||
typename std::iterator_traits<RandomAccessIterator>::value_type const& s)
|
||||
{ return m.str().compare(0, m.length(), &s, 1) == 0; }
|
||||
template <class RandomAccessIterator>
|
||||
inline bool operator != (const sub_match<RandomAccessIterator>& m,
|
||||
typename std::iterator_traits<RandomAccessIterator>::value_type const& s)
|
||||
{ return m.str().compare(0, m.length(), &s, 1) != 0; }
|
||||
template <class RandomAccessIterator>
|
||||
inline bool operator > (const sub_match<RandomAccessIterator>& m,
|
||||
typename std::iterator_traits<RandomAccessIterator>::value_type const& s)
|
||||
{ return m.str().compare(0, m.length(), &s, 1) > 0; }
|
||||
template <class RandomAccessIterator>
|
||||
inline bool operator < (const sub_match<RandomAccessIterator>& m,
|
||||
typename std::iterator_traits<RandomAccessIterator>::value_type const& s)
|
||||
{ return m.str().compare(0, m.length(), &s, 1) < 0; }
|
||||
template <class RandomAccessIterator>
|
||||
inline bool operator >= (const sub_match<RandomAccessIterator>& m,
|
||||
typename std::iterator_traits<RandomAccessIterator>::value_type const& s)
|
||||
{ return m.str().compare(0, m.length(), &s, 1) >= 0; }
|
||||
template <class RandomAccessIterator>
|
||||
inline bool operator <= (const sub_match<RandomAccessIterator>& m,
|
||||
typename std::iterator_traits<RandomAccessIterator>::value_type const& s)
|
||||
{ return m.str().compare(0, m.length(), &s, 1) <= 0; }
|
||||
// comparison to const charT* part 2:
|
||||
template <class RandomAccessIterator>
|
||||
inline bool operator == (typename std::iterator_traits<RandomAccessIterator>::value_type const& s,
|
||||
const sub_match<RandomAccessIterator>& m)
|
||||
{ return m.str().compare(0, m.length(), &s, 1) == 0; }
|
||||
template <class RandomAccessIterator>
|
||||
inline bool operator != (typename std::iterator_traits<RandomAccessIterator>::value_type const& s,
|
||||
const sub_match<RandomAccessIterator>& m)
|
||||
{ return m.str().compare(0, m.length(), &s, 1) != 0; }
|
||||
template <class RandomAccessIterator>
|
||||
inline bool operator < (typename std::iterator_traits<RandomAccessIterator>::value_type const& s,
|
||||
const sub_match<RandomAccessIterator>& m)
|
||||
{ return m.str().compare(0, m.length(), &s, 1) > 0; }
|
||||
template <class RandomAccessIterator>
|
||||
inline bool operator > (typename std::iterator_traits<RandomAccessIterator>::value_type const& s,
|
||||
const sub_match<RandomAccessIterator>& m)
|
||||
{ return m.str().compare(0, m.length(), &s, 1) < 0; }
|
||||
template <class RandomAccessIterator>
|
||||
inline bool operator <= (typename std::iterator_traits<RandomAccessIterator>::value_type const& s,
|
||||
const sub_match<RandomAccessIterator>& m)
|
||||
{ return m.str().compare(0, m.length(), &s, 1) >= 0; }
|
||||
template <class RandomAccessIterator>
|
||||
inline bool operator >= (typename std::iterator_traits<RandomAccessIterator>::value_type const& s,
|
||||
const sub_match<RandomAccessIterator>& m)
|
||||
{ return m.str().compare(0, m.length(), &s, 1) <= 0; }
|
||||
|
||||
// addition operators:
|
||||
template <class RandomAccessIterator, class traits, class Allocator>
|
||||
inline std::basic_string<typename std::iterator_traits<RandomAccessIterator>::value_type, traits, Allocator>
|
||||
operator + (const std::basic_string<typename std::iterator_traits<RandomAccessIterator>::value_type, traits, Allocator>& s,
|
||||
const sub_match<RandomAccessIterator>& m)
|
||||
{
|
||||
std::basic_string<typename std::iterator_traits<RandomAccessIterator>::value_type, traits, Allocator> result;
|
||||
result.reserve(s.size() + m.length() + 1);
|
||||
return result.append(s).append(m.first, m.second);
|
||||
}
|
||||
template <class RandomAccessIterator, class traits, class Allocator>
|
||||
inline std::basic_string<typename std::iterator_traits<RandomAccessIterator>::value_type, traits, Allocator>
|
||||
operator + (const sub_match<RandomAccessIterator>& m,
|
||||
const std::basic_string<typename std::iterator_traits<RandomAccessIterator>::value_type, traits, Allocator>& s)
|
||||
{
|
||||
std::basic_string<typename std::iterator_traits<RandomAccessIterator>::value_type, traits, Allocator> result;
|
||||
result.reserve(s.size() + m.length() + 1);
|
||||
return result.append(m.first, m.second).append(s);
|
||||
}
|
||||
template <class RandomAccessIterator>
|
||||
inline std::basic_string<typename std::iterator_traits<RandomAccessIterator>::value_type>
|
||||
operator + (typename std::iterator_traits<RandomAccessIterator>::value_type const* s,
|
||||
const sub_match<RandomAccessIterator>& m)
|
||||
{
|
||||
std::basic_string<typename std::iterator_traits<RandomAccessIterator>::value_type> result;
|
||||
result.reserve(std::char_traits<typename std::iterator_traits<RandomAccessIterator>::value_type>::length(s) + m.length() + 1);
|
||||
return result.append(s).append(m.first, m.second);
|
||||
}
|
||||
template <class RandomAccessIterator>
|
||||
inline std::basic_string<typename std::iterator_traits<RandomAccessIterator>::value_type>
|
||||
operator + (const sub_match<RandomAccessIterator>& m,
|
||||
typename std::iterator_traits<RandomAccessIterator>::value_type const * s)
|
||||
{
|
||||
std::basic_string<typename std::iterator_traits<RandomAccessIterator>::value_type> result;
|
||||
result.reserve(std::char_traits<typename std::iterator_traits<RandomAccessIterator>::value_type>::length(s) + m.length() + 1);
|
||||
return result.append(m.first, m.second).append(s);
|
||||
}
|
||||
template <class RandomAccessIterator>
|
||||
inline std::basic_string<typename std::iterator_traits<RandomAccessIterator>::value_type>
|
||||
operator + (typename std::iterator_traits<RandomAccessIterator>::value_type const& s,
|
||||
const sub_match<RandomAccessIterator>& m)
|
||||
{
|
||||
std::basic_string<typename std::iterator_traits<RandomAccessIterator>::value_type> result;
|
||||
result.reserve(m.length() + 2);
|
||||
return result.append(1, s).append(m.first, m.second);
|
||||
}
|
||||
template <class RandomAccessIterator>
|
||||
inline std::basic_string<typename std::iterator_traits<RandomAccessIterator>::value_type>
|
||||
operator + (const sub_match<RandomAccessIterator>& m,
|
||||
typename std::iterator_traits<RandomAccessIterator>::value_type const& s)
|
||||
{
|
||||
std::basic_string<typename std::iterator_traits<RandomAccessIterator>::value_type> result;
|
||||
result.reserve(m.length() + 2);
|
||||
return result.append(m.first, m.second).append(1, s);
|
||||
}
|
||||
template <class RandomAccessIterator>
|
||||
inline std::basic_string<typename std::iterator_traits<RandomAccessIterator>::value_type>
|
||||
operator + (const sub_match<RandomAccessIterator>& m1,
|
||||
const sub_match<RandomAccessIterator>& m2)
|
||||
{
|
||||
std::basic_string<typename std::iterator_traits<RandomAccessIterator>::value_type> result;
|
||||
result.reserve(m1.length() + m2.length() + 1);
|
||||
return result.append(m1.first, m1.second).append(m2.first, m2.second);
|
||||
}
|
||||
template <class charT, class traits, class RandomAccessIterator>
|
||||
std::basic_ostream<charT, traits>&
|
||||
operator << (std::basic_ostream<charT, traits>& os,
|
||||
const sub_match<RandomAccessIterator>& s)
|
||||
{
|
||||
return (os << s.str());
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
|
||||
105
regex/include/boost/regex/v5/syntax_type.hpp
Normal file
105
regex/include/boost/regex/v5/syntax_type.hpp
Normal file
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 2003
|
||||
* 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 syntax_type.hpp
|
||||
* VERSION see <boost/version.hpp>
|
||||
* DESCRIPTION: Declares regular expression synatx type enumerator.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_REGEX_SYNTAX_TYPE_HPP
|
||||
#define BOOST_REGEX_SYNTAX_TYPE_HPP
|
||||
|
||||
namespace boost{
|
||||
namespace regex_constants{
|
||||
|
||||
typedef unsigned char syntax_type;
|
||||
|
||||
//
|
||||
// values chosen are binary compatible with previous version:
|
||||
//
|
||||
static const syntax_type syntax_char = 0;
|
||||
static const syntax_type syntax_open_mark = 1;
|
||||
static const syntax_type syntax_close_mark = 2;
|
||||
static const syntax_type syntax_dollar = 3;
|
||||
static const syntax_type syntax_caret = 4;
|
||||
static const syntax_type syntax_dot = 5;
|
||||
static const syntax_type syntax_star = 6;
|
||||
static const syntax_type syntax_plus = 7;
|
||||
static const syntax_type syntax_question = 8;
|
||||
static const syntax_type syntax_open_set = 9;
|
||||
static const syntax_type syntax_close_set = 10;
|
||||
static const syntax_type syntax_or = 11;
|
||||
static const syntax_type syntax_escape = 12;
|
||||
static const syntax_type syntax_dash = 14;
|
||||
static const syntax_type syntax_open_brace = 15;
|
||||
static const syntax_type syntax_close_brace = 16;
|
||||
static const syntax_type syntax_digit = 17;
|
||||
static const syntax_type syntax_comma = 27;
|
||||
static const syntax_type syntax_equal = 37;
|
||||
static const syntax_type syntax_colon = 36;
|
||||
static const syntax_type syntax_not = 53;
|
||||
|
||||
// extensions:
|
||||
|
||||
static const syntax_type syntax_hash = 13;
|
||||
static const syntax_type syntax_newline = 26;
|
||||
|
||||
// escapes:
|
||||
|
||||
typedef syntax_type escape_syntax_type;
|
||||
|
||||
static const escape_syntax_type escape_type_word_assert = 18;
|
||||
static const escape_syntax_type escape_type_not_word_assert = 19;
|
||||
static const escape_syntax_type escape_type_control_f = 29;
|
||||
static const escape_syntax_type escape_type_control_n = 30;
|
||||
static const escape_syntax_type escape_type_control_r = 31;
|
||||
static const escape_syntax_type escape_type_control_t = 32;
|
||||
static const escape_syntax_type escape_type_control_v = 33;
|
||||
static const escape_syntax_type escape_type_ascii_control = 35;
|
||||
static const escape_syntax_type escape_type_hex = 34;
|
||||
static const escape_syntax_type escape_type_unicode = 0; // not used
|
||||
static const escape_syntax_type escape_type_identity = 0; // not used
|
||||
static const escape_syntax_type escape_type_backref = syntax_digit;
|
||||
static const escape_syntax_type escape_type_decimal = syntax_digit; // not used
|
||||
static const escape_syntax_type escape_type_class = 22;
|
||||
static const escape_syntax_type escape_type_not_class = 23;
|
||||
|
||||
// extensions:
|
||||
|
||||
static const escape_syntax_type escape_type_left_word = 20;
|
||||
static const escape_syntax_type escape_type_right_word = 21;
|
||||
static const escape_syntax_type escape_type_start_buffer = 24; // for \`
|
||||
static const escape_syntax_type escape_type_end_buffer = 25; // for \'
|
||||
static const escape_syntax_type escape_type_control_a = 28; // for \a
|
||||
static const escape_syntax_type escape_type_e = 38; // for \e
|
||||
static const escape_syntax_type escape_type_E = 47; // for \Q\E
|
||||
static const escape_syntax_type escape_type_Q = 48; // for \Q\E
|
||||
static const escape_syntax_type escape_type_X = 49; // for \X
|
||||
static const escape_syntax_type escape_type_C = 50; // for \C
|
||||
static const escape_syntax_type escape_type_Z = 51; // for \Z
|
||||
static const escape_syntax_type escape_type_G = 52; // for \G
|
||||
|
||||
static const escape_syntax_type escape_type_property = 54; // for \p
|
||||
static const escape_syntax_type escape_type_not_property = 55; // for \P
|
||||
static const escape_syntax_type escape_type_named_char = 56; // for \N
|
||||
static const escape_syntax_type escape_type_extended_backref = 57; // for \g
|
||||
static const escape_syntax_type escape_type_reset_start_mark = 58; // for \K
|
||||
static const escape_syntax_type escape_type_line_ending = 59; // for \R
|
||||
|
||||
static const escape_syntax_type syntax_max = 60;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
177
regex/include/boost/regex/v5/u32regex_iterator.hpp
Normal file
177
regex/include/boost/regex/v5/u32regex_iterator.hpp
Normal file
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 2003
|
||||
* 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 u32regex_iterator.hpp
|
||||
* VERSION see <boost/version.hpp>
|
||||
* DESCRIPTION: Provides u32regex_iterator implementation.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_REGEX_V5_U32REGEX_ITERATOR_HPP
|
||||
#define BOOST_REGEX_V5_U32REGEX_ITERATOR_HPP
|
||||
|
||||
namespace boost{
|
||||
|
||||
template <class BidirectionalIterator>
|
||||
class u32regex_iterator_implementation
|
||||
{
|
||||
typedef u32regex regex_type;
|
||||
|
||||
match_results<BidirectionalIterator> what; // current match
|
||||
BidirectionalIterator base; // start of sequence
|
||||
BidirectionalIterator end; // end of sequence
|
||||
const regex_type re; // the expression
|
||||
match_flag_type flags; // flags for matching
|
||||
|
||||
public:
|
||||
u32regex_iterator_implementation(const regex_type* p, BidirectionalIterator last, match_flag_type f)
|
||||
: base(), end(last), re(*p), flags(f){}
|
||||
bool init(BidirectionalIterator first)
|
||||
{
|
||||
base = first;
|
||||
return u32regex_search(first, end, what, re, flags, base);
|
||||
}
|
||||
bool compare(const u32regex_iterator_implementation& that)
|
||||
{
|
||||
if(this == &that) return true;
|
||||
return (&re.get_data() == &that.re.get_data()) && (end == that.end) && (flags == that.flags) && (what[0].first == that.what[0].first) && (what[0].second == that.what[0].second);
|
||||
}
|
||||
const match_results<BidirectionalIterator>& get()
|
||||
{ return what; }
|
||||
bool next()
|
||||
{
|
||||
//if(what.prefix().first != what[0].second)
|
||||
// flags |= match_prev_avail;
|
||||
BidirectionalIterator next_start = what[0].second;
|
||||
match_flag_type f(flags);
|
||||
if(!what.length())
|
||||
f |= regex_constants::match_not_initial_null;
|
||||
//if(base != next_start)
|
||||
// f |= regex_constants::match_not_bob;
|
||||
bool result = u32regex_search(next_start, end, what, re, f, base);
|
||||
if(result)
|
||||
what.set_base(base);
|
||||
return result;
|
||||
}
|
||||
private:
|
||||
u32regex_iterator_implementation& operator=(const u32regex_iterator_implementation&);
|
||||
};
|
||||
|
||||
template <class BidirectionalIterator>
|
||||
class u32regex_iterator
|
||||
{
|
||||
private:
|
||||
typedef u32regex_iterator_implementation<BidirectionalIterator> impl;
|
||||
typedef std::shared_ptr<impl> pimpl;
|
||||
public:
|
||||
typedef u32regex regex_type;
|
||||
typedef match_results<BidirectionalIterator> value_type;
|
||||
typedef typename std::iterator_traits<BidirectionalIterator>::difference_type
|
||||
difference_type;
|
||||
typedef const value_type* pointer;
|
||||
typedef const value_type& reference;
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
|
||||
u32regex_iterator(){}
|
||||
u32regex_iterator(BidirectionalIterator a, BidirectionalIterator b,
|
||||
const regex_type& re,
|
||||
match_flag_type m = match_default)
|
||||
: pdata(new impl(&re, b, m))
|
||||
{
|
||||
if(!pdata->init(a))
|
||||
{
|
||||
pdata.reset();
|
||||
}
|
||||
}
|
||||
u32regex_iterator(const u32regex_iterator& that)
|
||||
: pdata(that.pdata) {}
|
||||
u32regex_iterator& operator=(const u32regex_iterator& that)
|
||||
{
|
||||
pdata = that.pdata;
|
||||
return *this;
|
||||
}
|
||||
bool operator==(const u32regex_iterator& that)const
|
||||
{
|
||||
if((pdata.get() == 0) || (that.pdata.get() == 0))
|
||||
return pdata.get() == that.pdata.get();
|
||||
return pdata->compare(*(that.pdata.get()));
|
||||
}
|
||||
bool operator!=(const u32regex_iterator& that)const
|
||||
{ return !(*this == that); }
|
||||
const value_type& operator*()const
|
||||
{ return pdata->get(); }
|
||||
const value_type* operator->()const
|
||||
{ return &(pdata->get()); }
|
||||
u32regex_iterator& operator++()
|
||||
{
|
||||
cow();
|
||||
if(0 == pdata->next())
|
||||
{
|
||||
pdata.reset();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
u32regex_iterator operator++(int)
|
||||
{
|
||||
u32regex_iterator result(*this);
|
||||
++(*this);
|
||||
return result;
|
||||
}
|
||||
private:
|
||||
|
||||
pimpl pdata;
|
||||
|
||||
void cow()
|
||||
{
|
||||
// copy-on-write
|
||||
if(pdata.get() && (pdata.use_count() > 1))
|
||||
{
|
||||
pdata.reset(new impl(*(pdata.get())));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
typedef u32regex_iterator<const char*> utf8regex_iterator;
|
||||
typedef u32regex_iterator<const UChar*> utf16regex_iterator;
|
||||
typedef u32regex_iterator<const UChar32*> utf32regex_iterator;
|
||||
|
||||
inline u32regex_iterator<const char*> make_u32regex_iterator(const char* p, const u32regex& e, regex_constants::match_flag_type m = regex_constants::match_default)
|
||||
{
|
||||
return u32regex_iterator<const char*>(p, p+std::strlen(p), e, m);
|
||||
}
|
||||
#ifndef BOOST_NO_WREGEX
|
||||
inline u32regex_iterator<const wchar_t*> make_u32regex_iterator(const wchar_t* p, const u32regex& e, regex_constants::match_flag_type m = regex_constants::match_default)
|
||||
{
|
||||
return u32regex_iterator<const wchar_t*>(p, p+std::wcslen(p), e, m);
|
||||
}
|
||||
#endif
|
||||
#if !defined(BOOST_REGEX_UCHAR_IS_WCHAR_T)
|
||||
inline u32regex_iterator<const UChar*> make_u32regex_iterator(const UChar* p, const u32regex& e, regex_constants::match_flag_type m = regex_constants::match_default)
|
||||
{
|
||||
return u32regex_iterator<const UChar*>(p, p+u_strlen(p), e, m);
|
||||
}
|
||||
#endif
|
||||
template <class charT, class Traits, class Alloc>
|
||||
inline u32regex_iterator<typename std::basic_string<charT, Traits, Alloc>::const_iterator> make_u32regex_iterator(const std::basic_string<charT, Traits, Alloc>& p, const u32regex& e, regex_constants::match_flag_type m = regex_constants::match_default)
|
||||
{
|
||||
typedef typename std::basic_string<charT, Traits, Alloc>::const_iterator iter_type;
|
||||
return u32regex_iterator<iter_type>(p.begin(), p.end(), e, m);
|
||||
}
|
||||
inline u32regex_iterator<const UChar*> make_u32regex_iterator(const U_NAMESPACE_QUALIFIER UnicodeString& s, const u32regex& e, regex_constants::match_flag_type m = regex_constants::match_default)
|
||||
{
|
||||
return u32regex_iterator<const UChar*>(s.getBuffer(), s.getBuffer() + s.length(), e, m);
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_REGEX_V5_REGEX_ITERATOR_HPP
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user