Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b76bb1002e | ||
|
|
dea940222e | ||
|
|
4a075cc187 | ||
|
|
e17c10c965 | ||
|
|
8c96c02468 | ||
|
|
4260f94ce7 | ||
|
|
21f73e4eae | ||
|
|
743173df81 | ||
|
|
17b6ea23b4 | ||
|
|
840398c073 | ||
|
|
93384e4c37 | ||
|
|
566b11026e | ||
|
|
8fd2986a92 | ||
|
|
e7dd2cf434 | ||
|
|
cdfbf8795a | ||
|
|
d110ddad10 | ||
|
|
36cecf3acc | ||
|
|
066eaec993 | ||
|
|
746ebf9b02 | ||
|
|
1deffe6a98 | ||
|
|
7ac61f1cac | ||
|
|
e386c86316 | ||
|
|
da84eb027f | ||
|
|
1d9f2a2744 | ||
|
|
c1d0f46366 | ||
|
|
99bf00d27c | ||
|
|
7fd43bba2c | ||
|
|
48f14267e5 | ||
|
|
b785a4fbec | ||
|
|
3aa5ddfc32 | ||
|
|
c2277edb56 | ||
|
|
d82ec219f6 | ||
|
|
dc007c84ab | ||
|
|
ccd04b86d3 | ||
|
|
0531a37133 | ||
|
|
566cff8ded | ||
|
|
74c5e92d4b | ||
|
|
aaa374c8ed | ||
|
|
2a6902dbb5 | ||
|
|
02206a8967 | ||
|
|
af2a5a18b3 | ||
|
|
1d0e325813 | ||
|
|
f4e22a5c96 | ||
|
|
fb468f8594 | ||
|
|
4ff0aaad9c | ||
|
|
c0eb5e2087 | ||
|
|
c795635469 | ||
|
|
e844b9949d | ||
|
|
5c807e1859 | ||
|
|
b2edaf69c1 | ||
|
|
dfa6d043b3 | ||
|
|
5e3f01f350 | ||
|
|
f9a098d67b | ||
|
|
3324e27dee | ||
|
|
25f1c62d2c | ||
|
|
afd6ce0a1f | ||
|
|
fb62473b0b | ||
|
|
9b1bc82353 | ||
|
|
d1f0b517e4 | ||
|
|
ec50159a15 | ||
|
|
a7f513fd7c | ||
|
|
698024d47d | ||
|
|
eb8d91470b | ||
|
|
780f22818e | ||
|
|
fdcf9f7099 | ||
|
|
ec0445ec54 | ||
|
|
75f50cd5bb | ||
|
|
4d1af3ce9c | ||
|
|
7b6aa046f4 | ||
|
|
844f6ed86f | ||
|
|
7a8cbe202e | ||
|
|
ec2a4648e1 | ||
|
|
186682b6d4 | ||
|
|
db6811450e | ||
|
|
1c19b51fda | ||
|
|
28cad446b7 | ||
|
|
84867cc474 | ||
|
|
13c644efdc | ||
|
|
5085c35269 | ||
|
|
7682f1285e | ||
|
|
74a0cf012b | ||
|
|
d356e2e79f | ||
|
|
fe027b7fc7 | ||
|
|
501134c2fd | ||
|
|
debe2e63cb | ||
|
|
4452ec50fb | ||
|
|
f034f45b93 | ||
|
|
5160486dcd | ||
|
|
876c586620 | ||
|
|
85ef6faf7d | ||
|
|
6004a76884 | ||
|
|
944829a6be | ||
|
|
9b75a426c5 | ||
|
|
d6d63b7f88 | ||
|
|
d9adde161c | ||
|
|
3d45bbe12a | ||
|
|
90be761780 | ||
|
|
22c5cfdffd | ||
|
|
7834f61662 | ||
|
|
cafb1ef28d | ||
|
|
4211374126 | ||
|
|
cfa50198ee | ||
|
|
f4c1cebfd0 | ||
|
|
7cef499e67 | ||
|
|
e40da83827 | ||
|
|
d916dc4a9d | ||
|
|
791cc93f5f | ||
|
|
1df72dc2e0 | ||
|
|
cf3a9f6ae3 | ||
|
|
946f4b4339 | ||
|
|
e88a0b5ca3 | ||
|
|
6d23e01a82 | ||
|
|
0f8c6039ce | ||
|
|
2abae1c673 | ||
|
|
1e16d7b521 | ||
|
|
55dade8b51 | ||
|
|
2e53d3e4c9 | ||
|
|
4a0ce23184 | ||
|
|
02535eeeb2 | ||
|
|
6d49968a59 | ||
|
|
84ae416c2c | ||
|
|
dd4fd4d187 | ||
|
|
ade001359b | ||
|
|
ac2d3d6b33 | ||
|
|
537ea258ca | ||
|
|
32302c6a80 | ||
|
|
5ba969c561 | ||
|
|
5a4e60f645 | ||
|
|
456feb645a | ||
|
|
556a82e42b | ||
|
|
57f7b6d000 | ||
|
|
67a0b128f7 | ||
|
|
f60f08327c | ||
|
|
72c01bebba | ||
|
|
dede4695e9 | ||
|
|
5efefd3576 | ||
|
|
516eaa2086 | ||
|
|
c3a6f0b624 | ||
|
|
6594cddb65 | ||
|
|
bf2343015e | ||
|
|
228bcf5014 | ||
|
|
589263e902 | ||
|
|
02bdf755a3 | ||
|
|
61fe92e201 | ||
|
|
1b7264793e | ||
|
|
13fc56c24a | ||
|
|
18a6628d0e | ||
|
|
5746ab5ed9 | ||
|
|
ac90991a27 | ||
|
|
531d39d888 | ||
|
|
68576e9a95 | ||
|
|
f7d9956665 | ||
|
|
aa0c2e520f | ||
|
|
9ea48c7298 | ||
|
|
c065e55ca1 | ||
|
|
2c163503d9 | ||
|
|
212b6bfe4f | ||
|
|
ea6998dcad | ||
|
|
d6ec442945 | ||
|
|
6da27f7e86 | ||
|
|
50d605b5b4 | ||
|
|
b147a3db3e | ||
|
|
6018f35598 | ||
|
|
fccf448b3a | ||
|
|
0cd846728c | ||
|
|
876e29973c | ||
|
|
351f5edaa9 | ||
|
|
6edcf19694 | ||
|
|
73463e5c23 | ||
|
|
21267acb8c | ||
|
|
9889f8792f | ||
|
|
ae5a327116 | ||
|
|
8b12bb45c3 | ||
|
|
a32b9fb8a9 | ||
|
|
eb44ed1bc5 | ||
|
|
5fe252934c | ||
|
|
3c4a740759 | ||
|
|
29555ed584 | ||
|
|
f454b9df2d | ||
|
|
6266ce3c6c | ||
|
|
d0cfd73fab | ||
|
|
985700c79d | ||
|
|
e650fa4d8b | ||
|
|
72b2173dfc | ||
|
|
7f688e0fa4 | ||
|
|
c8f79c36b4 | ||
|
|
396ea3daf3 | ||
|
|
c4b2c1d760 | ||
|
|
0bf4ef711e | ||
|
|
affdd497ec | ||
|
|
6b6bd2e369 | ||
|
|
466b4f9a0f | ||
|
|
e90aad5994 | ||
|
|
338c8a8eee | ||
|
|
a390c3daa6 | ||
|
|
9e0dbe67e6 | ||
|
|
6b02bf5df0 | ||
|
|
029f519005 | ||
|
|
b6248459be | ||
|
|
51e3b2a1f7 | ||
|
|
b2504e9477 | ||
|
|
ec6ddd1c5c | ||
|
|
60705fe93b | ||
|
|
cf407da41b | ||
|
|
5435feb932 | ||
|
|
02e4f8e536 | ||
|
|
db090f9164 | ||
|
|
70967beebf | ||
|
|
5b7c2f6dbb | ||
|
|
2d7a3a4dd9 | ||
|
|
01d699fc74 | ||
|
|
6ed82f821f | ||
|
|
c59fa32efe | ||
|
|
dbdb0e4686 | ||
|
|
fc0df14992 | ||
|
|
a5771f1af9 | ||
|
|
4db097b0b0 | ||
|
|
65e4c4f7ac | ||
|
|
d1df4b2fad | ||
|
|
5009fbfbe4 | ||
|
|
cbfcf2bb3c | ||
|
|
63e16d0bac | ||
|
|
cd58c6ce90 | ||
|
|
6787b3c1fe | ||
|
|
980ff6f150 | ||
|
|
ef5f97ad88 | ||
|
|
9ad97c8390 | ||
|
|
8256ea2115 | ||
|
|
b6f97ba0a4 | ||
|
|
88a36c6f57 | ||
|
|
8932460b8c | ||
|
|
7e570cea45 | ||
|
|
1d781d3d54 | ||
|
|
c1070e375f | ||
|
|
582d4ad5cd | ||
|
|
907c9ac423 | ||
|
|
f9c805648a | ||
|
|
94e3e864bc | ||
|
|
53acbd9594 | ||
|
|
085f066958 | ||
|
|
594f177160 | ||
|
|
c53166f630 | ||
|
|
64f4a8077e | ||
|
|
a4bfdcefa8 | ||
|
|
e6b83c7473 | ||
|
|
107292a328 | ||
|
|
9f31c845ee | ||
|
|
3acee26d05 | ||
|
|
1b260fd745 | ||
|
|
02dd6176d7 | ||
|
|
d19c6acadd | ||
|
|
911ec96207 | ||
|
|
1cefc9d9ba | ||
|
|
da1b73feee | ||
|
|
8ce7d781a4 | ||
|
|
3db5941757 | ||
|
|
8b925ae0c4 | ||
|
|
ea7f65725e | ||
|
|
137736d6eb | ||
|
|
d0136e6a71 | ||
|
|
9abb0ff3a9 | ||
|
|
b706b114b3 | ||
|
|
3085c037ba | ||
|
|
c34ddd32a5 | ||
|
|
3c10a1e12a | ||
|
|
a154a813ad | ||
|
|
3b5c7365a1 | ||
|
|
0f78b7e91c | ||
|
|
cf93bf008f | ||
|
|
2bbe7788f1 | ||
|
|
025348bfe3 | ||
|
|
4cf809b579 | ||
|
|
9e1d92a7bc | ||
|
|
ef94137edc | ||
|
|
910f71ec9e | ||
|
|
f4973cdb4b | ||
|
|
4dcc8e23e7 | ||
|
|
044193c7ed | ||
|
|
29b2bb6635 | ||
|
|
d9f0314655 | ||
|
|
af6c230edc | ||
|
|
01746ab16d | ||
|
|
5865134b29 | ||
|
|
39d033c50d | ||
|
|
f64b3bc82d | ||
|
|
3f2353cc57 | ||
|
|
bc20a790da | ||
|
|
a238770418 | ||
|
|
90eb339a05 | ||
|
|
fa16ff964e | ||
|
|
ebb864f234 | ||
|
|
01a33b97a7 | ||
|
|
8b05464444 | ||
|
|
977396e852 | ||
|
|
84b6e84c49 | ||
|
|
33b96b459e | ||
|
|
a095f9f6bd | ||
|
|
828558bfcc | ||
|
|
e49b0cbf8c | ||
|
|
39fc4b2997 | ||
|
|
5d2925fd94 | ||
|
|
f6a2a1cab5 | ||
|
|
661bcfe56e | ||
|
|
821da2ce29 | ||
|
|
38ee3fabd9 | ||
|
|
ac54d29f66 | ||
|
|
b27b04ebf0 | ||
|
|
055438e740 | ||
|
|
5f11e9a7ce | ||
|
|
f128de2b30 | ||
|
|
88e9e8c2f7 | ||
|
|
235fba8a04 | ||
|
|
0183626c73 | ||
|
|
bcc36f260d | ||
|
|
ad796dad9e | ||
|
|
0ca482bc5d | ||
|
|
c72b746d0a | ||
|
|
b4b6980a0c | ||
|
|
534dcd129e | ||
|
|
3e4cefb04f | ||
|
|
dd392845a6 | ||
|
|
7f2fb32735 | ||
|
|
f3247ec13b | ||
|
|
ad014517b9 | ||
|
|
e3de5aa3fe | ||
|
|
6adac797d3 | ||
|
|
99c9d393c2 | ||
|
|
17f54a8848 | ||
|
|
f9c5ad470c | ||
|
|
da539e57a4 | ||
|
|
37d86b2914 | ||
|
|
acc84385b5 | ||
|
|
701ce81aab | ||
|
|
71bcfe80e3 | ||
|
|
b53bbe5a97 | ||
|
|
ccc9cd1a32 | ||
|
|
b78f8573b5 | ||
|
|
3b7576d95c | ||
|
|
cdb9a4c603 | ||
|
|
9a2606d96f | ||
|
|
b1ebc88a3c | ||
|
|
a33d4109d1 | ||
|
|
15ab09063b | ||
|
|
3f0b7c1681 | ||
|
|
b1150d8e86 | ||
|
|
b84f3d9218 | ||
|
|
9db25f3907 | ||
|
|
812bd2191e | ||
|
|
788a4760b8 | ||
|
|
d74da816a1 | ||
|
|
cfc11bef6e | ||
|
|
bedd8f362b | ||
|
|
7855ce9dfb | ||
|
|
81d6656f13 | ||
|
|
6fad220e7e | ||
|
|
2a0f32b2c7 | ||
|
|
212bdb80f8 | ||
|
|
6039667556 | ||
|
|
4960be8cd1 | ||
|
|
89b1a5a6bd | ||
|
|
173f379111 | ||
|
|
14288cbd1a | ||
|
|
4b72bd3824 | ||
|
|
902e06b893 | ||
|
|
ca9e83ce9b | ||
|
|
58919f3dae | ||
|
|
b042e8ad19 | ||
|
|
b188fab4df | ||
|
|
5f9801328f | ||
|
|
d7978e759d | ||
|
|
2d83424510 | ||
|
|
78391d236b | ||
|
|
7934433100 | ||
|
|
692fb1c7ca | ||
|
|
a6fa512e46 | ||
|
|
4809173feb | ||
|
|
2e49c6b7ed | ||
|
|
72064d2324 | ||
|
|
ce309529c5 | ||
|
|
cb1abab75f | ||
|
|
9c97f463c9 | ||
|
|
c6d910ec21 | ||
|
|
9574a6df20 | ||
|
|
39c57564a6 | ||
|
|
c0686dd234 | ||
|
|
134633e7ac | ||
|
|
c1a1aca7ec | ||
|
|
57f9605f70 | ||
|
|
4a658d8f43 | ||
|
|
e4e438b579 | ||
|
|
3080aa7f87 | ||
|
|
3e19e3e5cb | ||
|
|
09e9e7d380 | ||
|
|
cbd45a27fb | ||
|
|
b0b9c4169e | ||
|
|
8d6b75057e | ||
|
|
1ddcbc224e | ||
|
|
8dd21e2b82 | ||
|
|
2de5360ac8 | ||
|
|
28bc0fc826 | ||
|
|
98b96cdeb2 | ||
|
|
98798a3e57 | ||
|
|
4d04cd5089 | ||
|
|
0b8c94bf6f | ||
|
|
2f900bf3a2 | ||
|
|
71a34549ab | ||
|
|
a1c7855a63 | ||
|
|
d101a92750 | ||
|
|
fce77dc7d7 | ||
|
|
14a7e26e09 | ||
|
|
700ada0b5b | ||
|
|
740b544615 | ||
|
|
ad64427126 | ||
|
|
4463726d51 | ||
|
|
95cb1abab8 | ||
|
|
10af1ab1f2 | ||
|
|
824827ff26 | ||
|
|
60d9bf1922 | ||
|
|
cb42040a8d | ||
|
|
d9d681db5e | ||
|
|
1d5e8822e6 | ||
|
|
53a3f73156 | ||
|
|
28dacf4d74 | ||
|
|
2859666708 | ||
|
|
f861918789 | ||
|
|
8e2cf08be1 | ||
|
|
4f6f0ce9f6 | ||
|
|
3032bbc4e7 | ||
|
|
6f1dd37818 | ||
|
|
f8369fe436 | ||
|
|
ff3b07a086 | ||
|
|
e329946213 | ||
|
|
5572421eca | ||
|
|
ef0803cb4d | ||
|
|
60ba6078c2 | ||
|
|
8d66596995 | ||
|
|
07b6a27dc0 | ||
|
|
6e93516a4b | ||
|
|
5ce4a3aeb8 | ||
|
|
2e3d8e72b6 | ||
|
|
0be08399a0 | ||
|
|
0cd5202e74 | ||
|
|
1479256575 | ||
|
|
306fbd503b | ||
|
|
a5aff22d34 | ||
|
|
3a8d75fbf0 | ||
|
|
1d0762e756 | ||
|
|
d017f425d0 | ||
|
|
56dec521c5 | ||
|
|
fdce91471e | ||
|
|
2986bb4893 | ||
|
|
8f82cd5c8a | ||
|
|
11bbbe1155 | ||
|
|
80cc4c9515 | ||
|
|
c6f506781b | ||
|
|
be22e3b999 | ||
|
|
8cc7fb1e17 | ||
|
|
28c86de4c9 | ||
|
|
dac585c01b | ||
|
|
357207c6a8 | ||
|
|
4e1db889c0 | ||
|
|
8d4f4d26f7 | ||
|
|
6e4766149f | ||
|
|
d4bc3f01bf | ||
|
|
d5785606a0 | ||
|
|
d760a3d0f2 | ||
|
|
b013cbd65c | ||
|
|
698500fd3e | ||
|
|
f0dfeaf8c0 | ||
|
|
fed79c7de0 | ||
|
|
8eaef139e9 | ||
|
|
c6ebf9feb1 | ||
|
|
9ec1e52b5a | ||
|
|
d0db433bc8 | ||
|
|
b7be12c7aa | ||
|
|
7b1217100b | ||
|
|
b24e0ef6f2 | ||
|
|
dc6bd27d22 | ||
|
|
0f6ff2a4cb | ||
|
|
7075a4f4d5 | ||
|
|
f4ed97d5ea | ||
|
|
6d3a097f20 | ||
|
|
5265ebb939 | ||
|
|
9e783a5afc | ||
|
|
0feb3b4aaa | ||
|
|
6c624de79c | ||
|
|
b48bd99f70 | ||
|
|
cbd0d94d90 | ||
|
|
ee3adb70d4 | ||
|
|
d8af6a9af1 | ||
|
|
e20b4326a8 | ||
|
|
77e0278f93 | ||
|
|
32623afb9b | ||
|
|
e83abacffd | ||
|
|
52eb101aeb | ||
|
|
59b3a8a8e4 | ||
|
|
f87003b192 | ||
|
|
89fb954223 | ||
|
|
ecea03b271 | ||
|
|
f127fb9afd | ||
|
|
c77d23be7a | ||
|
|
72343e1067 | ||
|
|
0902345808 | ||
|
|
2ae1a561d7 | ||
|
|
d4c06f61d6 | ||
|
|
02cfa33907 | ||
|
|
6e8628b1df | ||
|
|
2b19afe66d | ||
|
|
7236841d64 | ||
|
|
49fb65ce71 | ||
|
|
ad87baee70 | ||
|
|
5e8fef98ec | ||
|
|
83baafa615 | ||
|
|
9f39db9517 | ||
|
|
19f2bcf286 | ||
|
|
02e8876acc | ||
|
|
4f78e3dd90 | ||
|
|
6888d0862d | ||
|
|
a95be84eac | ||
|
|
b76b5f2227 | ||
|
|
7a12c0880f | ||
|
|
58b0b1fab2 | ||
|
|
16b5c322d5 | ||
|
|
16d5b82ac8 | ||
|
|
be66a8749c | ||
|
|
5192a9d447 | ||
|
|
b9160ec173 | ||
|
|
675fad3fc1 | ||
|
|
f7c01d6c7b | ||
|
|
5bc6318dcd | ||
|
|
3d8b0c94df | ||
|
|
73fec7fa3f | ||
|
|
22971e8567 | ||
|
|
3df4cdae56 | ||
|
|
062096a0b4 | ||
|
|
978e7d41b7 | ||
|
|
33028f81d9 | ||
|
|
4cb12c5e0c | ||
|
|
b01acfeef3 | ||
|
|
b7676aaba8 | ||
|
|
e0a13c6867 | ||
|
|
9f5db6d034 | ||
|
|
5c3bfe8db0 | ||
|
|
5926e43bc5 | ||
|
|
f21f076386 | ||
|
|
da403b28c9 | ||
|
|
faba9270a0 | ||
|
|
9ca87eb296 | ||
|
|
b2b97f2c9a | ||
|
|
8494880943 | ||
|
|
0f8f38f0e1 | ||
|
|
8544163c46 | ||
|
|
fdcd190592 | ||
|
|
40e08796d1 | ||
|
|
1e72729056 | ||
|
|
731122e891 | ||
|
|
ebb3ab6017 | ||
|
|
3d2fe7fd50 | ||
|
|
9a70345f4a | ||
|
|
897a4efa96 | ||
|
|
6ab53c5436 | ||
|
|
6b5110e0b9 | ||
|
|
687c0bfe08 | ||
|
|
48b069fef4 | ||
|
|
ab48307235 | ||
|
|
93c43d8612 | ||
|
|
bf9889cb0c | ||
|
|
6e7d67aa61 | ||
|
|
16f60c678b | ||
|
|
1b8f7bd886 | ||
|
|
31278654a0 | ||
|
|
80e87d7868 | ||
|
|
e21ccb9671 | ||
|
|
e6cdcc9ee2 | ||
|
|
4a579b5141 | ||
|
|
dc166364de | ||
|
|
4564fd2948 | ||
|
|
c591823c3e | ||
|
|
7a1904c1ef | ||
|
|
5c5466d6b2 | ||
|
|
6aaf467950 | ||
|
|
428abcb3e7 | ||
|
|
9dea31e3d7 | ||
|
|
154b609576 | ||
|
|
7bfb502aa0 | ||
|
|
ded7d3bc86 | ||
|
|
526c1f6a69 | ||
|
|
6fd501d553 | ||
|
|
11aa08354e | ||
|
|
0bfbebeb8b | ||
|
|
413ba1c1a9 | ||
|
|
fdec3e8151 | ||
|
|
0012f831a8 | ||
|
|
c8962a4e67 | ||
|
|
74d09cf879 | ||
|
|
afdb516386 | ||
|
|
9a1f28fe9a | ||
|
|
b4583a7cc6 | ||
|
|
9918b13214 | ||
|
|
3f9d830294 | ||
|
|
7b2627b236 | ||
|
|
c40d87b3ae | ||
|
|
99f707b6c6 | ||
|
|
a561d5fef6 | ||
|
|
1d305e7626 | ||
|
|
194fb51f75 | ||
|
|
e2dc39bff2 | ||
|
|
836aa73430 | ||
|
|
63f5b885a3 | ||
|
|
c68d017475 | ||
|
|
bbe3bac923 | ||
|
|
2293e357f4 | ||
|
|
85dbceb14d | ||
|
|
45cba39be7 | ||
|
|
a0b235dd8a | ||
|
|
7e3db9ec30 | ||
|
|
6cc8770599 | ||
|
|
462d465f3a | ||
|
|
6ac62cd0de | ||
|
|
1174b62b8f | ||
|
|
ef713900a0 | ||
|
|
c60f6815fa | ||
|
|
7ca709fcbb | ||
|
|
c3ce878376 | ||
|
|
a06ac42eff | ||
|
|
444eb6c211 | ||
|
|
eb6cbe1ee0 | ||
|
|
bcae9a2c37 | ||
|
|
d411b34dae | ||
|
|
a0fad4375a | ||
|
|
ffb02984fe | ||
|
|
b400df2565 | ||
|
|
b06607cc37 | ||
|
|
8881f42470 | ||
|
|
6558d31680 | ||
|
|
6e949677ec | ||
|
|
72f2d166b6 | ||
|
|
7b13cdf7b3 | ||
|
|
c7bdaad30a | ||
|
|
fd9fce25fc | ||
|
|
5ba7add5b5 | ||
|
|
68889d3804 | ||
|
|
8ab18d433a | ||
|
|
13d83949c4 | ||
|
|
daf98009d4 | ||
|
|
0cf5848772 | ||
|
|
0ecc4bd8d3 | ||
|
|
388a195794 | ||
|
|
0f89010225 | ||
|
|
42da49c5c1 | ||
|
|
0ffba26b1f | ||
|
|
b19b094aaa | ||
|
|
5cc1e898b9 | ||
|
|
a4aa68a085 | ||
|
|
c954101bd9 | ||
|
|
d20aeb4121 | ||
|
|
9440de5ca9 | ||
|
|
c2955b508c | ||
|
|
fbf70814f0 | ||
|
|
a823790926 | ||
|
|
14838b82ae | ||
|
|
e11347c005 | ||
|
|
98842f238e | ||
|
|
5ffc87ad9b | ||
|
|
fb5d139443 | ||
|
|
9d6ee05660 | ||
|
|
1ee97606aa | ||
|
|
b6f721c167 | ||
|
|
ede4933819 | ||
|
|
70ce4a6d06 | ||
|
|
213c26db3f | ||
|
|
8ae3c42100 | ||
|
|
ff466a1d2d | ||
|
|
5e46ed7cb6 | ||
|
|
c197ba76fa | ||
|
|
fa2b10f3ce | ||
|
|
7b523aa075 | ||
|
|
0ca9971460 | ||
|
|
b3f23abec0 | ||
|
|
a2d735fee5 | ||
|
|
fb801d8ebb | ||
|
|
9a92bfec45 | ||
|
|
6d50abb3cf | ||
|
|
778872363a | ||
|
|
6c404d57c9 | ||
|
|
449b645278 | ||
|
|
02428a26c0 | ||
|
|
90bbc19923 | ||
|
|
4f5690c89b | ||
|
|
4000fa1a2e | ||
|
|
ba7ffafa7f | ||
|
|
33b59d5723 | ||
|
|
28551a9666 | ||
|
|
c5478d6a0e |
@@ -0,0 +1,109 @@
|
||||
---
|
||||
|
||||
# Exceptions:
|
||||
# bugprone-branch-clone is too noisy in parsing code.
|
||||
# bugprone-easily-swappable-parameters is too noisy.
|
||||
# cert-dcl50-cpp is triggered by hz::string_sprintf()'s C style.
|
||||
# clang-analyzer-deadcode.DeadStores is too noisy.
|
||||
# clang-analyzer-cplusplus.NewDeleteLeaks doesn't understand Gtkmm memory management.
|
||||
# cppcoreguidelines-avoid-magic-numbers, readability-magic-numbers is triggered by attribute database.
|
||||
# cppcoreguidelines-avoid-do-while is triggered in DBG macros.
|
||||
# cppcoreguidelines-owning-memory doesn't support deleting Gtkmm objects.
|
||||
# cppcoreguidelines-pro-type-cstyle-cast needed by GTK C casts.
|
||||
# cppcoreguidelines-pro-type-reinterpret-cast is needed by WinAPI-facing functions
|
||||
# cppcoreguidelines-pro-type-vararg is triggered by hz::string_sprintf().
|
||||
# cppcoreguidelines-pro-bounds-array-to-pointer-decay is triggered by va_start in hz::string_sprintf().
|
||||
# cppcoreguidelines-pro-bounds-pointer-arithmetic is useless (triggered by argv) until we have std::span.
|
||||
# misc-include-cleaner does not really work.
|
||||
# misc-no-recursion is too noisy.
|
||||
# modernize-raw-string-literal is very noisy.
|
||||
# modernize-use-trailing-return-type is contrary to our style.
|
||||
# performance-enum-size is too noisy.
|
||||
# readability-avoid-unconditional-preprocessor-if is triggered on platform-specific code
|
||||
# readability-convert-member-functions-to-static is triggered for many callbacks.
|
||||
# readability-function-cognitive-complexity needed by UI constructors.
|
||||
# readability-isolate-declaration is noisy.
|
||||
# readability-identifier-length is too noisy.
|
||||
|
||||
|
||||
Checks: >
|
||||
-abseil-*,
|
||||
-altera-*,
|
||||
-android-*,
|
||||
-boost-*,
|
||||
bugprone-*,
|
||||
-bugprone-branch-clone,
|
||||
-bugprone-easily-swappable-parameters,
|
||||
cert-*,
|
||||
-cert-dcl50-cpp,
|
||||
clang-analyzer-*,
|
||||
-clang-analyzer-deadcode.DeadStores,
|
||||
-clang-analyzer-cplusplus.NewDeleteLeaks,
|
||||
concurrency-*,
|
||||
cppcoreguidelines-*,
|
||||
-cppcoreguidelines-avoid-magic-numbers,
|
||||
-cppcoreguidelines-avoid-do-while,
|
||||
-cppcoreguidelines-owning-memory,
|
||||
-cppcoreguidelines-pro-bounds-array-to-pointer-decay,
|
||||
-cppcoreguidelines-pro-type-cstyle-cast,
|
||||
-cppcoreguidelines-pro-type-reinterpret-cast,
|
||||
-cppcoreguidelines-pro-type-vararg,
|
||||
-cppcoreguidelines-pro-bounds-pointer-arithmetic,
|
||||
-darwin-*,
|
||||
-fuchsia-*,
|
||||
google-*
|
||||
hicpp-*,
|
||||
-linuxkernel-*,
|
||||
-llvm-*,
|
||||
-llvmlibc-*,
|
||||
misc-*,
|
||||
-misc-include-cleaner,
|
||||
-misc-no-recursion,
|
||||
modernize-*,
|
||||
-modernize-use-trailing-return-type,
|
||||
-modernize-raw-string-literal,
|
||||
-mpi-*,
|
||||
-objc-*,
|
||||
openmp-*,
|
||||
performance-*,
|
||||
-performance-enum-size,
|
||||
portability-*,
|
||||
readability-*,
|
||||
-readability-avoid-unconditional-preprocessor-if,
|
||||
-readability-convert-member-functions-to-static,
|
||||
-readability-function-cognitive-complexity,
|
||||
-readability-isolate-declaration,
|
||||
-readability-magic-numbers,
|
||||
-readability-identifier-length,
|
||||
-zircon-*
|
||||
|
||||
WarningsAsErrors: ''
|
||||
HeaderFilterRegex: ''
|
||||
FormatStyle: none
|
||||
|
||||
CheckOptions:
|
||||
- key: bugprone-exception-escape.CheckCapsOnly
|
||||
value: '1'
|
||||
- key: cppcoreguidelines-macro-usage.CheckCapsOnly
|
||||
value: '1'
|
||||
- key: cppcoreguidelines-owning-memory.LegacyResourceConsumers
|
||||
value: '::free;::realloc;::freopen;::fclose;Gtk::manage'
|
||||
- key: misc-assert-side-effect.AssertMacros
|
||||
value: assert,DBG_ASSERT
|
||||
- key: misc-assert-side-effect.CheckFunctionCalls
|
||||
value: '0'
|
||||
- key: misc-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic
|
||||
value: '1'
|
||||
- key: misc-include-cleaner.IgnoreHeaders
|
||||
value: 'libdebug/*;local_glibmm.h;glib/*;gtk/*;gtkmm/*;glibmm/*'
|
||||
- key: performance-unnecessary-value-param.AllowedTypes
|
||||
value: 'RefPtr;Ptr$'
|
||||
- key: readability-braces-around-statements.ShortStatementLines
|
||||
value: '2'
|
||||
- key: readability-implicit-bool-conversion.AllowPointerConditions
|
||||
value: '1'
|
||||
- key: readability-implicit-bool-cast.AllowConditionalPointerCasts
|
||||
value: '1'
|
||||
|
||||
...
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
|
||||
# Make sure github recognizes header files as C++, not C.
|
||||
*.h linguist-language=C++
|
||||
@@ -0,0 +1,28 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: bug, enhancement
|
||||
assignees: ashaduri
|
||||
|
||||
---
|
||||
|
||||
**Version and Environment**
|
||||
- GSmartControl version: [Are you using the latest released version or git?]
|
||||
- OS: [e.g. openSUSE Linux 15.5]
|
||||
|
||||
**Describe the Bug**
|
||||
[A clear and concise description of what the bug is].
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
**Screenshots**
|
||||
[If applicable, add screenshots to help explain your problem].
|
||||
|
||||
**Additional Context**
|
||||
[Add any other context about the problem here (GTK+ version, etc.)]
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: enhancement
|
||||
assignees: ashaduri
|
||||
|
||||
---
|
||||
|
||||
**Version and Environment**
|
||||
- GSmartControl version: [Are you using the latest released version or git?]
|
||||
- OS: [e.g. openSUSE Linux 15.5]
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
||||
@@ -0,0 +1,15 @@
|
||||
---
|
||||
name: Other issue
|
||||
about: Issues other than bugs and enhancements
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ashaduri
|
||||
|
||||
---
|
||||
|
||||
**Version and Environment**
|
||||
- GSmartControl version: [Are you using the latest released version or git?]
|
||||
- OS: [e.g. openSUSE Linux 15.5]
|
||||
|
||||
**Describe the Issue**
|
||||
[A clear and concise description of what the issue is].
|
||||
@@ -0,0 +1,186 @@
|
||||
name: Build (Tier 1 platforms)
|
||||
|
||||
on:
|
||||
# Triggers the workflow on push or pull request events but only for the main branch
|
||||
push:
|
||||
branches: [ main ]
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
# Allows you to run this workflow manually from the Actions tab
|
||||
workflow_dispatch:
|
||||
|
||||
|
||||
env:
|
||||
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
|
||||
BUILD_TYPE: RelWithDebInfo
|
||||
SMARTMONTOOLS_INSTALLER: smartmontools-7.4-1.win32-setup.exe
|
||||
SMARTMONTOOLS_URL: https://downloads.sourceforge.net/project/smartmontools/smartmontools/7.4/smartmontools-7.4-1.win32-setup.exe
|
||||
|
||||
|
||||
jobs:
|
||||
|
||||
linux-ubuntu:
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Update Package Database
|
||||
run: sudo apt-get update
|
||||
|
||||
- name: Install Dependencies
|
||||
run: sudo apt-get install libgtkmm-3.0-dev gettext
|
||||
|
||||
- name: Create Build Directory
|
||||
run: cmake -E make_directory build
|
||||
|
||||
- name: Configure CMake
|
||||
shell: bash
|
||||
working-directory: ${{github.workspace}}/build
|
||||
env:
|
||||
CC: gcc-13
|
||||
CXX: g++-13
|
||||
run: >
|
||||
cmake $GITHUB_WORKSPACE
|
||||
-DCMAKE_BUILD_TYPE=$BUILD_TYPE
|
||||
-DCMAKE_TOOLCHAIN_FILE="$GITHUB_WORKSPACE/toolchains/linux-dev.cmake"
|
||||
|
||||
- name: Build
|
||||
shell: bash
|
||||
working-directory: ${{github.workspace}}/build
|
||||
run: cmake --build . --config $BUILD_TYPE
|
||||
|
||||
- name: Test
|
||||
working-directory: ${{github.workspace}}/build
|
||||
shell: bash
|
||||
run: ctest -C $BUILD_TYPE --rerun-failed --output-on-failure
|
||||
|
||||
- name: Pack (cmake install and make binary package)
|
||||
shell: bash
|
||||
working-directory: ${{github.workspace}}/build
|
||||
run: cpack -G TBZ2
|
||||
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Linux Packages
|
||||
path: ${{github.workspace}}/build/gsmartcontrol-*-Linux*.*
|
||||
|
||||
|
||||
windows-msys2:
|
||||
runs-on: windows-latest
|
||||
strategy:
|
||||
matrix:
|
||||
include: [
|
||||
{ msystem: MINGW64, arch: x86_64, platform: win64 },
|
||||
{ msystem: MINGW32, arch: i686, platform: win32 }
|
||||
]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: msys2/setup-msys2@v2
|
||||
# p7zip is needed to extract smartmontools
|
||||
# fontconfig owns /etc/fonts
|
||||
with:
|
||||
msystem: ${{ matrix.msystem }}
|
||||
update: true
|
||||
install: >-
|
||||
mingw-w64-${{ matrix.arch }}-gtkmm3
|
||||
mingw-w64-${{ matrix.arch }}-pkg-config
|
||||
mingw-w64-${{ matrix.arch }}-cmake
|
||||
mingw-w64-${{ matrix.arch }}-gcc
|
||||
mingw-w64-${{ matrix.arch }}-fontconfig
|
||||
make
|
||||
p7zip
|
||||
|
||||
- name: Download Package Requirements
|
||||
shell: msys2 {0}
|
||||
working-directory: ${{github.workspace}}
|
||||
run: |
|
||||
mkdir -p build/smartmontools
|
||||
cd build/smartmontools
|
||||
wget $SMARTMONTOOLS_URL
|
||||
|
||||
- name: Extract Package Requirements (64-bit)
|
||||
if: ${{ matrix.msystem == 'MINGW64' }}
|
||||
shell: msys2 {0}
|
||||
working-directory: ${{github.workspace}}/build/smartmontools
|
||||
run: >
|
||||
7z -bb1 e $SMARTMONTOOLS_INSTALLER
|
||||
bin/smartctl.exe
|
||||
bin/smartctl-nc.exe
|
||||
bin/update-smart-drivedb.ps1
|
||||
bin/drivedb.h
|
||||
|
||||
- name: Extract Package Requirements (32-bit)
|
||||
if: ${{ matrix.msystem == 'MINGW32' }}
|
||||
shell: msys2 {0}
|
||||
working-directory: ${{github.workspace}}/build/smartmontools
|
||||
run: >
|
||||
7z -bb1 e $SMARTMONTOOLS_INSTALLER
|
||||
bin32/smartctl.exe
|
||||
bin32/smartctl-nc.exe
|
||||
bin/update-smart-drivedb.ps1
|
||||
bin/drivedb.h
|
||||
|
||||
- name: List installed files
|
||||
shell: msys2 {0}
|
||||
run: |
|
||||
ls -1R /mingw64
|
||||
ls -1R /mingw32
|
||||
|
||||
- name: List Files in Workspace
|
||||
shell: msys2 {0}
|
||||
working-directory: ${{github.workspace}}
|
||||
run: ls -1R .
|
||||
|
||||
- name: Configure CMake
|
||||
shell: msys2 {0}
|
||||
run: >
|
||||
cmake -B build -S "$GITHUB_WORKSPACE"
|
||||
-G "MSYS Makefiles"
|
||||
-DCMAKE_BUILD_TYPE=$BUILD_TYPE
|
||||
-DCMAKE_TOOLCHAIN_FILE="$GITHUB_WORKSPACE/toolchains/${{ matrix.platform }}-mingw-msys2.cmake"
|
||||
|
||||
- name: Build
|
||||
shell: msys2 {0}
|
||||
working-directory: ${{github.workspace}}/build
|
||||
run: cmake --build . --config $BUILD_TYPE
|
||||
|
||||
- name: Test
|
||||
working-directory: ${{github.workspace}}/build
|
||||
shell: msys2 {0}
|
||||
run: ctest -C $BUILD_TYPE --rerun-failed --output-on-failure
|
||||
|
||||
- name: Package ZIP
|
||||
shell: msys2 {0}
|
||||
working-directory: ${{github.workspace}}/build
|
||||
run: cpack -G ZIP
|
||||
|
||||
- name: Package NSIS (64-bit)
|
||||
if: ${{ matrix.msystem == 'MINGW64' }}
|
||||
shell: msys2 {0}
|
||||
working-directory: ${{github.workspace}}/build
|
||||
run: cpack -G NSIS64
|
||||
|
||||
- name: Package NSIS (32-bit)
|
||||
if: ${{ matrix.msystem == 'MINGW32' }}
|
||||
shell: msys2 {0}
|
||||
working-directory: ${{github.workspace}}/build
|
||||
run: cpack -G NSIS
|
||||
|
||||
- name: Upload artifacts
|
||||
if: ${{ matrix.msystem == 'MINGW64' }}
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Windows 32-Bit Packages
|
||||
path: ${{github.workspace}}/build/gsmartcontrol-*-win*.*
|
||||
|
||||
- name: Upload artifacts
|
||||
if: ${{ matrix.msystem == 'MINGW32' }}
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Windows 64-Bit Packages
|
||||
path: ${{github.workspace}}/build/gsmartcontrol-*-win*.*
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
name: Build (Tier 2 platforms with flaky builds)
|
||||
|
||||
# FreeBSD build via vmactions/freebsd-vm is known to fail randomly,
|
||||
# so we don't want it to be triggered on every commit.
|
||||
|
||||
# Manually triggered
|
||||
on: [workflow_dispatch]
|
||||
|
||||
env:
|
||||
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
|
||||
BUILD_TYPE: RelWithDebInfo
|
||||
CXX: clang++-17
|
||||
|
||||
jobs:
|
||||
|
||||
freebsd:
|
||||
runs-on: ubuntu-latest
|
||||
# env:
|
||||
# variables to pass to VM
|
||||
# MYTOKEN : ${{ secrets.MYTOKEN }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Build and test in FreeBSD
|
||||
id: test
|
||||
uses: vmactions/freebsd-vm@v1
|
||||
with:
|
||||
envs: 'BUILD_TYPE CXX'
|
||||
usesh: true
|
||||
sync: rsync
|
||||
# release: "14.0"
|
||||
prepare: >
|
||||
pkg install -y cmake pkgconf gtkmm30 gettext libiconv llvm17
|
||||
|
||||
run: >
|
||||
mkdir build && cd build
|
||||
|
||||
cmake ..
|
||||
-DCMAKE_BUILD_TYPE=$BUILD_TYPE
|
||||
-DAPP_BUILD_EXAMPLES=ON
|
||||
-DAPP_BUILD_TESTS=ON
|
||||
-DAPP_COMPILER_ENABLE_WARNINGS=ON
|
||||
|
||||
cmake --build . --config $BUILD_TYPE
|
||||
|
||||
ctest -C $BUILD_TYPE --rerun-failed --output-on-failure
|
||||
@@ -0,0 +1,75 @@
|
||||
name: Build (Tier 2 platforms)
|
||||
|
||||
on:
|
||||
# Triggers the workflow on push or pull request events but only for the main branch
|
||||
push:
|
||||
branches: [ main ]
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
# Allows you to run this workflow manually from the Actions tab
|
||||
workflow_dispatch:
|
||||
|
||||
|
||||
env:
|
||||
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
|
||||
BUILD_TYPE: RelWithDebInfo
|
||||
|
||||
|
||||
jobs:
|
||||
|
||||
macos-homebrew:
|
||||
runs-on: macos-latest
|
||||
strategy:
|
||||
matrix:
|
||||
include: [
|
||||
# We need AppleClang 16, but GitHub only has 14 for now.
|
||||
# { compiler: apple-clang },
|
||||
{ compiler: clang }
|
||||
]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install Dependencies
|
||||
run: brew install pkg-config gtkmm3 cmake
|
||||
|
||||
- name: Install Clang Compiler
|
||||
if: ${{ matrix.compiler == 'clang' }}
|
||||
run: brew install llvm@17
|
||||
|
||||
- name: Create Build Directory
|
||||
run: cmake -E make_directory build
|
||||
|
||||
- name: Configure CMake (Apple Clang)
|
||||
if: ${{ matrix.compiler == 'apple-clang' }}
|
||||
shell: bash
|
||||
working-directory: ${{github.workspace}}/build
|
||||
run: >
|
||||
cmake $GITHUB_WORKSPACE
|
||||
-DCMAKE_BUILD_TYPE=$BUILD_TYPE
|
||||
-DAPP_BUILD_EXAMPLES=ON
|
||||
-DAPP_BUILD_TESTS=ON
|
||||
-DAPP_COMPILER_ENABLE_WARNINGS=ON
|
||||
|
||||
- name: Configure CMake
|
||||
if: ${{ matrix.compiler == 'clang' }}
|
||||
shell: bash
|
||||
working-directory: ${{github.workspace}}/build
|
||||
run: >
|
||||
cmake $GITHUB_WORKSPACE
|
||||
-DCMAKE_BUILD_TYPE=$BUILD_TYPE
|
||||
-DAPP_BUILD_EXAMPLES=ON
|
||||
-DAPP_BUILD_TESTS=ON
|
||||
-DAPP_COMPILER_ENABLE_WARNINGS=ON
|
||||
-DCMAKE_CXX_COMPILER=$(brew --prefix llvm@17)/bin/clang++
|
||||
|
||||
- name: Build
|
||||
shell: bash
|
||||
working-directory: ${{github.workspace}}/build
|
||||
run: cmake --build . --config $BUILD_TYPE
|
||||
|
||||
- name: Test
|
||||
working-directory: ${{github.workspace}}/build
|
||||
shell: bash
|
||||
run: ctest -C $BUILD_TYPE --rerun-failed --output-on-failure
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
# This workflow uses actions that are not certified by GitHub.
|
||||
# They are provided by a third-party and are governed by
|
||||
# separate terms of service, privacy policy, and support
|
||||
# documentation.
|
||||
|
||||
# This workflow checks out code, performs a Codacy security scan
|
||||
# and integrates the results with the
|
||||
# GitHub Advanced Security code scanning feature. For more information on
|
||||
# the Codacy security scan action usage and parameters, see
|
||||
# https://github.com/codacy/codacy-analysis-cli-action.
|
||||
# For more information on Codacy Analysis CLI in general, see
|
||||
# https://github.com/codacy/codacy-analysis-cli.
|
||||
|
||||
name: Codacy Security Scan
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
pull_request:
|
||||
# The branches below must be a subset of the branches above
|
||||
branches: [ main ]
|
||||
schedule:
|
||||
- cron: '27 22 * * 1'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
codacy-security-scan:
|
||||
permissions:
|
||||
contents: read # for actions/checkout to fetch code
|
||||
security-events: write # for github/codeql-action/upload-sarif to upload SARIF results
|
||||
actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status
|
||||
name: Codacy Security Scan
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
# Checkout the repository to the GitHub Actions runner
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# Execute Codacy Analysis CLI and generate a SARIF output with the security issues identified during the analysis
|
||||
- name: Run Codacy Analysis CLI
|
||||
uses: codacy/codacy-analysis-cli-action@d840f886c4bd4edc059706d09c6a1586111c540b
|
||||
with:
|
||||
# Check https://github.com/codacy/codacy-analysis-cli#project-token to get your project token from your Codacy repository
|
||||
# You can also omit the token and run the tools that support default configurations
|
||||
project-token: ${{ secrets.CODACY_PROJECT_TOKEN }}
|
||||
verbose: true
|
||||
output: results.sarif
|
||||
format: sarif
|
||||
# Adjust severity of non-security issues
|
||||
gh-code-scanning-compat: true
|
||||
# Force 0 exit code to allow SARIF file generation
|
||||
# This will handover control about PR rejection to the GitHub side
|
||||
max-allowed-issues: 2147483647
|
||||
|
||||
# Upload the SARIF file generated in the previous step
|
||||
- name: Upload SARIF results file
|
||||
uses: github/codeql-action/upload-sarif@v3
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
@@ -0,0 +1,85 @@
|
||||
# For most projects, this workflow file will not need changing; you simply need
|
||||
# to commit it to your repository.
|
||||
#
|
||||
# You may wish to alter this file to override the set of languages analyzed,
|
||||
# or to provide custom queries or build logic.
|
||||
#
|
||||
# ******** NOTE ********
|
||||
# We have attempted to detect the languages in your repository. Please check
|
||||
# the `language` matrix defined below to confirm you have the correct set of
|
||||
# supported CodeQL languages.
|
||||
#
|
||||
name: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
pull_request:
|
||||
# The branches below must be a subset of the branches above
|
||||
branches: [ main ]
|
||||
schedule:
|
||||
- cron: '24 10 * * 6'
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
# required for all workflows
|
||||
security-events: write
|
||||
|
||||
# required to fetch internal or private CodeQL packs
|
||||
#packages: read
|
||||
|
||||
# only required for workflows in private repositories
|
||||
#actions: read
|
||||
#contents: read
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: [ 'cpp' ]
|
||||
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
|
||||
# Learn more about CodeQL language support at https://git.io/codeql-language-support
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Update Package Database
|
||||
run: sudo apt-get update
|
||||
|
||||
- name: Install Dependencies
|
||||
run: sudo apt-get install libgtkmm-3.0-dev gettext
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||
# queries: ./path/to/local/query, your-org/your-repo/queries@main
|
||||
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
env:
|
||||
CC: gcc-13
|
||||
CXX: g++-13
|
||||
uses: github/codeql-action/autobuild@v3
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 https://git.io/JvXDl
|
||||
|
||||
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
|
||||
# and modify them (or add more) to build your code if your project
|
||||
# uses a compiled language
|
||||
|
||||
#- run: |
|
||||
# make bootstrap
|
||||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v3
|
||||
@@ -0,0 +1,36 @@
|
||||
# This workflow uses actions that are not certified by GitHub.
|
||||
# They are provided by a third-party and are governed by
|
||||
# separate terms of service, privacy policy, and support
|
||||
# documentation.
|
||||
|
||||
name: DevSkim
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
schedule:
|
||||
- cron: '25 22 * * 0'
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
name: DevSkim
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Run DevSkim scanner
|
||||
uses: microsoft/DevSkim-Action@v1
|
||||
with:
|
||||
ignore-globs: dummy_to_avoid_action_error,**/.git/**,*.txt,**/dependencies/**,env_tools.h,app_gtkmm_tools.cpp
|
||||
|
||||
- name: Upload DevSkim scan results to GitHub Security tab
|
||||
uses: github/codeql-action/upload-sarif@v3
|
||||
with:
|
||||
sarif_file: devskim-results.sarif
|
||||
@@ -0,0 +1,128 @@
|
||||
name: Windows Release
|
||||
|
||||
on:
|
||||
# Allows you to run this workflow manually from the Actions tab
|
||||
workflow_dispatch:
|
||||
|
||||
|
||||
env:
|
||||
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
|
||||
BUILD_TYPE: Release
|
||||
SMARTMONTOOLS_INSTALLER: smartmontools-7.4-1.win32-setup.exe
|
||||
SMARTMONTOOLS_URL: https://downloads.sourceforge.net/project/smartmontools/smartmontools/7.4/smartmontools-7.4-1.win32-setup.exe
|
||||
|
||||
|
||||
jobs:
|
||||
|
||||
windows-msys2:
|
||||
runs-on: windows-latest
|
||||
strategy:
|
||||
matrix:
|
||||
include: [
|
||||
{ msystem: MINGW64, arch: x86_64, platform: win64 },
|
||||
{ msystem: MINGW32, arch: i686, platform: win32 }
|
||||
]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: msys2/setup-msys2@v2
|
||||
# p7zip is needed to extract smartmontools
|
||||
# fontconfig owns /etc/fonts
|
||||
with:
|
||||
msystem: ${{ matrix.msystem }}
|
||||
update: true
|
||||
install: >-
|
||||
mingw-w64-${{ matrix.arch }}-gtkmm3
|
||||
mingw-w64-${{ matrix.arch }}-pkg-config
|
||||
mingw-w64-${{ matrix.arch }}-cmake
|
||||
mingw-w64-${{ matrix.arch }}-gcc
|
||||
mingw-w64-${{ matrix.arch }}-fontconfig
|
||||
make
|
||||
p7zip
|
||||
|
||||
- name: Download Package Requirements
|
||||
shell: msys2 {0}
|
||||
working-directory: ${{github.workspace}}
|
||||
run: |
|
||||
mkdir -p build/smartmontools
|
||||
cd build/smartmontools
|
||||
wget $SMARTMONTOOLS_URL
|
||||
|
||||
- name: Extract Package Requirements (64-bit)
|
||||
if: ${{ matrix.msystem == 'MINGW64' }}
|
||||
shell: msys2 {0}
|
||||
working-directory: ${{github.workspace}}/build/smartmontools
|
||||
run: >
|
||||
7z -bb1 e $SMARTMONTOOLS_INSTALLER
|
||||
bin/smartctl.exe
|
||||
bin/smartctl-nc.exe
|
||||
bin/update-smart-drivedb.ps1
|
||||
bin/drivedb.h
|
||||
|
||||
- name: Extract Package Requirements (32-bit)
|
||||
if: ${{ matrix.msystem == 'MINGW32' }}
|
||||
shell: msys2 {0}
|
||||
working-directory: ${{github.workspace}}/build/smartmontools
|
||||
run: >
|
||||
7z -bb1 e $SMARTMONTOOLS_INSTALLER
|
||||
bin32/smartctl.exe
|
||||
bin32/smartctl-nc.exe
|
||||
bin/update-smart-drivedb.ps1
|
||||
bin/drivedb.h
|
||||
|
||||
- name: List installed files
|
||||
shell: msys2 {0}
|
||||
run: |
|
||||
ls -1R /mingw64
|
||||
ls -1R /mingw32
|
||||
|
||||
- name: Configure CMake
|
||||
shell: msys2 {0}
|
||||
run: >
|
||||
cmake -B build -S "$GITHUB_WORKSPACE"
|
||||
-G "MSYS Makefiles"
|
||||
-DCMAKE_BUILD_TYPE=$BUILD_TYPE
|
||||
-DCMAKE_TOOLCHAIN_FILE="$GITHUB_WORKSPACE/toolchains/${{ matrix.platform }}-mingw-msys2.cmake"
|
||||
|
||||
- name: Build
|
||||
shell: msys2 {0}
|
||||
working-directory: ${{github.workspace}}/build
|
||||
run: cmake --build . --config $BUILD_TYPE
|
||||
|
||||
- name: Test
|
||||
working-directory: ${{github.workspace}}/build
|
||||
shell: msys2 {0}
|
||||
run: ctest -C $BUILD_TYPE --rerun-failed --output-on-failure
|
||||
|
||||
- name: Package ZIP
|
||||
shell: msys2 {0}
|
||||
working-directory: ${{github.workspace}}/build
|
||||
run: cpack -G ZIP
|
||||
|
||||
- name: Package NSIS (64-bit)
|
||||
if: ${{ matrix.msystem == 'MINGW64' }}
|
||||
shell: msys2 {0}
|
||||
working-directory: ${{github.workspace}}/build
|
||||
run: cpack -G NSIS64
|
||||
|
||||
- name: Package NSIS (32-bit)
|
||||
if: ${{ matrix.msystem == 'MINGW32' }}
|
||||
shell: msys2 {0}
|
||||
working-directory: ${{github.workspace}}/build
|
||||
run: cpack -G NSIS
|
||||
|
||||
- name: Upload artifacts
|
||||
if: ${{ matrix.msystem == 'MINGW64' }}
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Windows 64-Bit Packages
|
||||
path: ${{github.workspace}}/build/gsmartcontrol-*-win*.*
|
||||
|
||||
- name: Upload artifacts
|
||||
if: ${{ matrix.msystem == 'MINGW32' }}
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Windows 32-Bit Packages
|
||||
path: ${{github.workspace}}/build/gsmartcontrol-*-win*.*
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
|
||||
# Builds
|
||||
/0*
|
||||
/win32*
|
||||
/win64*
|
||||
/cmake-build-*
|
||||
|
||||
# Non-project files
|
||||
/TODO
|
||||
|
||||
# Doxygen generated
|
||||
/doxygen_doc
|
||||
|
||||
# OS-generated files
|
||||
.DS_Store
|
||||
.DS_Store?
|
||||
._*
|
||||
.Spotlight-V100
|
||||
.Trashes
|
||||
Icon?
|
||||
ehthumbs.db
|
||||
Thumbs.db
|
||||
|
||||
# IDE
|
||||
/.vs
|
||||
/*.pcs
|
||||
/.idea
|
||||
/CMakeLists.txt.user
|
||||
|
||||
# Translations
|
||||
/po/boldquot.sed
|
||||
/po/en@boldquot.header
|
||||
/po/en@quot.header
|
||||
/po/insert-header.sin
|
||||
/po/Makevars.template
|
||||
/po/quot.sed
|
||||
/po/remove-potcdate.sin
|
||||
/po/Rules-quot
|
||||
/po/gsmartcontrol.pot
|
||||
/po/*.gmo
|
||||
|
||||
@@ -0,0 +1,179 @@
|
||||
|
||||
# This file describes OBS workflows:
|
||||
# https://openbuildservice.org/help/manuals/obs-user-guide/cha.obs.scm_ci_workflow_integration.html
|
||||
|
||||
# Workflow for pull requests
|
||||
#build_pull_request_workflow:
|
||||
# steps:
|
||||
# - branch_package:
|
||||
# source_project: home:alex_sh:gsmartcontrol:github_ci:main
|
||||
# source_package: gsmartcontrol
|
||||
# target_project: home:alex_sh:gsmartcontrol:github_ci:main
|
||||
#
|
||||
# - configure_repositories:
|
||||
# project: home:alex_sh:gsmartcontrol:github_ci:main
|
||||
# repositories:
|
||||
# - name: openSUSE_Tumbleweed
|
||||
# paths:
|
||||
# - target_project: openSUSE:Factory
|
||||
# target_repository: snapshot
|
||||
# architectures:
|
||||
# - x86_64
|
||||
# - i586
|
||||
#
|
||||
# - set_flags:
|
||||
# flags:
|
||||
# - type: publish
|
||||
# status: disable
|
||||
# project: home:alex_sh:gsmartcontrol:github_ci:main
|
||||
#
|
||||
# filters:
|
||||
# event: pull_request
|
||||
# branches:
|
||||
# only:
|
||||
# - main
|
||||
|
||||
|
||||
# Workflow for pushes
|
||||
|
||||
# Note: This adds new repositories to the project if they do not exist.
|
||||
build_main_workflow:
|
||||
steps:
|
||||
- configure_repositories:
|
||||
project: home:alex_sh:gsmartcontrol:github_ci:main
|
||||
repositories:
|
||||
|
||||
- name: openSUSE_Tumbleweed
|
||||
paths:
|
||||
- target_project: openSUSE:Factory
|
||||
target_repository: snapshot
|
||||
architectures:
|
||||
- x86_64
|
||||
|
||||
- name: openSUSE_Slowroll
|
||||
paths:
|
||||
- target_project: openSUSE:Slowroll
|
||||
target_repository: standard
|
||||
architectures:
|
||||
- x86_64
|
||||
|
||||
- name: openSUSE_Leap_15.6
|
||||
paths:
|
||||
# - target_project: devel:gcc
|
||||
# target_repository: openSUSE_Leap_15.6
|
||||
- target_project: openSUSE:Leap:15.6
|
||||
target_repository: standard
|
||||
architectures:
|
||||
- x86_64
|
||||
|
||||
- name: openSUSE_Leap_15.5
|
||||
paths:
|
||||
- target_project: devel:gcc
|
||||
target_repository: openSUSE_Leap_15.5
|
||||
- target_project: openSUSE:Leap:15.5
|
||||
target_repository: standard
|
||||
architectures:
|
||||
- x86_64
|
||||
|
||||
- name: openSUSE_Factory_ARM
|
||||
paths:
|
||||
- target_project: openSUSE:Factory:ARM
|
||||
target_repository: standard
|
||||
architectures:
|
||||
- aarch64
|
||||
- armv7l
|
||||
|
||||
- name: SUSE_SLE-15-SP6
|
||||
paths:
|
||||
- target_project: devel:gcc
|
||||
target_repository: SLE-15
|
||||
- target_project: SUSE:SLE-15-SP6:GA
|
||||
target_repository: standard
|
||||
architectures:
|
||||
- x86_64
|
||||
|
||||
- name: Ubuntu_24.04
|
||||
paths:
|
||||
- target_project: openSUSE:Tools
|
||||
target_repository: xUbuntu_24.04
|
||||
- target_project: Ubuntu:21.10
|
||||
target_repository: universe
|
||||
architectures:
|
||||
- x86_64
|
||||
|
||||
- name: Ubuntu_23.10
|
||||
paths:
|
||||
- target_project: openSUSE:Tools
|
||||
target_repository: xUbuntu_23.10
|
||||
- target_project: Ubuntu:20.04
|
||||
target_repository: universe
|
||||
architectures:
|
||||
- x86_64
|
||||
|
||||
- name: Fedora_Rawhide
|
||||
paths:
|
||||
- target_project: openSUSE:Tools
|
||||
target_repository: Fedora_Rawhide
|
||||
- target_project: Fedora:Rawhide
|
||||
target_repository: standard
|
||||
architectures:
|
||||
- x86_64
|
||||
|
||||
- name: Fedora_40
|
||||
paths:
|
||||
- target_project: openSUSE:Tools
|
||||
target_repository: Fedora_40
|
||||
- target_project: Fedora:40
|
||||
target_repository: standard
|
||||
architectures:
|
||||
- x86_64
|
||||
- aarch64
|
||||
|
||||
- name: Fedora_39
|
||||
paths:
|
||||
- target_project: openSUSE:Tools
|
||||
target_repository: Fedora_39
|
||||
- target_project: Fedora:39
|
||||
target_repository: standard
|
||||
architectures:
|
||||
- x86_64
|
||||
- aarch64
|
||||
|
||||
- name: Debian_Unstable
|
||||
paths:
|
||||
- target_project: openSUSE:Tools
|
||||
target_repository: Debian_Unstable
|
||||
- target_project: Debian:Next
|
||||
target_repository: standard
|
||||
architectures:
|
||||
- x86_64
|
||||
|
||||
- name: Debian_Testing
|
||||
paths:
|
||||
- target_project: openSUSE:Tools
|
||||
target_repository: Debian_Testing
|
||||
- target_project: Debian:Testing
|
||||
target_repository: update
|
||||
architectures:
|
||||
- x86_64
|
||||
- i586
|
||||
|
||||
- set_flags:
|
||||
flags:
|
||||
- type: publish
|
||||
status: enable
|
||||
project: home:alex_sh:gsmartcontrol:github_ci:main
|
||||
- type: debuginfo
|
||||
status: enable
|
||||
project: home:alex_sh:gsmartcontrol:github_ci:main
|
||||
|
||||
- rebuild_package:
|
||||
project: home:alex_sh:gsmartcontrol:github_ci:main
|
||||
package: gsmartcontrol
|
||||
|
||||
filters:
|
||||
event: push
|
||||
branches:
|
||||
only:
|
||||
- main
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
###############################################################################
|
||||
# License: BSD Zero Clause License file
|
||||
# Copyright:
|
||||
# (C) 2021 - 2024 Alexander Shaduri <ashaduri@gmail.com>
|
||||
###############################################################################
|
||||
|
||||
# 3.14 for proper object library support (wrt linking)
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
# Use new policy for option() to supress warnings.
|
||||
set(CMAKE_POLICY_DEFAULT_CMP0077 NEW)
|
||||
|
||||
|
||||
include(${CMAKE_SOURCE_DIR}/version.txt)
|
||||
|
||||
project(gsmartcontrol
|
||||
VERSION ${CMAKE_PROJECT_VERSION}
|
||||
DESCRIPTION "Hard Disk Drive and SSD Health Inspection Tool"
|
||||
HOMEPAGE_URL "https://gsmartcontrol.shaduri.dev"
|
||||
LANGUAGES CXX
|
||||
)
|
||||
|
||||
|
||||
# Provide DATADIR, etc.
|
||||
include(GNUInstallDirs)
|
||||
|
||||
message(STATUS "Using toolchain file: ${CMAKE_TOOLCHAIN_FILE}")
|
||||
|
||||
include(src/build_config/compiler_options.cmake)
|
||||
|
||||
|
||||
# Disable RPATH manipulation, we don't have shared libraries
|
||||
set(CMAKE_SKIP_BUILD_RPATH TRUE)
|
||||
set(CMAKE_SKIP_INSTALL_RPATH TRUE)
|
||||
|
||||
# Write the binaries to project root (avoids conflicts with manifests, also it's more convenient this way)
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
|
||||
|
||||
|
||||
# User-controlled build options
|
||||
option(APP_BUILD_EXAMPLES "Build examples" OFF)
|
||||
option(APP_BUILD_TESTS "Build tests" OFF)
|
||||
|
||||
|
||||
# Install documentation
|
||||
set(DOC_FILES
|
||||
LICENSE.LGPL3.txt
|
||||
LICENSE.txt
|
||||
NEWS.txt
|
||||
README.md
|
||||
)
|
||||
if (WIN32)
|
||||
install(FILES ${DOC_FILES} DESTINATION doc/)
|
||||
install(DIRECTORY docs DESTINATION doc/
|
||||
PATTERN "*.yml" EXCLUDE
|
||||
PATTERN "CNAME" EXCLUDE
|
||||
)
|
||||
else()
|
||||
install(FILES ${DOC_FILES} TYPE DOC)
|
||||
install(DIRECTORY docs TYPE DOC
|
||||
PATTERN "*.yml" EXCLUDE
|
||||
PATTERN "CNAME" EXCLUDE
|
||||
)
|
||||
endif()
|
||||
|
||||
|
||||
# CTest support
|
||||
include(CTest)
|
||||
#include(${CMAKE_SOURCE_DIR}/dependencies/catch2/Catch2/extras/Catch.cmake)
|
||||
include(${CMAKE_SOURCE_DIR}/dependencies/catch2/Catch2/contrib/Catch.cmake)
|
||||
|
||||
|
||||
add_subdirectory(contrib)
|
||||
add_subdirectory(data)
|
||||
add_subdirectory(dependencies)
|
||||
add_subdirectory(packaging)
|
||||
add_subdirectory(src)
|
||||
|
||||
|
||||
# Packaging support
|
||||
include(packaging/cpack_options.cmake)
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
We as members, contributors, and leaders pledge to make participation in our
|
||||
community a harassment-free experience for everyone, regardless of age, body
|
||||
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
||||
identity and expression, level of experience, education, socio-economic status,
|
||||
nationality, personal appearance, race, religion, or sexual identity
|
||||
and orientation.
|
||||
|
||||
We pledge to act and interact in ways that contribute to an open, welcoming,
|
||||
diverse, inclusive, and healthy community.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to a positive environment for our
|
||||
community include:
|
||||
|
||||
* Demonstrating empathy and kindness toward other people
|
||||
* Being respectful of differing opinions, viewpoints, and experiences
|
||||
* Giving and gracefully accepting constructive feedback
|
||||
* Accepting responsibility and apologizing to those affected by our mistakes,
|
||||
and learning from the experience
|
||||
* Focusing on what is best not just for us as individuals, but for the
|
||||
overall community
|
||||
|
||||
Examples of unacceptable behavior include:
|
||||
|
||||
* The use of sexualized language or imagery, and sexual attention or
|
||||
advances of any kind
|
||||
* Trolling, insulting or derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or email
|
||||
address, without their explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
## Enforcement Responsibilities
|
||||
|
||||
Community leaders are responsible for clarifying and enforcing our standards of
|
||||
acceptable behavior and will take appropriate and fair corrective action in
|
||||
response to any behavior that they deem inappropriate, threatening, offensive,
|
||||
or harmful.
|
||||
|
||||
Community leaders have the right and responsibility to remove, edit, or reject
|
||||
comments, commits, code, wiki edits, issues, and other contributions that are
|
||||
not aligned to this Code of Conduct, and will communicate reasons for moderation
|
||||
decisions when appropriate.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies within all community spaces, and also applies when
|
||||
an individual is officially representing the community in public spaces.
|
||||
Examples of representing our community include using an official e-mail address,
|
||||
posting via an official social media account, or acting as an appointed
|
||||
representative at an online or offline event.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported to the community leaders responsible for enforcement at
|
||||
ashaduri@gmail.com.
|
||||
All complaints will be reviewed and investigated promptly and fairly.
|
||||
|
||||
All community leaders are obligated to respect the privacy and security of the
|
||||
reporter of any incident.
|
||||
|
||||
## Enforcement Guidelines
|
||||
|
||||
Community leaders will follow these Community Impact Guidelines in determining
|
||||
the consequences for any action they deem in violation of this Code of Conduct:
|
||||
|
||||
### 1. Correction
|
||||
|
||||
**Community Impact**: Use of inappropriate language or other behavior deemed
|
||||
unprofessional or unwelcome in the community.
|
||||
|
||||
**Consequence**: A private, written warning from community leaders, providing
|
||||
clarity around the nature of the violation and an explanation of why the
|
||||
behavior was inappropriate. A public apology may be requested.
|
||||
|
||||
### 2. Warning
|
||||
|
||||
**Community Impact**: A violation through a single incident or series
|
||||
of actions.
|
||||
|
||||
**Consequence**: A warning with consequences for continued behavior. No
|
||||
interaction with the people involved, including unsolicited interaction with
|
||||
those enforcing the Code of Conduct, for a specified period of time. This
|
||||
includes avoiding interactions in community spaces as well as external channels
|
||||
like social media. Violating these terms may lead to a temporary or
|
||||
permanent ban.
|
||||
|
||||
### 3. Temporary Ban
|
||||
|
||||
**Community Impact**: A serious violation of community standards, including
|
||||
sustained inappropriate behavior.
|
||||
|
||||
**Consequence**: A temporary ban from any sort of interaction or public
|
||||
communication with the community for a specified period of time. No public or
|
||||
private interaction with the people involved, including unsolicited interaction
|
||||
with those enforcing the Code of Conduct, is allowed during this period.
|
||||
Violating these terms may lead to a permanent ban.
|
||||
|
||||
### 4. Permanent Ban
|
||||
|
||||
**Community Impact**: Demonstrating a pattern of violation of community
|
||||
standards, including sustained inappropriate behavior, harassment of an
|
||||
individual, or aggression toward or disparagement of classes of individuals.
|
||||
|
||||
**Consequence**: A permanent ban from any sort of public interaction within
|
||||
the community.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
||||
version 2.0, available at
|
||||
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
|
||||
|
||||
Community Impact Guidelines were inspired by [Mozilla's code of conduct
|
||||
enforcement ladder](https://github.com/mozilla/diversity).
|
||||
|
||||
[homepage]: https://www.contributor-covenant.org
|
||||
|
||||
For answers to common questions about this code of conduct, see the FAQ at
|
||||
https://www.contributor-covenant.org/faq. Translations are available at
|
||||
https://www.contributor-covenant.org/translations.
|
||||
@@ -0,0 +1,165 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
||||
This version of the GNU Lesser General Public License incorporates
|
||||
the terms and conditions of version 3 of the GNU General Public
|
||||
License, supplemented by the additional permissions listed below.
|
||||
|
||||
0. Additional Definitions.
|
||||
|
||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||
General Public License.
|
||||
|
||||
"The Library" refers to a covered work governed by this License,
|
||||
other than an Application or a Combined Work as defined below.
|
||||
|
||||
An "Application" is any work that makes use of an interface provided
|
||||
by the Library, but which is not otherwise based on the Library.
|
||||
Defining a subclass of a class defined by the Library is deemed a mode
|
||||
of using an interface provided by the Library.
|
||||
|
||||
A "Combined Work" is a work produced by combining or linking an
|
||||
Application with the Library. The particular version of the Library
|
||||
with which the Combined Work was made is also called the "Linked
|
||||
Version".
|
||||
|
||||
The "Minimal Corresponding Source" for a Combined Work means the
|
||||
Corresponding Source for the Combined Work, excluding any source code
|
||||
for portions of the Combined Work that, considered in isolation, are
|
||||
based on the Application, and not on the Linked Version.
|
||||
|
||||
The "Corresponding Application Code" for a Combined Work means the
|
||||
object code and/or source code for the Application, including any data
|
||||
and utility programs needed for reproducing the Combined Work from the
|
||||
Application, but excluding the System Libraries of the Combined Work.
|
||||
|
||||
1. Exception to Section 3 of the GNU GPL.
|
||||
|
||||
You may convey a covered work under sections 3 and 4 of this License
|
||||
without being bound by section 3 of the GNU GPL.
|
||||
|
||||
2. Conveying Modified Versions.
|
||||
|
||||
If you modify a copy of the Library, and, in your modifications, a
|
||||
facility refers to a function or data to be supplied by an Application
|
||||
that uses the facility (other than as an argument passed when the
|
||||
facility is invoked), then you may convey a copy of the modified
|
||||
version:
|
||||
|
||||
a) under this License, provided that you make a good faith effort to
|
||||
ensure that, in the event an Application does not supply the
|
||||
function or data, the facility still operates, and performs
|
||||
whatever part of its purpose remains meaningful, or
|
||||
|
||||
b) under the GNU GPL, with none of the additional permissions of
|
||||
this License applicable to that copy.
|
||||
|
||||
3. Object Code Incorporating Material from Library Header Files.
|
||||
|
||||
The object code form of an Application may incorporate material from
|
||||
a header file that is part of the Library. You may convey such object
|
||||
code under terms of your choice, provided that, if the incorporated
|
||||
material is not limited to numerical parameters, data structure
|
||||
layouts and accessors, or small macros, inline functions and templates
|
||||
(ten or fewer lines in length), you do both of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the object code that the
|
||||
Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
4. Combined Works.
|
||||
|
||||
You may convey a Combined Work under terms of your choice that,
|
||||
taken together, effectively do not restrict modification of the
|
||||
portions of the Library contained in the Combined Work and reverse
|
||||
engineering for debugging such modifications, if you also do each of
|
||||
the following:
|
||||
|
||||
a) Give prominent notice with each copy of the Combined Work that
|
||||
the Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
c) For a Combined Work that displays copyright notices during
|
||||
execution, include the copyright notice for the Library among
|
||||
these notices, as well as a reference directing the user to the
|
||||
copies of the GNU GPL and this license document.
|
||||
|
||||
d) Do one of the following:
|
||||
|
||||
0) Convey the Minimal Corresponding Source under the terms of this
|
||||
License, and the Corresponding Application Code in a form
|
||||
suitable for, and under terms that permit, the user to
|
||||
recombine or relink the Application with a modified version of
|
||||
the Linked Version to produce a modified Combined Work, in the
|
||||
manner specified by section 6 of the GNU GPL for conveying
|
||||
Corresponding Source.
|
||||
|
||||
1) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (a) uses at run time
|
||||
a copy of the Library already present on the user's computer
|
||||
system, and (b) will operate properly with a modified version
|
||||
of the Library that is interface-compatible with the Linked
|
||||
Version.
|
||||
|
||||
e) Provide Installation Information, but only if you would otherwise
|
||||
be required to provide such information under section 6 of the
|
||||
GNU GPL, and only to the extent that such information is
|
||||
necessary to install and execute a modified version of the
|
||||
Combined Work produced by recombining or relinking the
|
||||
Application with a modified version of the Linked Version. (If
|
||||
you use option 4d0, the Installation Information must accompany
|
||||
the Minimal Corresponding Source and Corresponding Application
|
||||
Code. If you use option 4d1, you must provide the Installation
|
||||
Information in the manner specified by section 6 of the GNU GPL
|
||||
for conveying Corresponding Source.)
|
||||
|
||||
5. Combined Libraries.
|
||||
|
||||
You may place library facilities that are a work based on the
|
||||
Library side by side in a single library together with other library
|
||||
facilities that are not Applications and are not covered by this
|
||||
License, and convey such a combined library under terms of your
|
||||
choice, if you do both of the following:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based
|
||||
on the Library, uncombined with any other library facilities,
|
||||
conveyed under the terms of this License.
|
||||
|
||||
b) Give prominent notice with the combined library that part of it
|
||||
is a work based on the Library, and explaining where to find the
|
||||
accompanying uncombined form of the same work.
|
||||
|
||||
6. Revised Versions of the GNU Lesser General Public License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions
|
||||
of the GNU Lesser General Public License from time to time. Such new
|
||||
versions will be similar in spirit to the present version, but may
|
||||
differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Library as you received it specifies that a certain numbered version
|
||||
of the GNU Lesser General Public License "or any later version"
|
||||
applies to it, you have the option of following the terms and
|
||||
conditions either of that published version or of any later version
|
||||
published by the Free Software Foundation. If the Library as you
|
||||
received it does not specify a version number of the GNU Lesser
|
||||
General Public License, you may choose any version of the GNU Lesser
|
||||
General Public License ever published by the Free Software Foundation.
|
||||
|
||||
If the Library as you received it specifies that a proxy can decide
|
||||
whether future versions of the GNU Lesser General Public License shall
|
||||
apply, that proxy's public statement of acceptance of any version is
|
||||
permanent authorization for you to choose that version for the
|
||||
Library.
|
||||
@@ -0,0 +1,278 @@
|
||||
Version 2.0.1, released on 2024-11-26
|
||||
Windows: Fixed a crash when opening a native file dialog (#67).
|
||||
|
||||
Version 2.0.0, released on 2024-11-07
|
||||
New JSON-based parser for smartctl output (requires smartctl 7.3+) (#4).
|
||||
Support for NVMe drives (self-tests require smartctl 7.4+) (#4).
|
||||
New "Basic" JSON parser for SCSI, flash, and other non-ATA/NVMe drives.
|
||||
PCRE library is no longer required (the code has been ported to
|
||||
std::regex) (#40).
|
||||
A lot of code has been refactored and modernized using C++17 and C++20
|
||||
features, removing much of the custom library code.
|
||||
The build process requires a C++20-compliant compiler now (GCC 13+,
|
||||
Clang 17+, Apple Clang 15+).
|
||||
CMake (3.14+) is now used as a build system instead of autotools.
|
||||
GSmartControl is now licensed under GNU GPL 3 only.
|
||||
Icons come from Oxygen project now (LGPL 3+) instead of Crystal project.
|
||||
Documentation in md format comes with the source code ("docs" directory).
|
||||
Support new versions and prereleases of smartctl (#46, #42).
|
||||
Better detection of drive types thanks to the JSON parser.
|
||||
Removed ATA AODC feature, it has been deprecated for a while now.
|
||||
Information window: Some values are aligned and monospaced to improve
|
||||
readability.
|
||||
Fixed command execution popup dialog being on top of all windows (#17).
|
||||
Other minor UI improvements and fixes.
|
||||
Windows: Better support for HiDPI (including fractional scaling).
|
||||
Windows: NSIS package is generated by CPack now.
|
||||
Windows: Packages are built using GitHub CI now.
|
||||
|
||||
Version 1.1.4, released on 2022-02-04
|
||||
Fixed a crash when trying to render main window icons which have
|
||||
incomplete data; this fixes a rare crash when scanning devices (#13).
|
||||
Fixed rendering compatibility issues with newer GTK3 versions.
|
||||
Fixed build system conflict with C++20 version header (#14).
|
||||
Fixed "Running command ..." dialog floating above windows of other
|
||||
applications (#17).
|
||||
Fixed a crash when system locale is set to invalid locale.
|
||||
Support Finnish decimal separator (backported from the Debian package)
|
||||
(#23).
|
||||
Set LC_NUMERIC=C for smartctl process to avoid locale-dependent number
|
||||
formatting (#23).
|
||||
Fixed printing all GTK messages as warnings; the messages are sorted by
|
||||
severity now.
|
||||
Add current time to default filename in Save Output dialog.
|
||||
Support macos stat command in file2csource.sh.
|
||||
Fixed a few typos (backported from the Debian package).
|
||||
Windows port now uses Adwaita theme due to issues with win32 theme.
|
||||
Windows port is dpi-aware now.
|
||||
|
||||
Version 1.1.3, released on 2017-11-12
|
||||
Fixed gsmartcontrol-root not launching if GDK_* variables are not set.
|
||||
|
||||
Version 1.1.2, released on 2017-11-11
|
||||
Fixed gsmartcontrol-root not passing GDK_SCALE and GDK_DPI_SCALE variables
|
||||
to gsmartcontrol when using PolKit.
|
||||
Fixed blurriness of icons in the main window with GDK_SCALE=2.
|
||||
Tweaked the main window interface.
|
||||
Windows: Show volume labels beside drive letters in icon tooltips.
|
||||
|
||||
Version 1.1.1, released on 2017-09-25
|
||||
Windows: Use Adwaita GTK+ theme for systems which support Classic Windows
|
||||
theme, since the default win32 GTK+ theme is broken in it; this
|
||||
includes Windows 7 and Windows Server.
|
||||
Statistics entry values are formatted with commas for readability.
|
||||
Moved help information to website.
|
||||
|
||||
Version 1.1.0, released on 2017-09-07
|
||||
New Statistics, Temperature Log, Error Recovery, Physical and Directory
|
||||
tabs.
|
||||
General tab shows non-SMART device settings as well.
|
||||
Attributes tab shows entries in "brief" format.
|
||||
Error Log tab shows Extended error log by default (if supported).
|
||||
Self-Test Log tab now shows Extended self-test log by default (if
|
||||
supported).
|
||||
GSmartControl now uses "-x" equivalent for retrieving data (as upposed to
|
||||
"-a"); loading "-x" outputs as virtual drives is also supported.
|
||||
Implemented ability to copy rows in CSV format from Attribute, Statistics
|
||||
and Self-Test Log tables.
|
||||
Implemented "Update Drive Database" functionality.
|
||||
Windows: Drive letters are shown for each drive.
|
||||
Scan time is shown under virtual drive icons.
|
||||
Polkit is supported with gsmartcontrol-root script now.
|
||||
Pcrecpp is no longer bundled, use system-installed one instead.
|
||||
Smartmontools version 5.43 is required at runtime.
|
||||
Other minor improvements and fixes.
|
||||
|
||||
Version 1.0.2, released on 2017-07-21
|
||||
Fixed incomplete capturing of smartctl output under Windows.
|
||||
Added missing icons under Windows.
|
||||
Fixed being able to turn on AODC even if unsupported.
|
||||
|
||||
Version 1.0.1, released on 2017-06-19
|
||||
Fixed compilation under macOS.
|
||||
Fixed compilation under Fedora Rawhide.
|
||||
Don't use -mtune=generic for all targets.
|
||||
|
||||
Version 1.0.0, released on 2017-06-16
|
||||
Ported to GTK+ 3.
|
||||
Tweaked the user interface a bit.
|
||||
Dropped support for Windows XP, 2000 and 2003 (they are no longer
|
||||
supported by GTK+).
|
||||
Fixed detection of newer system-installed smartmontools under Windows.
|
||||
|
||||
Version 0.9.0, released on 2017-05-11
|
||||
Implemented (untested) support for Linux-based Areca controllers with
|
||||
enclosures.
|
||||
Implemented (untested) support for Windows-based Areca controllers (thanks
|
||||
to Richard Kagerer).
|
||||
Implemented (untested) support for Linux-based HP controllers with cciss
|
||||
and hpsa/hpahcisr drivers (thanks to Fabrice Bacchella).
|
||||
Changes in Preferences no longer fail silently until rescan/restart.
|
||||
Better drive detection under Windows after removable drives are detached.
|
||||
Windows version is no longer marked as "dpi aware" since it's not
|
||||
supported that well.
|
||||
Drive attribute descriptions have been updated (including clarifications
|
||||
for SSDs).
|
||||
Added support for SSD-only and HDD-only vendor attributes.
|
||||
Devices having only basic info can be displayed now in the info window.
|
||||
Fixed BDRW drive detection (it was detected as a HDD).
|
||||
Other minor improvements.
|
||||
A number of issues have been fixed (including a crash).
|
||||
|
||||
Version 0.8.7, released on 2012-08-11
|
||||
Implemented support for Adaptec RAID 5805 controller and possibly other
|
||||
Adaptec models as well (Linux).
|
||||
Implemented support for Areca RAID controller detection under Linux
|
||||
(untested).
|
||||
Implemented support for 3ware 3w-sas-supported (twl) RAID controller
|
||||
detection under Linux (untested).
|
||||
Implemented support for systems with several different 3ware controllers
|
||||
(twa/twe/twl).
|
||||
Fixed invalid parsing of tw_cli output which caused non-detection of
|
||||
drives and controllers with controller or port numbers greater than 9
|
||||
if tw_cli was found (3ware linux, windows).
|
||||
The duplicate drives are no longer shown for some Intel matrix controllers
|
||||
under Windows; Intel RAID controllers are fully supported under
|
||||
Windows now.
|
||||
Added options to show device name and serial number under drive icons.
|
||||
Updated SMART attribute definitions and added warnings for SSD lifetime
|
||||
attributes.
|
||||
gsmartcontrol-root has a new argument "--desktop=..." which replaces the
|
||||
old positional argument; compatibility with the old invocation syntax
|
||||
has been retained.
|
||||
Completely documented the source using doxygen tags.
|
||||
Added support for Fedora's consolehelper.
|
||||
Made GSmartControl DPI-aware under Windows.
|
||||
Fixed compilation issues with clang and gcc 4.7, as well as glib 2.31.x
|
||||
and newer.
|
||||
Fixed minor issues in NSIS installer.
|
||||
Fixed other minor bugs and made minor improvements.
|
||||
|
||||
Version 0.8.6, released on 2011-06-12
|
||||
Support detecting drives behind 3ware controllers (Linux, Windows),
|
||||
including tw_cli/cx/px mode in Windows. Having tw_cli is recommended
|
||||
but not required.
|
||||
Added support for specifying -d option and extra parameters via command
|
||||
line, "Add Device" and "Preferences" dialogs. This change effectively
|
||||
adds full support for multiple drives behind a single device name.
|
||||
Beesu and su-to-root are supported by gsmartcontrol-root script now.
|
||||
Completely revamped the attribute database and its handling, should be a
|
||||
lot more usable and forward-compatible now; SSD attributes are also
|
||||
included.
|
||||
In-program help has been expanded considerably.
|
||||
General improvements to user interface have been implemented (better GNOME
|
||||
HIG compliance, better tooltips, dialogs, etc.).
|
||||
Added ability to show smartctl output for devices whose info could not be
|
||||
parsed fully.
|
||||
Attributes in "brief" format are supported now.
|
||||
The parser has been updated to reflect the recent changes in smartctl.
|
||||
Quit and rescan operations are no longer denied without confirmation when
|
||||
tests are running.
|
||||
The Windows NSIS installer has been vastly improved.
|
||||
Better support for Windows Vista and 7.
|
||||
Changed copyright notices for files with Whatever License to use Unlicense.
|
||||
Added other minor features and fixed quite a few bugs.
|
||||
|
||||
Version 0.8.5, released on 2009-09-05
|
||||
GSmartControl now uses XDG config directory for per-user configuration on
|
||||
UNIX and CSIDL_PROFILE directory on Windows. Existing configuration is
|
||||
migrated automatically.
|
||||
The names are shown correctly for unsupported devices even with the latest
|
||||
smartctl snapshots now.
|
||||
Smartctl SVN revision is shown (if available).
|
||||
The progress bars update properly when parallel tests are run.
|
||||
Windows: GSmartControl should be able to operate on any valid filesystem
|
||||
path (not just locale-representable ones).
|
||||
Windows: GSmartControl is now officially compilable on x86_64 via mingw64.
|
||||
Fixed compilation under very old gtkmm/libglademm, and with gcc 4.4.
|
||||
Fixed parsing of multiple error types in SMART error log.
|
||||
Added minor features and fixed miscellaneous bugs.
|
||||
|
||||
Version 0.8.4, released on 2009-03-23
|
||||
Linux Software RAID devices are blacklisted now. (backported from Debian).
|
||||
Attributes tab is before the capabilities tab now.
|
||||
A man page has been generously contributed by Giuseppe Iuculano
|
||||
<giuseppe@iuculano.it>.
|
||||
Smartctl version now includes the CVS snapshot date (if available).
|
||||
Windows: Look for "smartctl-nc.exe" instead of "smartctl.exe" by default.
|
||||
Windows: Use smartmontools-supplied smartctl-nc.exe by default (if found).
|
||||
Other minor changes (mainly Debian backports).
|
||||
|
||||
Version 0.8.3, released on 2008-12-27
|
||||
A random "Smartctl returned an empty output" error on Windows was fixed.
|
||||
Thanks to Zurab Khetsuriani for testing.
|
||||
Fixed a parser issue which prevented running self-tests in Windows.
|
||||
The supplied icon (hopefully) shows correctly in Windows 2000 now.
|
||||
This release adds an official support for Windows 2000 SP4.
|
||||
Added scripts to allow GSmartControl to read smartctl data from
|
||||
cron-generated files. This allows users to read somewhat recent
|
||||
smartctl information without having to run GSmartControl as root.
|
||||
Generously contributed by Alex Butcher <alex dot butcher 'at'
|
||||
assursys.co.uk>.
|
||||
Configure script correctly aborts instead of printing a warning if gtkmm
|
||||
or libglademm (if needed) is not found.
|
||||
Configure script now accepts --enable-windows-console,
|
||||
--disable-abort-if-no-gtkmm, --disable-abort-if-no-glade-reader,
|
||||
as well as Windows-supporting "auto" for --enable-nsis-wine and
|
||||
--with-nsis.
|
||||
Configure's --with-win32-env has been renamed to --with-windows-dlls.
|
||||
The "About" dialog shows version information now.
|
||||
Minor bugs were fixed.
|
||||
|
||||
Version 0.8.2, released on 2008-12-10
|
||||
Fixed gsmartcontrol_root.sh script to support distributions with no
|
||||
/usr/sbin in their users' paths (thanks to Erwan Velu).
|
||||
Added desktop auto-detection to gsmartcontrol_root.sh script. This allows
|
||||
us to use only one desktop file (thanks to Erwan Velu).
|
||||
Added Debian package directory (named "debian.dist" for now to avoid
|
||||
control file conflicts with Build Service).
|
||||
Renamed gsmartcontrol_root.sh to gsmartcontrol-root, to make Debian happy.
|
||||
Added make targets for Windows packages (zip and NSIS).
|
||||
Fixed Windows-related issues (Vista is fully supported now).
|
||||
Fixed minor bugs:
|
||||
Smartctl parser is win32-locale-aware now.
|
||||
No more unnecessary parsing.
|
||||
No segfault on exit under Windows and Solaris.
|
||||
A friendlier message is displayed if smartctl was not found.
|
||||
No highlighted labels when switching tabs in Information window.
|
||||
|
||||
Version 0.8.1, released on 2008-11-11
|
||||
Disabled Linux "by-id" drive detection - it's unreliable on some broken
|
||||
systems.
|
||||
Added some more attribute descriptions.
|
||||
Our names for attributes override smartctls' now.
|
||||
Added a proper "Add Device" dialog for Windows.
|
||||
Added an icon and resource file for Windows.
|
||||
Fixed minor bugs.
|
||||
|
||||
Version 0.8.0rc4, released on 2008-10-20
|
||||
FreeBSD support (tested with DesktopBSD 1.6 (FreeBSD 6.3) / x86).
|
||||
NetBSD support (tested with NetBSD 4.0.1 / x86).
|
||||
OpenBSD support (tested with OpenBSD 4.3 / x86-64 / gcc-3.3.5).
|
||||
Solaris/gcc support (tested with Solaris 10 / x86 / gcc-3.4.3 / blastwave).
|
||||
Solaris/sunstudio support (tested with Solaris 10 / x86 / sunstudio12 /
|
||||
sunfreeware).
|
||||
Code to support Windows, Mac OS X, QNX.
|
||||
Support of older pcre versions (at least 4.5, maybe older too).
|
||||
Added gsmartcontrol_root.sh script to easily run gsmartcontrol as root.
|
||||
Improved .desktop files.
|
||||
License for tests and examples is legally more correct now.
|
||||
Minor bugfixes.
|
||||
|
||||
Version 0.8.0rc3, released on 2008-10-08
|
||||
Added support for udevless Linux distributions by providing a fallback
|
||||
/proc/partitions-based drive detection method. The new method adds
|
||||
support for Linux 2.4 and older systems. Thanks to Paul Marwick for
|
||||
reporting and testing.
|
||||
Fixed invalid error messages with directory-related operations.
|
||||
Fixed invalid verbosity levels of console output of debug messages in
|
||||
non-debug builds.
|
||||
Improved rpm spec file - now supports building on OpenSUSE build
|
||||
service with various distributions as targets.
|
||||
|
||||
Version 0.8.0rc2, released on 2008-10-05
|
||||
Fixed compilation under gcc 4.3. Thanks to Peter Linnell for reporting.
|
||||
Removed test data (there's a lot of it and it's unnecessary).
|
||||
|
||||
Version 0.8.0rc1, released on 2008-10-01
|
||||
Initial public release.
|
||||
@@ -0,0 +1,76 @@
|
||||
|
||||
# GSmartControl
|
||||
|
||||
***Hard disk drive and SSD health inspection tool***
|
||||
|
||||
[](https://gsmartcontrol.shaduri.dev)
|
||||
[](https://gsmartcontrol.shaduri.dev/downloads)
|
||||
[](https://www.gnu.org/licenses/gpl-3.0)
|
||||
[](https://gsmartcontrol.shaduri.dev/software-requirements)
|
||||
[](https://repology.org/project/gsmartcontrol/versions)
|
||||
[](https://app.codacy.com/gh/ashaduri/gsmartcontrol?utm_source=github.com&utm_medium=referral&utm_content=ashaduri/gsmartcontrol&utm_campaign=Badge_Grade_Settings)
|
||||
|
||||
---
|
||||
|
||||
[GSmartControl](https://gsmartcontrol.shaduri.dev)
|
||||
is a graphical user interface for smartctl (from [smartmontools](https://www.smartmontools.org/)
|
||||
package), which is a tool for
|
||||
querying and controlling [SMART](https://en.wikipedia.org/wiki/S.M.A.R.T.)
|
||||
(Self-Monitoring, Analysis, and Reporting
|
||||
Technology) data on modern hard disk and solid-state drives. It allows you to
|
||||
inspect the drive's SMART data to determine its health, as well as run various
|
||||
tests on it.
|
||||
|
||||
|
||||
## Downloads
|
||||
|
||||
The [Downloads](https://gsmartcontrol.shaduri.dev/downloads) page contains
|
||||
all the available packages of GSmartControl.
|
||||
|
||||
|
||||
## Features
|
||||
- automatically reports and highlights any anomalies;
|
||||
- allows enabling/disabling SMART;
|
||||
- supports configuration of global and per-drive options for smartctl;
|
||||
- performs SMART self-tests;
|
||||
- displays drive identity information, capabilities, attributes, device statistics, etc.;
|
||||
- can read in smartctl output from a saved file, interpreting it as a read-only virtual device;
|
||||
- works on most smartctl-supported operating systems;
|
||||
- has extensive help information.
|
||||
|
||||
|
||||
### Supported Hardware
|
||||
|
||||
GSmartControl supports SATA, PATA, and NVMe drives, as well as drives
|
||||
behind some USB bridges and RAID controllers.
|
||||
Please see the
|
||||
[Supported Hardware](https://gsmartcontrol.shaduri.dev/supported-hardware) page
|
||||
for more information.
|
||||
|
||||
|
||||
### Supported Platforms
|
||||
|
||||
GSmartControl supports all major desktop operating systems, including
|
||||
Linux, Windows, macOS, FreeBSD, and other BSD-style operating systems.
|
||||
Please see the
|
||||
[Software Requirements](https://gsmartcontrol.shaduri.dev/software-requirements) page
|
||||
for more information.
|
||||
|
||||
|
||||
## Copyright and Licensing
|
||||
|
||||
GSmartControl is Copyright (C) 2008 - 2024 Alexander Shaduri [ashaduri@gmail.com](mailto:ashaduri@gmail.com) and contributors.
|
||||
|
||||
GSmartControl is licensed under the terms of
|
||||
[GNU General Public License Version 3](https://www.gnu.org/licenses/gpl-3.0.en.html).
|
||||
|
||||
This program is free software: you can redistribute it and/or modify it under
|
||||
the terms of version 3 of the GNU General Public License as published by the
|
||||
Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public Licenses for more details.
|
||||
|
||||
This product includes icons from Oxygen Icons copyright [KDE](https://kde.org)
|
||||
and licenced under the [GNU LGPL version 3](https://www.gnu.org/licenses/lgpl-3.0.en.html) or later.
|
||||
@@ -0,0 +1,16 @@
|
||||
# Security Policy
|
||||
|
||||
## Supported Versions
|
||||
|
||||
The following versions are supported with security updates:
|
||||
|
||||
| Version | Supported |
|
||||
|----------| ------------------ |
|
||||
| git main | :white_check_mark: |
|
||||
| 2.0.x | :white_check_mark: |
|
||||
| < 2.0.0 | :x: |
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
Please report security vulnerabilities privately to
|
||||
Alexander Shaduri [ashaduri@gmail.com](mailto:ashaduri@gmail.com).
|
||||
@@ -0,0 +1,160 @@
|
||||
#!/bin/bash
|
||||
###############################################################################
|
||||
# License: BSD Zero Clause License file
|
||||
# Copyright:
|
||||
# (C) 2012 - 2021 Alexander Shaduri <ashaduri@gmail.com>
|
||||
###############################################################################
|
||||
|
||||
# Configure a build directory for development
|
||||
|
||||
|
||||
function print_usage() {
|
||||
echo -e "Usage:"
|
||||
echo -e " ${0} [-t <toolchain_name>] [-c <compiler>] [-b <build_type>]"
|
||||
echo -e " [-s <source_dir>] [-g <generator>] [-o <cmake_options>]"
|
||||
echo -e "\nDetails:"
|
||||
echo -e "-t <toolchain_name> - toolchain_name can be e.g. \"win32-mingw64\"."
|
||||
echo -e " A toolchain file \"toolchains/<toolchain_name>.cmake\" will be used."
|
||||
echo -e "-c <compiler> - compiler is one of:"
|
||||
echo -e " gcc, gcc-<version>, clang, intel."
|
||||
echo -e " The gcc version is the suffix of gcc and g++ executables, e.g. \"4.8\" in"
|
||||
echo -e " \"gcc-4.8\"."
|
||||
echo -e " If unspecified, CC and CXX environment variables are used."
|
||||
echo -e "-b <build_type> - build_type is one of:"
|
||||
echo -e " Debug, Release, RelWithDebInfo, MinSizeRel, none. The default is Debug."
|
||||
echo -e "-s <source_dir> - source_dir is \"..\" by default."
|
||||
echo -e "-g <cmake_generator> - cmake uses \"Unix Makefiles\" by default."
|
||||
echo -e "-o <cmake_options> - options to pass directly to cmake."
|
||||
}
|
||||
|
||||
compiler=""
|
||||
build_type="";
|
||||
source_dir=".."
|
||||
toolchain_name=""
|
||||
generator=""
|
||||
cmake_options=""
|
||||
|
||||
while getopts "t:c:b:s:g:o:h:" opt; do
|
||||
case $opt in
|
||||
t)
|
||||
echo "Requested toolchain: $OPTARG"
|
||||
toolchain_name="$OPTARG";
|
||||
;;
|
||||
c)
|
||||
echo "Requested compiler: $OPTARG"
|
||||
compiler="$OPTARG";
|
||||
;;
|
||||
b)
|
||||
echo "Requested build type: $OPTARG"
|
||||
build_type="$OPTARG";
|
||||
;;
|
||||
s)
|
||||
echo "Requested source directory type: $OPTARG"
|
||||
source_dir="$OPTARG";
|
||||
;;
|
||||
g)
|
||||
echo "Requested generator: $OPTARG"
|
||||
generator="$OPTARG";
|
||||
;;
|
||||
o)
|
||||
echo "Requested cmake options: $OPTARG"
|
||||
cmake_options="$OPTARG";
|
||||
;;
|
||||
h)
|
||||
print_usage;
|
||||
exit 1;
|
||||
;;
|
||||
\?)
|
||||
echo "Invalid option: $opt";
|
||||
print_usage;
|
||||
exit 1;
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
|
||||
if [ "$compiler" != "" ] && [ "$toolchain_name" != "" ]; then
|
||||
echo "Error: Conflicting options -c and -t specified."
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
|
||||
cmake_flags="-Wdev";
|
||||
|
||||
if [ "$build_type" = "none" ]; then
|
||||
build_type="";
|
||||
fi
|
||||
if [ "$build_type" != "" ]; then
|
||||
cmake_flags="$cmake_flags -DCMAKE_BUILD_TYPE=$build_type";
|
||||
fi
|
||||
|
||||
if [ "$generator" != "" ]; then
|
||||
cmake_flags="$cmake_flags -G${generator}";
|
||||
fi
|
||||
|
||||
|
||||
status=1
|
||||
|
||||
|
||||
# Toolchain mode
|
||||
if [ "$toolchain_name" != "" ]; then
|
||||
cmake_flags="$cmake_flags -DCMAKE_TOOLCHAIN_FILE='${source_dir}/data/cmake/toolchains/${toolchain_name}.cmake'"
|
||||
|
||||
echo "Running:"
|
||||
echo "cmake $cmake_flags $source_dir";
|
||||
|
||||
cmake $cmake_flags $cmake_options $source_dir
|
||||
status=$?
|
||||
|
||||
else # Compiler mode
|
||||
c_compiler="";
|
||||
cxx_compiler="";
|
||||
|
||||
# Detect gcc suffix like "-4.7"
|
||||
if [ "${compiler:0:4}" = "gcc-" ]; then
|
||||
suffix=${compiler:4};
|
||||
c_compiler="gcc-${suffix}";
|
||||
cxx_compiler="g++-${suffix}";
|
||||
compiler="gcc";
|
||||
fi
|
||||
|
||||
case $compiler in
|
||||
gcc)
|
||||
if [ "$c_compiler" = "" ]; then
|
||||
c_compiler="gcc${machine_bits_switch}";
|
||||
cxx_compiler="g++${machine_bits_switch}";
|
||||
fi
|
||||
;;
|
||||
intel)
|
||||
if [ $machine_bits_precise = "64" ]; then
|
||||
c_compiler="icc64";
|
||||
cxx_compiler="icpc64";
|
||||
else
|
||||
c_compiler="icc32";
|
||||
cxx_compiler="icpc32";
|
||||
fi
|
||||
;;
|
||||
clang)
|
||||
c_compiler="clang${machine_bits_switch}";
|
||||
cxx_compiler="clang++${machine_bits_switch}";
|
||||
;;
|
||||
"")
|
||||
c_compiler="$CC"
|
||||
cxx_compiler="$CXX"
|
||||
;;
|
||||
*)
|
||||
echo "Unsupported compiler given; use CC and CXX instead."
|
||||
exit 1;
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "Running:"
|
||||
echo "CC=\"$c_compiler\" CXX=\"$cxx_compiler\" cmake $cmake_flags $source_dir";
|
||||
|
||||
CC="$c_compiler" CXX="$cxx_compiler" cmake $cmake_flags $cmake_options $source_dir
|
||||
status=$?
|
||||
fi
|
||||
|
||||
|
||||
exit $status
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
###############################################################################
|
||||
# License: BSD Zero Clause License file
|
||||
# Copyright:
|
||||
# (C) 2021 Alexander Shaduri <ashaduri@gmail.com>
|
||||
###############################################################################
|
||||
|
||||
if (NOT WIN32)
|
||||
install(DIRECTORY "${CMAKE_SOURCE_DIR}/contrib" TYPE DOC
|
||||
PATTERN "CMakeLists.txt" EXCLUDE)
|
||||
endif()
|
||||
@@ -1,10 +1,10 @@
|
||||
#!/bin/bash
|
||||
############################################################################
|
||||
###############################################################################
|
||||
# License: BSD Zero Clause License file
|
||||
# Copyright:
|
||||
# (C) 2008 - 2009 Alex Butcher <alex dot butcher 'at' assursys.co.uk>
|
||||
# (C) 2008 - 2009 Alexander Shaduri <ashaduri 'at' gmail.com>
|
||||
# License: See LICENSE_whatever.txt file
|
||||
############################################################################
|
||||
# (C) 2008 - 2024 Alex Butcher <alex dot butcher 'at' assursys.co.uk>
|
||||
# (C) 2008 - 2024 Alexander Shaduri <ashaduri@gmail.com>
|
||||
###############################################################################
|
||||
|
||||
device="$1";
|
||||
|
||||
@@ -13,10 +13,10 @@ if [ "$device" = "" ]; then
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
dev_base="`basename \"$device\"`"
|
||||
dev_base=$(basename "$device")
|
||||
out_file=/var/run/smart-"$dev_base"
|
||||
|
||||
# Change the path to smartctl if necessary.
|
||||
smartctl -a "$device" 2>&1 > "$out_file"
|
||||
smartctl -x --json=o "$device" > "$out_file" 2>&1
|
||||
|
||||
chmod 644 "$out_file"
|
||||
@@ -0,0 +1,9 @@
|
||||
###############################################################################
|
||||
# License: BSD Zero Clause License file
|
||||
# Copyright:
|
||||
# (C) 2008 - 2021 Alex Butcher <alex dot butcher 'at' assursys.co.uk>
|
||||
# (C) 2008 - 2021 Alexander Shaduri <ashaduri@gmail.com>
|
||||
###############################################################################
|
||||
|
||||
*/10 * * * * root /usr/local/bin/cron-smart.sh /dev/sda
|
||||
*/10 * * * * root /usr/local/bin/cron-smart.sh /dev/sdb
|
||||
@@ -1,10 +1,10 @@
|
||||
#!/bin/bash
|
||||
############################################################################
|
||||
###############################################################################
|
||||
# License: BSD Zero Clause License file
|
||||
# Copyright:
|
||||
# (C) 2008 - 2009 Alex Butcher <alex dot butcher 'at' assursys.co.uk>
|
||||
# (C) 2008 - 2009 Alexander Shaduri <ashaduri 'at' gmail.com>
|
||||
# License: See LICENSE_whatever.txt file
|
||||
############################################################################
|
||||
# (C) 2008 - 2022 Alex Butcher <alex dot butcher 'at' assursys.co.uk>
|
||||
# (C) 2008 - 2022 Alexander Shaduri <ashaduri@gmail.com>
|
||||
###############################################################################
|
||||
|
||||
if [ "$1" = "-V" ]; then
|
||||
smartctl -V 2>&1
|
||||
@@ -21,7 +21,7 @@ if [ "$device" = "" ]; then
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
dev_base="`basename \"$device\"`"
|
||||
dev_base=$(basename "$device")
|
||||
out_file=/var/run/smart-"$dev_base"
|
||||
|
||||
cat "$out_file"
|
||||
|
After Width: | Height: | Size: 7.5 KiB |
|
After Width: | Height: | Size: 632 B |
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
@@ -0,0 +1,63 @@
|
||||
###############################################################################
|
||||
# License: BSD Zero Clause License file
|
||||
# Copyright:
|
||||
# (C) 2021 Alexander Shaduri <ashaduri@gmail.com>
|
||||
###############################################################################
|
||||
|
||||
|
||||
# Generate files
|
||||
configure_file("gsmartcontrol.appdata.in.xml" "gsmartcontrol.appdata.xml" ESCAPE_QUOTES @ONLY)
|
||||
configure_file("gsmartcontrol.in.desktop" "gsmartcontrol.desktop" ESCAPE_QUOTES @ONLY)
|
||||
configure_file("gsmartcontrol-root.in.sh" "gsmartcontrol-root.sh" ESCAPE_QUOTES @ONLY)
|
||||
configure_file("org.gsmartcontrol.in.policy" "org.gsmartcontrol.policy" ESCAPE_QUOTES @ONLY)
|
||||
|
||||
# Install app icons
|
||||
if (NOT WIN32)
|
||||
foreach(dir 16 22 24 32 48 64 128 256)
|
||||
install(FILES "${dir}/gsmartcontrol.png"
|
||||
DESTINATION "${CMAKE_INSTALL_DATADIR}/icons/hicolor/${dir}x${dir}/apps/")
|
||||
endforeach()
|
||||
# Don't run update-icon-cache, cpack is mostly for packaging.
|
||||
# install(CODE "execute_process (COMMAND gtk-update-icon-cache-3.0 -t -f \"@CMAKE_INSTALL_DATADIR@/icons/hicolor\")")
|
||||
endif()
|
||||
|
||||
if (WIN32)
|
||||
# .ico file
|
||||
install(FILES gsmartcontrol.ico DESTINATION .)
|
||||
endif()
|
||||
|
||||
set (DATA_ICONS
|
||||
icons/drive-optical.png
|
||||
icons/drive-harddisk.png
|
||||
icons/drive-removable-media-usb.png
|
||||
)
|
||||
|
||||
# Install internal icons
|
||||
if (WIN32)
|
||||
install(FILES ${DATA_ICONS} DESTINATION icons)
|
||||
else()
|
||||
install(FILES ${DATA_ICONS}
|
||||
DESTINATION "${CMAKE_INSTALL_DATADIR}/gsmartcontrol/icons")
|
||||
endif()
|
||||
|
||||
# Desktop file
|
||||
if (NOT WIN32)
|
||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/gsmartcontrol.desktop"
|
||||
DESTINATION "${CMAKE_INSTALL_DATADIR}/applications/")
|
||||
|
||||
# Appdata file
|
||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/gsmartcontrol.appdata.xml"
|
||||
DESTINATION "${CMAKE_INSTALL_DATADIR}/metainfo/")
|
||||
|
||||
# PolKit file
|
||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/org.gsmartcontrol.policy"
|
||||
DESTINATION "${CMAKE_INSTALL_DATADIR}/polkit-1/actions/")
|
||||
|
||||
# Man pages
|
||||
install(FILES "man1/gsmartcontrol.1" DESTINATION "${CMAKE_INSTALL_MANDIR}/man1")
|
||||
install(FILES "man1/gsmartcontrol.1" DESTINATION "${CMAKE_INSTALL_MANDIR}/man1" RENAME "gsmartcontrol-root.1")
|
||||
|
||||
# Scripts (this goes to bin, not sbin, as it doesn't require root privileges before running)
|
||||
install(PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/gsmartcontrol-root.sh" TYPE BIN RENAME "gsmartcontrol-root")
|
||||
endif()
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
png_name="gsmartcontrol.png"
|
||||
|
||||
# needs imagemagick
|
||||
convert 16/$png_name 22/$png_name 24/$png_name 32/$png_name \
|
||||
48/$png_name 64/$png_name 128/$png_name 256/$png_name gsmartcontrol.ico
|
||||
@@ -0,0 +1,33 @@
|
||||
/******************************************************************************
|
||||
License: GNU General Public License v3.0 only
|
||||
Copyright:
|
||||
(C) 2008 - 2021 Alexander Shaduri <ashaduri@gmail.com>
|
||||
******************************************************************************/
|
||||
|
||||
// This file is for generating documentation only. Do NOT include it.
|
||||
/// \file
|
||||
/// \author Alexander Shaduri
|
||||
|
||||
/**
|
||||
\mainpage GSmartControl Index
|
||||
|
||||
|
||||
\section intro_section Introduction
|
||||
This is GSmartControl internal documentation.
|
||||
*/
|
||||
|
||||
// Group definitions and titles.
|
||||
|
||||
/**
|
||||
\addtogroup applib Application-Specific Components
|
||||
\addtogroup applib_examples Examples of Application-Specific Components
|
||||
\addtogroup hz HZ Common System Components
|
||||
\addtogroup hz_examples Examples for HZ Common System Components
|
||||
\addtogroup libdebug LibDebug Flexible Debug Logging
|
||||
\addtogroup libdebug_examples Examples for LibDebug Flexible Debug Logging
|
||||
\addtogroup rconfig Resource Manager-Based Configuration
|
||||
\addtogroup rconfig_examples Examples for Resource Manager-Based Configuration
|
||||
\addtogroup gsc GSmartControl Application
|
||||
*/
|
||||
|
||||
|
||||
@@ -0,0 +1,168 @@
|
||||
#!/bin/bash
|
||||
###############################################################################
|
||||
# License: Zlib
|
||||
# Copyright:
|
||||
# (C) 2008 - 2022 Alexander Shaduri <ashaduri@gmail.com>
|
||||
###############################################################################
|
||||
|
||||
# Run gsmartcontrol with root, asking for root password first.
|
||||
# export GSMARTCONTROL_SU to override a su command (e.g. "kdesu -c").
|
||||
|
||||
EXEC_BIN="@CMAKE_INSTALL_FULL_SBINDIR@/gsmartcontrol";
|
||||
program_name="gsmartcontrol"
|
||||
|
||||
|
||||
# Preserve quotes in arguments
|
||||
final_args_quoted="";
|
||||
for i in "$@";do
|
||||
final_args_quoted="$final_args_quoted \"${i//\"/\\\"}\"";
|
||||
done;
|
||||
|
||||
|
||||
DESKTOP="auto";
|
||||
|
||||
# Compatibility with old syntax:
|
||||
# gsmartcontrol-root [<desktop> [program_options]]
|
||||
if [ "$1" == "auto" ] || [ "$1" == "kde" ] || [ "$1" == "gnome" ] || [ "$1" == "other" ]; then
|
||||
DESKTOP="$1";
|
||||
shift; # remove $1
|
||||
else
|
||||
# New syntax:
|
||||
# gsmartcontrol-root [--desktop=<auto|kde|gnome|other>] [program_options]
|
||||
|
||||
for arg in "$@"; do
|
||||
case $arg in
|
||||
--desktop=*)
|
||||
DESKTOP="${arg#*=}";
|
||||
final_args_quoted="${final_args_quoted/\"$arg\"/}";
|
||||
;;
|
||||
*)
|
||||
# unknown option
|
||||
;;
|
||||
esac
|
||||
done
|
||||
fi
|
||||
|
||||
if [ "$DESKTOP" != "auto" ] && [ "$DESKTOP" != "kde" ] && \
|
||||
[ "$DESKTOP" != "gnome" ] && [ "$DESKTOP" != "other" ]; then
|
||||
echo "Usage: $0 [--desktop=<auto|kde|gnome|other>] [<${program_name}_options>]";
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
|
||||
# Auto-detect current desktop if auto was specified.
|
||||
if [ "$DESKTOP" = "auto" ]; then
|
||||
# KDE_SESSION_UID is present on kde3 and kde4.
|
||||
# Note that it may be empty (but still set)
|
||||
if [ "${KDE_SESSION_UID+set}" = "set" ]; then
|
||||
DESKTOP="kde";
|
||||
# same with gnome
|
||||
elif [ "${GNOME_DESKTOP_SESSION_ID+set}" = "set" ]; then
|
||||
DESKTOP="gnome";
|
||||
else
|
||||
DESKTOP="other";
|
||||
fi
|
||||
fi
|
||||
|
||||
# echo $DESKTOP;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# They're basically the same, only the order is different.
|
||||
# pkexec is for PolKit.
|
||||
# sux requires xterm to ask for the password.
|
||||
# xdg-su is basically like this script, except worse :)
|
||||
# su-to-root is a debian/ubuntu official method (although gksu is available).
|
||||
gnome_sus="pkexec su-to-root gnomesu gksu kdesu beesu xdg-su sux";
|
||||
kde_sus="pkexec su-to-root kdesu gnomesu gksu beesu xdg-su sux";
|
||||
other_sus="$gnome_sus";
|
||||
|
||||
|
||||
candidates="";
|
||||
found_su=""
|
||||
|
||||
if [ "$DESKTOP" = "gnome" ]; then
|
||||
candidates="$gnome_sus";
|
||||
elif [ "$DESKTOP" = "kde" ]; then
|
||||
candidates="$kde_sus";
|
||||
elif [ "$DESKTOP" = "other" ]; then
|
||||
candidates="$other_sus";
|
||||
fi
|
||||
|
||||
if [ "$GSMARTCONTROL_SU" = "" ]; then
|
||||
for subin in $candidates; do
|
||||
which "$subin" &>/dev/null
|
||||
if [ $? -eq 0 ]; then
|
||||
found_su="$subin";
|
||||
break;
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$found_su" = "" ]; then
|
||||
xmessage "Error launching ${program_name}: No suitable su mechanism found.
|
||||
Try installing PolKit, kdesu, gnomesu, gksu, beesu or sux first.";
|
||||
exit 1;
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
# gnomesu and gksu (but not kdesu, not sure about others) fail to adopt
|
||||
# root's PATH. Since the user's PATH may not contain /usr/sbin (with smartctl)
|
||||
# on some distributions (e.g. mandriva), add it manually. We also add
|
||||
# /usr/local/sbin, since that's the default location of custom-compiled smartctl.
|
||||
# Add these directories _before_ existing PATH, so that the user is not
|
||||
# tricked into running it from some other path (we're running as root with
|
||||
# the user's env after all).
|
||||
# Add sbindir as well (freebsd seems to require it).
|
||||
# Note that beesu won't show a GUI login box if /usr/sbin is before /usr/bin,
|
||||
# so add it first as well.
|
||||
EXTRA_PATHS="/usr/bin:/usr/sbin:/usr/local/sbin:@CMAKE_INSTALL_FULL_SBINDIR@";
|
||||
export PATH="$EXTRA_PATHS:$PATH"
|
||||
|
||||
|
||||
# echo $found_su;
|
||||
|
||||
# Examples:
|
||||
# gnomesu -c 'gsmartcontrol --no-scan'
|
||||
# kdesu -c 'gsmartcontrol --no-scan'
|
||||
# beesu -P 'gsmartcontrol --no-scan'
|
||||
# su-to-root -X -c 'gsmartcontrol --no-scan'
|
||||
# xterm -e sux -c 'gsmartcontrol --no-scan' # sux asks for password in a terminal
|
||||
|
||||
|
||||
full_cmd="";
|
||||
|
||||
if [ "$GSMARTCONTROL_SU" != "" ]; then
|
||||
full_cmd="$GSMARTCONTROL_SU '$EXEC_BIN $final_args_quoted'";
|
||||
|
||||
elif [ "$found_su" = "pkexec" ]; then
|
||||
if [ "$GDK_SCALE" != "" ]; then
|
||||
final_args_quoted="$final_args_quoted --gdk-scale='$GDK_SCALE'"
|
||||
fi
|
||||
if [ "$GDK_DPI_SCALE" != "" ]; then
|
||||
final_args_quoted="$final_args_quoted --gdk-dpi-scale='$GDK_DPI_SCALE'"
|
||||
fi
|
||||
full_cmd="pkexec --disable-internal-agent $EXEC_BIN $final_args_quoted";
|
||||
|
||||
elif [ "$found_su" = "sux" ]; then
|
||||
full_cmd="xterm -e sux -c '$EXEC_BIN $final_args_quoted'";
|
||||
|
||||
elif [ "$found_su" = "gksu" ]; then
|
||||
full_cmd="$found_su '$EXEC_BIN $final_args_quoted'";
|
||||
|
||||
elif [ "$found_su" = "beesu" ]; then
|
||||
full_cmd="$found_su -P '$EXEC_BIN $final_args_quoted'";
|
||||
|
||||
elif [ "$found_su" = "su-to-root" ]; then
|
||||
full_cmd="$found_su -X -c '$EXEC_BIN $final_args_quoted'";
|
||||
|
||||
else # gnomesu, kdesu, xdg-su
|
||||
full_cmd="$found_su -c '$EXEC_BIN $final_args_quoted'";
|
||||
fi
|
||||
|
||||
|
||||
# echo $full_cmd
|
||||
eval "$full_cmd"
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<component type="desktop">
|
||||
<id>gsmartcontrol</id>
|
||||
<metadata_license>CC0-1.0</metadata_license>
|
||||
<project_license>GPL-3.0</project_license>
|
||||
<name>GSmartControl</name>
|
||||
<summary>Hard Disk and SSD Health Inspection</summary>
|
||||
<description>
|
||||
<p>
|
||||
GSmartControl is a graphical user interface for smartctl, which is a tool for
|
||||
querying and controlling SMART (Self-Monitoring, Analysis, and Reporting
|
||||
Technology) data in hard disk and solid-state drives. It allows you to inspect
|
||||
the drive's SMART data to determine its health, as well as run various tests
|
||||
on it.
|
||||
</p>
|
||||
</description>
|
||||
<launchable type="desktop-id">gsmartcontrol.desktop</launchable>
|
||||
<url type="homepage">https://gsmartcontrol.shaduri.dev</url>
|
||||
<screenshots>
|
||||
<screenshot type="default">
|
||||
<caption>Main window</caption>
|
||||
<image>https://gsmartcontrol.shaduri.dev/screenshots/main_ok.png</image>
|
||||
</screenshot>
|
||||
<screenshot>
|
||||
<caption>Drive identity information</caption>
|
||||
<image>https://gsmartcontrol.shaduri.dev/screenshots/info_identity.png</image>
|
||||
</screenshot>
|
||||
<screenshot>
|
||||
<caption>Attribute list of a failing drive</caption>
|
||||
<image>https://gsmartcontrol.shaduri.dev/screenshots/info_failing.png</image>
|
||||
</screenshot>
|
||||
</screenshots>
|
||||
</component>
|
||||
|
After Width: | Height: | Size: 130 KiB |
@@ -0,0 +1,35 @@
|
||||
###############################################################################
|
||||
# License: BSD Zero Clause License file
|
||||
# Copyright:
|
||||
# (C) 2008 - 2021 Alexander Shaduri <ashaduri@gmail.com>
|
||||
###############################################################################
|
||||
|
||||
[Desktop Entry]
|
||||
|
||||
# desktop file version
|
||||
Version=1.0
|
||||
Type=Application
|
||||
|
||||
Categories=System;Monitor;
|
||||
|
||||
Name=GSmartControl
|
||||
# short description, usually shown in parentheses after Name
|
||||
GenericName=Hard Disk and SSD Health Inspection
|
||||
GenericName[fr]=Inspecteur de santé de disque dur et de SSD
|
||||
|
||||
# tooltip
|
||||
Comment=Monitor and control SMART data on hard disk and solid-state drives
|
||||
Comment[fr]=Surveille et contrôle les données SMART des disques durs et des SSD
|
||||
|
||||
# If it's a name only, it looks for "name.[png|xpm]" file in
|
||||
# $XDG_DATA_DIRS/icons.
|
||||
# An absolute file path is also supported.
|
||||
Icon=gsmartcontrol
|
||||
|
||||
# Run with root permissions. This should work with newer GNOME too.
|
||||
# It _should_ work with kde, but it hangs on mine, so use plain kdesu.
|
||||
#X-KDE-SubstituteUID=true
|
||||
#X-KDE-RootOnly=true
|
||||
|
||||
# Run with root permissions.
|
||||
Exec="@CMAKE_INSTALL_FULL_BINDIR@/gsmartcontrol-root"
|
||||
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 3.4 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
@@ -1,16 +1,16 @@
|
||||
.TH GSmartControl "1" "" "gsmartcontrol " "User Commands"
|
||||
.SH NAME
|
||||
GSmartControl \- Hard disk drive health inspection tool
|
||||
GSmartControl \- Hard disk drive and SSD health inspection tool
|
||||
.SH SYNOPSIS
|
||||
\fBgsmartcontrol\fP [OPTIONS]
|
||||
|
||||
\fBgsmartcontrol\-root\fP [\fI<desktop>\fP [OPTIONS]]
|
||||
\fBgsmartcontrol\-root\fP [--desktop=\fI<desktop>\fP] [OPTIONS]
|
||||
.SH DESCRIPTION
|
||||
\fBGSmartControl\fP is a graphical user interface for smartctl (from
|
||||
smartmontools), which is a tool for querying and controlling SMART
|
||||
(Self-Monitoring, Analysis, and Reporting Technology) data on modern hard disk
|
||||
drives. It allows you to inspect the drive's SMART data to determine its
|
||||
health, as well as run various tests on it.
|
||||
and solid-state drives. It allows you to inspect the drive's SMART data to
|
||||
determine its health, as well as run various tests on it.
|
||||
.PP
|
||||
This manual page documents briefly the \fBgsmartcontrol\fP and
|
||||
\fBgsmartcontrol\-root\fP commands.
|
||||
@@ -37,7 +37,7 @@ Show logging options
|
||||
.SS "Application Options:"
|
||||
.TP
|
||||
\fB\-l\fP, \fB\-\-no\-locale\fP
|
||||
Disable locale
|
||||
Don't use system locale
|
||||
.TP
|
||||
\fB\-V\fP, \fB\-\-version\fP
|
||||
Display version information
|
||||
@@ -45,14 +45,18 @@ Display version information
|
||||
\fB\-\-no\-scan\fP
|
||||
Don't scan devices on startup
|
||||
.TP
|
||||
\fB\-\-no\-hide\-tabs\fP
|
||||
Don't hide non\-identity tabs when SMART is disabled. Useful for debugging.
|
||||
.TP
|
||||
\fB\-\-add\-virtual\fP
|
||||
Load smartctl data from file, creating a virtual drive
|
||||
Load smartctl data from file, creating a virtual drive. You
|
||||
can specify this option multiple times.
|
||||
.TP
|
||||
\fB\-\-add\-device\fP
|
||||
Add this device to device list. Useful with \fB\-\-no\-scan\fP to list certain drives only.
|
||||
Add this device to device list. The format of the device is
|
||||
\fI<device>::<type>::<extra_args>\fP, where type and extra_args are optional.
|
||||
This option is useful with \fB\-\-no\-scan\fP to list certain drives only. You
|
||||
can specify this option multiple times. Example:\fR
|
||||
.nf
|
||||
\-\-add\-device /dev/sda \-\-add\-device /dev/twa0::3ware,2 \-\-add\-device '/dev/sdb::::-T permissive'
|
||||
.fi
|
||||
.TP
|
||||
\fB\-\-display\fP=\fIDISPLAY\fP
|
||||
X display to use
|
||||
@@ -67,8 +71,8 @@ Disable logging; same as \fB\-\-verbosity\-level\fP 0
|
||||
Set verbosity level [0\-5]
|
||||
.PP
|
||||
.SH COPYRIGHT
|
||||
Copyright \(co 2008 \- 2009 Alexander Shaduri <ashaduri \'at\' gmail.com>
|
||||
Copyright \(co 2008 \- 2021 Alexander Shaduri <ashaduri@gmail.com>
|
||||
.PP
|
||||
.SH AUTHOR
|
||||
This manual page was originally written by Giuseppe Iuculano
|
||||
<giuseppe@iuculano.it>, for the Debian project.
|
||||
<giuseppe@iuculano.it> for the Debian project.
|
||||
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE policyconfig PUBLIC
|
||||
"-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
|
||||
"http://www.freedesktop.org/standards/PolicyKit/1/policyconfig.dtd">
|
||||
|
||||
<!--
|
||||
License: BSD Zero Clause License file
|
||||
Copyright:
|
||||
(C) 2008 - 2021 GSmartControl developers
|
||||
-->
|
||||
|
||||
<policyconfig>
|
||||
|
||||
<action id="org.gsmartcontrol">
|
||||
<message>Authentication is required to run GSmartControl</message>
|
||||
<icon_name>gsmartcontrol</icon_name>
|
||||
<defaults>
|
||||
<allow_any>auth_admin</allow_any>
|
||||
<allow_inactive>auth_admin</allow_inactive>
|
||||
<allow_active>auth_admin</allow_active>
|
||||
</defaults>
|
||||
<annotate key="org.freedesktop.policykit.exec.path">@CMAKE_INSTALL_FULL_SBINDIR@/gsmartcontrol</annotate>
|
||||
<annotate key="org.freedesktop.policykit.exec.allow_gui">true</annotate>
|
||||
</action>
|
||||
|
||||
</policyconfig>
|
||||
@@ -0,0 +1,73 @@
|
||||
###############################################################################
|
||||
# License: BSD Zero Clause License file
|
||||
# Copyright:
|
||||
# (C) 2021 - 2024 Alexander Shaduri <ashaduri@gmail.com>
|
||||
###############################################################################
|
||||
|
||||
# Disable all warnings
|
||||
if (${CMAKE_CXX_COMPILER_ID} STREQUAL Clang
|
||||
OR ${CMAKE_CXX_COMPILER_ID} STREQUAL GNU
|
||||
OR ${CMAKE_CXX_COMPILER_ID} STREQUAL AppleClang)
|
||||
add_compile_options(-w)
|
||||
elseif (${CMAKE_CXX_COMPILER_ID} STREQUAL MSVC)
|
||||
add_compile_options(/w)
|
||||
endif()
|
||||
|
||||
|
||||
find_package(PkgConfig REQUIRED) # pkg_check_modules()
|
||||
|
||||
|
||||
# Gtkmm.
|
||||
# Don't make it REQUIRED, we may want to build only the parsers
|
||||
pkg_check_modules(Gtkmm REQUIRED IMPORTED_TARGET GLOBAL "gtkmm-3.0>=3.0")
|
||||
add_library(app_gtkmm_interface INTERFACE)
|
||||
target_link_libraries(app_gtkmm_interface
|
||||
INTERFACE
|
||||
PkgConfig::Gtkmm
|
||||
)
|
||||
target_compile_definitions(app_gtkmm_interface
|
||||
INTERFACE
|
||||
ENABLE_GLIB=1
|
||||
ENABLE_GLIBMM=1
|
||||
# For porting to GTK4
|
||||
# GTK_DISABLE_DEPRECATED=1
|
||||
# GDK_DISABLE_DEPRECATED=1
|
||||
# GTKMM_DISABLE_DEPRECATED=1
|
||||
# GDKMM_DISABLE_DEPRECATED=1
|
||||
# GLIBMM_DISABLE_DEPRECATED=1
|
||||
# GIOMM_DISABLE_DEPRECATED=1
|
||||
)
|
||||
|
||||
# Support pre-C++17 glibmm with throw(...) exception specifications
|
||||
pkg_check_modules(Glibmm "glibmm-2.4")
|
||||
if ("${Glibmm_VERSION}" VERSION_LESS "2.50.1")
|
||||
target_compile_definitions(app_gtkmm_interface INTERFACE "APP_GLIBMM_USES_THROW")
|
||||
message(STATUS "Enabling old glibmm throw(...) workaround")
|
||||
endif()
|
||||
|
||||
|
||||
# Gettext libintl
|
||||
find_package(Intl REQUIRED)
|
||||
add_library(app_gettext_interface INTERFACE)
|
||||
if (Intl_INCLUDE_DIRS)
|
||||
target_include_directories(app_gettext_interface
|
||||
SYSTEM INTERFACE
|
||||
${Intl_INCLUDE_DIRS}
|
||||
)
|
||||
endif()
|
||||
if (Intl_LIBRARIES)
|
||||
target_link_libraries(app_gettext_interface
|
||||
INTERFACE
|
||||
${Intl_LIBRARIES}
|
||||
)
|
||||
endif()
|
||||
|
||||
# Gettext binaries and macros.
|
||||
# See https://cmake.org/cmake/help/v3.15/module/FindGettext.html
|
||||
# find_package(Gettext REQUIRED)
|
||||
|
||||
|
||||
add_subdirectory(catch2)
|
||||
add_subdirectory(nlohmann_json)
|
||||
add_subdirectory(whereami)
|
||||
add_subdirectory(tl_expected)
|
||||
@@ -0,0 +1,22 @@
|
||||
###############################################################################
|
||||
# License: BSD Zero Clause License file
|
||||
# Copyright:
|
||||
# (C) 2021 Alexander Shaduri <ashaduri@gmail.com>
|
||||
###############################################################################
|
||||
|
||||
#add_subdirectory(Catch2)
|
||||
|
||||
|
||||
add_library(Catch2 INTERFACE)
|
||||
|
||||
# Relative sources are allowed only since cmake 3.13.
|
||||
target_sources(Catch2 INTERFACE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/Catch2/single_include/catch2/catch.hpp
|
||||
)
|
||||
|
||||
target_include_directories(Catch2
|
||||
SYSTEM INTERFACE
|
||||
"${CMAKE_SOURCE_DIR}/dependencies/catch2/Catch2/single_include"
|
||||
)
|
||||
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
---
|
||||
AccessModifierOffset: '-4'
|
||||
AlignEscapedNewlines: Left
|
||||
AllowAllConstructorInitializersOnNextLine: 'true'
|
||||
BinPackArguments: 'false'
|
||||
BinPackParameters: 'false'
|
||||
BreakConstructorInitializers: AfterColon
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: 'true'
|
||||
DerivePointerAlignment: 'false'
|
||||
FixNamespaceComments: 'true'
|
||||
IncludeBlocks: Regroup
|
||||
IndentCaseLabels: 'false'
|
||||
IndentPPDirectives: AfterHash
|
||||
IndentWidth: '4'
|
||||
Language: Cpp
|
||||
NamespaceIndentation: All
|
||||
PointerAlignment: Left
|
||||
SpaceBeforeCtorInitializerColon: 'false'
|
||||
SpaceInEmptyParentheses: 'false'
|
||||
SpacesInParentheses: 'true'
|
||||
Standard: Cpp11
|
||||
TabWidth: '4'
|
||||
UseTab: Never
|
||||
|
||||
...
|
||||
@@ -0,0 +1,22 @@
|
||||
# This sets the default behaviour, overriding core.autocrlf
|
||||
* text=auto
|
||||
|
||||
# All source files should have unix line-endings in the repository,
|
||||
# but convert to native line-endings on checkout
|
||||
*.cpp text
|
||||
*.h text
|
||||
*.hpp text
|
||||
|
||||
# Windows specific files should retain windows line-endings
|
||||
*.sln text eol=crlf
|
||||
|
||||
# Keep executable scripts with LFs so they can be run after being
|
||||
# checked out on Windows
|
||||
*.py text eol=lf
|
||||
|
||||
|
||||
# Keep the single include header with LFs to make sure it is uploaded,
|
||||
# hashed etc with LF
|
||||
single_include/**/*.hpp eol=lf
|
||||
# Also keep the LICENCE file with LFs for the same reason
|
||||
LICENCE.txt eol=lf
|
||||
@@ -0,0 +1,31 @@
|
||||
*.build
|
||||
*.pbxuser
|
||||
*.mode1v3
|
||||
*.ncb
|
||||
*.suo
|
||||
Debug
|
||||
Release
|
||||
*.user
|
||||
*.xcuserstate
|
||||
.DS_Store
|
||||
xcuserdata
|
||||
CatchSelfTest.xcscheme
|
||||
Breakpoints.xcbkptlist
|
||||
projects/VS2010/TestCatch/_UpgradeReport_Files/
|
||||
projects/VS2010/TestCatch/TestCatch/TestCatch.vcxproj.filters
|
||||
projects/VisualStudio/TestCatch/UpgradeLog.XML
|
||||
projects/CMake/.idea
|
||||
projects/CMake/cmake-build-debug
|
||||
UpgradeLog.XML
|
||||
Resources/DWARF
|
||||
projects/Generated
|
||||
*.pyc
|
||||
DerivedData
|
||||
*.xccheckout
|
||||
Build
|
||||
.idea
|
||||
.vs
|
||||
cmake-build-*
|
||||
benchmark-dir
|
||||
.conan/test_package/build
|
||||
bazel-*
|
||||
@@ -0,0 +1,37 @@
|
||||
<a id="top"></a>
|
||||

|
||||
|
||||
[](https://github.com/catchorg/catch2/releases)
|
||||
[](https://travis-ci.org/catchorg/Catch2)
|
||||
[](https://ci.appveyor.com/project/catchorg/catch2)
|
||||
[](https://codecov.io/gh/catchorg/Catch2)
|
||||
[](https://wandbox.org/permlink/6JUH8Eybx4CtvkJS)
|
||||
[](https://discord.gg/4CWS9zD)
|
||||
|
||||
|
||||
<a href="https://github.com/catchorg/Catch2/releases/download/v2.13.10/catch.hpp">The latest version of the single header can be downloaded directly using this link</a>
|
||||
|
||||
## Catch2 is released!
|
||||
|
||||
If you've been using an earlier version of Catch, please see the
|
||||
Breaking Changes section of [the release notes](https://github.com/catchorg/Catch2/releases/tag/v2.0.1)
|
||||
before moving to Catch2. You might also like to read [this blog post](https://levelofindirection.com/blog/catch2-released.html) for more details.
|
||||
|
||||
## What's the Catch?
|
||||
|
||||
Catch2 is a multi-paradigm test framework for C++. which also supports
|
||||
Objective-C (and maybe C).
|
||||
It is primarily distributed as a single header file, although certain
|
||||
extensions may require additional headers.
|
||||
|
||||
## How to use it
|
||||
This documentation comprises these three parts:
|
||||
|
||||
* [Why do we need yet another C++ Test Framework?](docs/why-catch.md#top)
|
||||
* [Tutorial](docs/tutorial.md#top) - getting started
|
||||
* [Reference section](docs/Readme.md#top) - all the details
|
||||
|
||||
## More
|
||||
* Issues and bugs can be raised on the [Issue tracker on GitHub](https://github.com/catchorg/Catch2/issues)
|
||||
* For discussion or questions please use [the dedicated Google Groups forum](https://groups.google.com/forum/?fromgroups#!forum/catch-forum) or our [Discord](https://discord.gg/4CWS9zD)
|
||||
* See [who else is using Catch2](docs/opensource-users.md#top)
|
||||
@@ -0,0 +1,206 @@
|
||||
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
# file Copyright.txt or https://cmake.org/licensing for details.
|
||||
|
||||
#[=======================================================================[.rst:
|
||||
Catch
|
||||
-----
|
||||
|
||||
This module defines a function to help use the Catch test framework.
|
||||
|
||||
The :command:`catch_discover_tests` discovers tests by asking the compiled test
|
||||
executable to enumerate its tests. This does not require CMake to be re-run
|
||||
when tests change. However, it may not work in a cross-compiling environment,
|
||||
and setting test properties is less convenient.
|
||||
|
||||
This command is intended to replace use of :command:`add_test` to register
|
||||
tests, and will create a separate CTest test for each Catch test case. Note
|
||||
that this is in some cases less efficient, as common set-up and tear-down logic
|
||||
cannot be shared by multiple test cases executing in the same instance.
|
||||
However, it provides more fine-grained pass/fail information to CTest, which is
|
||||
usually considered as more beneficial. By default, the CTest test name is the
|
||||
same as the Catch name; see also ``TEST_PREFIX`` and ``TEST_SUFFIX``.
|
||||
|
||||
.. command:: catch_discover_tests
|
||||
|
||||
Automatically add tests with CTest by querying the compiled test executable
|
||||
for available tests::
|
||||
|
||||
catch_discover_tests(target
|
||||
[TEST_SPEC arg1...]
|
||||
[EXTRA_ARGS arg1...]
|
||||
[WORKING_DIRECTORY dir]
|
||||
[TEST_PREFIX prefix]
|
||||
[TEST_SUFFIX suffix]
|
||||
[PROPERTIES name1 value1...]
|
||||
[TEST_LIST var]
|
||||
[REPORTER reporter]
|
||||
[OUTPUT_DIR dir]
|
||||
[OUTPUT_PREFIX prefix}
|
||||
[OUTPUT_SUFFIX suffix]
|
||||
)
|
||||
|
||||
``catch_discover_tests`` sets up a post-build command on the test executable
|
||||
that generates the list of tests by parsing the output from running the test
|
||||
with the ``--list-test-names-only`` argument. This ensures that the full
|
||||
list of tests is obtained. Since test discovery occurs at build time, it is
|
||||
not necessary to re-run CMake when the list of tests changes.
|
||||
However, it requires that :prop_tgt:`CROSSCOMPILING_EMULATOR` is properly set
|
||||
in order to function in a cross-compiling environment.
|
||||
|
||||
Additionally, setting properties on tests is somewhat less convenient, since
|
||||
the tests are not available at CMake time. Additional test properties may be
|
||||
assigned to the set of tests as a whole using the ``PROPERTIES`` option. If
|
||||
more fine-grained test control is needed, custom content may be provided
|
||||
through an external CTest script using the :prop_dir:`TEST_INCLUDE_FILES`
|
||||
directory property. The set of discovered tests is made accessible to such a
|
||||
script via the ``<target>_TESTS`` variable.
|
||||
|
||||
The options are:
|
||||
|
||||
``target``
|
||||
Specifies the Catch executable, which must be a known CMake executable
|
||||
target. CMake will substitute the location of the built executable when
|
||||
running the test.
|
||||
|
||||
``TEST_SPEC arg1...``
|
||||
Specifies test cases, wildcarded test cases, tags and tag expressions to
|
||||
pass to the Catch executable with the ``--list-test-names-only`` argument.
|
||||
|
||||
``EXTRA_ARGS arg1...``
|
||||
Any extra arguments to pass on the command line to each test case.
|
||||
|
||||
``WORKING_DIRECTORY dir``
|
||||
Specifies the directory in which to run the discovered test cases. If this
|
||||
option is not provided, the current binary directory is used.
|
||||
|
||||
``TEST_PREFIX prefix``
|
||||
Specifies a ``prefix`` to be prepended to the name of each discovered test
|
||||
case. This can be useful when the same test executable is being used in
|
||||
multiple calls to ``catch_discover_tests()`` but with different
|
||||
``TEST_SPEC`` or ``EXTRA_ARGS``.
|
||||
|
||||
``TEST_SUFFIX suffix``
|
||||
Similar to ``TEST_PREFIX`` except the ``suffix`` is appended to the name of
|
||||
every discovered test case. Both ``TEST_PREFIX`` and ``TEST_SUFFIX`` may
|
||||
be specified.
|
||||
|
||||
``PROPERTIES name1 value1...``
|
||||
Specifies additional properties to be set on all tests discovered by this
|
||||
invocation of ``catch_discover_tests``.
|
||||
|
||||
``TEST_LIST var``
|
||||
Make the list of tests available in the variable ``var``, rather than the
|
||||
default ``<target>_TESTS``. This can be useful when the same test
|
||||
executable is being used in multiple calls to ``catch_discover_tests()``.
|
||||
Note that this variable is only available in CTest.
|
||||
|
||||
``REPORTER reporter``
|
||||
Use the specified reporter when running the test case. The reporter will
|
||||
be passed to the Catch executable as ``--reporter reporter``.
|
||||
|
||||
``OUTPUT_DIR dir``
|
||||
If specified, the parameter is passed along as
|
||||
``--out dir/<test_name>`` to Catch executable. The actual file name is the
|
||||
same as the test name. This should be used instead of
|
||||
``EXTRA_ARGS --out foo`` to avoid race conditions writing the result output
|
||||
when using parallel test execution.
|
||||
|
||||
``OUTPUT_PREFIX prefix``
|
||||
May be used in conjunction with ``OUTPUT_DIR``.
|
||||
If specified, ``prefix`` is added to each output file name, like so
|
||||
``--out dir/prefix<test_name>``.
|
||||
|
||||
``OUTPUT_SUFFIX suffix``
|
||||
May be used in conjunction with ``OUTPUT_DIR``.
|
||||
If specified, ``suffix`` is added to each output file name, like so
|
||||
``--out dir/<test_name>suffix``. This can be used to add a file extension to
|
||||
the output e.g. ".xml".
|
||||
|
||||
#]=======================================================================]
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
function(catch_discover_tests TARGET)
|
||||
cmake_parse_arguments(
|
||||
""
|
||||
""
|
||||
"TEST_PREFIX;TEST_SUFFIX;WORKING_DIRECTORY;TEST_LIST;REPORTER;OUTPUT_DIR;OUTPUT_PREFIX;OUTPUT_SUFFIX"
|
||||
"TEST_SPEC;EXTRA_ARGS;PROPERTIES"
|
||||
${ARGN}
|
||||
)
|
||||
|
||||
if(NOT _WORKING_DIRECTORY)
|
||||
set(_WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
endif()
|
||||
if(NOT _TEST_LIST)
|
||||
set(_TEST_LIST ${TARGET}_TESTS)
|
||||
endif()
|
||||
|
||||
## Generate a unique name based on the extra arguments
|
||||
string(SHA1 args_hash "${_TEST_SPEC} ${_EXTRA_ARGS} ${_REPORTER} ${_OUTPUT_DIR} ${_OUTPUT_PREFIX} ${_OUTPUT_SUFFIX}")
|
||||
string(SUBSTRING ${args_hash} 0 7 args_hash)
|
||||
|
||||
# Define rule to generate test list for aforementioned test executable
|
||||
set(ctest_include_file "${CMAKE_CURRENT_BINARY_DIR}/${TARGET}_include-${args_hash}.cmake")
|
||||
set(ctest_tests_file "${CMAKE_CURRENT_BINARY_DIR}/${TARGET}_tests-${args_hash}.cmake")
|
||||
get_property(crosscompiling_emulator
|
||||
TARGET ${TARGET}
|
||||
PROPERTY CROSSCOMPILING_EMULATOR
|
||||
)
|
||||
add_custom_command(
|
||||
TARGET ${TARGET} POST_BUILD
|
||||
BYPRODUCTS "${ctest_tests_file}"
|
||||
COMMAND "${CMAKE_COMMAND}"
|
||||
-D "TEST_TARGET=${TARGET}"
|
||||
-D "TEST_EXECUTABLE=$<TARGET_FILE:${TARGET}>"
|
||||
-D "TEST_EXECUTOR=${crosscompiling_emulator}"
|
||||
-D "TEST_WORKING_DIR=${_WORKING_DIRECTORY}"
|
||||
-D "TEST_SPEC=${_TEST_SPEC}"
|
||||
-D "TEST_EXTRA_ARGS=${_EXTRA_ARGS}"
|
||||
-D "TEST_PROPERTIES=${_PROPERTIES}"
|
||||
-D "TEST_PREFIX=${_TEST_PREFIX}"
|
||||
-D "TEST_SUFFIX=${_TEST_SUFFIX}"
|
||||
-D "TEST_LIST=${_TEST_LIST}"
|
||||
-D "TEST_REPORTER=${_REPORTER}"
|
||||
-D "TEST_OUTPUT_DIR=${_OUTPUT_DIR}"
|
||||
-D "TEST_OUTPUT_PREFIX=${_OUTPUT_PREFIX}"
|
||||
-D "TEST_OUTPUT_SUFFIX=${_OUTPUT_SUFFIX}"
|
||||
-D "CTEST_FILE=${ctest_tests_file}"
|
||||
-P "${_CATCH_DISCOVER_TESTS_SCRIPT}"
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
file(WRITE "${ctest_include_file}"
|
||||
"if(EXISTS \"${ctest_tests_file}\")\n"
|
||||
" include(\"${ctest_tests_file}\")\n"
|
||||
"else()\n"
|
||||
" add_test(${TARGET}_NOT_BUILT-${args_hash} ${TARGET}_NOT_BUILT-${args_hash})\n"
|
||||
"endif()\n"
|
||||
)
|
||||
|
||||
if(NOT ${CMAKE_VERSION} VERSION_LESS "3.10.0")
|
||||
# Add discovered tests to directory TEST_INCLUDE_FILES
|
||||
set_property(DIRECTORY
|
||||
APPEND PROPERTY TEST_INCLUDE_FILES "${ctest_include_file}"
|
||||
)
|
||||
else()
|
||||
# Add discovered tests as directory TEST_INCLUDE_FILE if possible
|
||||
get_property(test_include_file_set DIRECTORY PROPERTY TEST_INCLUDE_FILE SET)
|
||||
if (NOT ${test_include_file_set})
|
||||
set_property(DIRECTORY
|
||||
PROPERTY TEST_INCLUDE_FILE "${ctest_include_file}"
|
||||
)
|
||||
else()
|
||||
message(FATAL_ERROR
|
||||
"Cannot set more than one TEST_INCLUDE_FILE"
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
endfunction()
|
||||
|
||||
###############################################################################
|
||||
|
||||
set(_CATCH_DISCOVER_TESTS_SCRIPT
|
||||
${CMAKE_CURRENT_LIST_DIR}/CatchAddTests.cmake
|
||||
CACHE INTERNAL "Catch2 full path to CatchAddTests.cmake helper file"
|
||||
)
|
||||
@@ -0,0 +1,135 @@
|
||||
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
# file Copyright.txt or https://cmake.org/licensing for details.
|
||||
|
||||
set(prefix "${TEST_PREFIX}")
|
||||
set(suffix "${TEST_SUFFIX}")
|
||||
set(spec ${TEST_SPEC})
|
||||
set(extra_args ${TEST_EXTRA_ARGS})
|
||||
set(properties ${TEST_PROPERTIES})
|
||||
set(reporter ${TEST_REPORTER})
|
||||
set(output_dir ${TEST_OUTPUT_DIR})
|
||||
set(output_prefix ${TEST_OUTPUT_PREFIX})
|
||||
set(output_suffix ${TEST_OUTPUT_SUFFIX})
|
||||
set(script)
|
||||
set(suite)
|
||||
set(tests)
|
||||
|
||||
function(add_command NAME)
|
||||
set(_args "")
|
||||
# use ARGV* instead of ARGN, because ARGN splits arrays into multiple arguments
|
||||
math(EXPR _last_arg ${ARGC}-1)
|
||||
foreach(_n RANGE 1 ${_last_arg})
|
||||
set(_arg "${ARGV${_n}}")
|
||||
if(_arg MATCHES "[^-./:a-zA-Z0-9_]")
|
||||
set(_args "${_args} [==[${_arg}]==]") # form a bracket_argument
|
||||
else()
|
||||
set(_args "${_args} ${_arg}")
|
||||
endif()
|
||||
endforeach()
|
||||
set(script "${script}${NAME}(${_args})\n" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# Run test executable to get list of available tests
|
||||
if(NOT EXISTS "${TEST_EXECUTABLE}")
|
||||
message(FATAL_ERROR
|
||||
"Specified test executable '${TEST_EXECUTABLE}' does not exist"
|
||||
)
|
||||
endif()
|
||||
execute_process(
|
||||
COMMAND ${TEST_EXECUTOR} "${TEST_EXECUTABLE}" ${spec} --list-test-names-only
|
||||
OUTPUT_VARIABLE output
|
||||
RESULT_VARIABLE result
|
||||
WORKING_DIRECTORY "${TEST_WORKING_DIR}"
|
||||
)
|
||||
# Catch --list-test-names-only reports the number of tests, so 0 is... surprising
|
||||
if(${result} EQUAL 0)
|
||||
message(WARNING
|
||||
"Test executable '${TEST_EXECUTABLE}' contains no tests!\n"
|
||||
)
|
||||
elseif(${result} LESS 0)
|
||||
message(FATAL_ERROR
|
||||
"Error running test executable '${TEST_EXECUTABLE}':\n"
|
||||
" Result: ${result}\n"
|
||||
" Output: ${output}\n"
|
||||
)
|
||||
endif()
|
||||
|
||||
string(REPLACE "\n" ";" output "${output}")
|
||||
|
||||
# Run test executable to get list of available reporters
|
||||
execute_process(
|
||||
COMMAND ${TEST_EXECUTOR} "${TEST_EXECUTABLE}" ${spec} --list-reporters
|
||||
OUTPUT_VARIABLE reporters_output
|
||||
RESULT_VARIABLE reporters_result
|
||||
WORKING_DIRECTORY "${TEST_WORKING_DIR}"
|
||||
)
|
||||
if(${reporters_result} EQUAL 0)
|
||||
message(WARNING
|
||||
"Test executable '${TEST_EXECUTABLE}' contains no reporters!\n"
|
||||
)
|
||||
elseif(${reporters_result} LESS 0)
|
||||
message(FATAL_ERROR
|
||||
"Error running test executable '${TEST_EXECUTABLE}':\n"
|
||||
" Result: ${reporters_result}\n"
|
||||
" Output: ${reporters_output}\n"
|
||||
)
|
||||
endif()
|
||||
string(FIND "${reporters_output}" "${reporter}" reporter_is_valid)
|
||||
if(reporter AND ${reporter_is_valid} EQUAL -1)
|
||||
message(FATAL_ERROR
|
||||
"\"${reporter}\" is not a valid reporter!\n"
|
||||
)
|
||||
endif()
|
||||
|
||||
# Prepare reporter
|
||||
if(reporter)
|
||||
set(reporter_arg "--reporter ${reporter}")
|
||||
endif()
|
||||
|
||||
# Prepare output dir
|
||||
if(output_dir AND NOT IS_ABSOLUTE ${output_dir})
|
||||
set(output_dir "${TEST_WORKING_DIR}/${output_dir}")
|
||||
if(NOT EXISTS ${output_dir})
|
||||
file(MAKE_DIRECTORY ${output_dir})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Parse output
|
||||
foreach(line ${output})
|
||||
set(test ${line})
|
||||
# Escape characters in test case names that would be parsed by Catch2
|
||||
set(test_name ${test})
|
||||
foreach(char , [ ])
|
||||
string(REPLACE ${char} "\\${char}" test_name ${test_name})
|
||||
endforeach(char)
|
||||
# ...add output dir
|
||||
if(output_dir)
|
||||
string(REGEX REPLACE "[^A-Za-z0-9_]" "_" test_name_clean ${test_name})
|
||||
set(output_dir_arg "--out ${output_dir}/${output_prefix}${test_name_clean}${output_suffix}")
|
||||
endif()
|
||||
|
||||
# ...and add to script
|
||||
add_command(add_test
|
||||
"${prefix}${test}${suffix}"
|
||||
${TEST_EXECUTOR}
|
||||
"${TEST_EXECUTABLE}"
|
||||
"${test_name}"
|
||||
${extra_args}
|
||||
"${reporter_arg}"
|
||||
"${output_dir_arg}"
|
||||
)
|
||||
add_command(set_tests_properties
|
||||
"${prefix}${test}${suffix}"
|
||||
PROPERTIES
|
||||
WORKING_DIRECTORY "${TEST_WORKING_DIR}"
|
||||
${properties}
|
||||
)
|
||||
list(APPEND tests "${prefix}${test}${suffix}")
|
||||
endforeach()
|
||||
|
||||
# Create a list of all discovered tests, which users may use to e.g. set
|
||||
# properties on the tests
|
||||
add_command(set ${TEST_LIST} ${tests})
|
||||
|
||||
# Write CTest script
|
||||
file(WRITE "${CTEST_FILE}" "${script}")
|
||||
@@ -0,0 +1,252 @@
|
||||
#==================================================================================================#
|
||||
# supported macros #
|
||||
# - TEST_CASE, #
|
||||
# - TEMPLATE_TEST_CASE #
|
||||
# - SCENARIO, #
|
||||
# - TEST_CASE_METHOD, #
|
||||
# - CATCH_TEST_CASE, #
|
||||
# - CATCH_TEMPLATE_TEST_CASE #
|
||||
# - CATCH_SCENARIO, #
|
||||
# - CATCH_TEST_CASE_METHOD. #
|
||||
# #
|
||||
# Usage #
|
||||
# 1. make sure this module is in the path or add this otherwise: #
|
||||
# set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake.modules/") #
|
||||
# 2. make sure that you've enabled testing option for the project by the call: #
|
||||
# enable_testing() #
|
||||
# 3. add the lines to the script for testing target (sample CMakeLists.txt): #
|
||||
# project(testing_target) #
|
||||
# set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake.modules/") #
|
||||
# enable_testing() #
|
||||
# #
|
||||
# find_path(CATCH_INCLUDE_DIR "catch.hpp") #
|
||||
# include_directories(${INCLUDE_DIRECTORIES} ${CATCH_INCLUDE_DIR}) #
|
||||
# #
|
||||
# file(GLOB SOURCE_FILES "*.cpp") #
|
||||
# add_executable(${PROJECT_NAME} ${SOURCE_FILES}) #
|
||||
# #
|
||||
# include(ParseAndAddCatchTests) #
|
||||
# ParseAndAddCatchTests(${PROJECT_NAME}) #
|
||||
# #
|
||||
# The following variables affect the behavior of the script: #
|
||||
# #
|
||||
# PARSE_CATCH_TESTS_VERBOSE (Default OFF) #
|
||||
# -- enables debug messages #
|
||||
# PARSE_CATCH_TESTS_NO_HIDDEN_TESTS (Default OFF) #
|
||||
# -- excludes tests marked with [!hide], [.] or [.foo] tags #
|
||||
# PARSE_CATCH_TESTS_ADD_FIXTURE_IN_TEST_NAME (Default ON) #
|
||||
# -- adds fixture class name to the test name #
|
||||
# PARSE_CATCH_TESTS_ADD_TARGET_IN_TEST_NAME (Default ON) #
|
||||
# -- adds cmake target name to the test name #
|
||||
# PARSE_CATCH_TESTS_ADD_TO_CONFIGURE_DEPENDS (Default OFF) #
|
||||
# -- causes CMake to rerun when file with tests changes so that new tests will be discovered #
|
||||
# #
|
||||
# One can also set (locally) the optional variable OptionalCatchTestLauncher to precise the way #
|
||||
# a test should be run. For instance to use test MPI, one can write #
|
||||
# set(OptionalCatchTestLauncher ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${NUMPROC}) #
|
||||
# just before calling this ParseAndAddCatchTests function #
|
||||
# #
|
||||
# The AdditionalCatchParameters optional variable can be used to pass extra argument to the test #
|
||||
# command. For example, to include successful tests in the output, one can write #
|
||||
# set(AdditionalCatchParameters --success) #
|
||||
# #
|
||||
# After the script, the ParseAndAddCatchTests_TESTS property for the target, and for each source #
|
||||
# file in the target is set, and contains the list of the tests extracted from that target, or #
|
||||
# from that file. This is useful, for example to add further labels or properties to the tests. #
|
||||
# #
|
||||
#==================================================================================================#
|
||||
|
||||
if (CMAKE_MINIMUM_REQUIRED_VERSION VERSION_LESS 2.8.8)
|
||||
message(FATAL_ERROR "ParseAndAddCatchTests requires CMake 2.8.8 or newer")
|
||||
endif()
|
||||
|
||||
option(PARSE_CATCH_TESTS_VERBOSE "Print Catch to CTest parser debug messages" OFF)
|
||||
option(PARSE_CATCH_TESTS_NO_HIDDEN_TESTS "Exclude tests with [!hide], [.] or [.foo] tags" OFF)
|
||||
option(PARSE_CATCH_TESTS_ADD_FIXTURE_IN_TEST_NAME "Add fixture class name to the test name" ON)
|
||||
option(PARSE_CATCH_TESTS_ADD_TARGET_IN_TEST_NAME "Add target name to the test name" ON)
|
||||
option(PARSE_CATCH_TESTS_ADD_TO_CONFIGURE_DEPENDS "Add test file to CMAKE_CONFIGURE_DEPENDS property" OFF)
|
||||
|
||||
function(ParseAndAddCatchTests_PrintDebugMessage)
|
||||
if(PARSE_CATCH_TESTS_VERBOSE)
|
||||
message(STATUS "ParseAndAddCatchTests: ${ARGV}")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# This removes the contents between
|
||||
# - block comments (i.e. /* ... */)
|
||||
# - full line comments (i.e. // ... )
|
||||
# contents have been read into '${CppCode}'.
|
||||
# !keep partial line comments
|
||||
function(ParseAndAddCatchTests_RemoveComments CppCode)
|
||||
string(ASCII 2 CMakeBeginBlockComment)
|
||||
string(ASCII 3 CMakeEndBlockComment)
|
||||
string(REGEX REPLACE "/\\*" "${CMakeBeginBlockComment}" ${CppCode} "${${CppCode}}")
|
||||
string(REGEX REPLACE "\\*/" "${CMakeEndBlockComment}" ${CppCode} "${${CppCode}}")
|
||||
string(REGEX REPLACE "${CMakeBeginBlockComment}[^${CMakeEndBlockComment}]*${CMakeEndBlockComment}" "" ${CppCode} "${${CppCode}}")
|
||||
string(REGEX REPLACE "\n[ \t]*//+[^\n]+" "\n" ${CppCode} "${${CppCode}}")
|
||||
|
||||
set(${CppCode} "${${CppCode}}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# Worker function
|
||||
function(ParseAndAddCatchTests_ParseFile SourceFile TestTarget)
|
||||
# If SourceFile is an object library, do not scan it (as it is not a file). Exit without giving a warning about a missing file.
|
||||
if(SourceFile MATCHES "\\\$<TARGET_OBJECTS:.+>")
|
||||
ParseAndAddCatchTests_PrintDebugMessage("Detected OBJECT library: ${SourceFile} this will not be scanned for tests.")
|
||||
return()
|
||||
endif()
|
||||
# According to CMake docs EXISTS behavior is well-defined only for full paths.
|
||||
get_filename_component(SourceFile ${SourceFile} ABSOLUTE)
|
||||
if(NOT EXISTS ${SourceFile})
|
||||
message(WARNING "Cannot find source file: ${SourceFile}")
|
||||
return()
|
||||
endif()
|
||||
ParseAndAddCatchTests_PrintDebugMessage("parsing ${SourceFile}")
|
||||
file(STRINGS ${SourceFile} Contents NEWLINE_CONSUME)
|
||||
|
||||
# Remove block and fullline comments
|
||||
ParseAndAddCatchTests_RemoveComments(Contents)
|
||||
|
||||
# Find definition of test names
|
||||
# https://regex101.com/r/JygOND/1
|
||||
string(REGEX MATCHALL "[ \t]*(CATCH_)?(TEMPLATE_)?(TEST_CASE_METHOD|SCENARIO|TEST_CASE)[ \t]*\\([ \t\n]*\"[^\"]*\"[ \t\n]*(,[ \t\n]*\"[^\"]*\")?(,[ \t\n]*[^\,\)]*)*\\)[ \t\n]*\{+[ \t]*(//[^\n]*[Tt][Ii][Mm][Ee][Oo][Uu][Tt][ \t]*[0-9]+)*" Tests "${Contents}")
|
||||
|
||||
if(PARSE_CATCH_TESTS_ADD_TO_CONFIGURE_DEPENDS AND Tests)
|
||||
ParseAndAddCatchTests_PrintDebugMessage("Adding ${SourceFile} to CMAKE_CONFIGURE_DEPENDS property")
|
||||
set_property(
|
||||
DIRECTORY
|
||||
APPEND
|
||||
PROPERTY CMAKE_CONFIGURE_DEPENDS ${SourceFile}
|
||||
)
|
||||
endif()
|
||||
|
||||
# check CMP0110 policy for new add_test() behavior
|
||||
if(POLICY CMP0110)
|
||||
cmake_policy(GET CMP0110 _cmp0110_value) # new add_test() behavior
|
||||
else()
|
||||
# just to be thorough explicitly set the variable
|
||||
set(_cmp0110_value)
|
||||
endif()
|
||||
|
||||
foreach(TestName ${Tests})
|
||||
# Strip newlines
|
||||
string(REGEX REPLACE "\\\\\n|\n" "" TestName "${TestName}")
|
||||
|
||||
# Get test type and fixture if applicable
|
||||
string(REGEX MATCH "(CATCH_)?(TEMPLATE_)?(TEST_CASE_METHOD|SCENARIO|TEST_CASE)[ \t]*\\([^,^\"]*" TestTypeAndFixture "${TestName}")
|
||||
string(REGEX MATCH "(CATCH_)?(TEMPLATE_)?(TEST_CASE_METHOD|SCENARIO|TEST_CASE)" TestType "${TestTypeAndFixture}")
|
||||
string(REGEX REPLACE "${TestType}\\([ \t]*" "" TestFixture "${TestTypeAndFixture}")
|
||||
|
||||
# Get string parts of test definition
|
||||
string(REGEX MATCHALL "\"+([^\\^\"]|\\\\\")+\"+" TestStrings "${TestName}")
|
||||
|
||||
# Strip wrapping quotation marks
|
||||
string(REGEX REPLACE "^\"(.*)\"$" "\\1" TestStrings "${TestStrings}")
|
||||
string(REPLACE "\";\"" ";" TestStrings "${TestStrings}")
|
||||
|
||||
# Validate that a test name and tags have been provided
|
||||
list(LENGTH TestStrings TestStringsLength)
|
||||
if(TestStringsLength GREATER 2 OR TestStringsLength LESS 1)
|
||||
message(FATAL_ERROR "You must provide a valid test name and tags for all tests in ${SourceFile}")
|
||||
endif()
|
||||
|
||||
# Assign name and tags
|
||||
list(GET TestStrings 0 Name)
|
||||
if("${TestType}" STREQUAL "SCENARIO")
|
||||
set(Name "Scenario: ${Name}")
|
||||
endif()
|
||||
if(PARSE_CATCH_TESTS_ADD_FIXTURE_IN_TEST_NAME AND "${TestType}" MATCHES "(CATCH_)?TEST_CASE_METHOD" AND TestFixture )
|
||||
set(CTestName "${TestFixture}:${Name}")
|
||||
else()
|
||||
set(CTestName "${Name}")
|
||||
endif()
|
||||
if(PARSE_CATCH_TESTS_ADD_TARGET_IN_TEST_NAME)
|
||||
set(CTestName "${TestTarget}:${CTestName}")
|
||||
endif()
|
||||
# add target to labels to enable running all tests added from this target
|
||||
set(Labels ${TestTarget})
|
||||
if(TestStringsLength EQUAL 2)
|
||||
list(GET TestStrings 1 Tags)
|
||||
string(TOLOWER "${Tags}" Tags)
|
||||
# remove target from labels if the test is hidden
|
||||
if("${Tags}" MATCHES ".*\\[!?(hide|\\.)\\].*")
|
||||
list(REMOVE_ITEM Labels ${TestTarget})
|
||||
endif()
|
||||
string(REPLACE "]" ";" Tags "${Tags}")
|
||||
string(REPLACE "[" "" Tags "${Tags}")
|
||||
else()
|
||||
# unset tags variable from previous loop
|
||||
unset(Tags)
|
||||
endif()
|
||||
|
||||
list(APPEND Labels ${Tags})
|
||||
|
||||
set(HiddenTagFound OFF)
|
||||
foreach(label ${Labels})
|
||||
string(REGEX MATCH "^!hide|^\\." result ${label})
|
||||
if(result)
|
||||
set(HiddenTagFound ON)
|
||||
break()
|
||||
endif(result)
|
||||
endforeach(label)
|
||||
if(PARSE_CATCH_TESTS_NO_HIDDEN_TESTS AND ${HiddenTagFound} AND ${CMAKE_VERSION} VERSION_LESS "3.9")
|
||||
ParseAndAddCatchTests_PrintDebugMessage("Skipping test \"${CTestName}\" as it has [!hide], [.] or [.foo] label")
|
||||
else()
|
||||
ParseAndAddCatchTests_PrintDebugMessage("Adding test \"${CTestName}\"")
|
||||
if(Labels)
|
||||
ParseAndAddCatchTests_PrintDebugMessage("Setting labels to ${Labels}")
|
||||
endif()
|
||||
|
||||
# Escape commas in the test spec
|
||||
string(REPLACE "," "\\," Name ${Name})
|
||||
|
||||
# Work around CMake 3.18.0 change in `add_test()`, before the escaped quotes were necessary,
|
||||
# only with CMake 3.18.0 the escaped double quotes confuse the call. This change is reverted in 3.18.1
|
||||
# And properly introduced in 3.19 with the CMP0110 policy
|
||||
if(_cmp0110_value STREQUAL "NEW" OR ${CMAKE_VERSION} VERSION_EQUAL "3.18")
|
||||
ParseAndAddCatchTests_PrintDebugMessage("CMP0110 set to NEW, no need for add_test(\"\") workaround")
|
||||
else()
|
||||
ParseAndAddCatchTests_PrintDebugMessage("CMP0110 set to OLD adding \"\" for add_test() workaround")
|
||||
set(CTestName "\"${CTestName}\"")
|
||||
endif()
|
||||
|
||||
# Handle template test cases
|
||||
if("${TestTypeAndFixture}" MATCHES ".*TEMPLATE_.*")
|
||||
set(Name "${Name} - *")
|
||||
endif()
|
||||
|
||||
# Add the test and set its properties
|
||||
add_test(NAME "${CTestName}" COMMAND ${OptionalCatchTestLauncher} $<TARGET_FILE:${TestTarget}> ${Name} ${AdditionalCatchParameters})
|
||||
# Old CMake versions do not document VERSION_GREATER_EQUAL, so we use VERSION_GREATER with 3.8 instead
|
||||
if(PARSE_CATCH_TESTS_NO_HIDDEN_TESTS AND ${HiddenTagFound} AND ${CMAKE_VERSION} VERSION_GREATER "3.8")
|
||||
ParseAndAddCatchTests_PrintDebugMessage("Setting DISABLED test property")
|
||||
set_tests_properties("${CTestName}" PROPERTIES DISABLED ON)
|
||||
else()
|
||||
set_tests_properties("${CTestName}" PROPERTIES FAIL_REGULAR_EXPRESSION "No tests ran"
|
||||
LABELS "${Labels}")
|
||||
endif()
|
||||
set_property(
|
||||
TARGET ${TestTarget}
|
||||
APPEND
|
||||
PROPERTY ParseAndAddCatchTests_TESTS "${CTestName}")
|
||||
set_property(
|
||||
SOURCE ${SourceFile}
|
||||
APPEND
|
||||
PROPERTY ParseAndAddCatchTests_TESTS "${CTestName}")
|
||||
endif()
|
||||
|
||||
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
# entry point
|
||||
function(ParseAndAddCatchTests TestTarget)
|
||||
message(DEPRECATION "ParseAndAddCatchTest: function deprecated because of possibility of missed test cases. Consider using 'catch_discover_tests' from 'Catch.cmake'")
|
||||
ParseAndAddCatchTests_PrintDebugMessage("Started parsing ${TestTarget}")
|
||||
get_target_property(SourceFiles ${TestTarget} SOURCES)
|
||||
ParseAndAddCatchTests_PrintDebugMessage("Found the following sources: ${SourceFiles}")
|
||||
foreach(SourceFile ${SourceFiles})
|
||||
ParseAndAddCatchTests_ParseFile(${SourceFile} ${TestTarget})
|
||||
endforeach()
|
||||
ParseAndAddCatchTests_PrintDebugMessage("Finished parsing ${TestTarget}")
|
||||
endfunction()
|
||||
@@ -0,0 +1,2 @@
|
||||
Catch2 v2.13.10.
|
||||
https://github.com/catchorg/Catch2
|
||||
@@ -0,0 +1,18 @@
|
||||
###############################################################################
|
||||
# License: BSD Zero Clause License file
|
||||
# Copyright:
|
||||
# (C) 2021 Alexander Shaduri <ashaduri@gmail.com>
|
||||
###############################################################################
|
||||
|
||||
add_library(nlohmann_json INTERFACE)
|
||||
|
||||
# Relative sources are allowed only since cmake 3.13.
|
||||
target_sources(nlohmann_json INTERFACE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/nlohmann/json.hpp
|
||||
)
|
||||
|
||||
target_include_directories(nlohmann_json
|
||||
SYSTEM INTERFACE
|
||||
"${CMAKE_SOURCE_DIR}/dependencies/nlohmann_json"
|
||||
)
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
JSON for Modern C++
|
||||
version 3.9.1
|
||||
https://github.com/nlohmann/json
|
||||
@@ -0,0 +1,20 @@
|
||||
###############################################################################
|
||||
# License: BSD Zero Clause License file
|
||||
# Copyright:
|
||||
# (C) 2024 Alexander Shaduri <ashaduri@gmail.com>
|
||||
###############################################################################
|
||||
|
||||
|
||||
add_library(tl_expected INTERFACE)
|
||||
|
||||
# Relative sources are allowed only since cmake 3.13.
|
||||
target_sources(tl_expected INTERFACE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/expected/include/tl/expected.hpp
|
||||
)
|
||||
|
||||
target_include_directories(tl_expected
|
||||
SYSTEM INTERFACE
|
||||
"${CMAKE_SOURCE_DIR}/dependencies/tl_expected/expected/include"
|
||||
)
|
||||
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
os:
|
||||
- Visual Studio 2015
|
||||
- Visual Studio 2017
|
||||
- Visual Studio 2019
|
||||
- Visual Studio 2022
|
||||
|
||||
build_script:
|
||||
- cmake -Bbuild -S.
|
||||
- cmake --build build
|
||||
- cmake --build build --target RUN_TESTS
|
||||
@@ -0,0 +1 @@
|
||||
BasedOnStyle: LLVM
|
||||
@@ -0,0 +1,131 @@
|
||||
name: CMake
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "master" ]
|
||||
pull_request:
|
||||
branches: [ "master" ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-20.04
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
std: [11, 14]
|
||||
cxx: [g++-4.8, g++-4.9, g++-5, g++-6, g++-7, g++-8, g++-9, g++-10, clang++-3.5, clang++-3.6, clang++-3.7, clang++-3.8, clang++-3.9, clang++-4.0, clang++-5.0, clang++-6.0, clang++-7, clang++-8, clang++-9, clang++-10, clang++-11]
|
||||
|
||||
exclude:
|
||||
- cxx: g++-4.8
|
||||
std: 14
|
||||
- cxx: g++4.9
|
||||
std: 14
|
||||
|
||||
include:
|
||||
- cxx: g++-4.8
|
||||
install: sudo apt install g++-4.8
|
||||
- cxx: g++-4.9
|
||||
install: sudo apt install g++-4.9
|
||||
- cxx: g++-5
|
||||
install: sudo apt install g++-5
|
||||
- cxx: g++-6
|
||||
install: sudo apt install g++-6
|
||||
- cxx: g++-7
|
||||
install: sudo apt install g++-7
|
||||
- cxx: g++-8
|
||||
std: 11
|
||||
install: sudo apt install g++-8
|
||||
- cxx: g++-8
|
||||
std: 14
|
||||
install: sudo apt install g++-8
|
||||
- cxx: g++-8
|
||||
std: 17
|
||||
install: sudo apt install g++-8
|
||||
- cxx: g++-9
|
||||
std: 14
|
||||
- cxx: g++-9
|
||||
std: 17
|
||||
- cxx: g++-10
|
||||
std: 14
|
||||
- cxx: g++-10
|
||||
std: 17
|
||||
- cxx: g++-11
|
||||
std: 14
|
||||
install: sudo apt install g++-11
|
||||
- cxx: g++-11
|
||||
std: 17
|
||||
install: sudo apt install g++-11
|
||||
- cxx: g++-11
|
||||
std: 20
|
||||
install: sudo apt install g++-11
|
||||
|
||||
|
||||
- cxx: clang++-3.5
|
||||
install: sudo apt install clang-3.5
|
||||
- cxx: clang++-3.6
|
||||
install: sudo apt install clang-3.6
|
||||
- cxx: clang++-3.7
|
||||
install: sudo apt install clang-3.7
|
||||
- cxx: clang++-3.8
|
||||
install: sudo apt install clang-3.8
|
||||
- cxx: clang++-3.9
|
||||
install: sudo apt install clang-3.9
|
||||
- cxx: clang++-4.0
|
||||
install: sudo apt install clang-4.0
|
||||
- cxx: clang++-5.0
|
||||
install: sudo apt install clang-5.0
|
||||
- cxx: clang++-6.0
|
||||
install: sudo apt install clang-6.0
|
||||
- cxx: clang++-7
|
||||
install: sudo apt install clang-7
|
||||
- cxx: clang++-8
|
||||
install: sudo apt install clang-8
|
||||
- cxx: clang++-9
|
||||
install: sudo apt install clang-9
|
||||
- cxx: clang++-10
|
||||
install: sudo apt install clang-10
|
||||
- cxx: clang++-11
|
||||
install: sudo apt install clang-11
|
||||
|
||||
|
||||
- cxx: clang++-6.0
|
||||
std: 17
|
||||
install: sudo apt install clang-6.0
|
||||
- cxx: clang++-7
|
||||
std: 17
|
||||
install: sudo apt install clang-7
|
||||
- cxx: clang++-8
|
||||
std: 17
|
||||
install: sudo apt install clang-8
|
||||
- cxx: clang++-9
|
||||
std: 17
|
||||
install: sudo apt install clang-9
|
||||
- cxx: clang++-10
|
||||
std: 17
|
||||
install: sudo apt install clang-10
|
||||
- cxx: clang++-11
|
||||
std: 17
|
||||
install: sudo apt install clang-11
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Toolchain
|
||||
run: |
|
||||
sudo apt-add-repository 'deb http://azure.archive.ubuntu.com/ubuntu/ xenial main'
|
||||
sudo apt-add-repository 'deb http://azure.archive.ubuntu.com/ubuntu/ xenial universe'
|
||||
sudo apt-add-repository 'deb http://azure.archive.ubuntu.com/ubuntu/ bionic main'
|
||||
sudo apt-add-repository 'deb http://azure.archive.ubuntu.com/ubuntu/ bionic universe'
|
||||
${{matrix.install}}
|
||||
|
||||
- name: Configure CMake
|
||||
env:
|
||||
CXX: ${{matrix.cxx}}
|
||||
run: cmake -B ${{github.workspace}}/build -DCMAKE_CXX_STANDARD=${{matrix.std}}
|
||||
|
||||
- name: Build
|
||||
run: cmake --build ${{github.workspace}}/build
|
||||
|
||||
- name: Test
|
||||
working-directory: ${{github.workspace}}/build
|
||||
run: cmake --build ${{github.workspace}}/build --target test
|
||||
@@ -0,0 +1,3 @@
|
||||
\#*
|
||||
.\#*
|
||||
/build/
|
||||
@@ -0,0 +1,268 @@
|
||||
language: cpp
|
||||
|
||||
dist: xenial
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- g++-5
|
||||
env: COMPILER=g++-5 CXXSTD=11
|
||||
- compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- g++-6
|
||||
env: COMPILER=g++-6 CXXSTD=11
|
||||
- compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- g++-7
|
||||
env: COMPILER=g++-7 CXXSTD=11
|
||||
- compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- g++-8
|
||||
env: COMPILER=g++-8 CXXSTD=11
|
||||
- compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- g++-4.9
|
||||
env: COMPILER=g++-4.9 CXXSTD=11
|
||||
- compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- g++-4.8
|
||||
env: COMPILER=g++-4.8 CXXSTD=11
|
||||
- compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- llvm-toolchain-precise-3.5
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- clang++-3.5
|
||||
- libc++-dev
|
||||
env: COMPILER=clang++-3.5 CXXSTD=11
|
||||
- compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- llvm-toolchain-precise-3.6
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- clang++-3.6
|
||||
- libc++-dev
|
||||
env: COMPILER=clang++-3.6 CXXSTD=11
|
||||
- compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- llvm-toolchain-precise-3.7
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- clang++-3.7
|
||||
- libc++-dev
|
||||
env: COMPILER=clang++-3.7 CXXSTD=11
|
||||
- compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- sourceline: "deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-3.8 main"
|
||||
key_url: "http://apt.llvm.org/llvm-snapshot.gpg.key"
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- clang++-3.8
|
||||
- libc++-dev
|
||||
env: COMPILER=clang++-3.8 CXXSTD=11
|
||||
- compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- sourceline: "deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-3.9 main"
|
||||
key_url: "http://apt.llvm.org/llvm-snapshot.gpg.key"
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- clang++-3.9
|
||||
- libc++-dev
|
||||
env: COMPILER=clang++-3.9 CXXSTD=11
|
||||
- compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- llvm-toolchain-xenial-4.0
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- clang++-4.0
|
||||
- libc++-dev
|
||||
env: COMPILER=clang++-4.0 CXXSTD=11
|
||||
- compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- llvm-toolchain-xenial-5.0
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- clang++-5.0
|
||||
- libc++-dev
|
||||
env: COMPILER=clang++-5.0 CXXSTD=11
|
||||
- compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- llvm-toolchain-xenial-6.0
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- clang++-6.0
|
||||
- libc++-dev
|
||||
env: COMPILER=clang++-6.0 CXXSTD=11
|
||||
|
||||
- compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- g++-5
|
||||
env: COMPILER=g++-5 CXXSTD=14
|
||||
- compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- g++-6
|
||||
env: COMPILER=g++-6 CXXSTD=14
|
||||
- compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- g++-7
|
||||
env: COMPILER=g++-7 CXXSTD=14
|
||||
- compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- g++-8
|
||||
env: COMPILER=g++-8 CXXSTD=14
|
||||
- compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- llvm-toolchain-precise-3.5
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- clang++-3.5
|
||||
- libc++-dev
|
||||
env: COMPILER=clang++-3.5 CXXSTD=14
|
||||
- compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- llvm-toolchain-precise-3.6
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- clang++-3.6
|
||||
- libc++-dev
|
||||
env: COMPILER=clang++-3.6 CXXSTD=14
|
||||
- compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- llvm-toolchain-precise-3.7
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- clang++-3.7
|
||||
- libc++-dev
|
||||
env: COMPILER=clang++-3.7 CXXSTD=14
|
||||
- compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- sourceline: "deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-3.8 main"
|
||||
key_url: "http://apt.llvm.org/llvm-snapshot.gpg.key"
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- clang++-3.8
|
||||
- libc++-dev
|
||||
env: COMPILER=clang++-3.8 CXXSTD=14
|
||||
- compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- sourceline: "deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-3.9 main"
|
||||
key_url: "http://apt.llvm.org/llvm-snapshot.gpg.key"
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- clang++-3.9
|
||||
- libc++-dev
|
||||
env: COMPILER=clang++-3.9 CXXSTD=14
|
||||
- compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- llvm-toolchain-xenial-4.0
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- clang++-4.0
|
||||
- libc++-dev
|
||||
env: COMPILER=clang++-4.0 CXXSTD=14
|
||||
- compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- llvm-toolchain-xenial-5.0
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- clang++-5.0
|
||||
- libc++-dev
|
||||
env: COMPILER=clang++-5.0 CXXSTD=14
|
||||
- compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- llvm-toolchain-xenial-6.0
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- clang++-6.0
|
||||
- libc++-dev
|
||||
env: COMPILER=clang++-6.0 CXXSTD=14
|
||||
|
||||
before_install:
|
||||
- sudo apt update
|
||||
- sudo apt install -y apt-transport-https ca-certificates gnupg software-properties-common
|
||||
- curl -L https://apt.kitware.com/keys/kitware-archive-latest.asc | sudo apt-key add -
|
||||
- sudo apt-add-repository 'deb https://apt.kitware.com/ubuntu/ xenial main'
|
||||
- sudo apt update
|
||||
|
||||
install:
|
||||
- if [ "$CXX" = "clang++" ]; then export CXX="$COMPILER -stdlib=libc++"; fi
|
||||
- if [ "$CXX" = "g++" ]; then export CXX="$COMPILER"; fi
|
||||
- sudo apt install -y cmake
|
||||
|
||||
script:
|
||||
- /usr/bin/cmake -B build -S . "-DCMAKE_CXX_STANDARD=$CXXSTD"
|
||||
- /usr/bin/cmake --build build
|
||||
- /usr/bin/cmake --build build --target test
|
||||
@@ -0,0 +1,117 @@
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
project(tl-expected
|
||||
HOMEPAGE_URL https://tl.tartanllama.xyz
|
||||
DESCRIPTION "C++11/14/17 std::expected with functional-style extensions"
|
||||
VERSION 1.0.0
|
||||
LANGUAGES CXX)
|
||||
|
||||
include(CMakePackageConfigHelpers)
|
||||
include(CMakeDependentOption)
|
||||
include(GNUInstallDirs)
|
||||
include(FetchContent)
|
||||
include(CTest)
|
||||
|
||||
if (NOT DEFINED CMAKE_CXX_STANDARD)
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
endif()
|
||||
|
||||
option(EXPECTED_BUILD_PACKAGE "Build package files as well" ON)
|
||||
|
||||
cmake_dependent_option(EXPECTED_BUILD_TESTS
|
||||
"Enable tl::expected tests" ON
|
||||
"BUILD_TESTING" OFF)
|
||||
|
||||
cmake_dependent_option(EXPECTED_BUILD_PACKAGE_DEB
|
||||
"Create a DEB" ON
|
||||
"EXPECTED_BUILD_PACKAGE" OFF)
|
||||
|
||||
add_library(expected INTERFACE)
|
||||
target_include_directories(expected
|
||||
INTERFACE
|
||||
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
|
||||
$<INSTALL_INTERFACE:include>)
|
||||
|
||||
if (NOT CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
|
||||
add_library(tl::expected ALIAS expected)
|
||||
endif()
|
||||
|
||||
# Installation help
|
||||
configure_package_config_file(
|
||||
"${PROJECT_SOURCE_DIR}/cmake/${PROJECT_NAME}-config.cmake.in"
|
||||
"${PROJECT_BINARY_DIR}/${PROJECT_NAME}-config.cmake"
|
||||
INSTALL_DESTINATION "share/cmake/${PROJECT_NAME}")
|
||||
|
||||
write_basic_package_version_file(
|
||||
"${PROJECT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake"
|
||||
COMPATIBILITY SameMajorVersion
|
||||
ARCH_INDEPENDENT)
|
||||
|
||||
install(TARGETS expected
|
||||
EXPORT ${PROJECT_NAME}-targets
|
||||
INCLUDES DESTINATION "${CMAKE_INSTALL_DATADIR}")
|
||||
|
||||
install(EXPORT ${PROJECT_NAME}-targets
|
||||
DESTINATION "${CMAKE_INSTALL_DATADIR}/cmake/${PROJECT_NAME}"
|
||||
NAMESPACE tl::
|
||||
FILE "${PROJECT_NAME}-targets.cmake")
|
||||
|
||||
install(FILES
|
||||
"${PROJECT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake"
|
||||
"${PROJECT_BINARY_DIR}/${PROJECT_NAME}-config.cmake"
|
||||
DESTINATION "${CMAKE_INSTALL_DATADIR}/cmake/${PROJECT_NAME}")
|
||||
|
||||
install(DIRECTORY "include/" TYPE INCLUDE)
|
||||
|
||||
if(EXPECTED_BUILD_TESTS)
|
||||
set(CMAKE_POLICY_DEFAULT_CMP0077 NEW)
|
||||
set(CATCH_INSTALL_HELPERS OFF)
|
||||
set(CATCH_BUILD_TESTING OFF)
|
||||
set(CATCH_INSTALL_DOCS OFF)
|
||||
FetchContent_Declare(Catch2 URL
|
||||
https://github.com/catchorg/Catch2/archive/v2.13.10.zip)
|
||||
FetchContent_MakeAvailable(Catch2)
|
||||
|
||||
file(GLOB test-sources CONFIGURE_DEPENDS tests/*.cpp)
|
||||
list(FILTER test-sources EXCLUDE REGEX "tests/test.cpp")
|
||||
add_executable(${PROJECT_NAME}-tests "${test-sources}")
|
||||
target_compile_options(${PROJECT_NAME}-tests PRIVATE
|
||||
$<$<NOT:$<CXX_COMPILER_ID:MSVC>>:-Wall -Wextra>)
|
||||
|
||||
target_link_libraries(${PROJECT_NAME}-tests
|
||||
PRIVATE
|
||||
Catch2::Catch2
|
||||
expected)
|
||||
add_test(NAME tl::expected::tests COMMAND ${PROJECT_NAME}-tests)
|
||||
endif()
|
||||
|
||||
if (NOT EXPECTED_BUILD_PACKAGE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
list(APPEND source-generators TBZ2 TGZ TXZ ZIP)
|
||||
|
||||
if (CMAKE_HOST_WIN32)
|
||||
list(APPEND binary-generators "WIX")
|
||||
endif()
|
||||
|
||||
if (EXPECTED_BUILD_PACKAGE_DEB)
|
||||
list(APPEND binary-generators "DEB")
|
||||
endif()
|
||||
|
||||
if (EXPECTED_BUILD_RPM)
|
||||
list(APPEND binary-generators "RPM")
|
||||
endif()
|
||||
|
||||
|
||||
set(CPACK_SOURCE_GENERATOR ${source-generators})
|
||||
set(CPACK_GENERATOR ${binary-generators})
|
||||
|
||||
set(CPACK_PACKAGE_FILE_NAME "${PROJECT_NAME}-${PROJECT_VERSION}")
|
||||
set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}")
|
||||
|
||||
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Sy Brand")
|
||||
|
||||
list(APPEND CPACK_SOURCE_IGNORE_FILES /.git/ /build/ .gitignore .DS_Store)
|
||||
|
||||
include(CPack)
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
Creative Commons Legal Code
|
||||
|
||||
CC0 1.0 Universal
|
||||
|
||||
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
|
||||
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
|
||||
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
|
||||
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
|
||||
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
|
||||
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
|
||||
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
|
||||
HEREUNDER.
|
||||
|
||||
Statement of Purpose
|
||||
|
||||
The laws of most jurisdictions throughout the world automatically confer
|
||||
exclusive Copyright and Related Rights (defined below) upon the creator
|
||||
and subsequent owner(s) (each and all, an "owner") of an original work of
|
||||
authorship and/or a database (each, a "Work").
|
||||
|
||||
Certain owners wish to permanently relinquish those rights to a Work for
|
||||
the purpose of contributing to a commons of creative, cultural and
|
||||
scientific works ("Commons") that the public can reliably and without fear
|
||||
of later claims of infringement build upon, modify, incorporate in other
|
||||
works, reuse and redistribute as freely as possible in any form whatsoever
|
||||
and for any purposes, including without limitation commercial purposes.
|
||||
These owners may contribute to the Commons to promote the ideal of a free
|
||||
culture and the further production of creative, cultural and scientific
|
||||
works, or to gain reputation or greater distribution for their Work in
|
||||
part through the use and efforts of others.
|
||||
|
||||
For these and/or other purposes and motivations, and without any
|
||||
expectation of additional consideration or compensation, the person
|
||||
associating CC0 with a Work (the "Affirmer"), to the extent that he or she
|
||||
is an owner of Copyright and Related Rights in the Work, voluntarily
|
||||
elects to apply CC0 to the Work and publicly distribute the Work under its
|
||||
terms, with knowledge of his or her Copyright and Related Rights in the
|
||||
Work and the meaning and intended legal effect of CC0 on those rights.
|
||||
|
||||
1. Copyright and Related Rights. A Work made available under CC0 may be
|
||||
protected by copyright and related or neighboring rights ("Copyright and
|
||||
Related Rights"). Copyright and Related Rights include, but are not
|
||||
limited to, the following:
|
||||
|
||||
i. the right to reproduce, adapt, distribute, perform, display,
|
||||
communicate, and translate a Work;
|
||||
ii. moral rights retained by the original author(s) and/or performer(s);
|
||||
iii. publicity and privacy rights pertaining to a person's image or
|
||||
likeness depicted in a Work;
|
||||
iv. rights protecting against unfair competition in regards to a Work,
|
||||
subject to the limitations in paragraph 4(a), below;
|
||||
v. rights protecting the extraction, dissemination, use and reuse of data
|
||||
in a Work;
|
||||
vi. database rights (such as those arising under Directive 96/9/EC of the
|
||||
European Parliament and of the Council of 11 March 1996 on the legal
|
||||
protection of databases, and under any national implementation
|
||||
thereof, including any amended or successor version of such
|
||||
directive); and
|
||||
vii. other similar, equivalent or corresponding rights throughout the
|
||||
world based on applicable law or treaty, and any national
|
||||
implementations thereof.
|
||||
|
||||
2. Waiver. To the greatest extent permitted by, but not in contravention
|
||||
of, applicable law, Affirmer hereby overtly, fully, permanently,
|
||||
irrevocably and unconditionally waives, abandons, and surrenders all of
|
||||
Affirmer's Copyright and Related Rights and associated claims and causes
|
||||
of action, whether now known or unknown (including existing as well as
|
||||
future claims and causes of action), in the Work (i) in all territories
|
||||
worldwide, (ii) for the maximum duration provided by applicable law or
|
||||
treaty (including future time extensions), (iii) in any current or future
|
||||
medium and for any number of copies, and (iv) for any purpose whatsoever,
|
||||
including without limitation commercial, advertising or promotional
|
||||
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
|
||||
member of the public at large and to the detriment of Affirmer's heirs and
|
||||
successors, fully intending that such Waiver shall not be subject to
|
||||
revocation, rescission, cancellation, termination, or any other legal or
|
||||
equitable action to disrupt the quiet enjoyment of the Work by the public
|
||||
as contemplated by Affirmer's express Statement of Purpose.
|
||||
|
||||
3. Public License Fallback. Should any part of the Waiver for any reason
|
||||
be judged legally invalid or ineffective under applicable law, then the
|
||||
Waiver shall be preserved to the maximum extent permitted taking into
|
||||
account Affirmer's express Statement of Purpose. In addition, to the
|
||||
extent the Waiver is so judged Affirmer hereby grants to each affected
|
||||
person a royalty-free, non transferable, non sublicensable, non exclusive,
|
||||
irrevocable and unconditional license to exercise Affirmer's Copyright and
|
||||
Related Rights in the Work (i) in all territories worldwide, (ii) for the
|
||||
maximum duration provided by applicable law or treaty (including future
|
||||
time extensions), (iii) in any current or future medium and for any number
|
||||
of copies, and (iv) for any purpose whatsoever, including without
|
||||
limitation commercial, advertising or promotional purposes (the
|
||||
"License"). The License shall be deemed effective as of the date CC0 was
|
||||
applied by Affirmer to the Work. Should any part of the License for any
|
||||
reason be judged legally invalid or ineffective under applicable law, such
|
||||
partial invalidity or ineffectiveness shall not invalidate the remainder
|
||||
of the License, and in such case Affirmer hereby affirms that he or she
|
||||
will not (i) exercise any of his or her remaining Copyright and Related
|
||||
Rights in the Work or (ii) assert any associated claims and causes of
|
||||
action with respect to the Work, in either case contrary to Affirmer's
|
||||
express Statement of Purpose.
|
||||
|
||||
4. Limitations and Disclaimers.
|
||||
|
||||
a. No trademark or patent rights held by Affirmer are waived, abandoned,
|
||||
surrendered, licensed or otherwise affected by this document.
|
||||
b. Affirmer offers the Work as-is and makes no representations or
|
||||
warranties of any kind concerning the Work, express, implied,
|
||||
statutory or otherwise, including without limitation warranties of
|
||||
title, merchantability, fitness for a particular purpose, non
|
||||
infringement, or the absence of latent or other defects, accuracy, or
|
||||
the present or absence of errors, whether or not discoverable, all to
|
||||
the greatest extent permissible under applicable law.
|
||||
c. Affirmer disclaims responsibility for clearing rights of other persons
|
||||
that may apply to the Work or any use thereof, including without
|
||||
limitation any person's Copyright and Related Rights in the Work.
|
||||
Further, Affirmer disclaims responsibility for obtaining any necessary
|
||||
consents, permissions or other rights required for any use of the
|
||||
Work.
|
||||
d. Affirmer understands and acknowledges that Creative Commons is not a
|
||||
party to this document and has no duty or obligation with respect to
|
||||
this CC0 or use of the Work.
|
||||
@@ -0,0 +1,76 @@
|
||||
# expected
|
||||
Single header implementation of `std::expected` with functional-style extensions.
|
||||
|
||||
[](https://tl.tartanllama.xyz/en/latest/?badge=latest)
|
||||
Clang + GCC: [](https://github.com/TartanLlama/expected/actions/workflows/cmake.yml)
|
||||
MSVC: [](https://ci.appveyor.com/project/TartanLlama/expected)
|
||||
|
||||
Available on [Vcpkg](https://github.com/microsoft/vcpkg/tree/master/ports/tl-expected) and [Conan](https://github.com/yipdw/conan-tl-expected).
|
||||
|
||||
[`std::expected`](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0323r3.pdf) is proposed as the preferred way to represent object which will either have an expected value, or an unexpected value giving information about why something failed. Unfortunately, chaining together many computations which may fail can be verbose, as error-checking code will be mixed in with the actual programming logic. This implementation provides a number of utilities to make coding with `expected` cleaner.
|
||||
|
||||
For example, instead of writing this code:
|
||||
|
||||
```cpp
|
||||
std::expected<image,fail_reason> get_cute_cat (const image& img) {
|
||||
auto cropped = crop_to_cat(img);
|
||||
if (!cropped) {
|
||||
return cropped;
|
||||
}
|
||||
|
||||
auto with_tie = add_bow_tie(*cropped);
|
||||
if (!with_tie) {
|
||||
return with_tie;
|
||||
}
|
||||
|
||||
auto with_sparkles = make_eyes_sparkle(*with_tie);
|
||||
if (!with_sparkles) {
|
||||
return with_sparkles;
|
||||
}
|
||||
|
||||
return add_rainbow(make_smaller(*with_sparkles));
|
||||
}
|
||||
```
|
||||
|
||||
You can do this:
|
||||
|
||||
```cpp
|
||||
tl::expected<image,fail_reason> get_cute_cat (const image& img) {
|
||||
return crop_to_cat(img)
|
||||
.and_then(add_bow_tie)
|
||||
.and_then(make_eyes_sparkle)
|
||||
.map(make_smaller)
|
||||
.map(add_rainbow);
|
||||
}
|
||||
```
|
||||
|
||||
The interface is the same as `std::expected` as proposed in [p0323r3](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0323r3.pdf), but the following member functions are also defined. Explicit types are for clarity.
|
||||
|
||||
- `map`: carries out some operation on the stored object if there is one.
|
||||
* `tl::expected<std::size_t,std::error_code> s = exp_string.map(&std::string::size);`
|
||||
- `map_error`: carries out some operation on the unexpected object if there is one.
|
||||
* `my_error_code translate_error (std::error_code);`
|
||||
* `tl::expected<int,my_error_code> s = exp_int.map_error(translate_error);`
|
||||
- `and_then`: like `map`, but for operations which return a `tl::expected`.
|
||||
* `tl::expected<ast, fail_reason> parse (const std::string& s);`
|
||||
* `tl::expected<ast, fail_reason> exp_ast = exp_string.and_then(parse);`
|
||||
- `or_else`: calls some function if there is no value stored.
|
||||
* `exp.or_else([] { throw std::runtime_error{"oh no"}; });`
|
||||
|
||||
p0323r3 specifies calling `.error()` on an expected value, or using the `*` or `->` operators on an unexpected value, to be undefined behaviour. In this implementation it causes an assertion failure. The implementation of assertions can be overridden by defining the macro `TL_ASSERT(boolean_condition)` before #including <tl/expected.hpp>; by default, `assert(boolean_condition)` from the `<cassert>` header is used. Note that correct code would not rely on these assertions.
|
||||
|
||||
### Compiler support
|
||||
|
||||
Tested on:
|
||||
|
||||
- Linux
|
||||
* clang++ 3.5, 3.6, 3.7, 3.8, 3.9, 4, 5, 6, 7, 8, 9, 10, 11
|
||||
* g++ 4.8, 4.9, 5.5, 6.4, 7.5, 8, 9, 10
|
||||
- Windows
|
||||
* MSVC 2015, 2017, 2019, 2022
|
||||
|
||||
----------
|
||||
|
||||
[]("http://creativecommons.org/publicdomain/zero/1.0/")
|
||||
|
||||
To the extent possible under law, [Sy Brand](https://twitter.com/TartanLlama) has waived all copyright and related or neighboring rights to the `expected` library. This work is published from: United Kingdom.
|
||||
@@ -0,0 +1,3 @@
|
||||
@PACKAGE_INIT@
|
||||
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/tl-expected-targets.cmake")
|
||||
@@ -0,0 +1,18 @@
|
||||
#include <catch2/catch.hpp>
|
||||
#include <stdexcept>
|
||||
|
||||
#define TL_ASSERT(cond) if (!(cond)) { throw std::runtime_error(std::string("assertion failure")); }
|
||||
|
||||
#include <tl/expected.hpp>
|
||||
|
||||
TEST_CASE("Assertions", "[assertions]") {
|
||||
tl::expected<int,int> o1 = 42;
|
||||
REQUIRE_THROWS_WITH(o1.error(), "assertion failure");
|
||||
|
||||
tl::expected<int,int> o2 {tl::unexpect, 0};
|
||||
REQUIRE_THROWS_WITH(*o2, "assertion failure");
|
||||
|
||||
struct foo { int bar; };
|
||||
tl::expected<struct foo,int> o3 {tl::unexpect, 0};
|
||||
REQUIRE_THROWS_WITH(o3->bar, "assertion failure");
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
#include <catch2/catch.hpp>
|
||||
#include <tl/expected.hpp>
|
||||
|
||||
TEST_CASE("Simple assignment", "[assignment.simple]") {
|
||||
tl::expected<int, int> e1 = 42;
|
||||
tl::expected<int, int> e2 = 17;
|
||||
tl::expected<int, int> e3 = 21;
|
||||
tl::expected<int, int> e4 = tl::make_unexpected(42);
|
||||
tl::expected<int, int> e5 = tl::make_unexpected(17);
|
||||
tl::expected<int, int> e6 = tl::make_unexpected(21);
|
||||
|
||||
e1 = e2;
|
||||
REQUIRE(e1);
|
||||
REQUIRE(*e1 == 17);
|
||||
REQUIRE(e2);
|
||||
REQUIRE(*e2 == 17);
|
||||
|
||||
e1 = std::move(e2);
|
||||
REQUIRE(e1);
|
||||
REQUIRE(*e1 == 17);
|
||||
REQUIRE(e2);
|
||||
REQUIRE(*e2 == 17);
|
||||
|
||||
e1 = 42;
|
||||
REQUIRE(e1);
|
||||
REQUIRE(*e1 == 42);
|
||||
|
||||
auto unex = tl::make_unexpected(12);
|
||||
e1 = unex;
|
||||
REQUIRE(!e1);
|
||||
REQUIRE(e1.error() == 12);
|
||||
|
||||
e1 = tl::make_unexpected(42);
|
||||
REQUIRE(!e1);
|
||||
REQUIRE(e1.error() == 42);
|
||||
|
||||
e1 = e3;
|
||||
REQUIRE(e1);
|
||||
REQUIRE(*e1 == 21);
|
||||
|
||||
e4 = e5;
|
||||
REQUIRE(!e4);
|
||||
REQUIRE(e4.error() == 17);
|
||||
|
||||
e4 = std::move(e6);
|
||||
REQUIRE(!e4);
|
||||
REQUIRE(e4.error() == 21);
|
||||
|
||||
e4 = e1;
|
||||
REQUIRE(e4);
|
||||
REQUIRE(*e4 == 21);
|
||||
}
|
||||
|
||||
TEST_CASE("Assignment deletion", "[assignment.deletion]") {
|
||||
struct has_all {
|
||||
has_all() = default;
|
||||
has_all(const has_all &) = default;
|
||||
has_all(has_all &&) noexcept = default;
|
||||
has_all &operator=(const has_all &) = default;
|
||||
};
|
||||
|
||||
tl::expected<has_all, has_all> e1 = {};
|
||||
tl::expected<has_all, has_all> e2 = {};
|
||||
e1 = e2;
|
||||
|
||||
struct except_move {
|
||||
except_move() = default;
|
||||
except_move(const except_move &) = default;
|
||||
except_move(except_move &&) noexcept(false){};
|
||||
except_move &operator=(const except_move &) = default;
|
||||
};
|
||||
tl::expected<except_move, except_move> e3 = {};
|
||||
tl::expected<except_move, except_move> e4 = {};
|
||||
// e3 = e4; should not compile
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
#include <catch2/catch.hpp>
|
||||
#include <tl/expected.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
// Old versions of GCC don't have the correct trait names. Could fix them up if needs be.
|
||||
#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 && \
|
||||
!defined(__clang__))
|
||||
// nothing for now
|
||||
#else
|
||||
TEST_CASE("Triviality", "[bases.triviality]") {
|
||||
REQUIRE(std::is_trivially_copy_constructible<tl::expected<int,int>>::value);
|
||||
REQUIRE(std::is_trivially_copy_assignable<tl::expected<int,int>>::value);
|
||||
REQUIRE(std::is_trivially_move_constructible<tl::expected<int,int>>::value);
|
||||
REQUIRE(std::is_trivially_move_assignable<tl::expected<int,int>>::value);
|
||||
REQUIRE(std::is_trivially_destructible<tl::expected<int,int>>::value);
|
||||
|
||||
REQUIRE(std::is_trivially_copy_constructible<tl::expected<void,int>>::value);
|
||||
REQUIRE(std::is_trivially_move_constructible<tl::expected<void,int>>::value);
|
||||
REQUIRE(std::is_trivially_destructible<tl::expected<void,int>>::value);
|
||||
|
||||
|
||||
{
|
||||
struct T {
|
||||
T(const T&) = default;
|
||||
T(T&&) = default;
|
||||
T& operator=(const T&) = default;
|
||||
T& operator=(T&&) = default;
|
||||
~T() = default;
|
||||
};
|
||||
REQUIRE(std::is_trivially_copy_constructible<tl::expected<T,int>>::value);
|
||||
REQUIRE(std::is_trivially_copy_assignable<tl::expected<T,int>>::value);
|
||||
REQUIRE(std::is_trivially_move_constructible<tl::expected<T,int>>::value);
|
||||
REQUIRE(std::is_trivially_move_assignable<tl::expected<T,int>>::value);
|
||||
REQUIRE(std::is_trivially_destructible<tl::expected<T,int>>::value);
|
||||
}
|
||||
|
||||
{
|
||||
struct T {
|
||||
T(const T&){}
|
||||
T(T&&) {}
|
||||
T& operator=(const T&) { return *this; }
|
||||
T& operator=(T&&) { return *this; }
|
||||
~T(){}
|
||||
};
|
||||
REQUIRE(!std::is_trivially_copy_constructible<tl::expected<T,int>>::value);
|
||||
REQUIRE(!std::is_trivially_copy_assignable<tl::expected<T,int>>::value);
|
||||
REQUIRE(!std::is_trivially_move_constructible<tl::expected<T,int>>::value);
|
||||
REQUIRE(!std::is_trivially_move_assignable<tl::expected<T,int>>::value);
|
||||
REQUIRE(!std::is_trivially_destructible<tl::expected<T,int>>::value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
TEST_CASE("Deletion", "[bases.deletion]") {
|
||||
REQUIRE(std::is_copy_constructible<tl::expected<int,int>>::value);
|
||||
REQUIRE(std::is_copy_assignable<tl::expected<int,int>>::value);
|
||||
REQUIRE(std::is_move_constructible<tl::expected<int,int>>::value);
|
||||
REQUIRE(std::is_move_assignable<tl::expected<int,int>>::value);
|
||||
REQUIRE(std::is_destructible<tl::expected<int,int>>::value);
|
||||
|
||||
{
|
||||
struct T {
|
||||
T()=default;
|
||||
};
|
||||
REQUIRE(std::is_default_constructible<tl::expected<T,int>>::value);
|
||||
}
|
||||
|
||||
{
|
||||
struct T {
|
||||
T(int){}
|
||||
};
|
||||
REQUIRE(!std::is_default_constructible<tl::expected<T,int>>::value);
|
||||
}
|
||||
|
||||
{
|
||||
struct T {
|
||||
T(const T&) = default;
|
||||
T(T&&) = default;
|
||||
T& operator=(const T&) = default;
|
||||
T& operator=(T&&) = default;
|
||||
~T() = default;
|
||||
};
|
||||
REQUIRE(std::is_copy_constructible<tl::expected<T,int>>::value);
|
||||
REQUIRE(std::is_copy_assignable<tl::expected<T,int>>::value);
|
||||
REQUIRE(std::is_move_constructible<tl::expected<T,int>>::value);
|
||||
REQUIRE(std::is_move_assignable<tl::expected<T,int>>::value);
|
||||
REQUIRE(std::is_destructible<tl::expected<T,int>>::value);
|
||||
}
|
||||
|
||||
{
|
||||
struct T {
|
||||
T(const T&)=delete;
|
||||
T(T&&)=delete;
|
||||
T& operator=(const T&)=delete;
|
||||
T& operator=(T&&)=delete;
|
||||
};
|
||||
REQUIRE(!std::is_copy_constructible<tl::expected<T,int>>::value);
|
||||
REQUIRE(!std::is_copy_assignable<tl::expected<T,int>>::value);
|
||||
REQUIRE(!std::is_move_constructible<tl::expected<T,int>>::value);
|
||||
REQUIRE(!std::is_move_assignable<tl::expected<T,int>>::value);
|
||||
}
|
||||
|
||||
{
|
||||
struct T {
|
||||
T(const T&)=delete;
|
||||
T(T&&)=default;
|
||||
T& operator=(const T&)=delete;
|
||||
T& operator=(T&&)=default;
|
||||
};
|
||||
REQUIRE(!std::is_copy_constructible<tl::expected<T,int>>::value);
|
||||
REQUIRE(!std::is_copy_assignable<tl::expected<T,int>>::value);
|
||||
REQUIRE(std::is_move_constructible<tl::expected<T,int>>::value);
|
||||
REQUIRE(std::is_move_assignable<tl::expected<T,int>>::value);
|
||||
}
|
||||
|
||||
{
|
||||
struct T {
|
||||
T(const T&)=default;
|
||||
T(T&&)=delete;
|
||||
T& operator=(const T&)=default;
|
||||
T& operator=(T&&)=delete;
|
||||
};
|
||||
REQUIRE(std::is_copy_constructible<tl::expected<T,int>>::value);
|
||||
REQUIRE(std::is_copy_assignable<tl::expected<T,int>>::value);
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<int, int> e;
|
||||
REQUIRE(std::is_default_constructible<decltype(e)>::value);
|
||||
REQUIRE(std::is_copy_constructible<decltype(e)>::value);
|
||||
REQUIRE(std::is_move_constructible<decltype(e)>::value);
|
||||
REQUIRE(std::is_copy_assignable<decltype(e)>::value);
|
||||
REQUIRE(std::is_move_assignable<decltype(e)>::value);
|
||||
REQUIRE(TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(decltype(e))::value);
|
||||
REQUIRE(TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(decltype(e))::value);
|
||||
# if !defined(TL_EXPECTED_GCC49)
|
||||
REQUIRE(std::is_trivially_move_constructible<decltype(e)>::value);
|
||||
REQUIRE(std::is_trivially_move_assignable<decltype(e)>::value);
|
||||
# endif
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<int, std::string> e;
|
||||
REQUIRE(std::is_default_constructible<decltype(e)>::value);
|
||||
REQUIRE(std::is_copy_constructible<decltype(e)>::value);
|
||||
REQUIRE(std::is_move_constructible<decltype(e)>::value);
|
||||
REQUIRE(std::is_copy_assignable<decltype(e)>::value);
|
||||
REQUIRE(std::is_move_assignable<decltype(e)>::value);
|
||||
REQUIRE(!TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(decltype(e))::value);
|
||||
REQUIRE(!TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(decltype(e))::value);
|
||||
# if !defined(TL_EXPECTED_GCC49)
|
||||
REQUIRE(!std::is_trivially_move_constructible<decltype(e)>::value);
|
||||
REQUIRE(!std::is_trivially_move_assignable<decltype(e)>::value);
|
||||
# endif
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<std::string, int> e;
|
||||
REQUIRE(std::is_default_constructible<decltype(e)>::value);
|
||||
REQUIRE(std::is_copy_constructible<decltype(e)>::value);
|
||||
REQUIRE(std::is_move_constructible<decltype(e)>::value);
|
||||
REQUIRE(std::is_copy_assignable<decltype(e)>::value);
|
||||
REQUIRE(std::is_move_assignable<decltype(e)>::value);
|
||||
REQUIRE(!TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(decltype(e))::value);
|
||||
REQUIRE(!TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(decltype(e))::value);
|
||||
# if !defined(TL_EXPECTED_GCC49)
|
||||
REQUIRE(!std::is_trivially_move_constructible<decltype(e)>::value);
|
||||
REQUIRE(!std::is_trivially_move_assignable<decltype(e)>::value);
|
||||
# endif
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<std::string, std::string> e;
|
||||
REQUIRE(std::is_default_constructible<decltype(e)>::value);
|
||||
REQUIRE(std::is_copy_constructible<decltype(e)>::value);
|
||||
REQUIRE(std::is_move_constructible<decltype(e)>::value);
|
||||
REQUIRE(std::is_copy_assignable<decltype(e)>::value);
|
||||
REQUIRE(std::is_move_assignable<decltype(e)>::value);
|
||||
REQUIRE(!TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(decltype(e))::value);
|
||||
REQUIRE(!TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(decltype(e))::value);
|
||||
# if !defined(TL_EXPECTED_GCC49)
|
||||
REQUIRE(!std::is_trivially_move_constructible<decltype(e)>::value);
|
||||
REQUIRE(!std::is_trivially_move_assignable<decltype(e)>::value);
|
||||
# endif
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,6 @@
|
||||
#include <catch2/catch.hpp>
|
||||
#include <tl/expected.hpp>
|
||||
|
||||
TEST_CASE("Constexpr", "[constexpr]") {
|
||||
//TODO
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
#include <catch2/catch.hpp>
|
||||
#include <tl/expected.hpp>
|
||||
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
struct takes_init_and_variadic {
|
||||
std::vector<int> v;
|
||||
std::tuple<int, int> t;
|
||||
template <class... Args>
|
||||
takes_init_and_variadic(std::initializer_list<int> l, Args &&... args)
|
||||
: v(l), t(std::forward<Args>(args)...) {}
|
||||
};
|
||||
|
||||
TEST_CASE("Constructors", "[constructors]") {
|
||||
{
|
||||
tl::expected<int,int> e;
|
||||
REQUIRE(e);
|
||||
REQUIRE(e == 0);
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<int,int> e = tl::make_unexpected(0);
|
||||
REQUIRE(!e);
|
||||
REQUIRE(e.error() == 0);
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<int,int> e (tl::unexpect, 0);
|
||||
REQUIRE(!e);
|
||||
REQUIRE(e.error() == 0);
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<int,int> e (tl::in_place, 42);
|
||||
REQUIRE(e);
|
||||
REQUIRE(e == 42);
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<std::vector<int>,int> e (tl::in_place, {0,1});
|
||||
REQUIRE(e);
|
||||
REQUIRE((*e)[0] == 0);
|
||||
REQUIRE((*e)[1] == 1);
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<std::tuple<int,int>,int> e (tl::in_place, 0, 1);
|
||||
REQUIRE(e);
|
||||
REQUIRE(std::get<0>(*e) == 0);
|
||||
REQUIRE(std::get<1>(*e) == 1);
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<takes_init_and_variadic,int> e (tl::in_place, {0,1}, 2, 3);
|
||||
REQUIRE(e);
|
||||
REQUIRE(e->v[0] == 0);
|
||||
REQUIRE(e->v[1] == 1);
|
||||
REQUIRE(std::get<0>(e->t) == 2);
|
||||
REQUIRE(std::get<1>(e->t) == 3);
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<int, int> e;
|
||||
REQUIRE(std::is_default_constructible<decltype(e)>::value);
|
||||
REQUIRE(std::is_copy_constructible<decltype(e)>::value);
|
||||
REQUIRE(std::is_move_constructible<decltype(e)>::value);
|
||||
REQUIRE(std::is_copy_assignable<decltype(e)>::value);
|
||||
REQUIRE(std::is_move_assignable<decltype(e)>::value);
|
||||
REQUIRE(TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(decltype(e))::value);
|
||||
REQUIRE(TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(decltype(e))::value);
|
||||
# if !defined(TL_EXPECTED_GCC49)
|
||||
REQUIRE(std::is_trivially_move_constructible<decltype(e)>::value);
|
||||
REQUIRE(std::is_trivially_move_assignable<decltype(e)>::value);
|
||||
# endif
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<int, std::string> e;
|
||||
REQUIRE(std::is_default_constructible<decltype(e)>::value);
|
||||
REQUIRE(std::is_copy_constructible<decltype(e)>::value);
|
||||
REQUIRE(std::is_move_constructible<decltype(e)>::value);
|
||||
REQUIRE(std::is_copy_assignable<decltype(e)>::value);
|
||||
REQUIRE(std::is_move_assignable<decltype(e)>::value);
|
||||
REQUIRE(!TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(decltype(e))::value);
|
||||
REQUIRE(!TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(decltype(e))::value);
|
||||
# if !defined(TL_EXPECTED_GCC49)
|
||||
REQUIRE(!std::is_trivially_move_constructible<decltype(e)>::value);
|
||||
REQUIRE(!std::is_trivially_move_assignable<decltype(e)>::value);
|
||||
# endif
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<std::string, int> e;
|
||||
REQUIRE(std::is_default_constructible<decltype(e)>::value);
|
||||
REQUIRE(std::is_copy_constructible<decltype(e)>::value);
|
||||
REQUIRE(std::is_move_constructible<decltype(e)>::value);
|
||||
REQUIRE(std::is_copy_assignable<decltype(e)>::value);
|
||||
REQUIRE(std::is_move_assignable<decltype(e)>::value);
|
||||
REQUIRE(!TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(decltype(e))::value);
|
||||
REQUIRE(!TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(decltype(e))::value);
|
||||
# if !defined(TL_EXPECTED_GCC49)
|
||||
REQUIRE(!std::is_trivially_move_constructible<decltype(e)>::value);
|
||||
REQUIRE(!std::is_trivially_move_assignable<decltype(e)>::value);
|
||||
# endif
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<std::string, std::string> e;
|
||||
REQUIRE(std::is_default_constructible<decltype(e)>::value);
|
||||
REQUIRE(std::is_copy_constructible<decltype(e)>::value);
|
||||
REQUIRE(std::is_move_constructible<decltype(e)>::value);
|
||||
REQUIRE(std::is_copy_assignable<decltype(e)>::value);
|
||||
REQUIRE(std::is_move_assignable<decltype(e)>::value);
|
||||
REQUIRE(!TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(decltype(e))::value);
|
||||
REQUIRE(!TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(decltype(e))::value);
|
||||
# if !defined(TL_EXPECTED_GCC49)
|
||||
REQUIRE(!std::is_trivially_move_constructible<decltype(e)>::value);
|
||||
REQUIRE(!std::is_trivially_move_assignable<decltype(e)>::value);
|
||||
# endif
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<void,int> e;
|
||||
REQUIRE(e);
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<void,int> e (tl::unexpect, 42);
|
||||
REQUIRE(!e);
|
||||
REQUIRE(e.error() == 42);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
#include <catch2/catch.hpp>
|
||||
#include <tl/expected.hpp>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <tuple>
|
||||
|
||||
namespace {
|
||||
struct takes_init_and_variadic {
|
||||
std::vector<int> v;
|
||||
std::tuple<int, int> t;
|
||||
template <class... Args>
|
||||
takes_init_and_variadic(std::initializer_list<int> l, Args &&... args)
|
||||
: v(l), t(std::forward<Args>(args)...) {}
|
||||
};
|
||||
}
|
||||
|
||||
TEST_CASE("Emplace", "[emplace]") {
|
||||
{
|
||||
tl::expected<std::unique_ptr<int>,int> e;
|
||||
e.emplace(new int{42});
|
||||
REQUIRE(e);
|
||||
REQUIRE(**e == 42);
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<std::vector<int>,int> e;
|
||||
e.emplace({0,1});
|
||||
REQUIRE(e);
|
||||
REQUIRE((*e)[0] == 0);
|
||||
REQUIRE((*e)[1] == 1);
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<std::tuple<int,int>,int> e;
|
||||
e.emplace(2,3);
|
||||
REQUIRE(e);
|
||||
REQUIRE(std::get<0>(*e) == 2);
|
||||
REQUIRE(std::get<1>(*e) == 3);
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<takes_init_and_variadic,int> e = tl::make_unexpected(0);
|
||||
e.emplace({0,1}, 2, 3);
|
||||
REQUIRE(e);
|
||||
REQUIRE(e->v[0] == 0);
|
||||
REQUIRE(e->v[1] == 1);
|
||||
REQUIRE(std::get<0>(e->t) == 2);
|
||||
REQUIRE(std::get<1>(e->t) == 3);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,830 @@
|
||||
#include <catch2/catch.hpp>
|
||||
#include <tl/expected.hpp>
|
||||
|
||||
#define TOKENPASTE(x, y) x##y
|
||||
#define TOKENPASTE2(x, y) TOKENPASTE(x, y)
|
||||
#undef STATIC_REQUIRE
|
||||
#define STATIC_REQUIRE(e) \
|
||||
constexpr bool TOKENPASTE2(rqure, __LINE__) = e; \
|
||||
(void)TOKENPASTE2(rqure, __LINE__); \
|
||||
REQUIRE(e);
|
||||
|
||||
TEST_CASE("Map extensions", "[extensions.map]") {
|
||||
auto mul2 = [](int a) { return a * 2; };
|
||||
auto ret_void = [](int a) { (void)a; };
|
||||
|
||||
{
|
||||
tl::expected<int, int> e = 21;
|
||||
auto ret = e.map(mul2);
|
||||
REQUIRE(ret);
|
||||
REQUIRE(*ret == 42);
|
||||
}
|
||||
|
||||
{
|
||||
const tl::expected<int, int> e = 21;
|
||||
auto ret = e.map(mul2);
|
||||
REQUIRE(ret);
|
||||
REQUIRE(*ret == 42);
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<int, int> e = 21;
|
||||
auto ret = std::move(e).map(mul2);
|
||||
REQUIRE(ret);
|
||||
REQUIRE(*ret == 42);
|
||||
}
|
||||
|
||||
{
|
||||
const tl::expected<int, int> e = 21;
|
||||
auto ret = std::move(e).map(mul2);
|
||||
REQUIRE(ret);
|
||||
REQUIRE(*ret == 42);
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<int, int> e(tl::unexpect, 21);
|
||||
auto ret = e.map(mul2);
|
||||
REQUIRE(!ret);
|
||||
REQUIRE(ret.error() == 21);
|
||||
}
|
||||
|
||||
{
|
||||
const tl::expected<int, int> e(tl::unexpect, 21);
|
||||
auto ret = e.map(mul2);
|
||||
REQUIRE(!ret);
|
||||
REQUIRE(ret.error() == 21);
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<int, int> e(tl::unexpect, 21);
|
||||
auto ret = std::move(e).map(mul2);
|
||||
REQUIRE(!ret);
|
||||
REQUIRE(ret.error() == 21);
|
||||
}
|
||||
|
||||
{
|
||||
const tl::expected<int, int> e(tl::unexpect, 21);
|
||||
auto ret = std::move(e).map(mul2);
|
||||
REQUIRE(!ret);
|
||||
REQUIRE(ret.error() == 21);
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<int, int> e = 21;
|
||||
auto ret = e.map(ret_void);
|
||||
REQUIRE(ret);
|
||||
STATIC_REQUIRE(
|
||||
(std::is_same<decltype(ret), tl::expected<void, int>>::value));
|
||||
}
|
||||
|
||||
{
|
||||
const tl::expected<int, int> e = 21;
|
||||
auto ret = e.map(ret_void);
|
||||
REQUIRE(ret);
|
||||
STATIC_REQUIRE(
|
||||
(std::is_same<decltype(ret), tl::expected<void, int>>::value));
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<int, int> e = 21;
|
||||
auto ret = std::move(e).map(ret_void);
|
||||
REQUIRE(ret);
|
||||
STATIC_REQUIRE(
|
||||
(std::is_same<decltype(ret), tl::expected<void, int>>::value));
|
||||
}
|
||||
|
||||
{
|
||||
const tl::expected<int, int> e = 21;
|
||||
auto ret = std::move(e).map(ret_void);
|
||||
REQUIRE(ret);
|
||||
STATIC_REQUIRE(
|
||||
(std::is_same<decltype(ret), tl::expected<void, int>>::value));
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<int, int> e(tl::unexpect, 21);
|
||||
auto ret = e.map(ret_void);
|
||||
REQUIRE(!ret);
|
||||
STATIC_REQUIRE(
|
||||
(std::is_same<decltype(ret), tl::expected<void, int>>::value));
|
||||
}
|
||||
|
||||
{
|
||||
const tl::expected<int, int> e(tl::unexpect, 21);
|
||||
auto ret = e.map(ret_void);
|
||||
REQUIRE(!ret);
|
||||
STATIC_REQUIRE(
|
||||
(std::is_same<decltype(ret), tl::expected<void, int>>::value));
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<int, int> e(tl::unexpect, 21);
|
||||
auto ret = std::move(e).map(ret_void);
|
||||
REQUIRE(!ret);
|
||||
STATIC_REQUIRE(
|
||||
(std::is_same<decltype(ret), tl::expected<void, int>>::value));
|
||||
}
|
||||
|
||||
{
|
||||
const tl::expected<int, int> e(tl::unexpect, 21);
|
||||
auto ret = std::move(e).map(ret_void);
|
||||
REQUIRE(!ret);
|
||||
STATIC_REQUIRE(
|
||||
(std::is_same<decltype(ret), tl::expected<void, int>>::value));
|
||||
}
|
||||
|
||||
|
||||
// mapping functions which return references
|
||||
{
|
||||
tl::expected<int, int> e(42);
|
||||
auto ret = e.map([](int& i) -> int& { return i; });
|
||||
REQUIRE(ret);
|
||||
REQUIRE(ret == 42);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Map error extensions", "[extensions.map_error]") {
|
||||
auto mul2 = [](int a) { return a * 2; };
|
||||
auto ret_void = [](int a) { (void)a; };
|
||||
|
||||
{
|
||||
tl::expected<int, int> e = 21;
|
||||
auto ret = e.map_error(mul2);
|
||||
REQUIRE(ret);
|
||||
REQUIRE(*ret == 21);
|
||||
}
|
||||
|
||||
{
|
||||
const tl::expected<int, int> e = 21;
|
||||
auto ret = e.map_error(mul2);
|
||||
REQUIRE(ret);
|
||||
REQUIRE(*ret == 21);
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<int, int> e = 21;
|
||||
auto ret = std::move(e).map_error(mul2);
|
||||
REQUIRE(ret);
|
||||
REQUIRE(*ret == 21);
|
||||
}
|
||||
|
||||
{
|
||||
const tl::expected<int, int> e = 21;
|
||||
auto ret = std::move(e).map_error(mul2);
|
||||
REQUIRE(ret);
|
||||
REQUIRE(*ret == 21);
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<int, int> e(tl::unexpect, 21);
|
||||
auto ret = e.map_error(mul2);
|
||||
REQUIRE(!ret);
|
||||
REQUIRE(ret.error() == 42);
|
||||
}
|
||||
|
||||
{
|
||||
const tl::expected<int, int> e(tl::unexpect, 21);
|
||||
auto ret = e.map_error(mul2);
|
||||
REQUIRE(!ret);
|
||||
REQUIRE(ret.error() == 42);
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<int, int> e(tl::unexpect, 21);
|
||||
auto ret = std::move(e).map_error(mul2);
|
||||
REQUIRE(!ret);
|
||||
REQUIRE(ret.error() == 42);
|
||||
}
|
||||
|
||||
{
|
||||
const tl::expected<int, int> e(tl::unexpect, 21);
|
||||
auto ret = std::move(e).map_error(mul2);
|
||||
REQUIRE(!ret);
|
||||
REQUIRE(ret.error() == 42);
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<int, int> e = 21;
|
||||
auto ret = e.map_error(ret_void);
|
||||
REQUIRE(ret);
|
||||
}
|
||||
|
||||
{
|
||||
const tl::expected<int, int> e = 21;
|
||||
auto ret = e.map_error(ret_void);
|
||||
REQUIRE(ret);
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<int, int> e = 21;
|
||||
auto ret = std::move(e).map_error(ret_void);
|
||||
REQUIRE(ret);
|
||||
}
|
||||
|
||||
{
|
||||
const tl::expected<int, int> e = 21;
|
||||
auto ret = std::move(e).map_error(ret_void);
|
||||
REQUIRE(ret);
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<int, int> e(tl::unexpect, 21);
|
||||
auto ret = e.map_error(ret_void);
|
||||
REQUIRE(!ret);
|
||||
}
|
||||
|
||||
{
|
||||
const tl::expected<int, int> e(tl::unexpect, 21);
|
||||
auto ret = e.map_error(ret_void);
|
||||
REQUIRE(!ret);
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<int, int> e(tl::unexpect, 21);
|
||||
auto ret = std::move(e).map_error(ret_void);
|
||||
REQUIRE(!ret);
|
||||
}
|
||||
|
||||
{
|
||||
const tl::expected<int, int> e(tl::unexpect, 21);
|
||||
auto ret = std::move(e).map_error(ret_void);
|
||||
REQUIRE(!ret);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
TEST_CASE("And then extensions", "[extensions.and_then]") {
|
||||
auto succeed = [](int a) { (void)a; return tl::expected<int, int>(21 * 2); };
|
||||
auto fail = [](int a) { (void)a; return tl::expected<int, int>(tl::unexpect, 17); };
|
||||
|
||||
{
|
||||
tl::expected<int, int> e = 21;
|
||||
auto ret = e.and_then(succeed);
|
||||
REQUIRE(ret);
|
||||
REQUIRE(*ret == 42);
|
||||
}
|
||||
|
||||
{
|
||||
const tl::expected<int, int> e = 21;
|
||||
auto ret = e.and_then(succeed);
|
||||
REQUIRE(ret);
|
||||
REQUIRE(*ret == 42);
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<int, int> e = 21;
|
||||
auto ret = std::move(e).and_then(succeed);
|
||||
REQUIRE(ret);
|
||||
REQUIRE(*ret == 42);
|
||||
}
|
||||
|
||||
{
|
||||
const tl::expected<int, int> e = 21;
|
||||
auto ret = std::move(e).and_then(succeed);
|
||||
REQUIRE(ret);
|
||||
REQUIRE(*ret == 42);
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<int, int> e = 21;
|
||||
auto ret = e.and_then(fail);
|
||||
REQUIRE(!ret);
|
||||
REQUIRE(ret.error() == 17);
|
||||
}
|
||||
|
||||
{
|
||||
const tl::expected<int, int> e = 21;
|
||||
auto ret = e.and_then(fail);
|
||||
REQUIRE(!ret);
|
||||
REQUIRE(ret.error() == 17);
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<int, int> e = 21;
|
||||
auto ret = std::move(e).and_then(fail);
|
||||
REQUIRE(!ret);
|
||||
REQUIRE(ret.error() == 17);
|
||||
}
|
||||
|
||||
{
|
||||
const tl::expected<int, int> e = 21;
|
||||
auto ret = std::move(e).and_then(fail);
|
||||
REQUIRE(!ret);
|
||||
REQUIRE(ret.error() == 17);
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<int, int> e(tl::unexpect, 21);
|
||||
auto ret = e.and_then(succeed);
|
||||
REQUIRE(!ret);
|
||||
REQUIRE(ret.error() == 21);
|
||||
}
|
||||
|
||||
{
|
||||
const tl::expected<int, int> e(tl::unexpect, 21);
|
||||
auto ret = e.and_then(succeed);
|
||||
REQUIRE(!ret);
|
||||
REQUIRE(ret.error() == 21);
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<int, int> e(tl::unexpect, 21);
|
||||
auto ret = std::move(e).and_then(succeed);
|
||||
REQUIRE(!ret);
|
||||
REQUIRE(ret.error() == 21);
|
||||
}
|
||||
|
||||
{
|
||||
const tl::expected<int, int> e(tl::unexpect, 21);
|
||||
auto ret = std::move(e).and_then(succeed);
|
||||
REQUIRE(!ret);
|
||||
REQUIRE(ret.error() == 21);
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<int, int> e(tl::unexpect, 21);
|
||||
auto ret = e.and_then(fail);
|
||||
REQUIRE(!ret);
|
||||
REQUIRE(ret.error() == 21);
|
||||
}
|
||||
|
||||
{
|
||||
const tl::expected<int, int> e(tl::unexpect, 21);
|
||||
auto ret = e.and_then(fail);
|
||||
REQUIRE(!ret);
|
||||
REQUIRE(ret.error() == 21);
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<int, int> e(tl::unexpect, 21);
|
||||
auto ret = std::move(e).and_then(fail);
|
||||
REQUIRE(!ret);
|
||||
REQUIRE(ret.error() == 21);
|
||||
}
|
||||
|
||||
{
|
||||
const tl::expected<int, int> e(tl::unexpect, 21);
|
||||
auto ret = std::move(e).and_then(fail);
|
||||
REQUIRE(!ret);
|
||||
REQUIRE(ret.error() == 21);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("or_else", "[extensions.or_else]") {
|
||||
using eptr = std::unique_ptr<int>;
|
||||
auto succeed = [](int a) { (void)a; return tl::expected<int, int>(21 * 2); };
|
||||
auto succeedptr = [](eptr e) { (void)e; return tl::expected<int,eptr>(21*2);};
|
||||
auto fail = [](int a) { (void)a; return tl::expected<int,int>(tl::unexpect, 17);};
|
||||
auto failptr = [](eptr e) { *e = 17;return tl::expected<int,eptr>(tl::unexpect, std::move(e));};
|
||||
auto failvoid = [](int) {};
|
||||
auto failvoidptr = [](const eptr&) { /* don't consume */};
|
||||
auto consumeptr = [](eptr) {};
|
||||
auto make_u_int = [](int n) { return std::unique_ptr<int>(new int(n));};
|
||||
|
||||
{
|
||||
tl::expected<int, int> e = 21;
|
||||
auto ret = e.or_else(succeed);
|
||||
REQUIRE(ret);
|
||||
REQUIRE(*ret == 21);
|
||||
}
|
||||
|
||||
{
|
||||
const tl::expected<int, int> e = 21;
|
||||
auto ret = e.or_else(succeed);
|
||||
REQUIRE(ret);
|
||||
REQUIRE(*ret == 21);
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<int, int> e = 21;
|
||||
auto ret = std::move(e).or_else(succeed);
|
||||
REQUIRE(ret);
|
||||
REQUIRE(*ret == 21);
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<int, eptr> e = 21;
|
||||
auto ret = std::move(e).or_else(succeedptr);
|
||||
REQUIRE(ret);
|
||||
REQUIRE(*ret == 21);
|
||||
}
|
||||
|
||||
{
|
||||
const tl::expected<int, int> e = 21;
|
||||
auto ret = std::move(e).or_else(succeed);
|
||||
REQUIRE(ret);
|
||||
REQUIRE(*ret == 21);
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<int, int> e = 21;
|
||||
auto ret = e.or_else(fail);
|
||||
REQUIRE(ret);
|
||||
REQUIRE(*ret == 21);
|
||||
}
|
||||
|
||||
{
|
||||
const tl::expected<int, int> e = 21;
|
||||
auto ret = e.or_else(fail);
|
||||
REQUIRE(ret);
|
||||
REQUIRE(*ret == 21);
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<int, int> e = 21;
|
||||
auto ret = std::move(e).or_else(fail);
|
||||
REQUIRE(ret);
|
||||
REQUIRE(ret == 21);
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
tl::expected<int, eptr> e = 21;
|
||||
auto ret = std::move(e).or_else(failptr);
|
||||
REQUIRE(ret);
|
||||
REQUIRE(ret == 21);
|
||||
}
|
||||
|
||||
{
|
||||
const tl::expected<int, int> e = 21;
|
||||
auto ret = std::move(e).or_else(fail);
|
||||
REQUIRE(ret);
|
||||
REQUIRE(*ret == 21);
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<int, int> e(tl::unexpect, 21);
|
||||
auto ret = e.or_else(succeed);
|
||||
REQUIRE(ret);
|
||||
REQUIRE(*ret == 42);
|
||||
}
|
||||
|
||||
{
|
||||
const tl::expected<int, int> e(tl::unexpect, 21);
|
||||
auto ret = e.or_else(succeed);
|
||||
REQUIRE(ret);
|
||||
REQUIRE(*ret == 42);
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<int, int> e(tl::unexpect, 21);
|
||||
auto ret = std::move(e).or_else(succeed);
|
||||
REQUIRE(ret);
|
||||
REQUIRE(*ret == 42);
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<int, eptr> e(tl::unexpect, make_u_int(21));
|
||||
auto ret = std::move(e).or_else(succeedptr);
|
||||
REQUIRE(ret);
|
||||
REQUIRE(*ret == 42);
|
||||
}
|
||||
|
||||
{
|
||||
const tl::expected<int, int> e(tl::unexpect, 21);
|
||||
auto ret = std::move(e).or_else(succeed);
|
||||
REQUIRE(ret);
|
||||
REQUIRE(*ret == 42);
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<int, int> e(tl::unexpect, 21);
|
||||
auto ret = e.or_else(fail);
|
||||
REQUIRE(!ret);
|
||||
REQUIRE(ret.error() == 17);
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<int, int> e(tl::unexpect, 21);
|
||||
auto ret = e.or_else(failvoid);
|
||||
REQUIRE(!ret);
|
||||
REQUIRE(ret.error() == 21);
|
||||
}
|
||||
|
||||
{
|
||||
const tl::expected<int, int> e(tl::unexpect, 21);
|
||||
auto ret = e.or_else(fail);
|
||||
REQUIRE(!ret);
|
||||
REQUIRE(ret.error() == 17);
|
||||
}
|
||||
|
||||
{
|
||||
const tl::expected<int, int> e(tl::unexpect, 21);
|
||||
auto ret = e.or_else(failvoid);
|
||||
REQUIRE(!ret);
|
||||
REQUIRE(ret.error() == 21);
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<int, int> e(tl::unexpect, 21);
|
||||
auto ret = std::move(e).or_else(fail);
|
||||
REQUIRE(!ret);
|
||||
REQUIRE(ret.error() == 17);
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<int, int> e(tl::unexpect, 21);
|
||||
auto ret = std::move(e).or_else(failvoid);
|
||||
REQUIRE(!ret);
|
||||
REQUIRE(ret.error() == 21);
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<int, eptr> e(tl::unexpect, make_u_int(21));
|
||||
auto ret = std::move(e).or_else(failvoidptr);
|
||||
REQUIRE(!ret);
|
||||
REQUIRE(*ret.error() == 21);
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<int, eptr> e(tl::unexpect, make_u_int(21));
|
||||
auto ret = std::move(e).or_else(consumeptr);
|
||||
REQUIRE(!ret);
|
||||
REQUIRE(ret.error() == nullptr);
|
||||
}
|
||||
|
||||
{
|
||||
const tl::expected<int, int> e(tl::unexpect, 21);
|
||||
auto ret = std::move(e).or_else(fail);
|
||||
REQUIRE(!ret);
|
||||
REQUIRE(ret.error() == 17);
|
||||
}
|
||||
|
||||
{
|
||||
const tl::expected<int, int> e(tl::unexpect, 21);
|
||||
auto ret = std::move(e).or_else(failvoid);
|
||||
REQUIRE(!ret);
|
||||
REQUIRE(ret.error() == 21);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
TEST_CASE("Transform extensions", "[extensions.tronsfarm]") {
|
||||
auto mul2 = [](int a) { return a * 2; };
|
||||
auto ret_void = [](int a) { (void)a; };
|
||||
|
||||
{
|
||||
tl::expected<int, int> e = 21;
|
||||
auto ret = e.transform(mul2);
|
||||
REQUIRE(ret);
|
||||
REQUIRE(*ret == 42);
|
||||
}
|
||||
|
||||
{
|
||||
const tl::expected<int, int> e = 21;
|
||||
auto ret = e.transform(mul2);
|
||||
REQUIRE(ret);
|
||||
REQUIRE(*ret == 42);
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<int, int> e = 21;
|
||||
auto ret = std::move(e).transform(mul2);
|
||||
REQUIRE(ret);
|
||||
REQUIRE(*ret == 42);
|
||||
}
|
||||
|
||||
{
|
||||
const tl::expected<int, int> e = 21;
|
||||
auto ret = std::move(e).transform(mul2);
|
||||
REQUIRE(ret);
|
||||
REQUIRE(*ret == 42);
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<int, int> e(tl::unexpect, 21);
|
||||
auto ret = e.transform(mul2);
|
||||
REQUIRE(!ret);
|
||||
REQUIRE(ret.error() == 21);
|
||||
}
|
||||
|
||||
{
|
||||
const tl::expected<int, int> e(tl::unexpect, 21);
|
||||
auto ret = e.transform(mul2);
|
||||
REQUIRE(!ret);
|
||||
REQUIRE(ret.error() == 21);
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<int, int> e(tl::unexpect, 21);
|
||||
auto ret = std::move(e).transform(mul2);
|
||||
REQUIRE(!ret);
|
||||
REQUIRE(ret.error() == 21);
|
||||
}
|
||||
|
||||
{
|
||||
const tl::expected<int, int> e(tl::unexpect, 21);
|
||||
auto ret = std::move(e).transform(mul2);
|
||||
REQUIRE(!ret);
|
||||
REQUIRE(ret.error() == 21);
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<int, int> e = 21;
|
||||
auto ret = e.transform(ret_void);
|
||||
REQUIRE(ret);
|
||||
STATIC_REQUIRE(
|
||||
(std::is_same<decltype(ret), tl::expected<void, int>>::value));
|
||||
}
|
||||
|
||||
{
|
||||
const tl::expected<int, int> e = 21;
|
||||
auto ret = e.transform(ret_void);
|
||||
REQUIRE(ret);
|
||||
STATIC_REQUIRE(
|
||||
(std::is_same<decltype(ret), tl::expected<void, int>>::value));
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<int, int> e = 21;
|
||||
auto ret = std::move(e).transform(ret_void);
|
||||
REQUIRE(ret);
|
||||
STATIC_REQUIRE(
|
||||
(std::is_same<decltype(ret), tl::expected<void, int>>::value));
|
||||
}
|
||||
|
||||
{
|
||||
const tl::expected<int, int> e = 21;
|
||||
auto ret = std::move(e).transform(ret_void);
|
||||
REQUIRE(ret);
|
||||
STATIC_REQUIRE(
|
||||
(std::is_same<decltype(ret), tl::expected<void, int>>::value));
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<int, int> e(tl::unexpect, 21);
|
||||
auto ret = e.transform(ret_void);
|
||||
REQUIRE(!ret);
|
||||
STATIC_REQUIRE(
|
||||
(std::is_same<decltype(ret), tl::expected<void, int>>::value));
|
||||
}
|
||||
|
||||
{
|
||||
const tl::expected<int, int> e(tl::unexpect, 21);
|
||||
auto ret = e.transform(ret_void);
|
||||
REQUIRE(!ret);
|
||||
STATIC_REQUIRE(
|
||||
(std::is_same<decltype(ret), tl::expected<void, int>>::value));
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<int, int> e(tl::unexpect, 21);
|
||||
auto ret = std::move(e).transform(ret_void);
|
||||
REQUIRE(!ret);
|
||||
STATIC_REQUIRE(
|
||||
(std::is_same<decltype(ret), tl::expected<void, int>>::value));
|
||||
}
|
||||
|
||||
{
|
||||
const tl::expected<int, int> e(tl::unexpect, 21);
|
||||
auto ret = std::move(e).transform(ret_void);
|
||||
REQUIRE(!ret);
|
||||
STATIC_REQUIRE(
|
||||
(std::is_same<decltype(ret), tl::expected<void, int>>::value));
|
||||
}
|
||||
|
||||
|
||||
// mapping functions which return references
|
||||
{
|
||||
tl::expected<int, int> e(42);
|
||||
auto ret = e.transform([](int& i) -> int& { return i; });
|
||||
REQUIRE(ret);
|
||||
REQUIRE(ret == 42);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Transform error extensions", "[extensions.transform_error]") {
|
||||
auto mul2 = [](int a) { return a * 2; };
|
||||
auto ret_void = [](int a) { (void)a; };
|
||||
|
||||
{
|
||||
tl::expected<int, int> e = 21;
|
||||
auto ret = e.transform_error(mul2);
|
||||
REQUIRE(ret);
|
||||
REQUIRE(*ret == 21);
|
||||
}
|
||||
|
||||
{
|
||||
const tl::expected<int, int> e = 21;
|
||||
auto ret = e.transform_error(mul2);
|
||||
REQUIRE(ret);
|
||||
REQUIRE(*ret == 21);
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<int, int> e = 21;
|
||||
auto ret = std::move(e).transform_error(mul2);
|
||||
REQUIRE(ret);
|
||||
REQUIRE(*ret == 21);
|
||||
}
|
||||
|
||||
{
|
||||
const tl::expected<int, int> e = 21;
|
||||
auto ret = std::move(e).transform_error(mul2);
|
||||
REQUIRE(ret);
|
||||
REQUIRE(*ret == 21);
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<int, int> e(tl::unexpect, 21);
|
||||
auto ret = e.transform_error(mul2);
|
||||
REQUIRE(!ret);
|
||||
REQUIRE(ret.error() == 42);
|
||||
}
|
||||
|
||||
{
|
||||
const tl::expected<int, int> e(tl::unexpect, 21);
|
||||
auto ret = e.transform_error(mul2);
|
||||
REQUIRE(!ret);
|
||||
REQUIRE(ret.error() == 42);
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<int, int> e(tl::unexpect, 21);
|
||||
auto ret = std::move(e).transform_error(mul2);
|
||||
REQUIRE(!ret);
|
||||
REQUIRE(ret.error() == 42);
|
||||
}
|
||||
|
||||
{
|
||||
const tl::expected<int, int> e(tl::unexpect, 21);
|
||||
auto ret = std::move(e).transform_error(mul2);
|
||||
REQUIRE(!ret);
|
||||
REQUIRE(ret.error() == 42);
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<int, int> e = 21;
|
||||
auto ret = e.transform_error(ret_void);
|
||||
REQUIRE(ret);
|
||||
}
|
||||
|
||||
{
|
||||
const tl::expected<int, int> e = 21;
|
||||
auto ret = e.transform_error(ret_void);
|
||||
REQUIRE(ret);
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<int, int> e = 21;
|
||||
auto ret = std::move(e).transform_error(ret_void);
|
||||
REQUIRE(ret);
|
||||
}
|
||||
|
||||
{
|
||||
const tl::expected<int, int> e = 21;
|
||||
auto ret = std::move(e).transform_error(ret_void);
|
||||
REQUIRE(ret);
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<int, int> e(tl::unexpect, 21);
|
||||
auto ret = e.transform_error(ret_void);
|
||||
REQUIRE(!ret);
|
||||
}
|
||||
|
||||
{
|
||||
const tl::expected<int, int> e(tl::unexpect, 21);
|
||||
auto ret = e.transform_error(ret_void);
|
||||
REQUIRE(!ret);
|
||||
}
|
||||
|
||||
{
|
||||
tl::expected<int, int> e(tl::unexpect, 21);
|
||||
auto ret = std::move(e).transform_error(ret_void);
|
||||
REQUIRE(!ret);
|
||||
}
|
||||
|
||||
{
|
||||
const tl::expected<int, int> e(tl::unexpect, 21);
|
||||
auto ret = std::move(e).transform_error(ret_void);
|
||||
REQUIRE(!ret);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
struct S {
|
||||
int x;
|
||||
};
|
||||
|
||||
struct F {
|
||||
int x;
|
||||
};
|
||||
|
||||
TEST_CASE("14", "[issue.14]") {
|
||||
auto res = tl::expected<S,F>{tl::unexpect, F{}};
|
||||
|
||||
res.map_error([](F f) {
|
||||
(void)f;
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("32", "[issue.32]") {
|
||||
int i = 0;
|
||||
tl::expected<void, int> a;
|
||||
a.map([&i]{i = 42;});
|
||||
REQUIRE(i == 42);
|
||||
|
||||
auto x = a.map([]{return 42;});
|
||||
REQUIRE(*x == 42);
|
||||
}
|
||||
@@ -0,0 +1,195 @@
|
||||
#include <catch2/catch.hpp>
|
||||
#include <tl/expected.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
using std::string;
|
||||
|
||||
tl::expected<int, string> getInt3(int val) { return val; }
|
||||
|
||||
tl::expected<int, string> getInt2(int val) { return val; }
|
||||
|
||||
tl::expected<int, string> getInt1() { return getInt2(5).and_then(getInt3); }
|
||||
|
||||
TEST_CASE("Issue 1", "[issues.1]") { getInt1(); }
|
||||
|
||||
tl::expected<int, int> operation1() { return 42; }
|
||||
|
||||
tl::expected<std::string, int> operation2(int const val) { (void)val; return "Bananas"; }
|
||||
|
||||
TEST_CASE("Issue 17", "[issues.17]") {
|
||||
auto const intermediate_result = operation1();
|
||||
|
||||
intermediate_result.and_then(operation2);
|
||||
}
|
||||
|
||||
struct a {};
|
||||
struct b : a {};
|
||||
|
||||
auto doit() -> tl::expected<std::unique_ptr<b>, int> {
|
||||
return tl::make_unexpected(0);
|
||||
}
|
||||
|
||||
TEST_CASE("Issue 23", "[issues.23]") {
|
||||
tl::expected<std::unique_ptr<a>, int> msg = doit();
|
||||
REQUIRE(!msg.has_value());
|
||||
}
|
||||
|
||||
TEST_CASE("Issue 26", "[issues.26]") {
|
||||
tl::expected<a, int> exp = tl::expected<b, int>(tl::unexpect, 0);
|
||||
REQUIRE(!exp.has_value());
|
||||
}
|
||||
|
||||
struct foo {
|
||||
foo() = default;
|
||||
foo(foo &) = delete;
|
||||
foo(foo &&){};
|
||||
};
|
||||
|
||||
TEST_CASE("Issue 29", "[issues.29]") {
|
||||
std::vector<foo> v;
|
||||
v.emplace_back();
|
||||
tl::expected<std::vector<foo>, int> ov = std::move(v);
|
||||
REQUIRE(ov->size() == 1);
|
||||
}
|
||||
|
||||
tl::expected<int, std::string> error() {
|
||||
return tl::make_unexpected(std::string("error1 "));
|
||||
}
|
||||
std::string maperror(std::string s) { return s + "maperror "; }
|
||||
|
||||
TEST_CASE("Issue 30", "[issues.30]") {
|
||||
error().map_error(maperror);
|
||||
}
|
||||
|
||||
struct i31{
|
||||
int i;
|
||||
};
|
||||
TEST_CASE("Issue 31", "[issues.31]") {
|
||||
const tl::expected<i31, int> a = i31{42};
|
||||
(void)a->i;
|
||||
|
||||
tl::expected< void, std::string > result;
|
||||
tl::expected< void, std::string > result2 = result;
|
||||
result2 = result;
|
||||
}
|
||||
|
||||
TEST_CASE("Issue 33", "[issues.33]") {
|
||||
tl::expected<void, int> res {tl::unexpect, 0};
|
||||
REQUIRE(!res);
|
||||
res = res.map_error([](int i) { (void)i; return 42; });
|
||||
REQUIRE(res.error() == 42);
|
||||
}
|
||||
|
||||
|
||||
tl::expected<void, std::string> voidWork() { return {}; }
|
||||
tl::expected<int, std::string> work2() { return 42; }
|
||||
void errorhandling(std::string){}
|
||||
|
||||
TEST_CASE("Issue 34", "[issues.34]") {
|
||||
tl::expected <int, std::string> result = voidWork ()
|
||||
.and_then (work2);
|
||||
result.map_error ([&] (std::string result) {errorhandling (result);});
|
||||
}
|
||||
|
||||
struct non_copyable {
|
||||
non_copyable(non_copyable&&) = default;
|
||||
non_copyable(non_copyable const&) = delete;
|
||||
non_copyable() = default;
|
||||
};
|
||||
|
||||
TEST_CASE("Issue 42", "[issues.42]") {
|
||||
tl::expected<non_copyable,int>{}.map([](non_copyable) {});
|
||||
}
|
||||
|
||||
TEST_CASE("Issue 43", "[issues.43]") {
|
||||
auto result = tl::expected<void, std::string>{};
|
||||
result = tl::make_unexpected(std::string{ "foo" });
|
||||
}
|
||||
|
||||
#if !(__GNUC__ <= 5)
|
||||
#include <memory>
|
||||
|
||||
using MaybeDataPtr = tl::expected<int, std::unique_ptr<int>>;
|
||||
|
||||
MaybeDataPtr test(int i) noexcept
|
||||
{
|
||||
return std::move(i);
|
||||
}
|
||||
|
||||
MaybeDataPtr test2(int i) noexcept
|
||||
{
|
||||
return std::move(i);
|
||||
}
|
||||
|
||||
TEST_CASE("Issue 49", "[issues.49]") {
|
||||
auto m = test(10)
|
||||
.and_then(test2);
|
||||
}
|
||||
#endif
|
||||
|
||||
tl::expected<int, std::unique_ptr<std::string>> func()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
TEST_CASE("Issue 61", "[issues.61]") {
|
||||
REQUIRE(func().value() == 1);
|
||||
}
|
||||
|
||||
struct move_tracker {
|
||||
int moved = 0;
|
||||
|
||||
move_tracker() = default;
|
||||
|
||||
move_tracker(move_tracker const &other) noexcept {};
|
||||
move_tracker(move_tracker &&orig) noexcept
|
||||
: moved(orig.moved + 1) {}
|
||||
|
||||
move_tracker &
|
||||
operator=(move_tracker const &other) noexcept {};
|
||||
|
||||
move_tracker &operator=(move_tracker &&orig) noexcept {
|
||||
moved = orig.moved + 1;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
TEST_CASE("Issue 122", "[issues.122]") {
|
||||
tl::expected<move_tracker, int> res;
|
||||
res.emplace();
|
||||
REQUIRE(res.value().moved == 0);
|
||||
}
|
||||
|
||||
#ifdef __cpp_deduction_guides
|
||||
TEST_CASE("Issue 89", "[issues.89]") {
|
||||
auto s = tl::unexpected("Some string");
|
||||
REQUIRE(s.value() == std::string("Some string"));
|
||||
}
|
||||
#endif
|
||||
|
||||
struct S {
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
S(int i) : i(i) {}
|
||||
S(int i, int j) : i(i), j(j) {}
|
||||
};
|
||||
|
||||
TEST_CASE("Issue 107", "[issues.107]") {
|
||||
tl::expected<int, S> ex1(tl::unexpect, 2);
|
||||
tl::expected<int, S> ex2(tl::unexpect, 2, 2);
|
||||
|
||||
REQUIRE(ex1.error().i == 2);
|
||||
REQUIRE(ex1.error().j == 0);
|
||||
REQUIRE(ex2.error().i == 2);
|
||||
REQUIRE(ex2.error().j == 2);
|
||||
}
|
||||
|
||||
TEST_CASE("Issue 129", "[issues.129]") {
|
||||
tl::expected<std::unique_ptr<int>, int> x1 {std::unique_ptr<int>(new int(4))};
|
||||
tl::expected<std::unique_ptr<int>, int> y1 {std::unique_ptr<int>(new int(2))};
|
||||
x1 = std::move(y1);
|
||||
|
||||
REQUIRE(**x1 == 2);
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
#define CATCH_CONFIG_MAIN
|
||||
#include <catch2/catch.hpp>
|
||||
@@ -0,0 +1,6 @@
|
||||
#include <catch2/catch.hpp>
|
||||
#include <tl/expected.hpp>
|
||||
|
||||
TEST_CASE("Noexcept", "[noexcept]") {
|
||||
//TODO
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
#include <catch2/catch.hpp>
|
||||
#include <tl/expected.hpp>
|
||||
|
||||
struct move_detector {
|
||||
move_detector() = default;
|
||||
move_detector(move_detector &&rhs) { rhs.been_moved = true; }
|
||||
bool been_moved = false;
|
||||
};
|
||||
|
||||
TEST_CASE("Observers", "[observers]") {
|
||||
tl::expected<int,int> o1 = 42;
|
||||
tl::expected<int,int> o2 {tl::unexpect, 0};
|
||||
const tl::expected<int,int> o3 = 42;
|
||||
|
||||
REQUIRE(*o1 == 42);
|
||||
REQUIRE(*o1 == o1.value());
|
||||
REQUIRE(o2.value_or(42) == 42);
|
||||
REQUIRE(o2.error() == 0);
|
||||
REQUIRE(o3.value() == 42);
|
||||
auto success = std::is_same<decltype(o1.value()), int &>::value;
|
||||
REQUIRE(success);
|
||||
success = std::is_same<decltype(o3.value()), const int &>::value;
|
||||
REQUIRE(success);
|
||||
success = std::is_same<decltype(std::move(o1).value()), int &&>::value;
|
||||
REQUIRE(success);
|
||||
|
||||
#ifndef TL_EXPECTED_NO_CONSTRR
|
||||
success = std::is_same<decltype(std::move(o3).value()), const int &&>::value;
|
||||
REQUIRE(success);
|
||||
#endif
|
||||
|
||||
tl::expected<move_detector,int> o4{tl::in_place};
|
||||
move_detector o5 = std::move(o4).value();
|
||||
REQUIRE(o4->been_moved);
|
||||
REQUIRE(!o5.been_moved);
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#include <catch2/catch.hpp>
|
||||
#include <tl/expected.hpp>
|
||||
|
||||
TEST_CASE("Relational operators", "[relops]") {
|
||||
tl::expected<int, int> o1 = 42;
|
||||
tl::expected<int, int> o2{tl::unexpect, 0};
|
||||
const tl::expected<int, int> o3 = 42;
|
||||
|
||||
REQUIRE(o1 == o1);
|
||||
REQUIRE(o1 != o2);
|
||||
REQUIRE(o1 == o3);
|
||||
REQUIRE(o3 == o3);
|
||||
|
||||
tl::expected<void, int> o6;
|
||||
|
||||
REQUIRE(o6 == o6);
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
#include <catch2/catch.hpp>
|
||||
#include <tl/expected.hpp>
|
||||
|
||||
struct no_throw {
|
||||
no_throw(std::string i) : i(i) {}
|
||||
std::string i;
|
||||
};
|
||||
struct canthrow_move {
|
||||
canthrow_move(std::string i) : i(i) {}
|
||||
canthrow_move(canthrow_move const &) = default;
|
||||
canthrow_move(canthrow_move &&other) noexcept(false) : i(other.i) {}
|
||||
canthrow_move &operator=(canthrow_move &&) = default;
|
||||
std::string i;
|
||||
};
|
||||
|
||||
bool should_throw = false;
|
||||
|
||||
#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED
|
||||
struct willthrow_move {
|
||||
willthrow_move(std::string i) : i(i) {}
|
||||
willthrow_move(willthrow_move const &) = default;
|
||||
willthrow_move(willthrow_move &&other) : i(other.i) {
|
||||
if (should_throw)
|
||||
throw 0;
|
||||
}
|
||||
willthrow_move &operator=(willthrow_move &&) = default;
|
||||
std::string i;
|
||||
};
|
||||
#endif // TL_EXPECTED_EXCEPTIONS_ENABLED
|
||||
|
||||
static_assert(tl::detail::is_swappable<no_throw>::value, "");
|
||||
|
||||
template <class T1, class T2> void swap_test() {
|
||||
std::string s1 = "abcdefghijklmnopqrstuvwxyz";
|
||||
std::string s2 = "zyxwvutsrqponmlkjihgfedcba";
|
||||
|
||||
tl::expected<T1, T2> a{s1};
|
||||
tl::expected<T1, T2> b{s2};
|
||||
swap(a, b);
|
||||
REQUIRE(a->i == s2);
|
||||
REQUIRE(b->i == s1);
|
||||
|
||||
a = s1;
|
||||
b = tl::unexpected<T2>(s2);
|
||||
swap(a, b);
|
||||
REQUIRE(a.error().i == s2);
|
||||
REQUIRE(b->i == s1);
|
||||
|
||||
a = tl::unexpected<T2>(s1);
|
||||
b = s2;
|
||||
swap(a, b);
|
||||
REQUIRE(a->i == s2);
|
||||
REQUIRE(b.error().i == s1);
|
||||
|
||||
a = tl::unexpected<T2>(s1);
|
||||
b = tl::unexpected<T2>(s2);
|
||||
swap(a, b);
|
||||
REQUIRE(a.error().i == s2);
|
||||
REQUIRE(b.error().i == s1);
|
||||
|
||||
a = s1;
|
||||
b = s2;
|
||||
a.swap(b);
|
||||
REQUIRE(a->i == s2);
|
||||
REQUIRE(b->i == s1);
|
||||
|
||||
a = s1;
|
||||
b = tl::unexpected<T2>(s2);
|
||||
a.swap(b);
|
||||
REQUIRE(a.error().i == s2);
|
||||
REQUIRE(b->i == s1);
|
||||
|
||||
a = tl::unexpected<T2>(s1);
|
||||
b = s2;
|
||||
a.swap(b);
|
||||
REQUIRE(a->i == s2);
|
||||
REQUIRE(b.error().i == s1);
|
||||
|
||||
a = tl::unexpected<T2>(s1);
|
||||
b = tl::unexpected<T2>(s2);
|
||||
a.swap(b);
|
||||
REQUIRE(a.error().i == s2);
|
||||
REQUIRE(b.error().i == s1);
|
||||
}
|
||||
|
||||
#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED
|
||||
TEST_CASE("swap") {
|
||||
|
||||
swap_test<no_throw, no_throw>();
|
||||
swap_test<no_throw, canthrow_move>();
|
||||
swap_test<canthrow_move, no_throw>();
|
||||
|
||||
std::string s1 = "abcdefghijklmnopqrstuvwxyz";
|
||||
std::string s2 = "zyxwvutsrqponmlkjihgfedcbaxxx";
|
||||
tl::expected<no_throw, willthrow_move> a{s1};
|
||||
tl::expected<no_throw, willthrow_move> b{tl::unexpect, s2};
|
||||
should_throw = 1;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
//this seems to break catch on GCC and Clang
|
||||
REQUIRE_THROWS(swap(a, b));
|
||||
#endif
|
||||
|
||||
REQUIRE(a->i == s1);
|
||||
REQUIRE(b.error().i == s2);
|
||||
}
|
||||
#endif // TL_EXPECTED_EXCEPTIONS_ENABLED
|
||||
@@ -0,0 +1,32 @@
|
||||
struct no_throw {
|
||||
no_throw(std::string i) : i(i) {}
|
||||
std::string i;
|
||||
};
|
||||
struct canthrow_move {
|
||||
canthrow_move(std::string i) : i(i) {}
|
||||
canthrow_move(canthrow_move const &) = default;
|
||||
canthrow_move(canthrow_move &&other) noexcept(false) : i(other.i) {}
|
||||
canthrow_move &operator=(canthrow_move &&) = default;
|
||||
std::string i;
|
||||
};
|
||||
|
||||
bool should_throw = false;
|
||||
struct willthrow_move {
|
||||
willthrow_move(std::string i) : i(i) {}
|
||||
willthrow_move(willthrow_move const &) = default;
|
||||
willthrow_move(willthrow_move &&other) : i(other.i) {
|
||||
if (should_throw)
|
||||
throw 0;
|
||||
}
|
||||
willthrow_move &operator=(willthrow_move &&) = default;
|
||||
std::string i;
|
||||
};
|
||||
|
||||
int main() {
|
||||
std::string s1 = "abcdefghijklmnopqrstuvwxyz";
|
||||
std::string s2 = "zyxwvutsrqponmlkjihgfedcbaxxx";
|
||||
tl::expected<no_throw, willthrow_move> a{s1};
|
||||
tl::expected<no_throw, willthrow_move> b{tl::unexpect, s2};
|
||||
should_throw = 1;
|
||||
swap(a, b);
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
Expected 1.1.0
|
||||
https://github.com/TartanLlama/expected
|
||||
@@ -0,0 +1,18 @@
|
||||
###############################################################################
|
||||
# License: BSD Zero Clause License file
|
||||
# Copyright:
|
||||
# (C) 2022 Alexander Shaduri <ashaduri@gmail.com>
|
||||
###############################################################################
|
||||
|
||||
add_library(whereami STATIC)
|
||||
|
||||
target_sources(whereami PRIVATE
|
||||
whereami/src/whereami.cpp
|
||||
whereami/src/whereami.h
|
||||
)
|
||||
|
||||
target_include_directories(whereami
|
||||
SYSTEM PUBLIC
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/whereami/src"
|
||||
)
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
Where Am I?
|
||||
git master 2022-01-15
|
||||
https://github.com/gpakosz/whereami
|
||||
|
||||
whereami.c renamed to whereami.cpp
|
||||
@@ -0,0 +1,18 @@
|
||||
Copyright Gregory Pakosz
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
@@ -0,0 +1,25 @@
|
||||
--------------------------------------------------------------------------------
|
||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
Version 2, December 2004
|
||||
|
||||
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim or modified
|
||||
copies of this license document, and changing it is allowed as long
|
||||
as the name is changed.
|
||||
|
||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. You just DO WHAT THE FUCK YOU WANT TO.
|
||||
1. Bla bla bla
|
||||
2. Montesqieu et camembert, vive la France, zut alors!
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
WTFPLv2 is very permissive, see http://www.wtfpl.net/faq/
|
||||
|
||||
However, if this WTFPLV2 is REALLY a blocker and is the reason you can't use
|
||||
this project, contact me and I'll dual license it.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
@@ -0,0 +1,123 @@
|
||||
# Where Am I?
|
||||
|
||||
A drop-in two files library to locate the current executable and the current
|
||||
module on the file system.
|
||||
|
||||
Supported platforms:
|
||||
|
||||
- Windows
|
||||
- Linux
|
||||
- Mac
|
||||
- iOS
|
||||
- Android
|
||||
- QNX Neutrino
|
||||
- FreeBSD
|
||||
- NetBSD
|
||||
- DragonFly BSD
|
||||
- SunOS
|
||||
- OpenBSD
|
||||
|
||||
Just drop `whereami.h` and `whereami.c` into your build and get started. (see
|
||||
also [customizing compilation])
|
||||
|
||||
[customizing compilation]: #customizing-compilation
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
## Usage
|
||||
|
||||
- `wai_getExecutablePath()` returns the path of the enclosing executable
|
||||
- `wai_getModulePath()` returns the path of the enclosing module
|
||||
|
||||
Example usage:
|
||||
|
||||
- first call `int length = wai_getExecutablePath(NULL, 0, NULL);` to retrieve
|
||||
the length of the path
|
||||
- allocate the destination buffer with `path = (char*)malloc(length + 1);`
|
||||
- call `wai_getExecutablePath(path, length, &dirname_length)` again to retrieve
|
||||
the path
|
||||
- add a terminal `NUL` character with `path[length] = '\0';`
|
||||
|
||||
Here is the output of the example:
|
||||
|
||||
$ make -j -C _gnu-make
|
||||
$ cp ./bin/mac-x86_64/library.dylib /tmp/
|
||||
$ ./bin/mac-x86_64/executable --load-library=/tmp/library.dylib
|
||||
|
||||
executable path: /Users/gregory/Projects/whereami/bin/mac-x86_64/executable
|
||||
dirname: /Users/gregory/Projects/whereami/bin/mac-x86_64
|
||||
basename: executable
|
||||
module path: /Users/gregory/Projects/whereami/bin/mac-x86_64/executable
|
||||
dirname: /Users/gregory/Projects/whereami/bin/mac-x86_64
|
||||
basename: executable
|
||||
|
||||
library loaded
|
||||
executable path: /Users/gregory/Projects/whereami/bin/mac-x86_64/executable
|
||||
dirname: /Users/gregory/Projects/whereami/bin/mac-x86_64
|
||||
basename: executable
|
||||
module path: /private/tmp/library.dylib
|
||||
dirname: /private/tmp
|
||||
basename: library.dylib
|
||||
library unloaded
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
## Customizing compilation
|
||||
|
||||
You can customize the library's behavior by defining the following macros:
|
||||
|
||||
- `WAI_FUNCSPEC`
|
||||
- `WAI_PREFIX`
|
||||
- `WAI_MALLOC`
|
||||
- `WAI_REALLOC`
|
||||
- `WAI_FREE`
|
||||
|
||||
## Compiling for Windows
|
||||
|
||||
There is a Visual Studio 2015 solution in the `_win-vs14/` folder.
|
||||
|
||||
## Compiling for Linux or Mac
|
||||
|
||||
There is a GNU Make 3.81 `MakeFile` in the `_gnu-make/` folder:
|
||||
|
||||
$ make -j -C _gnu-make/
|
||||
|
||||
## Compiling for Mac
|
||||
|
||||
See above if you want to compile from command line. Otherwise there is an Xcode
|
||||
project located in the `_mac-xcode/` folder.
|
||||
|
||||
## Compiling for iOS
|
||||
|
||||
There is an Xcode project located in the `_ios-xcode/` folder.
|
||||
|
||||
If you prefer compiling from command line and deploying to a jailbroken device
|
||||
through SSH, use:
|
||||
|
||||
$ make -j -C _gnu-make/ binsubdir=ios CC="$(xcrun --sdk iphoneos --find clang) -isysroot $(xcrun --sdk iphoneos --show-sdk-path) -arch armv7 -arch armv7s -arch arm64" postbuild="codesign -s 'iPhone Developer'"
|
||||
|
||||
## Compiling for Android
|
||||
|
||||
You will have to install the Android NDK, and point the `$NDK_ROOT` environment
|
||||
variable to the NDK path: e.g. `export NDK_ROOT=/opt/android-ndk` (without a
|
||||
trailing `/` character).
|
||||
|
||||
Next, the easy way is to make a standalone Android toolchain with the following
|
||||
command:
|
||||
|
||||
$ $NDK_ROOT/build/tools/make_standalone_toolchain.py --arch=arm64 --api 21 --install-dir=/tmp/android-toolchain
|
||||
|
||||
Now you can compile the example by running:
|
||||
|
||||
$ make -j -C _gnu-make/ platform=android architecture=arm64 CC=/tmp/android-toolchain/bin/aarch64-linux-android-gcc CXX=/tmp/android-toolchain/bin/aarch64-linux-android-g++
|
||||
|
||||
Loading page aligned library straight from APKs is supported. To test, use the
|
||||
following:
|
||||
|
||||
$ zip -Z store app bin/android/library.so
|
||||
$ zipalign -v -f -p 4 ./app.zip ./app.apk
|
||||
|
||||
Then copy `bin/android/executable` and `app.apk` to your Android device and
|
||||
there launch:
|
||||
|
||||
$ ./executable --load-library=$PWD/app.apk!/bin/android/library.so
|
||||
@@ -0,0 +1,796 @@
|
||||
// (‑●‑●)> dual licensed under the WTFPL v2 and MIT licenses
|
||||
// without any warranty.
|
||||
// by Gregory Pakosz (@gpakosz)
|
||||
// https://github.com/gpakosz/whereami
|
||||
|
||||
// in case you want to #include "whereami.c" in a larger compilation unit
|
||||
#if !defined(WHEREAMI_H)
|
||||
#include <whereami.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if !defined(WAI_MALLOC) || !defined(WAI_FREE) || !defined(WAI_REALLOC)
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#if !defined(WAI_MALLOC)
|
||||
#define WAI_MALLOC(size) malloc(size)
|
||||
#endif
|
||||
|
||||
#if !defined(WAI_FREE)
|
||||
#define WAI_FREE(p) free(p)
|
||||
#endif
|
||||
|
||||
#if !defined(WAI_REALLOC)
|
||||
#define WAI_REALLOC(p, size) realloc(p, size)
|
||||
#endif
|
||||
|
||||
#ifndef WAI_NOINLINE
|
||||
#if defined(_MSC_VER)
|
||||
#define WAI_NOINLINE __declspec(noinline)
|
||||
#elif defined(__GNUC__)
|
||||
#define WAI_NOINLINE __attribute__((noinline))
|
||||
#else
|
||||
#error unsupported compiler
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define WAI_RETURN_ADDRESS() _ReturnAddress()
|
||||
#elif defined(__GNUC__)
|
||||
#define WAI_RETURN_ADDRESS() __builtin_extract_return_addr(__builtin_return_address(0))
|
||||
#else
|
||||
#error unsupported compiler
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32)
|
||||
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(push, 3)
|
||||
#endif
|
||||
#include <windows.h>
|
||||
#include <intrin.h>
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
#include <stdbool.h>
|
||||
|
||||
static int WAI_PREFIX(getModulePath_)(HMODULE module, char* out, int capacity, int* dirname_length)
|
||||
{
|
||||
wchar_t buffer1[MAX_PATH];
|
||||
wchar_t buffer2[MAX_PATH];
|
||||
wchar_t* path = NULL;
|
||||
int length = -1;
|
||||
bool ok;
|
||||
|
||||
for (ok = false; !ok; ok = true)
|
||||
{
|
||||
DWORD size;
|
||||
int length_, length__;
|
||||
|
||||
size = GetModuleFileNameW(module, buffer1, sizeof(buffer1) / sizeof(buffer1[0]));
|
||||
|
||||
if (size == 0)
|
||||
break;
|
||||
else if (size == (DWORD)(sizeof(buffer1) / sizeof(buffer1[0])))
|
||||
{
|
||||
DWORD size_ = size;
|
||||
do
|
||||
{
|
||||
wchar_t* path_;
|
||||
|
||||
path_ = (wchar_t*)WAI_REALLOC(path, sizeof(wchar_t) * size_ * 2);
|
||||
if (!path_)
|
||||
break;
|
||||
size_ *= 2;
|
||||
path = path_;
|
||||
size = GetModuleFileNameW(module, path, size_);
|
||||
}
|
||||
while (size == size_);
|
||||
|
||||
if (size == size_)
|
||||
break;
|
||||
}
|
||||
else
|
||||
path = buffer1;
|
||||
|
||||
if (!_wfullpath(buffer2, path, MAX_PATH))
|
||||
break;
|
||||
length_ = (int)wcslen(buffer2);
|
||||
length__ = WideCharToMultiByte(CP_UTF8, 0, buffer2, length_ , out, capacity, NULL, NULL);
|
||||
|
||||
if (length__ == 0)
|
||||
length__ = WideCharToMultiByte(CP_UTF8, 0, buffer2, length_, NULL, 0, NULL, NULL);
|
||||
if (length__ == 0)
|
||||
break;
|
||||
|
||||
if (length__ <= capacity && dirname_length)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = length__ - 1; i >= 0; --i)
|
||||
{
|
||||
if (out[i] == '\\')
|
||||
{
|
||||
*dirname_length = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
length = length__;
|
||||
}
|
||||
|
||||
if (path != buffer1)
|
||||
WAI_FREE(path);
|
||||
|
||||
return ok ? length : -1;
|
||||
}
|
||||
|
||||
WAI_NOINLINE WAI_FUNCSPEC
|
||||
int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length)
|
||||
{
|
||||
return WAI_PREFIX(getModulePath_)(NULL, out, capacity, dirname_length);
|
||||
}
|
||||
|
||||
WAI_NOINLINE WAI_FUNCSPEC
|
||||
int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length)
|
||||
{
|
||||
HMODULE module;
|
||||
int length = -1;
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4054)
|
||||
#endif
|
||||
if (GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCTSTR)WAI_RETURN_ADDRESS(), &module))
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
{
|
||||
length = WAI_PREFIX(getModulePath_)(module, out, capacity, dirname_length);
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
#elif defined(__linux__) || defined(__CYGWIN__) || defined(__sun) || defined(WAI_USE_PROC_SELF_EXE)
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#if defined(__linux__)
|
||||
#include <linux/limits.h>
|
||||
#else
|
||||
#include <limits.h>
|
||||
#endif
|
||||
#ifndef __STDC_FORMAT_MACROS
|
||||
#define __STDC_FORMAT_MACROS
|
||||
#endif
|
||||
#include <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#if !defined(WAI_PROC_SELF_EXE)
|
||||
#if defined(__sun)
|
||||
#define WAI_PROC_SELF_EXE "/proc/self/path/a.out"
|
||||
#else
|
||||
#define WAI_PROC_SELF_EXE "/proc/self/exe"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
WAI_FUNCSPEC
|
||||
int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length)
|
||||
{
|
||||
char buffer[PATH_MAX];
|
||||
char* resolved = NULL;
|
||||
int length = -1;
|
||||
bool ok;
|
||||
|
||||
for (ok = false; !ok; ok = true)
|
||||
{
|
||||
resolved = realpath(WAI_PROC_SELF_EXE, buffer);
|
||||
if (!resolved)
|
||||
break;
|
||||
|
||||
length = (int)strlen(resolved);
|
||||
if (length <= capacity)
|
||||
{
|
||||
memcpy(out, resolved, length);
|
||||
|
||||
if (dirname_length)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = length - 1; i >= 0; --i)
|
||||
{
|
||||
if (out[i] == '/')
|
||||
{
|
||||
*dirname_length = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ok ? length : -1;
|
||||
}
|
||||
|
||||
#if !defined(WAI_PROC_SELF_MAPS_RETRY)
|
||||
#define WAI_PROC_SELF_MAPS_RETRY 5
|
||||
#endif
|
||||
|
||||
#if !defined(WAI_PROC_SELF_MAPS)
|
||||
#if defined(__sun)
|
||||
#define WAI_PROC_SELF_MAPS "/proc/self/map"
|
||||
#else
|
||||
#define WAI_PROC_SELF_MAPS "/proc/self/maps"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__ANDROID__) || defined(ANDROID)
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <stdbool.h>
|
||||
|
||||
WAI_NOINLINE WAI_FUNCSPEC
|
||||
int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length)
|
||||
{
|
||||
int length = -1;
|
||||
FILE* maps = NULL;
|
||||
|
||||
for (int r = 0; r < WAI_PROC_SELF_MAPS_RETRY; ++r)
|
||||
{
|
||||
maps = fopen(WAI_PROC_SELF_MAPS, "r");
|
||||
if (!maps)
|
||||
break;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
char buffer[PATH_MAX < 1024 ? 1024 : PATH_MAX];
|
||||
uint64_t low, high;
|
||||
char perms[5];
|
||||
uint64_t offset;
|
||||
uint32_t major, minor;
|
||||
char path[PATH_MAX];
|
||||
uint32_t inode;
|
||||
|
||||
if (!fgets(buffer, sizeof(buffer), maps))
|
||||
break;
|
||||
|
||||
if (sscanf(buffer, "%" PRIx64 "-%" PRIx64 " %s %" PRIx64 " %x:%x %u %s\n", &low, &high, perms, &offset, &major, &minor, &inode, path) == 8)
|
||||
{
|
||||
uint64_t addr = (uintptr_t)WAI_RETURN_ADDRESS();
|
||||
if (low <= addr && addr <= high)
|
||||
{
|
||||
char* resolved;
|
||||
|
||||
resolved = realpath(path, buffer);
|
||||
if (!resolved)
|
||||
break;
|
||||
|
||||
length = (int)strlen(resolved);
|
||||
#if defined(__ANDROID__) || defined(ANDROID)
|
||||
if (length > 4
|
||||
&&buffer[length - 1] == 'k'
|
||||
&&buffer[length - 2] == 'p'
|
||||
&&buffer[length - 3] == 'a'
|
||||
&&buffer[length - 4] == '.')
|
||||
{
|
||||
int fd = open(path, O_RDONLY);
|
||||
if (fd == -1)
|
||||
{
|
||||
length = -1; // retry
|
||||
break;
|
||||
}
|
||||
|
||||
char* begin = (char*)mmap(0, offset, PROT_READ, MAP_SHARED, fd, 0);
|
||||
if (begin == MAP_FAILED)
|
||||
{
|
||||
close(fd);
|
||||
length = -1; // retry
|
||||
break;
|
||||
}
|
||||
|
||||
char* p = begin + offset - 30; // minimum size of local file header
|
||||
while (p >= begin) // scan backwards
|
||||
{
|
||||
if (*((uint32_t*)p) == 0x04034b50UL) // local file header signature found
|
||||
{
|
||||
uint16_t length_ = *((uint16_t*)(p + 26));
|
||||
|
||||
if (length + 2 + length_ < (int)sizeof(buffer))
|
||||
{
|
||||
memcpy(&buffer[length], "!/", 2);
|
||||
memcpy(&buffer[length + 2], p + 30, length_);
|
||||
length += 2 + length_;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
--p;
|
||||
}
|
||||
|
||||
munmap(begin, offset);
|
||||
close(fd);
|
||||
}
|
||||
#endif
|
||||
if (length <= capacity)
|
||||
{
|
||||
memcpy(out, resolved, length);
|
||||
|
||||
if (dirname_length)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = length - 1; i >= 0; --i)
|
||||
{
|
||||
if (out[i] == '/')
|
||||
{
|
||||
*dirname_length = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fclose(maps);
|
||||
maps = NULL;
|
||||
|
||||
if (length != -1)
|
||||
break;
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
|
||||
#define _DARWIN_BETTER_REALPATH
|
||||
#include <mach-o/dyld.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <dlfcn.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
WAI_FUNCSPEC
|
||||
int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length)
|
||||
{
|
||||
char buffer1[PATH_MAX];
|
||||
char buffer2[PATH_MAX];
|
||||
char* path = buffer1;
|
||||
char* resolved = NULL;
|
||||
int length = -1;
|
||||
bool ok;
|
||||
|
||||
for (ok = false; !ok; ok = true)
|
||||
{
|
||||
uint32_t size = (uint32_t)sizeof(buffer1);
|
||||
if (_NSGetExecutablePath(path, &size) == -1)
|
||||
{
|
||||
path = (char*)WAI_MALLOC(size);
|
||||
if (!_NSGetExecutablePath(path, &size))
|
||||
break;
|
||||
}
|
||||
|
||||
resolved = realpath(path, buffer2);
|
||||
if (!resolved)
|
||||
break;
|
||||
|
||||
length = (int)strlen(resolved);
|
||||
if (length <= capacity)
|
||||
{
|
||||
memcpy(out, resolved, length);
|
||||
|
||||
if (dirname_length)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = length - 1; i >= 0; --i)
|
||||
{
|
||||
if (out[i] == '/')
|
||||
{
|
||||
*dirname_length = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (path != buffer1)
|
||||
WAI_FREE(path);
|
||||
|
||||
return ok ? length : -1;
|
||||
}
|
||||
|
||||
WAI_NOINLINE WAI_FUNCSPEC
|
||||
int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length)
|
||||
{
|
||||
char buffer[PATH_MAX];
|
||||
char* resolved = NULL;
|
||||
int length = -1;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
Dl_info info;
|
||||
|
||||
if (dladdr(WAI_RETURN_ADDRESS(), &info))
|
||||
{
|
||||
resolved = realpath(info.dli_fname, buffer);
|
||||
if (!resolved)
|
||||
break;
|
||||
|
||||
length = (int)strlen(resolved);
|
||||
if (length <= capacity)
|
||||
{
|
||||
memcpy(out, resolved, length);
|
||||
|
||||
if (dirname_length)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = length - 1; i >= 0; --i)
|
||||
{
|
||||
if (out[i] == '/')
|
||||
{
|
||||
*dirname_length = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
#elif defined(__QNXNTO__)
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <dlfcn.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#if !defined(WAI_PROC_SELF_EXE)
|
||||
#define WAI_PROC_SELF_EXE "/proc/self/exefile"
|
||||
#endif
|
||||
|
||||
WAI_FUNCSPEC
|
||||
int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length)
|
||||
{
|
||||
char buffer1[PATH_MAX];
|
||||
char buffer2[PATH_MAX];
|
||||
char* resolved = NULL;
|
||||
FILE* self_exe = NULL;
|
||||
int length = -1;
|
||||
bool ok;
|
||||
|
||||
for (ok = false; !ok; ok = true)
|
||||
{
|
||||
self_exe = fopen(WAI_PROC_SELF_EXE, "r");
|
||||
if (!self_exe)
|
||||
break;
|
||||
|
||||
if (!fgets(buffer1, sizeof(buffer1), self_exe))
|
||||
break;
|
||||
|
||||
resolved = realpath(buffer1, buffer2);
|
||||
if (!resolved)
|
||||
break;
|
||||
|
||||
length = (int)strlen(resolved);
|
||||
if (length <= capacity)
|
||||
{
|
||||
memcpy(out, resolved, length);
|
||||
|
||||
if (dirname_length)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = length - 1; i >= 0; --i)
|
||||
{
|
||||
if (out[i] == '/')
|
||||
{
|
||||
*dirname_length = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fclose(self_exe);
|
||||
|
||||
return ok ? length : -1;
|
||||
}
|
||||
|
||||
WAI_FUNCSPEC
|
||||
int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length)
|
||||
{
|
||||
char buffer[PATH_MAX];
|
||||
char* resolved = NULL;
|
||||
int length = -1;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
Dl_info info;
|
||||
|
||||
if (dladdr(WAI_RETURN_ADDRESS(), &info))
|
||||
{
|
||||
resolved = realpath(info.dli_fname, buffer);
|
||||
if (!resolved)
|
||||
break;
|
||||
|
||||
length = (int)strlen(resolved);
|
||||
if (length <= capacity)
|
||||
{
|
||||
memcpy(out, resolved, length);
|
||||
|
||||
if (dirname_length)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = length - 1; i >= 0; --i)
|
||||
{
|
||||
if (out[i] == '/')
|
||||
{
|
||||
*dirname_length = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
#elif defined(__DragonFly__) || defined(__FreeBSD__) || \
|
||||
defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__)
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <dlfcn.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#if defined(__OpenBSD__)
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
WAI_FUNCSPEC
|
||||
int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length)
|
||||
{
|
||||
char buffer1[4096];
|
||||
char buffer2[PATH_MAX];
|
||||
char buffer3[PATH_MAX];
|
||||
char** argv = (char**)buffer1;
|
||||
char* resolved = NULL;
|
||||
int length = -1;
|
||||
bool ok;
|
||||
|
||||
for (ok = false; !ok; ok = true)
|
||||
{
|
||||
int mib[4] = { CTL_KERN, KERN_PROC_ARGS, getpid(), KERN_PROC_ARGV };
|
||||
size_t size;
|
||||
|
||||
if (sysctl(mib, 4, NULL, &size, NULL, 0) != 0)
|
||||
break;
|
||||
|
||||
if (size > sizeof(buffer1))
|
||||
{
|
||||
argv = (char**)WAI_MALLOC(size);
|
||||
if (!argv)
|
||||
break;
|
||||
}
|
||||
|
||||
if (sysctl(mib, 4, argv, &size, NULL, 0) != 0)
|
||||
break;
|
||||
|
||||
if (strchr(argv[0], '/'))
|
||||
{
|
||||
resolved = realpath(argv[0], buffer2);
|
||||
if (!resolved)
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
const char* PATH = getenv("PATH");
|
||||
if (!PATH)
|
||||
break;
|
||||
|
||||
size_t argv0_length = strlen(argv[0]);
|
||||
|
||||
const char* begin = PATH;
|
||||
while (1)
|
||||
{
|
||||
const char* separator = strchr(begin, ':');
|
||||
const char* end = separator ? separator : begin + strlen(begin);
|
||||
|
||||
if (end - begin > 0)
|
||||
{
|
||||
if (*(end -1) == '/')
|
||||
--end;
|
||||
|
||||
if (((end - begin) + 1 + argv0_length + 1) <= sizeof(buffer2))
|
||||
{
|
||||
memcpy(buffer2, begin, end - begin);
|
||||
buffer2[end - begin] = '/';
|
||||
memcpy(buffer2 + (end - begin) + 1, argv[0], argv0_length + 1);
|
||||
|
||||
resolved = realpath(buffer2, buffer3);
|
||||
if (resolved)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!separator)
|
||||
break;
|
||||
|
||||
begin = ++separator;
|
||||
}
|
||||
|
||||
if (!resolved)
|
||||
break;
|
||||
}
|
||||
|
||||
length = (int)strlen(resolved);
|
||||
if (length <= capacity)
|
||||
{
|
||||
memcpy(out, resolved, length);
|
||||
|
||||
if (dirname_length)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = length - 1; i >= 0; --i)
|
||||
{
|
||||
if (out[i] == '/')
|
||||
{
|
||||
*dirname_length = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (argv != (char**)buffer1)
|
||||
WAI_FREE(argv);
|
||||
|
||||
return ok ? length : -1;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
WAI_FUNCSPEC
|
||||
int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length)
|
||||
{
|
||||
char buffer1[PATH_MAX];
|
||||
char buffer2[PATH_MAX];
|
||||
char* path = buffer1;
|
||||
char* resolved = NULL;
|
||||
int length = -1;
|
||||
bool ok;
|
||||
|
||||
for (ok = false; !ok; ok = true)
|
||||
{
|
||||
#if defined(__NetBSD__)
|
||||
int mib[4] = { CTL_KERN, KERN_PROC_ARGS, -1, KERN_PROC_PATHNAME };
|
||||
#else
|
||||
int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 };
|
||||
#endif
|
||||
size_t size = sizeof(buffer1);
|
||||
|
||||
if (sysctl(mib, 4, path, &size, NULL, 0) != 0)
|
||||
break;
|
||||
|
||||
resolved = realpath(path, buffer2);
|
||||
if (!resolved)
|
||||
break;
|
||||
|
||||
length = (int)strlen(resolved);
|
||||
if (length <= capacity)
|
||||
{
|
||||
memcpy(out, resolved, length);
|
||||
|
||||
if (dirname_length)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = length - 1; i >= 0; --i)
|
||||
{
|
||||
if (out[i] == '/')
|
||||
{
|
||||
*dirname_length = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ok ? length : -1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
WAI_NOINLINE WAI_FUNCSPEC
|
||||
int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length)
|
||||
{
|
||||
char buffer[PATH_MAX];
|
||||
char* resolved = NULL;
|
||||
int length = -1;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
Dl_info info;
|
||||
|
||||
if (dladdr(WAI_RETURN_ADDRESS(), &info))
|
||||
{
|
||||
resolved = realpath(info.dli_fname, buffer);
|
||||
if (!resolved)
|
||||
break;
|
||||
|
||||
length = (int)strlen(resolved);
|
||||
if (length <= capacity)
|
||||
{
|
||||
memcpy(out, resolved, length);
|
||||
|
||||
if (dirname_length)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = length - 1; i >= 0; --i)
|
||||
{
|
||||
if (out[i] == '/')
|
||||
{
|
||||
*dirname_length = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#error unsupported platform
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,67 @@
|
||||
// (‑●‑●)> dual licensed under the WTFPL v2 and MIT licenses
|
||||
// without any warranty.
|
||||
// by Gregory Pakosz (@gpakosz)
|
||||
// https://github.com/gpakosz/whereami
|
||||
|
||||
#ifndef WHEREAMI_H
|
||||
#define WHEREAMI_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef WAI_FUNCSPEC
|
||||
#define WAI_FUNCSPEC
|
||||
#endif
|
||||
#ifndef WAI_PREFIX
|
||||
#define WAI_PREFIX(function) wai_##function
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Returns the path to the current executable.
|
||||
*
|
||||
* Usage:
|
||||
* - first call `int length = wai_getExecutablePath(NULL, 0, NULL);` to
|
||||
* retrieve the length of the path
|
||||
* - allocate the destination buffer with `path = (char*)malloc(length + 1);`
|
||||
* - call `wai_getExecutablePath(path, length, NULL)` again to retrieve the
|
||||
* path
|
||||
* - add a terminal NUL character with `path[length] = '\0';`
|
||||
*
|
||||
* @param out destination buffer, optional
|
||||
* @param capacity destination buffer capacity
|
||||
* @param dirname_length optional recipient for the length of the dirname part
|
||||
* of the path.
|
||||
*
|
||||
* @return the length of the executable path on success (without a terminal NUL
|
||||
* character), otherwise `-1`
|
||||
*/
|
||||
WAI_FUNCSPEC
|
||||
int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length);
|
||||
|
||||
/**
|
||||
* Returns the path to the current module
|
||||
*
|
||||
* Usage:
|
||||
* - first call `int length = wai_getModulePath(NULL, 0, NULL);` to retrieve
|
||||
* the length of the path
|
||||
* - allocate the destination buffer with `path = (char*)malloc(length + 1);`
|
||||
* - call `wai_getModulePath(path, length, NULL)` again to retrieve the path
|
||||
* - add a terminal NUL character with `path[length] = '\0';`
|
||||
*
|
||||
* @param out destination buffer, optional
|
||||
* @param capacity destination buffer capacity
|
||||
* @param dirname_length optional recipient for the length of the dirname part
|
||||
* of the path.
|
||||
*
|
||||
* @return the length of the module path on success (without a terminal NUL
|
||||
* character), otherwise `-1`
|
||||
*/
|
||||
WAI_FUNCSPEC
|
||||
int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // #ifndef WHEREAMI_H
|
||||
@@ -0,0 +1 @@
|
||||
gsmartcontrol.shaduri.dev
|
||||
@@ -0,0 +1,12 @@
|
||||
remote_theme: clearpathrobotics/jekyll-rtd-theme
|
||||
|
||||
title: GSmartControl
|
||||
description: Hard disk drive and SSD health inspection tool
|
||||
|
||||
# Sitemap
|
||||
url: "https://gsmartcontrol.shaduri.dev" # the base hostname & protocol for your site
|
||||
plugins:
|
||||
- jekyll-sitemap
|
||||
|
||||
exclude:
|
||||
- CNAME
|
||||
@@ -0,0 +1,25 @@
|
||||
|
||||
/* Hide sidebar footer with GitHub links */
|
||||
div.addons-wrap {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Hide page breadcrumbs */
|
||||
div.navigation-top {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Hide a line after page breadcrumbs */
|
||||
div.content > hr {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Customize navbar links */
|
||||
a.caption {
|
||||
text-transform: none !important;
|
||||
padding-left: 12px !important;
|
||||
padding: .5em !important;
|
||||
color: #fff !important;
|
||||
font-weight: normal !important;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,806 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="256px" height="256px" viewBox="0 0 256 256" enable-background="new 0 0 256 256" xml:space="preserve"> <image id="image0" width="256" height="256" x="0" y="0"
|
||||
xlink:href="data:image/png;base64,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" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 61 KiB |