mirror of
https://github.com/open-source-parsers/jsoncpp.git
synced 2025-04-19 15:47:13 +02:00
Compare commits
1381 Commits
svn-releas
...
master
Author | SHA1 | Date | |
---|---|---|---|
![]() |
ca98c98457 | ||
![]() |
037752d9a1 | ||
![]() |
ba004477a6 | ||
![]() |
60ccc1f5de | ||
![]() |
07a8fe6a23 | ||
![]() |
dca8a24cf8 | ||
![]() |
3f86349128 | ||
![]() |
2b3815c90d | ||
![]() |
bd25fc5ea0 | ||
![]() |
8214f717e7 | ||
![]() |
07e3d1b076 | ||
![]() |
871f0cc43b | ||
![]() |
54fc4e28ed | ||
![]() |
76ff1db84d | ||
![]() |
89e2973c75 | ||
![]() |
7f36cdb3ea | ||
![]() |
2067f66d66 | ||
![]() |
3aa1192a00 | ||
![]() |
99e8ca69b1 | ||
![]() |
162ead383d | ||
![]() |
4b1bd4405e | ||
![]() |
f459022786 | ||
![]() |
fa0dff18fd | ||
![]() |
48d2e106a7 | ||
![]() |
2072e2b4e3 | ||
![]() |
fdb529bd06 | ||
![]() |
8d1ea7054f | ||
![]() |
d13801e832 | ||
![]() |
d791737ccd | ||
![]() |
a4a083c307 | ||
![]() |
62f7f3efe6 | ||
![]() |
742c645ab3 | ||
![]() |
31754ce2e2 | ||
![]() |
483f1c310e | ||
![]() |
c04c0c2131 | ||
![]() |
c857395951 | ||
![]() |
d39b0dff0c | ||
![]() |
fd1abe4cca | ||
![]() |
badbbc7185 | ||
![]() |
caf5fb0742 | ||
![]() |
57de64bf69 | ||
![]() |
78893d3961 | ||
![]() |
034976a19d | ||
![]() |
e1a3c64fef | ||
![]() |
3c2205cd97 | ||
![]() |
0a9b9d9c6e | ||
![]() |
c3a986600f | ||
![]() |
073ad7e96e | ||
![]() |
65d92a4313 | ||
![]() |
ccea7db6c3 | ||
![]() |
4290915354 | ||
![]() |
cc28be0590 | ||
![]() |
255ebc54af | ||
![]() |
c8166ddf1c | ||
![]() |
73c94501ed | ||
![]() |
d2a9495fda | ||
![]() |
5c003ecacc | ||
![]() |
6668fa51ee | ||
![]() |
79ade90248 | ||
![]() |
01b11d2e4b | ||
![]() |
cd8173c6d3 | ||
![]() |
69098a18b9 | ||
![]() |
3d9bf8ee54 | ||
![]() |
8190e061bc | ||
![]() |
42e892d96e | ||
![]() |
a1f1613bdd | ||
![]() |
2d55c7445f | ||
![]() |
5defb4ed1a | ||
![]() |
c4904b2c0d | ||
![]() |
54a5432c01 | ||
![]() |
b22302e560 | ||
![]() |
29f9853455 | ||
![]() |
fa747b1ae3 | ||
![]() |
94a6220f7c | ||
![]() |
c39fbdac0f | ||
![]() |
65bb1b1c1d | ||
![]() |
375a1119f8 | ||
![]() |
5fabc5e6d2 | ||
![]() |
ed1ab7ac45 | ||
![]() |
bb34617267 | ||
![]() |
993e4e2828 | ||
![]() |
2af4a4c6c8 | ||
![]() |
a3914b792f | ||
![]() |
cee42e0bd7 | ||
![]() |
62f3e03475 | ||
![]() |
b640795571 | ||
![]() |
94cda30dbd | ||
![]() |
1ee39a6752 | ||
![]() |
b1bd848241 | ||
![]() |
09c5ecd84f | ||
![]() |
fda274ddd2 | ||
![]() |
da9e17d257 | ||
![]() |
ac2870298e | ||
![]() |
c9a976238b | ||
![]() |
eab8ebe644 | ||
![]() |
fe9663e7ed | ||
![]() |
5c4219b8ae | ||
![]() |
be4a512887 | ||
![]() |
940982438d | ||
![]() |
8954092f0a | ||
![]() |
ceae0e3867 | ||
![]() |
30170d651c | ||
![]() |
5f4e10462f | ||
![]() |
bb9db78fe2 | ||
![]() |
1664b6bbf8 | ||
![]() |
5d1cb30e40 | ||
![]() |
c60ebf787a | ||
![]() |
72db276986 | ||
![]() |
9059f5cad0 | ||
![]() |
45733df96c | ||
![]() |
5be07bdc5e | ||
![]() |
bf0cfa5b46 | ||
![]() |
cfc1ad72ad | ||
![]() |
c8453d39d1 | ||
![]() |
632044ad95 | ||
![]() |
b3189a0800 | ||
![]() |
9be5895985 | ||
![]() |
6aba23f4a8 | ||
![]() |
c161f4ac69 | ||
![]() |
75b360af4a | ||
![]() |
e36cff19f0 | ||
![]() |
b8cb8889aa | ||
![]() |
d2d4c74a03 | ||
![]() |
8b7ea09b80 | ||
![]() |
a4fb5db543 | ||
![]() |
d517d598a7 | ||
![]() |
e9b0b96be6 | ||
![]() |
3f0d63b5a9 | ||
![]() |
524234e479 | ||
![]() |
9abf11935c | ||
![]() |
8a5e792f20 | ||
![]() |
30eb5ce128 | ||
![]() |
12ceb01485 | ||
![]() |
edc6239f39 | ||
![]() |
5a0152ae1b | ||
![]() |
c648b0378a | ||
![]() |
a3afd74b80 | ||
![]() |
2cb16b35dc | ||
![]() |
83946a28db | ||
![]() |
91f1553f2c | ||
![]() |
5813ab1bc1 | ||
![]() |
a0b8c3ecb4 | ||
![]() |
b349221938 | ||
![]() |
9e23f66f61 | ||
![]() |
411d88fae8 | ||
![]() |
1ff6bb65a0 | ||
![]() |
8b20b7a317 | ||
![]() |
2e54e8ff1c | ||
![]() |
90ca694e46 | ||
![]() |
3beb37ea14 | ||
![]() |
dc180eb25e | ||
![]() |
a6fe8e27d8 | ||
![]() |
edf528edfa | ||
![]() |
6317f9a406 | ||
![]() |
6bc55ec35d | ||
![]() |
f11611c878 | ||
![]() |
8f7f35c5cd | ||
![]() |
7e5485ab5b | ||
![]() |
92d90250f2 | ||
![]() |
d6c4a8fb2d | ||
![]() |
a3c8642886 | ||
![]() |
2983f5a89a | ||
![]() |
a0bd9adfef | ||
![]() |
9e0d70aa66 | ||
![]() |
f200239d5b | ||
![]() |
cfc3e927fc | ||
![]() |
a481201af1 | ||
![]() |
9704cedb20 | ||
![]() |
781eec4da8 | ||
![]() |
1c8f7d8ae5 | ||
![]() |
554d961625 | ||
![]() |
01db7b7430 | ||
![]() |
d2e6a971f4 | ||
![]() |
53c8e2cb3b | ||
![]() |
645cd0412c | ||
![]() |
ff58fdcc75 | ||
![]() |
82b736734d | ||
![]() |
a86e129983 | ||
![]() |
5fb17a66b8 | ||
![]() |
7429bb2bfa | ||
![]() |
2eb20a938c | ||
![]() |
638ad269e7 | ||
![]() |
ec9302c4ed | ||
![]() |
fb9aaf8112 | ||
![]() |
2703c306a3 | ||
![]() |
c634b98e7d | ||
![]() |
6c9408d128 | ||
![]() |
54bd178bd8 | ||
![]() |
41ffff01d3 | ||
![]() |
b082693b9e | ||
![]() |
a955529e47 | ||
![]() |
f59ac2a1d7 | ||
![]() |
a07b37e4ec | ||
![]() |
aebc7faa4f | ||
![]() |
bdacfd7bc0 | ||
![]() |
c5f66ab816 | ||
![]() |
bcad4e4de2 | ||
![]() |
7329223f58 | ||
![]() |
2e33c218cb | ||
![]() |
ddc0748c4f | ||
![]() |
2ee3b1dbb1 | ||
![]() |
f34bf24bbd | ||
![]() |
c4bc6da87d | ||
![]() |
736409f1b5 | ||
![]() |
7e97345e26 | ||
![]() |
227c7cdfa5 | ||
![]() |
00c2c9f6e4 | ||
![]() |
d448610770 | ||
![]() |
00b979f086 | ||
![]() |
ae4dc9aa62 | ||
![]() |
e9ccbe0145 | ||
![]() |
21e3d21243 | ||
![]() |
c97bd59ff2 | ||
![]() |
81ae1d55f7 | ||
![]() |
18f790fbe7 | ||
![]() |
3013ed48b3 | ||
![]() |
2cb9a5803e | ||
![]() |
c5cb313ca0 | ||
![]() |
abcd3f7b1f | ||
![]() |
d622250c3e | ||
![]() |
db61dba885 | ||
![]() |
7ef0f9fa5b | ||
![]() |
3550a0a939 | ||
![]() |
21ab82916b | ||
![]() |
fd940255ce | ||
![]() |
472adb60ee | ||
![]() |
c92c87b47d | ||
![]() |
b941149a37 | ||
![]() |
2cf939e8c3 | ||
![]() |
7b28698c5c | ||
![]() |
0d27381acf | ||
![]() |
12325b814f | ||
![]() |
b27c83f691 | ||
![]() |
483eba84a7 | ||
![]() |
b3507948e2 | ||
![]() |
645250b669 | ||
![]() |
25c57812e2 | ||
![]() |
9ef812a097 | ||
![]() |
60ba071aac | ||
![]() |
3c32dca892 | ||
![]() |
7924d3ff97 | ||
![]() |
95b3092ce4 | ||
![]() |
f8db40ff83 | ||
![]() |
44bc38f0a1 | ||
![]() |
ddc9e0fcd7 | ||
![]() |
879a5b80ce | ||
![]() |
dc170e30e2 | ||
![]() |
d148e28b9b | ||
![]() |
bcc0472621 | ||
![]() |
c4d1cb1cd1 | ||
![]() |
336c300ca4 | ||
![]() |
400ec89811 | ||
![]() |
181f9eb129 | ||
![]() |
13afd0e455 | ||
![]() |
caa2f3bf42 | ||
![]() |
fdcd2fc232 | ||
![]() |
92cc77392e | ||
![]() |
7e69f15a64 | ||
![]() |
8e01024ce3 | ||
![]() |
6d236e1948 | ||
![]() |
d81a3caece | ||
![]() |
2939d85b84 | ||
![]() |
9725530a4f | ||
![]() |
576b271a04 | ||
![]() |
9d6db96f36 | ||
![]() |
46d35659ef | ||
![]() |
29434414d7 | ||
![]() |
3247202676 | ||
![]() |
0e3b22dd3a | ||
![]() |
786851819e | ||
![]() |
629a727b5f | ||
![]() |
c51d718ead | ||
![]() |
7c7ccbf934 | ||
![]() |
b7feb2d493 | ||
![]() |
5510f14a71 | ||
![]() |
d34479ec34 | ||
![]() |
dd6921f479 | ||
![]() |
101d4797db | ||
![]() |
2690bc9a9a | ||
![]() |
c84f2e19c9 | ||
![]() |
408b466b57 | ||
![]() |
2a3ae0e79f | ||
![]() |
2d211de06e | ||
![]() |
18e51e23fd | ||
![]() |
56c41fbd88 | ||
![]() |
4babd12a25 | ||
![]() |
6935317d84 | ||
![]() |
d5bd1a7716 | ||
![]() |
f7182a0fdc | ||
![]() |
be4dc51c1f | ||
![]() |
12461e5bf1 | ||
![]() |
185dfd592d | ||
![]() |
518875d2ea | ||
![]() |
3e4c8f8f1d | ||
![]() |
83cc92161b | ||
![]() |
85f5b1c8f9 | ||
![]() |
1234f4227b | ||
![]() |
8d2095af3c | ||
![]() |
0155f38b5b | ||
![]() |
5b91551f39 | ||
![]() |
27290cf81d | ||
![]() |
27b9501683 | ||
![]() |
b16abf8ce1 | ||
![]() |
cd1121290a | ||
![]() |
69402d1fbb | ||
![]() |
3e2f8d3ea8 | ||
![]() |
99a99d4032 | ||
![]() |
9a629bc5e1 | ||
![]() |
d76fe5687d | ||
![]() |
eb7bd9546e | ||
![]() |
0adb053294 | ||
![]() |
863aa36165 | ||
![]() |
9a55d22d3d | ||
![]() |
00558b38db | ||
![]() |
433107f1d9 | ||
![]() |
a732207060 | ||
![]() |
36d8cfd768 | ||
![]() |
2ab1d63480 | ||
![]() |
b4ca2db5ff | ||
![]() |
0c1cc6e1a3 | ||
![]() |
d85d75045c | ||
![]() |
2b593a9da8 | ||
![]() |
756a08fbbd | ||
![]() |
2c257590a1 | ||
![]() |
deb6cca214 | ||
![]() |
b9ed29a221 | ||
![]() |
1c2ed7a10f | ||
![]() |
6e7cbf8f54 | ||
![]() |
dc4a7f9b61 | ||
![]() |
21a4185634 | ||
![]() |
d11732043a | ||
![]() |
e3e05c7085 | ||
![]() |
e817e4fc25 | ||
![]() |
b5093e8122 | ||
![]() |
1fc3de7ca1 | ||
![]() |
cbeed7b076 | ||
![]() |
3beadff472 | ||
![]() |
d3d2e17b64 | ||
![]() |
908383abeb | ||
![]() |
fdc0824505 | ||
![]() |
4e8b4e313f | ||
![]() |
31d65711d6 | ||
![]() |
2853b1cdac | ||
![]() |
8b31c6f0fd | ||
![]() |
a3c8e86c0b | ||
![]() |
10a1a38b37 | ||
![]() |
fa61a49b83 | ||
![]() |
f8ad1ab352 | ||
![]() |
056850c44b | ||
![]() |
009a3ad24c | ||
![]() |
7d16e10113 | ||
![]() |
d8723104f3 | ||
![]() |
08ddeed927 | ||
![]() |
97e05c41f2 | ||
![]() |
b3b92df879 | ||
![]() |
892a386018 | ||
![]() |
0417e626c0 | ||
![]() |
2cb1ad5d0c | ||
![]() |
4bfa962967 | ||
![]() |
e50bfefef1 | ||
![]() |
5c8e539af4 | ||
![]() |
ccd077ffce | ||
![]() |
4abf4ec208 | ||
![]() |
9026a16ff5 | ||
![]() |
f64244ed3f | ||
![]() |
6219eae304 | ||
![]() |
b955e0f699 | ||
![]() |
d501fbe741 | ||
![]() |
ec4251b728 | ||
![]() |
a72266d00b | ||
![]() |
010a2d04d3 | ||
![]() |
2baad4923e | ||
![]() |
e32ee4717c | ||
![]() |
80bc776bae | ||
![]() |
da498591fc | ||
![]() |
745287275c | ||
![]() |
c00a3b95c2 | ||
![]() |
c59db80002 | ||
![]() |
473afca1e3 | ||
![]() |
59d41de5b1 | ||
![]() |
b87f6dbc8a | ||
![]() |
ee34ac1fbb | ||
![]() |
d31a5300e1 | ||
![]() |
86789e7c2f | ||
![]() |
c4103ab390 | ||
![]() |
a5d7c714b1 | ||
![]() |
84ca7d6f0b | ||
![]() |
fc20134c92 | ||
![]() |
091e03979d | ||
![]() |
a7d0ffc717 | ||
![]() |
48112c8b62 | ||
![]() |
c8bb600d27 | ||
![]() |
85a263e89f | ||
![]() |
cfab607c0d | ||
![]() |
b5e1fe89aa | ||
![]() |
abd39e791b | ||
![]() |
768e31fc68 | ||
![]() |
aa1b383666 | ||
![]() |
8bf20bdc35 | ||
![]() |
0ba5c435f4 | ||
![]() |
fdcc2e4428 | ||
![]() |
9ebfc8d37b | ||
![]() |
4cec95a2e7 | ||
![]() |
cf73619e28 | ||
![]() |
ded953e0a6 | ||
![]() |
0a62267fe4 | ||
![]() |
2cc9b24f0d | ||
![]() |
6e5e9be736 | ||
![]() |
4050143288 | ||
![]() |
3f0d91f08a | ||
![]() |
02211117f1 | ||
![]() |
323450eafc | ||
![]() |
af17fecd29 | ||
![]() |
ffc62d26f3 | ||
![]() |
a07fc53287 | ||
![]() |
af2598cdd3 | ||
![]() |
1d95628ba8 | ||
![]() |
3e2b8ea9cc | ||
![]() |
1ab310e3ed | ||
![]() |
c7728e8658 | ||
![]() |
313a0e4c34 | ||
![]() |
592d942b3b | ||
![]() |
5b45aa55ca | ||
![]() |
07a324fb14 | ||
![]() |
1ec85c76a4 | ||
![]() |
c27936e0aa | ||
![]() |
04abe38148 | ||
![]() |
edb4bdb7ec | ||
![]() |
0ced843c97 | ||
![]() |
9b569c8ce3 | ||
![]() |
392e3a5b49 | ||
![]() |
c69148c946 | ||
![]() |
2f227cb122 | ||
![]() |
798f6ba055 | ||
![]() |
72f6cc7fd0 | ||
![]() |
d3ce75c74e | ||
![]() |
de5fb8e022 | ||
![]() |
899894f0f5 | ||
![]() |
ddabf50f72 | ||
![]() |
63ab03ca28 | ||
![]() |
41ff85f443 | ||
![]() |
9079422ac1 | ||
![]() |
c39aa295e4 | ||
![]() |
42ca02b833 | ||
![]() |
e6a588a246 | ||
![]() |
7c979e8661 | ||
![]() |
c469326b47 | ||
![]() |
240c85a10c | ||
![]() |
d61cddedac | ||
![]() |
5a2dc7a2ad | ||
![]() |
a06b390187 | ||
![]() |
42a161fc80 | ||
![]() |
a3a4059367 | ||
![]() |
4d587638af | ||
![]() |
75e0c39393 | ||
![]() |
43fd41d1fc | ||
![]() |
7287065b63 | ||
![]() |
9249878229 | ||
![]() |
17c14e73a9 | ||
![]() |
21e133c6fb | ||
![]() |
ff6b449a07 | ||
![]() |
f2f19b03fb | ||
![]() |
026c39fa1a | ||
![]() |
614671d09b | ||
![]() |
132840aaa1 | ||
![]() |
9bb984a594 | ||
![]() |
66d4573206 | ||
![]() |
b29fc9834f | ||
![]() |
1a54511aa1 | ||
![]() |
a7ad98fb82 | ||
![]() |
692164d471 | ||
![]() |
c95a841fef | ||
![]() |
e895eccd18 | ||
![]() |
3b5f8bef41 | ||
![]() |
c89f0282d1 | ||
![]() |
1b68b02ccd | ||
![]() |
adb9ab1424 | ||
![]() |
49da91c786 | ||
![]() |
e8378d1e74 | ||
![]() |
2de18021fc | ||
![]() |
c98e1d85e3 | ||
![]() |
d830c0ab94 | ||
![]() |
90591c70cd | ||
![]() |
4cfae897c0 | ||
![]() |
f4ec601fd3 | ||
![]() |
d40f26d472 | ||
![]() |
c668af9d41 | ||
![]() |
13b5ed7287 | ||
![]() |
6d31cec7cf | ||
![]() |
5331d295aa | ||
![]() |
004270db37 | ||
![]() |
9006194139 | ||
![]() |
6062f9b848 | ||
![]() |
ef16a35328 | ||
![]() |
7354da8077 | ||
![]() |
6a15ca6442 | ||
![]() |
9a048e5766 | ||
![]() |
59e4d35339 | ||
![]() |
f26edb05e5 | ||
![]() |
cadb6dd9a6 | ||
![]() |
ea9f0cec30 | ||
![]() |
ffdcc9355d | ||
![]() |
f45c01a46e | ||
![]() |
3c2069fdd1 | ||
![]() |
414b179d86 | ||
![]() |
0ba8bd73f5 | ||
![]() |
23c44d9f9e | ||
![]() |
8996c377aa | ||
![]() |
a679dde58d | ||
![]() |
c21b4bbfdb | ||
![]() |
d14d8c35c3 | ||
![]() |
ed258de63d | ||
![]() |
154652ee7a | ||
![]() |
4a9d77bcf7 | ||
![]() |
56efb6ba83 | ||
![]() |
7f9cc2705c | ||
![]() |
d7347a2623 | ||
![]() |
2e319850d1 | ||
![]() |
a3d35d7fb8 | ||
![]() |
19fc55f408 | ||
![]() |
acf74290f1 | ||
![]() |
746ef154f1 | ||
![]() |
559b4416e6 | ||
![]() |
6ca374371e | ||
![]() |
f7df408a6a | ||
![]() |
86ed860c4b | ||
![]() |
c442fd96e6 | ||
![]() |
c68443f3a0 | ||
![]() |
11c48d0047 | ||
![]() |
264c3edca7 | ||
![]() |
a47fc398ef | ||
![]() |
2f178f390f | ||
![]() |
f251f15e6a | ||
![]() |
60bfcf1715 | ||
![]() |
81065748e3 | ||
![]() |
11836ae9aa | ||
![]() |
e25fb5384a | ||
![]() |
f700fe4559 | ||
![]() |
d167a09b1c | ||
![]() |
ba158fd22d | ||
![]() |
f3a4941590 | ||
![]() |
0d25d9aebf | ||
![]() |
5021e799dc | ||
![]() |
762ad0fe9d | ||
![]() |
d6e666f573 | ||
![]() |
2ecd2a59de | ||
![]() |
a691cb19de | ||
![]() |
ee7935986e | ||
![]() |
b4abc8241f | ||
![]() |
12e9ef32f9 | ||
![]() |
77632b2611 | ||
![]() |
89aa87bd24 | ||
![]() |
34fc0020c0 | ||
![]() |
f880a9432d | ||
![]() |
5a82131033 | ||
![]() |
1839f2da34 | ||
![]() |
91c1d23461 | ||
![]() |
86f085b810 | ||
![]() |
ac372d2b00 | ||
![]() |
0e24e3c64f | ||
![]() |
89ab7eca7f | ||
![]() |
a1db52b030 | ||
![]() |
1572539bec | ||
![]() |
d8cd848ede | ||
![]() |
92259f7147 | ||
![]() |
4a431bcdac | ||
![]() |
7d868636de | ||
![]() |
ab0f1e234a | ||
![]() |
45a560a8c0 | ||
![]() |
4893a8f667 | ||
![]() |
f6d785fda8 | ||
![]() |
8d54e333ff | ||
![]() |
b063cf4ada | ||
![]() |
c4ab6d733f | ||
![]() |
2f97c0147b | ||
![]() |
52cfe5ae88 | ||
![]() |
a304d61a7b | ||
![]() |
0a97e38ea5 | ||
![]() |
894e78bff1 | ||
![]() |
126bdc2b05 | ||
![]() |
094a7d8564 | ||
![]() |
b9afdf190d | ||
![]() |
80a82ea269 | ||
![]() |
f78f685bab | ||
![]() |
7d8eddb98c | ||
![]() |
7e0571b444 | ||
![]() |
b14c8c1423 | ||
![]() |
b299d3581f | ||
![]() |
48d2a69d47 | ||
![]() |
772e257fc9 | ||
![]() |
101fcf0806 | ||
![]() |
7e4df50d17 | ||
![]() |
318f30357c | ||
![]() |
0f288aecdd | ||
![]() |
e0f9aab0bf | ||
![]() |
43203f1d09 | ||
![]() |
55176b2bdd | ||
![]() |
4356d9bba1 | ||
![]() |
ea4af18317 | ||
![]() |
b999616df8 | ||
![]() |
660307d357 | ||
![]() |
911e2b0fea | ||
![]() |
d4a49cf511 | ||
![]() |
8bd4f943da | ||
![]() |
4018422a05 | ||
![]() |
ba6fa48d31 | ||
![]() |
17fc9b1a80 | ||
![]() |
6f22b0e076 | ||
![]() |
980cdf0fb5 | ||
![]() |
45da594e71 | ||
![]() |
c8a7b445ea | ||
![]() |
c8054483f8 | ||
![]() |
96d32b37ea | ||
![]() |
ef2ff8754a | ||
![]() |
b58c844579 | ||
![]() |
b803b92d11 | ||
![]() |
98e981dff9 | ||
![]() |
1c47796479 | ||
![]() |
12c67e810d | ||
![]() |
c018d9fc3a | ||
![]() |
ae564653c4 | ||
![]() |
f8674c63b1 | ||
![]() |
b50a124fa6 | ||
![]() |
59e327f50b | ||
![]() |
0b597b4b48 | ||
![]() |
d97ea5bf8d | ||
![]() |
e29b671ed5 | ||
![]() |
fbe1cf3916 | ||
![]() |
cf86c473a5 | ||
![]() |
75570d7068 | ||
![]() |
5da29e2707 | ||
![]() |
c80faa400c | ||
![]() |
8aabf93cc1 | ||
![]() |
3e51598176 | ||
![]() |
1b5e61d008 | ||
![]() |
b84e0c159d | ||
![]() |
1e990640a9 | ||
![]() |
38bb491400 | ||
![]() |
724ba29bd3 | ||
![]() |
de5b792168 | ||
![]() |
1b8e3b7f4d | ||
![]() |
4878913143 | ||
![]() |
d179e24c14 | ||
![]() |
ccd70540e3 | ||
![]() |
b4d2b65841 | ||
![]() |
7e46bf76e8 | ||
![]() |
da0c50f7b2 | ||
![]() |
02bc3d77de | ||
![]() |
6b562c850d | ||
![]() |
2713f4f456 | ||
![]() |
83bc9c7cf6 | ||
![]() |
95f120f68e | ||
![]() |
9a4b1e39bf | ||
![]() |
2c872ec997 | ||
![]() |
b860cc38e8 | ||
![]() |
fef4b75796 | ||
![]() |
779d8a33fc | ||
![]() |
d4513fcf45 | ||
![]() |
baefec773c | ||
![]() |
bc72070f43 | ||
![]() |
bc9b445fee | ||
![]() |
2646ac5fa5 | ||
![]() |
2cca1cd239 | ||
![]() |
9234cbbc90 | ||
![]() |
7c93031c9b | ||
![]() |
48bfe91062 | ||
![]() |
0cce773019 | ||
![]() |
6b10ce8c0d | ||
![]() |
34bdbb58b4 | ||
![]() |
527965cbde | ||
![]() |
2b00891a86 | ||
![]() |
a4ce2829dc | ||
![]() |
69e7f1c858 | ||
![]() |
d1a2b94d5b | ||
![]() |
772f634548 | ||
![]() |
9fd1ca8d68 | ||
![]() |
38022157b2 | ||
![]() |
039a6e3b61 | ||
![]() |
9c17e61bd0 | ||
![]() |
c8a8cfcd4b | ||
![]() |
4994c77d09 | ||
![]() |
beae99924f | ||
![]() |
8b9940fd24 | ||
![]() |
b96d90efbd | ||
![]() |
e375b8c89e | ||
![]() |
49393ead06 | ||
![]() |
8df11d518b | ||
![]() |
8e400e9be7 | ||
![]() |
dc5aa4ad7f | ||
![]() |
80def66fa5 | ||
![]() |
6992831c1c | ||
![]() |
7e4875a239 | ||
![]() |
979cbec237 | ||
![]() |
2e625dd9af | ||
![]() |
83ea25e5e2 | ||
![]() |
5721f1ca57 | ||
![]() |
9942f6a1c7 | ||
![]() |
6c14548293 | ||
![]() |
6ee0bff822 | ||
![]() |
e3b35992f8 | ||
![]() |
cc5cdb565c | ||
![]() |
aadd0b1b63 | ||
![]() |
3ee15b7bcc | ||
![]() |
68509e6161 | ||
![]() |
4cea1f6f6c | ||
![]() |
6f9ed421d0 | ||
![]() |
7f7bbeff76 | ||
![]() |
bfffe8cec7 | ||
![]() |
73154fb546 | ||
![]() |
63c747218b | ||
![]() |
2084563efb | ||
![]() |
6329975e6d | ||
![]() |
7acfd599f0 | ||
![]() |
63a961a752 | ||
![]() |
cb2378fa41 | ||
![]() |
37aaaec70e | ||
![]() |
585446e6b3 | ||
![]() |
7f4be39e9f | ||
![]() |
47595e922b | ||
![]() |
9f7dbcb19b | ||
![]() |
c1996256d6 | ||
![]() |
25e4adc4e1 | ||
![]() |
cc2c15c3eb | ||
![]() |
912d55094d | ||
![]() |
d7b84f69c5 | ||
![]() |
9dad198af6 | ||
![]() |
7f06e9dc28 | ||
![]() |
d84702c903 | ||
![]() |
949babd7b0 | ||
![]() |
6ed877c77c | ||
![]() |
1c69568f8d | ||
![]() |
770fdda28b | ||
![]() |
81cf237917 | ||
![]() |
cac79543f8 | ||
![]() |
d8186f36a6 | ||
![]() |
7f240623d3 | ||
![]() |
784433ac72 | ||
![]() |
7275e3ce3c | ||
![]() |
46aa9d75fa | ||
![]() |
f94a0e8989 | ||
![]() |
e22a2f36f7 | ||
![]() |
fac87108a4 | ||
![]() |
14fc9f124e | ||
![]() |
658fa37e63 | ||
![]() |
056e5f9b64 | ||
![]() |
d8e8c14ffc | ||
![]() |
f4e6fccd46 | ||
![]() |
2428889813 | ||
![]() |
89704039a0 | ||
![]() |
6ca8ffcb91 | ||
![]() |
b5e70f950e | ||
![]() |
b26804d1c2 | ||
![]() |
702a539762 | ||
![]() |
81cb7e5c5b | ||
![]() |
d259f608fd | ||
![]() |
4652f818fe | ||
![]() |
ce32274ba5 | ||
![]() |
717c791d4e | ||
![]() |
6e52e272da | ||
![]() |
6416350438 | ||
![]() |
bcb83b921c | ||
![]() |
3f05b1a897 | ||
![]() |
de2c85f576 | ||
![]() |
b389d81bf9 | ||
![]() |
89c51f3457 | ||
![]() |
e6f1cffdd3 | ||
![]() |
64441486ac | ||
![]() |
d5e54d2609 | ||
![]() |
97e093a361 | ||
![]() |
d57ac97db8 | ||
![]() |
31e9962754 | ||
![]() |
5256551b03 | ||
![]() |
6649009ffa | ||
![]() |
2a10f4a3b8 | ||
![]() |
28d086e1d9 | ||
![]() |
a0a7c5f6de | ||
![]() |
fcbab02e4a | ||
![]() |
f4ee48bc21 | ||
![]() |
88184d142b | ||
![]() |
ae177fd901 | ||
![]() |
3f6345234f | ||
![]() |
a53070c42b | ||
![]() |
c09e121aeb | ||
![]() |
4f8ec9d207 | ||
![]() |
0fe61a68f8 | ||
![]() |
43019088f0 | ||
![]() |
0c1c076b7c | ||
![]() |
11130997c3 | ||
![]() |
30bb4ccb67 | ||
![]() |
74143f39e7 | ||
![]() |
56650e83c5 | ||
![]() |
441f8cdfa1 | ||
![]() |
a658759039 | ||
![]() |
0eb0e502c8 | ||
![]() |
e983204906 | ||
![]() |
fe06acb587 | ||
![]() |
1b49a55ea1 | ||
![]() |
13c36e9807 | ||
![]() |
50069d72da | ||
![]() |
24682e37bf | ||
![]() |
c2b988ee74 | ||
![]() |
e255ce31a4 | ||
![]() |
779b5bc5ba | ||
![]() |
63860617b3 | ||
![]() |
9cb88d2ca6 | ||
![]() |
363e51c0a9 | ||
![]() |
240ddb6a1b | ||
![]() |
9dd77dc0ef | ||
![]() |
244b1496e1 | ||
![]() |
c083835261 | ||
![]() |
cbe7e7c9cb | ||
![]() |
be183def8f | ||
![]() |
951bd3d05d | ||
![]() |
1c58876185 | ||
![]() |
2f2034629e | ||
![]() |
7020451b44 | ||
![]() |
80497f102e | ||
![]() |
f9feb66be2 | ||
![]() |
ed495edcc1 | ||
![]() |
3c0a383877 | ||
![]() |
5003983029 | ||
![]() |
871b311e7e | ||
![]() |
cdbc35f6ac | ||
![]() |
4e30c4fcdb | ||
![]() |
0d33cb3639 | ||
![]() |
2250b3c29d | ||
![]() |
9376368d86 | ||
![]() |
5383794cc9 | ||
![]() |
75279ccec2 | ||
![]() |
717b08695e | ||
![]() |
ee4ea0ec3f | ||
![]() |
ce19001238 | ||
![]() |
078f991c57 | ||
![]() |
72b5293695 | ||
![]() |
a63d82d78a | ||
![]() |
ee83f8891c | ||
![]() |
5c448687e1 | ||
![]() |
401e98269e | ||
![]() |
b2a7438d08 | ||
![]() |
62ad140d18 | ||
![]() |
527332d5d5 | ||
![]() |
cada3b951f | ||
![]() |
ff61752444 | ||
![]() |
7f439f4276 | ||
![]() |
3976f17ffd | ||
![]() |
80ca11bb41 | ||
![]() |
2fc08b4ebd | ||
![]() |
239c733ab5 | ||
![]() |
295e73ff3c | ||
![]() |
2a840c105c | ||
![]() |
7ec98dc9fe | ||
![]() |
0fd2875a44 | ||
![]() |
d31151d150 | ||
![]() |
f50145fbda | ||
![]() |
b3e6f3d70f | ||
![]() |
13e063c336 | ||
![]() |
f57da48f48 | ||
![]() |
eaa3fd8eca | ||
![]() |
ff63d034e5 | ||
![]() |
2aa4557e79 | ||
![]() |
37dde9d29d | ||
![]() |
c312dd5ef7 | ||
![]() |
42d7e59fe0 | ||
![]() |
a8104a8035 | ||
![]() |
7b22768c33 | ||
![]() |
19c49a459d | ||
![]() |
99822b27cd | ||
![]() |
8a70297869 | ||
![]() |
24f544996f | ||
![]() |
0c91927da2 | ||
![]() |
493f6dcebe | ||
![]() |
eaa06355e1 | ||
![]() |
effd732aa1 | ||
![]() |
70cd04d49a | ||
![]() |
9e49e3d84a | ||
![]() |
2d653bd15d | ||
![]() |
585b267595 | ||
![]() |
c28610fb5d | ||
![]() |
a53283568f | ||
![]() |
ef21fbc785 | ||
![]() |
25342bac13 | ||
![]() |
2b9abc3ebf | ||
![]() |
e6b46e4503 | ||
![]() |
8a77037320 | ||
![]() |
57ad051f67 | ||
![]() |
b383fdc61e | ||
![]() |
5d79275a5b | ||
![]() |
c1e834a110 | ||
![]() |
0570f9eefb | ||
![]() |
b947b0b3df | ||
![]() |
8051cf6ba7 | ||
![]() |
c8bf184ea9 | ||
![]() |
9998094eee | ||
![]() |
4ac4cac2be | ||
![]() |
4788764844 | ||
![]() |
6c898441e3 | ||
![]() |
7d1f656859 | ||
![]() |
0c66e698fb | ||
![]() |
b9229b7400 | ||
![]() |
f9db82af17 | ||
![]() |
ae71879549 | ||
![]() |
7b3683ccd1 | ||
![]() |
58499031a4 | ||
![]() |
2c8c1ac0ec | ||
![]() |
c58e93b014 | ||
![]() |
eed193e151 | ||
![]() |
4382a7b585 | ||
![]() |
30d923f155 | ||
![]() |
2f4e40bc95 | ||
![]() |
505e086ebc | ||
![]() |
c6582415d8 | ||
![]() |
0ee7e2426f | ||
![]() |
1522e4dfb1 | ||
![]() |
09b8670536 | ||
![]() |
f164288646 | ||
![]() |
3bfd215938 | ||
![]() |
400b744195 | ||
![]() |
bd55164089 | ||
![]() |
4c5832a0be | ||
![]() |
8ba9875962 | ||
![]() |
9c91b995dd | ||
![]() |
e7233bf056 | ||
![]() |
9c90456890 | ||
![]() |
f4be815c86 | ||
![]() |
aa13a8ba40 | ||
![]() |
da0fcfbaa2 | ||
![]() |
3ebba5cea8 | ||
![]() |
acbf4eb2ef | ||
![]() |
56df206847 | ||
![]() |
4dca80da49 | ||
![]() |
249ad9f47f | ||
![]() |
99b8e856f6 | ||
![]() |
89b72e1653 | ||
![]() |
2474989f24 | ||
![]() |
315b8c9f2c | ||
![]() |
29501c4d9f | ||
![]() |
7796f20eab | ||
![]() |
20d09676c2 | ||
![]() |
5a744708fc | ||
![]() |
07f0e9308d | ||
![]() |
052050df07 | ||
![]() |
435d2a2f8d | ||
![]() |
6123bd1505 | ||
![]() |
7477bcfa3a | ||
![]() |
5e3e68af2e | ||
![]() |
04a607d95b | ||
![]() |
db75cdf21e | ||
![]() |
c41609b9f9 | ||
![]() |
b56381a636 | ||
![]() |
f757c18ca0 | ||
![]() |
3cf9175bde | ||
![]() |
a9e1ab302d | ||
![]() |
694dbcb328 | ||
![]() |
732abb80ef | ||
![]() |
f3b3358a0e | ||
![]() |
1357cddf1e | ||
![]() |
8df98f6112 | ||
![]() |
16bdfd8af3 | ||
![]() |
ce799b3aa3 | ||
![]() |
3a65581b20 | ||
![]() |
6451412c99 | ||
![]() |
66a8ba255f | ||
![]() |
249fd18114 | ||
![]() |
a587d04f77 | ||
![]() |
2c1197c2c8 | ||
![]() |
2a94618589 | ||
![]() |
dee4602b8f | ||
![]() |
ea2d167a38 | ||
![]() |
41edda5ebe | ||
![]() |
2941cb3fe2 | ||
![]() |
636121485c | ||
![]() |
fe855fb4dd | ||
![]() |
198cc350c5 | ||
![]() |
5e8595c0e2 | ||
![]() |
38042b3892 | ||
![]() |
3b5f2b85ca | ||
![]() |
7eca3b4e88 | ||
![]() |
999f5912f0 | ||
![]() |
472d29f57b | ||
![]() |
6065a1c142 | ||
![]() |
28a20917b0 | ||
![]() |
177b7b8f22 | ||
![]() |
9da9f84903 | ||
![]() |
54b8e6939a | ||
![]() |
c7b39c2e25 | ||
![]() |
d78caa3851 | ||
![]() |
c6e0688e5a | ||
![]() |
1e21e63853 | ||
![]() |
dea6f8d9a6 | ||
![]() |
648843d148 | ||
![]() |
fe3979cd8a | ||
![]() |
94665eab72 | ||
![]() |
9e4bcf354f | ||
![]() |
9243d602fe | ||
![]() |
beb6f35c63 | ||
![]() |
ceef7f5219 | ||
![]() |
77ce057f14 | ||
![]() |
d49ab5aee1 | ||
![]() |
4d649402b0 | ||
![]() |
489707ff60 | ||
![]() |
5fbfe3cdb9 | ||
![]() |
948f29032e | ||
![]() |
964affd333 | ||
![]() |
c038e08efc | ||
![]() |
74c2d82e19 | ||
![]() |
30726082f3 | ||
![]() |
1e3149ab75 | ||
![]() |
7312b1022d | ||
![]() |
2f046b584d | ||
![]() |
dd91914b1b | ||
![]() |
2a46e295ec | ||
![]() |
f4bc0bf4ec | ||
![]() |
f357688893 | ||
![]() |
bb0c80b3e5 | ||
![]() |
ff5abe76a5 | ||
![]() |
9cc0bb80b2 | ||
![]() |
494950a63d | ||
![]() |
7d82b14726 | ||
![]() |
2bc6137ada | ||
![]() |
201904bfbb | ||
![]() |
216ecd3085 | ||
![]() |
8d15e51228 | ||
![]() |
9fbd12b27c | ||
![]() |
f8ca6cbb25 | ||
![]() |
d383056fbb | ||
![]() |
ddb4ff7dec | ||
![]() |
3efc587fba | ||
![]() |
70704b9a70 | ||
![]() |
ac6bbbc739 | ||
![]() |
26c52861b9 | ||
![]() |
3682f60927 | ||
![]() |
58c31ac550 | ||
![]() |
08cfd02d8c | ||
![]() |
79211e1aeb | ||
![]() |
632c9b5032 | ||
![]() |
05810a7607 | ||
![]() |
942e2c999a | ||
![]() |
2160c9a042 | ||
![]() |
ee8b58f82f | ||
![]() |
9132aa94b1 | ||
![]() |
76746b09fc | ||
![]() |
70b795bd45 | ||
![]() |
26842530f2 | ||
![]() |
e3f24286c1 | ||
![]() |
00b8ce81db | ||
![]() |
40810fe326 | ||
![]() |
59167d8627 | ||
![]() |
05c1b8344d | ||
![]() |
e893625e88 | ||
![]() |
e87e41cdb0 | ||
![]() |
9de2c2d84d | ||
![]() |
7956ccd61e | ||
![]() |
9454e687a3 | ||
![]() |
46a925ba4a | ||
![]() |
c407f1407f | ||
![]() |
ec251df6b7 | ||
![]() |
51c0afab22 | ||
![]() |
e39fb0083c | ||
![]() |
ec727e2f6b | ||
![]() |
4ce4bb8404 | ||
![]() |
2cd0f4ec21 | ||
![]() |
836f0fb863 | ||
![]() |
37644abd77 | ||
![]() |
66eb72f121 | ||
![]() |
94b0297dc5 | ||
![]() |
55db3c3cb2 | ||
![]() |
c07ef37904 | ||
![]() |
62ab94ddd3 | ||
![]() |
09d352ac13 | ||
![]() |
50753bb808 | ||
![]() |
8f3aa220db | ||
![]() |
73e127892e | ||
![]() |
4997dfb8af | ||
![]() |
c1441ef5e0 | ||
![]() |
e0bfb45000 | ||
![]() |
4bc311503c | ||
![]() |
cd140b5141 | ||
![]() |
01aee4a0dc | ||
![]() |
59a01652ab | ||
![]() |
8371a4337c | ||
![]() |
dc2e1c98b9 | ||
![]() |
d98b5f4230 | ||
![]() |
4ca9d25ccc | ||
![]() |
6eaf150dc7 | ||
![]() |
8b489f891a | ||
![]() |
65cee6ea16 | ||
![]() |
dfc5f879c1 | ||
![]() |
1a4dc3a888 | ||
![]() |
0f6884f771 | ||
![]() |
748328a0d1 | ||
![]() |
f44278cd4e | ||
![]() |
d2b6992f3e | ||
![]() |
54764dd85b | ||
![]() |
8dd32e1e2e | ||
![]() |
3fd7f8b470 | ||
![]() |
e99e6d9cc6 | ||
![]() |
9ca1aaab14 | ||
![]() |
27639ce578 | ||
![]() |
f8a3a599ac | ||
![]() |
7165f6ac4c | ||
![]() |
37a9fa9f9d | ||
![]() |
83683da13f | ||
![]() |
e5de78db82 | ||
![]() |
ffd7295ab8 | ||
![]() |
433876866d | ||
![]() |
bd1e895287 | ||
![]() |
9aa6144b2a | ||
![]() |
5fda247dab | ||
![]() |
767713be2b | ||
![]() |
3e3a8d5bd2 | ||
![]() |
abc1e07543 | ||
![]() |
00b0a1b992 | ||
![]() |
1fe6c59827 | ||
![]() |
20672ed02c | ||
![]() |
8eb5d89db6 | ||
![]() |
9c80798038 | ||
![]() |
72e5223658 | ||
![]() |
dc84d96a49 | ||
![]() |
1c3a20de50 | ||
![]() |
533dbe0898 | ||
![]() |
6cb2f7bd65 | ||
![]() |
b84a39cae5 | ||
![]() |
7bd75b0fb4 | ||
![]() |
f74a4ff17a | ||
![]() |
b7eccbb110 | ||
![]() |
ebe2d6e6ee | ||
![]() |
4cd31f01bb | ||
![]() |
ab19fa1d6f | ||
![]() |
bc8b5d871f | ||
![]() |
fd06bfca79 | ||
![]() |
4d23492d11 | ||
![]() |
aa650c5b9d | ||
![]() |
ae5a56f9ff | ||
![]() |
8aec8d88f2 | ||
![]() |
9dc9026e0b | ||
![]() |
4002f8a4be | ||
![]() |
0375af2eb5 | ||
![]() |
ba330893d7 | ||
![]() |
57dde78308 | ||
![]() |
69c324ead5 | ||
![]() |
263a4706fa | ||
![]() |
4bceabf2f9 | ||
![]() |
877dd17206 | ||
![]() |
16709c6ee8 | ||
![]() |
b2a1ca5b54 | ||
![]() |
9aa4681052 | ||
![]() |
af77b5b594 | ||
![]() |
11086dd6a7 | ||
![]() |
30b07c0275 | ||
![]() |
32009b17e4 | ||
![]() |
b4357fa224 | ||
![]() |
540db3b052 | ||
![]() |
f4b06cd607 | ||
![]() |
dd5b57a3d9 | ||
![]() |
6270858c43 | ||
![]() |
d9ced92d40 | ||
![]() |
8f730b8a60 | ||
![]() |
b061ff4a1e | ||
![]() |
8ececfa538 | ||
![]() |
d2fa664a12 | ||
![]() |
b7894977e7 | ||
![]() |
53262c66d9 | ||
![]() |
09228968ea | ||
![]() |
83b43caf8e | ||
![]() |
0dc03d0848 | ||
![]() |
45cd9490cd | ||
![]() |
236db83742 | ||
![]() |
a70b00750d | ||
![]() |
033677cc1a | ||
![]() |
9d694516a0 | ||
![]() |
d94caac1ea | ||
![]() |
8eb6f88a87 | ||
![]() |
64d591b720 | ||
![]() |
fe2cd01e80 | ||
![]() |
b02ff20bd3 | ||
![]() |
5bf16105b5 | ||
![]() |
3515db184a | ||
![]() |
48d9a92a1b | ||
![]() |
f97723dbb7 | ||
![]() |
1a6426ac19 | ||
![]() |
bc5dbc6d41 | ||
![]() |
1ac2295c21 | ||
![]() |
81d16dfda1 | ||
![]() |
c138933784 | ||
![]() |
b3deb61f87 | ||
![]() |
740e0207b1 | ||
![]() |
97c77b4a86 | ||
![]() |
7ebdabc059 | ||
![]() |
c6d9424f71 | ||
![]() |
19d0ece5f9 | ||
![]() |
35e4f2abd6 | ||
![]() |
b548cdf49c | ||
![]() |
3b9b7402fd | ||
![]() |
3585477f33 | ||
![]() |
27e3263894 | ||
![]() |
8582876c5c | ||
![]() |
496c655523 | ||
![]() |
49c732607b | ||
![]() |
655a9db0cc | ||
![]() |
f3989977c0 | ||
![]() |
60f778b9fc | ||
![]() |
50f6779578 | ||
![]() |
5a65132e72 | ||
![]() |
bef834edca | ||
![]() |
0973f2e6bc | ||
![]() |
5031a59518 | ||
![]() |
5850b83a5b | ||
![]() |
9dd7eea945 | ||
![]() |
35bea41bc9 | ||
![]() |
542cd1d3f5 | ||
![]() |
ba50403414 | ||
![]() |
0db9d6ea01 | ||
![]() |
b8aaa03367 | ||
![]() |
06dcb1fc89 | ||
![]() |
973de3988b | ||
![]() |
41b79398a3 | ||
![]() |
66b77384d8 | ||
![]() |
17c244e644 | ||
![]() |
8050d8b677 | ||
![]() |
28836b8acc | ||
![]() |
47f1577fd3 | ||
![]() |
9cc184146f | ||
![]() |
c151549937 | ||
![]() |
d61fa29da8 | ||
![]() |
b2a086adeb | ||
![]() |
8d0f8d0dcd | ||
![]() |
49ed6c9774 | ||
![]() |
38c9826423 | ||
![]() |
969921748b | ||
![]() |
ff22ca7973 | ||
![]() |
4b687640cb | ||
![]() |
3a0c4fcc82 | ||
![]() |
445328ace6 | ||
![]() |
9fa4e849a1 | ||
![]() |
1b137a3802 | ||
![]() |
fd6ada015e | ||
![]() |
8540868347 | ||
![]() |
2de98d9bd1 | ||
![]() |
6764059395 | ||
![]() |
5d32295a6e | ||
![]() |
68db655347 | ||
![]() |
642befc836 | ||
![]() |
77cd83890d | ||
![]() |
09439b7bc7 | ||
![]() |
ea0797351f | ||
![]() |
94d17e9fdf | ||
![]() |
a3f19c23a0 | ||
![]() |
d2618806ba | ||
![]() |
36400ac0c1 | ||
![]() |
32ffb931e7 | ||
![]() |
bb53cd0899 | ||
![]() |
4c531bb584 | ||
![]() |
42d918b7aa | ||
![]() |
700b38020e | ||
![]() |
7b62ceacee | ||
![]() |
cb5ae30f6e | ||
![]() |
58b6541478 | ||
![]() |
1ccfdfcb9b | ||
![]() |
71860de813 | ||
![]() |
c515b8ec30 | ||
![]() |
5fff185aa4 | ||
![]() |
10712e85d6 | ||
![]() |
53c08ad916 | ||
![]() |
79e90fba0b | ||
![]() |
ce277aa6e4 | ||
![]() |
eafd702a17 | ||
![]() |
a8afdd40af | ||
![]() |
f92ace5e82 | ||
![]() |
3f124172ce | ||
![]() |
f8715856f3 | ||
![]() |
42321f24a6 | ||
![]() |
aff1171153 | ||
![]() |
ae3c7a7aab | ||
![]() |
f572e8e42e | ||
![]() |
2b853c4067 | ||
![]() |
7c507d7eba | ||
![]() |
c3763f55da | ||
![]() |
3b3540d9ef | ||
![]() |
9d317c3794 | ||
![]() |
03288e8eb6 | ||
![]() |
c9f91dd929 | ||
![]() |
2ba3bc3252 | ||
![]() |
ac5df77bbc | ||
![]() |
468564b3fe | ||
![]() |
dc0f736f59 | ||
![]() |
139da63aef | ||
![]() |
d496e044b1 | ||
![]() |
f587e6a420 | ||
![]() |
f0b24e705f | ||
![]() |
e807a7640e | ||
![]() |
d3cd9a7fc5 | ||
![]() |
a2fb7fb918 | ||
![]() |
4b819c2309 | ||
![]() |
c649badb95 | ||
![]() |
a9eb1eccc0 | ||
![]() |
6ffff91c54 | ||
![]() |
acdefb0869 | ||
![]() |
c025697ea5 | ||
![]() |
b0ec41c3e3 | ||
![]() |
2a2b5cf3ad | ||
![]() |
b6620e2801 | ||
![]() |
ccde848fd1 | ||
![]() |
e082248001 | ||
![]() |
7b5edd9859 | ||
![]() |
e91a68cb9e | ||
![]() |
1b138e8544 | ||
![]() |
4f081b50e6 | ||
![]() |
3c9fdeb859 | ||
![]() |
4b79fd1a00 | ||
![]() |
e12d84ebaa | ||
![]() |
078e0d7c37 | ||
![]() |
fee49b1a37 | ||
![]() |
22eede44c1 | ||
![]() |
d9ec234fc2 | ||
![]() |
3e5b347f75 | ||
![]() |
96408a30e1 | ||
![]() |
1d648f089a | ||
![]() |
f40c880585 | ||
![]() |
39ba2dbea9 | ||
![]() |
a761530f14 | ||
![]() |
ae9ffb5443 | ||
![]() |
e656c5fa2d | ||
![]() |
f1053e7acb | ||
![]() |
e3d0eca9f4 | ||
![]() |
a77a803c85 | ||
![]() |
785ba2675d | ||
![]() |
3b556ec633 | ||
![]() |
5fb0f09cbb | ||
![]() |
73911f2e33 | ||
![]() |
d21c256fae | ||
![]() |
72c406b550 | ||
![]() |
eadc478e50 | ||
![]() |
1837a1c508 | ||
![]() |
e3cc0f004b | ||
![]() |
fb17080142 | ||
![]() |
e0e1fd37cd | ||
![]() |
d0a9f3d98d | ||
![]() |
7953a801c1 | ||
![]() |
df4de558c3 | ||
![]() |
62d7bc75db | ||
![]() |
224a1aee72 | ||
![]() |
40388494bd | ||
![]() |
bafb43c203 | ||
![]() |
64e40aafe5 | ||
![]() |
91923f2cbc | ||
![]() |
13698b5835 | ||
![]() |
5349225f43 | ||
![]() |
b2e8cccbc6 | ||
![]() |
99043b32b5 | ||
![]() |
9c98f2277b | ||
![]() |
565a1f3d39 | ||
![]() |
61324b5f77 | ||
![]() |
842e9ac54b | ||
![]() |
5c5628aec2 | ||
![]() |
b96aed0f3e | ||
![]() |
fa130ef871 | ||
![]() |
e6046e589e | ||
![]() |
402c13eb3d | ||
![]() |
7469f1d014 | ||
![]() |
201fb2cf0d | ||
![]() |
377d21e145 | ||
![]() |
afd9cef928 | ||
![]() |
d38ba2a2cb | ||
![]() |
130730ffd7 | ||
![]() |
e1b26455e7 | ||
![]() |
cd6cb5d0e6 | ||
![]() |
0a899589c2 | ||
![]() |
a11e47d9ad | ||
![]() |
59ff11281a | ||
![]() |
e6a77410f4 | ||
![]() |
0c5fff142d | ||
![]() |
d89d7961d6 | ||
![]() |
64ba062076 | ||
![]() |
35bdc07ebd | ||
![]() |
e94d2f483b | ||
![]() |
7c171ee726 | ||
![]() |
fcf145ecd4 | ||
![]() |
1f4847cbd9 | ||
![]() |
35503e5917 | ||
![]() |
57ee0e3b37 | ||
![]() |
8d3790d217 |
4
.clang-format
Normal file
4
.clang-format
Normal file
@ -0,0 +1,4 @@
|
||||
BasedOnStyle: LLVM
|
||||
DerivePointerAlignment: false
|
||||
PointerAlignment: Left
|
||||
SpacesBeforeTrailingComments: 1
|
11
.clang-tidy
Normal file
11
.clang-tidy
Normal file
@ -0,0 +1,11 @@
|
||||
---
|
||||
Checks: 'google-readability-casting,modernize-deprecated-headers,modernize-loop-convert,modernize-use-auto,modernize-use-default-member-init,modernize-use-using,readability-else-after-return,readability-redundant-member-init,readability-redundant-string-cstr'
|
||||
WarningsAsErrors: ''
|
||||
HeaderFilterRegex: ''
|
||||
AnalyzeTemporaryDtors: false
|
||||
FormatStyle: none
|
||||
CheckOptions:
|
||||
- key: modernize-use-using.IgnoreMacros
|
||||
value: '0'
|
||||
...
|
||||
|
11
.gitattributes
vendored
Normal file
11
.gitattributes
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
* text=auto
|
||||
*.h text
|
||||
*.cpp text
|
||||
*.json text
|
||||
*.in text
|
||||
*.sh eol=lf
|
||||
*.bat eol=crlf
|
||||
*.vcproj eol=crlf
|
||||
*.vcxproj eol=crlf
|
||||
*.sln eol=crlf
|
||||
devtools/agent_vm* eol=crlf
|
26
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
26
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
1.
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Desktop (please complete the following information):**
|
||||
- OS: [e.g. iOS]
|
||||
- Meson version
|
||||
- Ninja version
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**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.
|
20
.github/workflows/clang-format.yml
vendored
Normal file
20
.github/workflows/clang-format.yml
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
name: clang-format check
|
||||
on: [check_run, pull_request, push]
|
||||
|
||||
jobs:
|
||||
formatting-check:
|
||||
name: formatting check
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
path:
|
||||
- 'src'
|
||||
- 'examples'
|
||||
- 'include'
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: runs clang-format style check for C/C++/Protobuf programs.
|
||||
uses: jidicula/clang-format-action@v4.13.0
|
||||
with:
|
||||
clang-format-version: '18'
|
||||
check-path: ${{ matrix.path }}
|
18
.github/workflows/cmake.yml
vendored
Normal file
18
.github/workflows/cmake.yml
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
name: cmake
|
||||
on: [check_run, push, pull_request]
|
||||
jobs:
|
||||
cmake-publish:
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
|
||||
steps:
|
||||
- name: checkout project
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: build project
|
||||
uses: threeal/cmake-action@v2.0.0
|
||||
|
65
.github/workflows/meson.yml
vendored
Normal file
65
.github/workflows/meson.yml
vendored
Normal file
@ -0,0 +1,65 @@
|
||||
name: meson build and test
|
||||
run-name: update pushed to ${{ github.ref }}
|
||||
on: [check_run, push, pull_request]
|
||||
|
||||
jobs:
|
||||
meson-publish:
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: setup python
|
||||
uses: actions/setup-python@v5
|
||||
|
||||
- name: meson build
|
||||
uses: BSFishy/meson-build@v1.0.3
|
||||
with:
|
||||
meson-version: 1.5.1
|
||||
ninja-version: 1.11.1.1
|
||||
action: build
|
||||
|
||||
- name: meson test
|
||||
uses: BSFishy/meson-build@v1.0.3
|
||||
with:
|
||||
meson-version: 1.5.1
|
||||
ninja-version: 1.11.1.1
|
||||
action: test
|
||||
|
||||
meson-coverage:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: setup python
|
||||
uses: actions/setup-python@v5
|
||||
|
||||
- name: meson build
|
||||
uses: BSFishy/meson-build@v1.0.3
|
||||
with:
|
||||
meson-version: 1.5.1
|
||||
ninja-version: 1.11.1.1
|
||||
setup-options: -Db_coverage=true
|
||||
action: build
|
||||
|
||||
- name: meson test
|
||||
uses: BSFishy/meson-build@v1.0.3
|
||||
with:
|
||||
meson-version: 1.5.1
|
||||
ninja-version: 1.11.1.1
|
||||
setup-options: -Db_coverage=true
|
||||
action: test
|
||||
|
||||
- name: generate code coverage report
|
||||
uses: threeal/gcovr-action@v1.0.0
|
||||
with:
|
||||
coveralls-send: true
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
61
.gitignore
vendored
Normal file
61
.gitignore
vendored
Normal file
@ -0,0 +1,61 @@
|
||||
/build/
|
||||
/build-*/
|
||||
*.pyc
|
||||
*.swp
|
||||
*.actual
|
||||
*.actual-rewrite
|
||||
*.process-output
|
||||
*.rewrite
|
||||
/bin/
|
||||
/libs/
|
||||
/doc/doxyfile
|
||||
/dist/
|
||||
/.cache/
|
||||
|
||||
# MSVC project files:
|
||||
*.sln
|
||||
*.vcxproj
|
||||
*.filters
|
||||
*.user
|
||||
*.sdf
|
||||
*.opensdf
|
||||
*.suo
|
||||
|
||||
# MSVC build files:
|
||||
*.lib
|
||||
*.obj
|
||||
*.tlog/
|
||||
*.pdb
|
||||
|
||||
# CMake-generated files:
|
||||
CMakeFiles/
|
||||
/pkg-config/jsoncpp.pc
|
||||
jsoncpp_lib_static.dir/
|
||||
compile_commands.json
|
||||
|
||||
# In case someone runs cmake in the root-dir:
|
||||
/CMakeCache.txt
|
||||
/Makefile
|
||||
/include/Makefile
|
||||
/src/Makefile
|
||||
/src/jsontestrunner/Makefile
|
||||
/src/jsontestrunner/jsontestrunner_exe
|
||||
/src/lib_json/Makefile
|
||||
/src/test_lib_json/Makefile
|
||||
/src/test_lib_json/jsoncpp_test
|
||||
*.a
|
||||
|
||||
# eclipse project files
|
||||
.project
|
||||
.cproject
|
||||
/.settings/
|
||||
|
||||
# DS_Store
|
||||
.DS_Store
|
||||
|
||||
# temps
|
||||
/version
|
||||
|
||||
# Bazel output paths
|
||||
/bazel-*
|
||||
/MODULE.bazel.lock
|
114
AUTHORS
114
AUTHORS
@ -1 +1,115 @@
|
||||
Baptiste Lepilleur <blep@users.sourceforge.net>
|
||||
|
||||
Aaron Jacobs <aaronjjacobs@gmail.com>
|
||||
Aaron Jacobs <jacobsa@google.com>
|
||||
Adam Boseley <ABoseley@agjunction.com>
|
||||
Adam Boseley <adam.boseley@gmail.com>
|
||||
Aleksandr Derbenev <13alexac@gmail.com>
|
||||
Alexander Gazarov <DrMetallius@users.noreply.github.com>
|
||||
Alexander V. Brezgin <abrezgin@appliedtech.ru>
|
||||
Alexandr Brezgin <albrezgin@mail.ru>
|
||||
Alexey Kruchinin <alexey@mopals.com>
|
||||
Anton Indrawan <anton.indrawan@gmail.com>
|
||||
Baptiste Jonglez <git@bitsofnetworks.org>
|
||||
Baptiste Lepilleur <baptiste.lepilleur@gmail.com>
|
||||
Baruch Siach <baruch@tkos.co.il>
|
||||
Ben Boeckel <mathstuf@gmail.com>
|
||||
Benjamin Knecht <bknecht@logitech.com>
|
||||
Bernd Kuhls <bernd.kuhls@t-online.de>
|
||||
Billy Donahue <billy.donahue@gmail.com>
|
||||
Braden McDorman <bmcdorman@gmail.com>
|
||||
Brandon Myers <bmyers1788@gmail.com>
|
||||
Brendan Drew <brendan.drew@daqri.com>
|
||||
chason <cxchao802@gmail.com>
|
||||
chenguoping <chenguopingdota@163.com>
|
||||
Chris Gilling <cgilling@iparadigms.com>
|
||||
Christopher Dawes <christopher.dawes.1981@googlemail.com>
|
||||
Christopher Dunn <cdunn2001@gmail.com>
|
||||
Chuck Atkins <chuck.atkins@kitware.com>
|
||||
Cody P Schafer <dev@codyps.com>
|
||||
Connor Manning <connor@hobu.co>
|
||||
Cory Quammen <cory.quammen@kitware.com>
|
||||
Cristóvão B da Cruz e Silva <CrisXed@gmail.com>
|
||||
Daniel Krügler <daniel.kruegler@gmail.com>
|
||||
Dani-Hub <daniel.kruegler@googlemail.com>
|
||||
Dan Liu <gzliudan>
|
||||
datadiode <datadiode@users.noreply.github.com>
|
||||
datadiode <jochen.neubeck@vodafone.de>
|
||||
David Seifert <soap@gentoo.org>
|
||||
David West <david-west@idexx.com>
|
||||
dawesc <chris.dawes@eftlab.co.uk>
|
||||
Devin Jeanpierre <jeanpierreda@google.com>
|
||||
Dmitry Marakasov <amdmi3@amdmi3.ru>
|
||||
dominicpezzuto <dom@dompezzuto.com>
|
||||
Don Milham <dmilham@gmail.com>
|
||||
drgler <daniel.kruegler@gmail.com>
|
||||
ds283 <D.Seery@sussex.ac.uk>
|
||||
Egor Tensin <Egor.Tensin@gmail.com>
|
||||
eightnoteight <mr.eightnoteight@gmail.com>
|
||||
Evince <baneyue@gmail.com>
|
||||
filipjs <filipjs@users.noreply.github.com>
|
||||
findblar <ft@finbarr.ca>
|
||||
Florian Meier <florian.meier@koalo.de>
|
||||
Gaëtan Lehmann <gaetan.lehmann@gmail.com>
|
||||
Gaurav <g.gupta@samsung.com>
|
||||
Gergely Nagy <ngg@ngg.hu>
|
||||
Gida Pataki <gida.pataki@prezi.com>
|
||||
I3ck <buckmartin@buckmartin.de>
|
||||
Iñaki Baz Castillo <ibc@aliax.net>
|
||||
Jacco <jacco@geul.net>
|
||||
Jean-Christophe Fillion-Robin <jchris.fillionr@kitware.com>
|
||||
Jonas Platte <mail@jonasplatte.de>
|
||||
Jordan Bayles <bayles.jordan@gmail.com>
|
||||
Jörg Krause <joerg.krause@embedded.rocks>
|
||||
Keith Lea <keith@whamcitylights.com>
|
||||
Kevin Grant <kbradleygrant@gmail.com>
|
||||
Kirill V. Lyadvinsky <jia3ep@gmail.com>
|
||||
Kirill V. Lyadvinsky <mail@codeatcpp.com>
|
||||
Kobi Gurkan <kobigurk@gmail.com>
|
||||
Magnus Bjerke Vik <mbvett@gmail.com>
|
||||
Malay Shah <malays@users.sourceforge.net>
|
||||
Mara Kim <hacker.root@gmail.com>
|
||||
Marek Kotewicz <marek.kotewicz@gmail.com>
|
||||
Mark Lakata <mark@lakata.org>
|
||||
Mark Zeren <mzeren@vmware.com>
|
||||
Martin Buck <buckmartin@buckmartin.de>
|
||||
Martyn Gigg <martyn.gigg@gmail.com>
|
||||
Mattes D <github@xoft.cz>
|
||||
Matthias Loy <matthias.loy@hbm.com>
|
||||
Merlyn Morgan-Graham <kavika@gmail.com>
|
||||
Michael Shields <mshields@google.com>
|
||||
Michał Górny <mgorny@gentoo.org>
|
||||
Mike Naberezny <mike@naberezny.com>
|
||||
mloy <matthias.loy@googlemail.com>
|
||||
Motti <lanzkron@gmail.com>
|
||||
nnkur <nnkur@mail.ru>
|
||||
Omkar Wagh <owagh@owaghlinux.ny.tower-research.com>
|
||||
paulo <paulobrizolara@users.noreply.github.com>
|
||||
pavel.pimenov <pavel.pimenov@gmail.com>
|
||||
Paweł Bylica <chfast@gmail.com>
|
||||
Péricles Lopes Machado <pericles.raskolnikoff@gmail.com>
|
||||
Peter Spiess-Knafl <psk@autistici.org>
|
||||
pffang <pffang@vip.qq.com>
|
||||
Rémi Verschelde <remi@verschelde.fr>
|
||||
renu555 <renu.tyagi@samsung.com>
|
||||
Robert Dailey <rcdailey@gmail.com>
|
||||
Sam Clegg <sbc@chromium.org>
|
||||
selaselah <selah@outlook.com>
|
||||
Sergiy80 <sil2004@gmail.com>
|
||||
sergzub <sergzub@gmail.com>
|
||||
Stefan Schweter <stefan@schweter.it>
|
||||
Stefano Fiorentino <stefano.fiore84@gmail.com>
|
||||
Steffen Kieß <Steffen.Kiess@ipvs.uni-stuttgart.de>
|
||||
Steven Hahn <hahnse@ornl.gov>
|
||||
Stuart Eichert <stuart@fivemicro.com>
|
||||
SuperManitu <supermanitu@gmail.com>
|
||||
Techwolf <dring@g33kworld.net>
|
||||
Tengiz Sharafiev <btolfa+github@gmail.com>
|
||||
Tomasz Maciejewski <tmaciejewsk@gmail.com>
|
||||
Vicente Olivert Riera <Vincent.Riera@imgtec.com>
|
||||
xiaoyur347 <xiaoyur347@gmail.com>
|
||||
ycqiu <429148848@qq.com>
|
||||
yiqiju <fred_ju@selinc.com>
|
||||
Yu Xiaolei <dreifachstein@gmail.com>
|
||||
|
||||
Google Inc.
|
||||
|
37
BUILD.bazel
Normal file
37
BUILD.bazel
Normal file
@ -0,0 +1,37 @@
|
||||
licenses(["unencumbered"]) # Public Domain or MIT
|
||||
|
||||
exports_files(["LICENSE"])
|
||||
|
||||
cc_library(
|
||||
name = "jsoncpp",
|
||||
srcs = [
|
||||
"src/lib_json/json_reader.cpp",
|
||||
"src/lib_json/json_tool.h",
|
||||
"src/lib_json/json_value.cpp",
|
||||
"src/lib_json/json_writer.cpp",
|
||||
],
|
||||
hdrs = [
|
||||
"include/json/allocator.h",
|
||||
"include/json/assertions.h",
|
||||
"include/json/config.h",
|
||||
"include/json/json_features.h",
|
||||
"include/json/forwards.h",
|
||||
"include/json/json.h",
|
||||
"include/json/reader.h",
|
||||
"include/json/value.h",
|
||||
"include/json/version.h",
|
||||
"include/json/writer.h",
|
||||
],
|
||||
copts = [
|
||||
"-DJSON_USE_EXCEPTION=0",
|
||||
"-DJSON_HAS_INT64",
|
||||
],
|
||||
includes = ["include"],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [":private"],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "private",
|
||||
textual_hdrs = ["src/lib_json/json_valueiterator.inl"],
|
||||
)
|
214
CMakeLists.txt
Normal file
214
CMakeLists.txt
Normal file
@ -0,0 +1,214 @@
|
||||
# vim: et ts=4 sts=4 sw=4 tw=0
|
||||
|
||||
# ==== Define cmake build policies that affect compilation and linkage default behaviors
|
||||
#
|
||||
# Set the JSONCPP_NEWEST_VALIDATED_POLICIES_VERSION string to the newest cmake version
|
||||
# policies that provide successful builds. By setting JSONCPP_NEWEST_VALIDATED_POLICIES_VERSION
|
||||
# to a value greater than the oldest policies, all policies between
|
||||
# JSONCPP_OLDEST_VALIDATED_POLICIES_VERSION and CMAKE_VERSION (used for this build)
|
||||
# are set to their NEW behavior, thereby suppressing policy warnings related to policies
|
||||
# between the JSONCPP_OLDEST_VALIDATED_POLICIES_VERSION and CMAKE_VERSION.
|
||||
#
|
||||
# CMake versions greater than the JSONCPP_NEWEST_VALIDATED_POLICIES_VERSION policies will
|
||||
# continue to generate policy warnings "CMake Warning (dev)...Policy CMP0XXX is not set:"
|
||||
#
|
||||
set(JSONCPP_OLDEST_VALIDATED_POLICIES_VERSION "3.8.0")
|
||||
set(JSONCPP_NEWEST_VALIDATED_POLICIES_VERSION "3.13.2")
|
||||
cmake_minimum_required(VERSION ${JSONCPP_OLDEST_VALIDATED_POLICIES_VERSION})
|
||||
if("${CMAKE_VERSION}" VERSION_LESS "${JSONCPP_NEWEST_VALIDATED_POLICIES_VERSION}")
|
||||
#Set and use the newest available cmake policies that are validated to work
|
||||
set(JSONCPP_CMAKE_POLICY_VERSION "${CMAKE_VERSION}")
|
||||
else()
|
||||
set(JSONCPP_CMAKE_POLICY_VERSION "${JSONCPP_NEWEST_VALIDATED_POLICIES_VERSION}")
|
||||
endif()
|
||||
cmake_policy(VERSION ${JSONCPP_CMAKE_POLICY_VERSION})
|
||||
if(POLICY CMP0091)
|
||||
cmake_policy(SET CMP0091 NEW)
|
||||
endif()
|
||||
#
|
||||
# Now enumerate specific policies newer than JSONCPP_NEWEST_VALIDATED_POLICIES_VERSION
|
||||
# that may need to be individually set to NEW/OLD
|
||||
#
|
||||
foreach(pnew "") # Currently Empty
|
||||
if(POLICY ${pnew})
|
||||
cmake_policy(SET ${pnew} NEW)
|
||||
endif()
|
||||
endforeach()
|
||||
foreach(pold "") # Currently Empty
|
||||
if(POLICY ${pold})
|
||||
cmake_policy(SET ${pold} OLD)
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Build the library with C++11 standard support, independent from other including
|
||||
# software which may use a different CXX_STANDARD or CMAKE_CXX_STANDARD.
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
# Ensure that CMAKE_BUILD_TYPE has a value specified for single configuration generators.
|
||||
if(NOT DEFINED CMAKE_BUILD_TYPE AND NOT DEFINED CMAKE_CONFIGURATION_TYPES)
|
||||
set(CMAKE_BUILD_TYPE Release CACHE STRING
|
||||
"Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel Coverage.")
|
||||
endif()
|
||||
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||
|
||||
project(jsoncpp
|
||||
# Note: version must be updated in four places when doing a release. This
|
||||
# annoying process ensures that amalgamate, CMake, and meson all report the
|
||||
# correct version.
|
||||
# 1. ./meson.build
|
||||
# 2. ./include/json/version.h
|
||||
# 3. ./CMakeLists.txt
|
||||
# 4. ./MODULE.bazel
|
||||
# IMPORTANT: also update the PROJECT_SOVERSION!!
|
||||
VERSION 1.9.7 # <major>[.<minor>[.<patch>[.<tweak>]]]
|
||||
LANGUAGES CXX)
|
||||
|
||||
message(STATUS "JsonCpp Version: ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
|
||||
set(PROJECT_SOVERSION 27)
|
||||
|
||||
include(${CMAKE_CURRENT_SOURCE_DIR}/include/PreventInSourceBuilds.cmake)
|
||||
include(${CMAKE_CURRENT_SOURCE_DIR}/include/PreventInBuildInstalls.cmake)
|
||||
|
||||
option(JSONCPP_WITH_TESTS "Compile and (for jsoncpp_check) run JsonCpp test executables" ON)
|
||||
option(JSONCPP_WITH_POST_BUILD_UNITTEST "Automatically run unit-tests as a post build step" ON)
|
||||
option(JSONCPP_WITH_WARNING_AS_ERROR "Force compilation to fail if a warning occurs" OFF)
|
||||
option(JSONCPP_WITH_STRICT_ISO "Issue all the warnings demanded by strict ISO C and ISO C++" ON)
|
||||
option(JSONCPP_WITH_PKGCONFIG_SUPPORT "Generate and install .pc files" ON)
|
||||
option(JSONCPP_WITH_CMAKE_PACKAGE "Generate and install cmake package files" ON)
|
||||
option(JSONCPP_WITH_EXAMPLE "Compile JsonCpp example" OFF)
|
||||
option(JSONCPP_STATIC_WINDOWS_RUNTIME "Use static (MT/MTd) Windows runtime" OFF)
|
||||
option(BUILD_SHARED_LIBS "Build jsoncpp_lib as a shared library." ON)
|
||||
option(BUILD_STATIC_LIBS "Build jsoncpp_lib as a static library." ON)
|
||||
option(BUILD_OBJECT_LIBS "Build jsoncpp_lib as a object library." ON)
|
||||
|
||||
# Adhere to GNU filesystem layout conventions
|
||||
include(GNUInstallDirs)
|
||||
|
||||
if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
|
||||
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib" CACHE PATH "Archive output dir.")
|
||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib" CACHE PATH "Library output dir.")
|
||||
set(CMAKE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin" CACHE PATH "PDB (MSVC debug symbol)output dir.")
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin" CACHE PATH "Executable/dll output dir.")
|
||||
endif()
|
||||
|
||||
include(CheckFunctionExists)
|
||||
check_function_exists(memset_s HAVE_MEMSET_S)
|
||||
if(HAVE_MEMSET_S)
|
||||
add_definitions("-DHAVE_MEMSET_S=1")
|
||||
endif()
|
||||
|
||||
if(JSONCPP_USE_SECURE_MEMORY)
|
||||
add_definitions("-DJSONCPP_USE_SECURE_MEMORY=1")
|
||||
endif()
|
||||
|
||||
configure_file("${PROJECT_SOURCE_DIR}/version.in"
|
||||
"${PROJECT_BINARY_DIR}/version"
|
||||
NEWLINE_STYLE UNIX)
|
||||
|
||||
macro(use_compilation_warning_as_error)
|
||||
if(MSVC)
|
||||
# Only enabled in debug because some old versions of VS STL generate
|
||||
# warnings when compiled in release configuration.
|
||||
add_compile_options($<$<CONFIG:Debug>:/WX>)
|
||||
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
add_compile_options(-Werror)
|
||||
if(JSONCPP_WITH_STRICT_ISO)
|
||||
add_compile_options(-pedantic-errors)
|
||||
endif()
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
# Include our configuration header
|
||||
include_directories(${jsoncpp_SOURCE_DIR}/include)
|
||||
|
||||
if(MSVC)
|
||||
# Only enabled in debug because some old versions of VS STL generate
|
||||
# unreachable code warning when compiled in release configuration.
|
||||
add_compile_options($<$<CONFIG:Debug>:/W4>)
|
||||
if (JSONCPP_STATIC_WINDOWS_RUNTIME)
|
||||
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
# using regular Clang or AppleClang
|
||||
add_compile_options(-Wall -Wconversion -Wshadow)
|
||||
|
||||
if(JSONCPP_WITH_WARNING_AS_ERROR)
|
||||
add_compile_options(-Werror=conversion -Werror=sign-compare)
|
||||
endif()
|
||||
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
# using GCC
|
||||
add_compile_options(-Wall -Wconversion -Wshadow -Wextra)
|
||||
# not yet ready for -Wsign-conversion
|
||||
|
||||
if(JSONCPP_WITH_STRICT_ISO)
|
||||
add_compile_options(-Wpedantic)
|
||||
endif()
|
||||
if(JSONCPP_WITH_WARNING_AS_ERROR)
|
||||
add_compile_options(-Werror=conversion)
|
||||
endif()
|
||||
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Intel")
|
||||
# using Intel compiler
|
||||
add_compile_options(-Wall -Wconversion -Wshadow -Wextra)
|
||||
|
||||
if(JSONCPP_WITH_WARNING_AS_ERROR)
|
||||
add_compile_options(-Werror=conversion)
|
||||
elseif(JSONCPP_WITH_STRICT_ISO)
|
||||
add_compile_options(-Wpedantic)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(JSONCPP_WITH_WARNING_AS_ERROR)
|
||||
use_compilation_warning_as_error()
|
||||
endif()
|
||||
|
||||
if(JSONCPP_WITH_PKGCONFIG_SUPPORT)
|
||||
include(JoinPaths)
|
||||
|
||||
join_paths(libdir_for_pc_file "\${exec_prefix}" "${CMAKE_INSTALL_LIBDIR}")
|
||||
join_paths(includedir_for_pc_file "\${prefix}" "${CMAKE_INSTALL_INCLUDEDIR}")
|
||||
|
||||
configure_file(
|
||||
"pkg-config/jsoncpp.pc.in"
|
||||
"pkg-config/jsoncpp.pc"
|
||||
@ONLY)
|
||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/pkg-config/jsoncpp.pc"
|
||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
|
||||
endif()
|
||||
|
||||
if(JSONCPP_WITH_CMAKE_PACKAGE)
|
||||
include(CMakePackageConfigHelpers)
|
||||
install(EXPORT jsoncpp
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/jsoncpp
|
||||
FILE jsoncpp-targets.cmake)
|
||||
configure_package_config_file(jsoncppConfig.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/jsoncppConfig.cmake
|
||||
INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/jsoncpp)
|
||||
|
||||
write_basic_package_version_file("${CMAKE_CURRENT_BINARY_DIR}/jsoncppConfigVersion.cmake"
|
||||
VERSION ${PROJECT_VERSION}
|
||||
COMPATIBILITY SameMajorVersion)
|
||||
install(FILES
|
||||
${CMAKE_CURRENT_BINARY_DIR}/jsoncppConfigVersion.cmake ${CMAKE_CURRENT_BINARY_DIR}/jsoncppConfig.cmake
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/jsoncpp-namespaced-targets.cmake
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/jsoncpp)
|
||||
endif()
|
||||
|
||||
if(JSONCPP_WITH_TESTS)
|
||||
enable_testing()
|
||||
include(CTest)
|
||||
endif()
|
||||
|
||||
# Build the different applications
|
||||
add_subdirectory(src)
|
||||
|
||||
#install the includes
|
||||
add_subdirectory(include)
|
||||
|
||||
#install the example
|
||||
if(JSONCPP_WITH_EXAMPLE)
|
||||
add_subdirectory(example)
|
||||
endif()
|
152
CONTRIBUTING.md
Normal file
152
CONTRIBUTING.md
Normal file
@ -0,0 +1,152 @@
|
||||
# Contributing to JsonCpp
|
||||
|
||||
## Building
|
||||
|
||||
Both CMake and Meson tools are capable of generating a variety of build environments for you preferred development environment.
|
||||
Using cmake or meson you can generate an XCode, Visual Studio, Unix Makefile, Ninja, or other environment that fits your needs.
|
||||
|
||||
An example of a common Meson/Ninja environment is described next.
|
||||
|
||||
## Building and testing with Meson/Ninja
|
||||
Thanks to David Seifert (@SoapGentoo), we (the maintainers) now use
|
||||
[meson](http://mesonbuild.com/) and [ninja](https://ninja-build.org/) to build
|
||||
for debugging, as well as for continuous integration (see
|
||||
[`./.travis_scripts/meson_builder.sh`](./.travis_scripts/meson_builder.sh) ). Other systems may work, but minor
|
||||
things like version strings might break.
|
||||
|
||||
First, install both meson (which requires Python3) and ninja.
|
||||
If you wish to install to a directory other than /usr/local, set an environment variable called DESTDIR with the desired path:
|
||||
DESTDIR=/path/to/install/dir
|
||||
|
||||
Then,
|
||||
```sh
|
||||
cd jsoncpp/
|
||||
BUILD_TYPE=debug
|
||||
#BUILD_TYPE=release
|
||||
LIB_TYPE=shared
|
||||
#LIB_TYPE=static
|
||||
meson --buildtype ${BUILD_TYPE} --default-library ${LIB_TYPE} . build-${LIB_TYPE}
|
||||
ninja -v -C build-${LIB_TYPE}
|
||||
|
||||
ninja -C build-static/ test
|
||||
|
||||
# Or
|
||||
#cd build-${LIB_TYPE}
|
||||
#meson test --no-rebuild --print-errorlogs
|
||||
|
||||
sudo ninja install
|
||||
```
|
||||
|
||||
## Building and testing with other build systems
|
||||
See https://github.com/open-source-parsers/jsoncpp/wiki/Building
|
||||
|
||||
## Running the tests manually
|
||||
|
||||
You need to run tests manually only if you are troubleshooting an issue.
|
||||
|
||||
In the instructions below, replace `path/to/jsontest` with the path of the
|
||||
`jsontest` executable that was compiled on your platform.
|
||||
|
||||
cd test
|
||||
# This will run the Reader/Writer tests
|
||||
python runjsontests.py path/to/jsontest
|
||||
|
||||
# This will run the Reader/Writer tests, using JSONChecker test suite
|
||||
# (http://www.json.org/JSON_checker/).
|
||||
# Notes: not all tests pass: JsonCpp is too lenient (for example,
|
||||
# it allows an integer to start with '0'). The goal is to improve
|
||||
# strict mode parsing to get all tests to pass.
|
||||
python runjsontests.py --with-json-checker path/to/jsontest
|
||||
|
||||
# This will run the unit tests (mostly Value)
|
||||
python rununittests.py path/to/test_lib_json
|
||||
|
||||
# You can run the tests using valgrind:
|
||||
python rununittests.py --valgrind path/to/test_lib_json
|
||||
|
||||
## Building the documentation
|
||||
|
||||
Run the Python script `doxybuild.py` from the top directory:
|
||||
|
||||
python doxybuild.py --doxygen=$(which doxygen) --open --with-dot
|
||||
|
||||
See `doxybuild.py --help` for options.
|
||||
|
||||
## Adding a reader/writer test
|
||||
|
||||
To add a test, you need to create two files in test/data:
|
||||
|
||||
* a `TESTNAME.json` file, that contains the input document in JSON format.
|
||||
* a `TESTNAME.expected` file, that contains a flattened representation of the
|
||||
input document.
|
||||
|
||||
The `TESTNAME.expected` file format is as follows:
|
||||
|
||||
* Each line represents a JSON element of the element tree represented by the
|
||||
input document.
|
||||
* Each line has two parts: the path to access the element separated from the
|
||||
element value by `=`. Array and object values are always empty (i.e.
|
||||
represented by either `[]` or `{}`).
|
||||
* Element path `.` represents the root element, and is used to separate object
|
||||
members. `[N]` is used to specify the value of an array element at index `N`.
|
||||
|
||||
See the examples `test_complex_01.json` and `test_complex_01.expected` to better understand element paths.
|
||||
|
||||
## Understanding reader/writer test output
|
||||
|
||||
When a test is run, output files are generated beside the input test files. Below is a short description of the content of each file:
|
||||
|
||||
* `test_complex_01.json`: input JSON document.
|
||||
* `test_complex_01.expected`: flattened JSON element tree used to check if
|
||||
parsing was corrected.
|
||||
* `test_complex_01.actual`: flattened JSON element tree produced by `jsontest`
|
||||
from reading `test_complex_01.json`.
|
||||
* `test_complex_01.rewrite`: JSON document written by `jsontest` using the
|
||||
`Json::Value` parsed from `test_complex_01.json` and serialized using
|
||||
`Json::StyledWritter`.
|
||||
* `test_complex_01.actual-rewrite`: flattened JSON element tree produced by
|
||||
`jsontest` from reading `test_complex_01.rewrite`.
|
||||
* `test_complex_01.process-output`: `jsontest` output, typically useful for
|
||||
understanding parsing errors.
|
||||
|
||||
## Versioning rules
|
||||
|
||||
Consumers of this library require a strict approach to incrementing versioning of the JsonCpp library. Currently, we follow the below set of rules:
|
||||
|
||||
* Any new public symbols require a minor version bump.
|
||||
* Any alteration or removal of public symbols requires a major version bump, including changing the size of a class. This is necessary for
|
||||
consumers to do dependency injection properly.
|
||||
|
||||
## Preparing code for submission
|
||||
|
||||
Generally, JsonCpp's style guide has been pretty relaxed, with the following common themes:
|
||||
|
||||
* Variables and function names use lower camel case (E.g. parseValue or collectComments).
|
||||
* Class use camel case (e.g. OurReader)
|
||||
* Member variables have a trailing underscore
|
||||
* Prefer `nullptr` over `NULL`.
|
||||
* Passing by non-const reference is allowed.
|
||||
* Single statement if blocks may omit brackets.
|
||||
* Generally prefer less space over more space.
|
||||
|
||||
For an example:
|
||||
|
||||
```c++
|
||||
bool Reader::decodeNumber(Token& token) {
|
||||
Value decoded;
|
||||
if (!decodeNumber(token, decoded))
|
||||
return false;
|
||||
currentValue().swapPayload(decoded);
|
||||
currentValue().setOffsetStart(token.start_ - begin_);
|
||||
currentValue().setOffsetLimit(token.end_ - begin_);
|
||||
return true;
|
||||
}
|
||||
```
|
||||
|
||||
Before submitting your code, ensure that you meet the versioning requirements above, follow the style guide of the file you are modifying (or the above rules for new files), and run clang format. Meson exposes clang format with the following command:
|
||||
```
|
||||
ninja -v -C build-${LIB_TYPE}/ clang-format
|
||||
```
|
||||
|
||||
For convenience, you can also run the `reformat.sh` script located in the root directory.
|
||||
|
15
CTestConfig.cmake
Normal file
15
CTestConfig.cmake
Normal file
@ -0,0 +1,15 @@
|
||||
## This file should be placed in the root directory of your project.
|
||||
## Then modify the CMakeLists.txt file in the root directory of your
|
||||
## project to incorporate the testing dashboard.
|
||||
##
|
||||
## # The following are required to submit to the CDash dashboard:
|
||||
## ENABLE_TESTING()
|
||||
## INCLUDE(CTest)
|
||||
|
||||
set(CTEST_PROJECT_NAME "jsoncpp")
|
||||
set(CTEST_NIGHTLY_START_TIME "01:23:45 UTC")
|
||||
|
||||
set(CTEST_DROP_METHOD "https")
|
||||
set(CTEST_DROP_SITE "my.cdash.org")
|
||||
set(CTEST_DROP_LOCATION "/submit.php?project=jsoncpp")
|
||||
set(CTEST_DROP_SITE_CDASH TRUE)
|
55
LICENSE
Normal file
55
LICENSE
Normal file
@ -0,0 +1,55 @@
|
||||
The JsonCpp library's source code, including accompanying documentation,
|
||||
tests and demonstration applications, are licensed under the following
|
||||
conditions...
|
||||
|
||||
Baptiste Lepilleur and The JsonCpp Authors explicitly disclaim copyright in all
|
||||
jurisdictions which recognize such a disclaimer. In such jurisdictions,
|
||||
this software is released into the Public Domain.
|
||||
|
||||
In jurisdictions which do not recognize Public Domain property (e.g. Germany as of
|
||||
2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur and
|
||||
The JsonCpp Authors, and is released under the terms of the MIT License (see below).
|
||||
|
||||
In jurisdictions which recognize Public Domain property, the user of this
|
||||
software may choose to accept it either as 1) Public Domain, 2) under the
|
||||
conditions of the MIT License (see below), or 3) under the terms of dual
|
||||
Public Domain/MIT License conditions described here, as they choose.
|
||||
|
||||
The MIT License is about as close to Public Domain as a license can get, and is
|
||||
described in clear, concise terms at:
|
||||
|
||||
http://en.wikipedia.org/wiki/MIT_License
|
||||
|
||||
The full text of the MIT License follows:
|
||||
|
||||
========================================================================
|
||||
Copyright (c) 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
|
||||
|
||||
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.
|
||||
========================================================================
|
||||
(END LICENSE TEXT)
|
||||
|
||||
The MIT license is compatible with both the GPL and commercial
|
||||
software, affording one all of the rights of Public Domain with the
|
||||
minor nuisance of being required to keep the above copyright notice
|
||||
and license text in the source code. Note also that by accepting the
|
||||
Public Domain "license" you can re-license your copy using whatever
|
||||
license you like.
|
14
MODULE.bazel
Normal file
14
MODULE.bazel
Normal file
@ -0,0 +1,14 @@
|
||||
module(
|
||||
name = "jsoncpp",
|
||||
|
||||
# Note: version must be updated in four places when doing a release. This
|
||||
# annoying process ensures that amalgamate, CMake, and meson all report the
|
||||
# correct version.
|
||||
# 1. /meson.build
|
||||
# 2. /include/json/version.h
|
||||
# 3. /CMakeLists.txt
|
||||
# 4. /MODULE.bazel
|
||||
# IMPORTANT: also update the SOVERSION!!
|
||||
version = "1.9.7",
|
||||
compatibility_level = 1,
|
||||
)
|
67
README.md
Normal file
67
README.md
Normal file
@ -0,0 +1,67 @@
|
||||
# JsonCpp
|
||||
|
||||
[](https://bintray.com/theirix/conan-repo/jsoncpp%3Atheirix)
|
||||
[](https://github.com/open-source-parsers/jsoncpp/blob/master/LICENSE)
|
||||
[](http://open-source-parsers.github.io/jsoncpp-docs/doxygen/index.html)
|
||||
[](https://coveralls.io/github/open-source-parsers/jsoncpp?branch=master)
|
||||
|
||||
|
||||
[JSON][json-org] is a lightweight data-interchange format. It can represent
|
||||
numbers, strings, ordered sequences of values, and collections of name/value
|
||||
pairs.
|
||||
|
||||
[json-org]: http://json.org/
|
||||
|
||||
JsonCpp is a C++ library that allows manipulating JSON values, including
|
||||
serialization and deserialization to and from strings. It can also preserve
|
||||
existing comment in unserialization/serialization steps, making it a convenient
|
||||
format to store user input files.
|
||||
|
||||
|
||||
## Documentation
|
||||
|
||||
[JsonCpp documentation][JsonCpp-documentation] is generated using [Doxygen][].
|
||||
|
||||
[JsonCpp-documentation]: http://open-source-parsers.github.io/jsoncpp-docs/doxygen/index.html
|
||||
[Doxygen]: http://www.doxygen.org
|
||||
|
||||
|
||||
## A note on backward-compatibility
|
||||
|
||||
* `1.y.z` is built with C++11.
|
||||
* `0.y.z` can be used with older compilers.
|
||||
* `00.11.z` can be used both in old and new compilers.
|
||||
* Major versions maintain binary-compatibility.
|
||||
|
||||
### Special note
|
||||
The branch `00.11.z`is a new branch, its major version number `00` is to show that it is
|
||||
different from `0.y.z` and `1.y.z`, the main purpose of this branch is to make a balance
|
||||
between the other two branches. Thus, users can use some new features in this new branch
|
||||
that introduced in 1.y.z, but can hardly applied into 0.y.z.
|
||||
|
||||
## Using JsonCpp in your project
|
||||
|
||||
### The vcpkg dependency manager
|
||||
You can download and install JsonCpp using the [vcpkg](https://github.com/Microsoft/vcpkg/) dependency manager:
|
||||
|
||||
git clone https://github.com/Microsoft/vcpkg.git
|
||||
cd vcpkg
|
||||
./bootstrap-vcpkg.sh
|
||||
./vcpkg integrate install
|
||||
./vcpkg install jsoncpp
|
||||
|
||||
The JsonCpp port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository.
|
||||
|
||||
### Amalgamated source
|
||||
https://github.com/open-source-parsers/jsoncpp/wiki/Amalgamated-(Possibly-outdated)
|
||||
|
||||
### The Meson Build System
|
||||
If you are using the [Meson Build System](http://mesonbuild.com), then you can get a wrap file by downloading it from [Meson WrapDB](https://wrapdb.mesonbuild.com/jsoncpp), or simply use `meson wrap install jsoncpp`.
|
||||
|
||||
### Other ways
|
||||
If you have trouble, see the [Wiki](https://github.com/open-source-parsers/jsoncpp/wiki), or post a question as an Issue.
|
||||
|
||||
## License
|
||||
|
||||
See the `LICENSE` file for details. In summary, JsonCpp is licensed under the
|
||||
MIT license, or public domain if desired and recognized in your jurisdiction.
|
53
README.txt
53
README.txt
@ -1,53 +0,0 @@
|
||||
* Introduction:
|
||||
|
||||
JSON (JavaScript Object Notation) is a lightweight data-interchange format.
|
||||
It can represent integer, real number, string, an ordered sequence of
|
||||
value, and a collection of name/value pairs.
|
||||
|
||||
JsonCpp is a simple API to manipulate JSON value, and handle serialization
|
||||
and unserialization to string.
|
||||
|
||||
It can also preserve existing comment in unserialization/serialization steps,
|
||||
making it a convenient format to store user input files.
|
||||
|
||||
Unserialization parsing is user friendly and provides precise error reports.
|
||||
|
||||
* Building/Testing:
|
||||
|
||||
JsonCpp uses Scons (http://www.scons.org) as a build system. Scons requires
|
||||
python to be installed (http://www.python.org).
|
||||
|
||||
You download scons-local distribution from the following url:
|
||||
http://sourceforge.net/project/showfiles.php?group_id=30337&package_id=67375
|
||||
|
||||
Unzip it in the directory where you found this README file. scons.py Should be
|
||||
at the same level as README.
|
||||
|
||||
python scons.py platform=PLTFRM [TARGET]
|
||||
where PLTFRM may be one of:
|
||||
suncc Sun C++ (Solaris)
|
||||
vacpp Visual Age C++ (AIX)
|
||||
mingw
|
||||
msvc6 Microsoft Visual Studio 6 service pack 5-6
|
||||
msvc70 Microsoft Visual Studio 2002
|
||||
msvc71 Microsoft Visual Studio 2003
|
||||
msvc80 Microsoft Visual Studio 2005
|
||||
linux-gcc Gnu C++ (linux, also reported to work for Mac OS X)
|
||||
|
||||
adding platform is fairly simple. You need to change the Sconstruct file
|
||||
to do so.
|
||||
|
||||
and TARGET may be:
|
||||
check: build library and run unit tests.
|
||||
doc: build documentation
|
||||
doc-dist: build documentation tarball
|
||||
|
||||
To run the test manually:
|
||||
cd test
|
||||
# This will run the Reader/Writer tests
|
||||
python runjsontests.py "path to jsontest.exe"
|
||||
# This will run the unit tests (mostly Value)
|
||||
python rununittests.py "path to test_lib_json.exe"
|
||||
|
||||
You can run the tests using valgrind using:
|
||||
python rununittests.py --valgrind "path to test_lib_json.exe"
|
300
SConstruct
300
SConstruct
@ -1,300 +0,0 @@
|
||||
"""
|
||||
Build system can be clean-up by sticking to a few core production factory, with automatic dependencies resolution.
|
||||
4 basic project productions:
|
||||
- library
|
||||
- binary
|
||||
- documentation
|
||||
- tests
|
||||
|
||||
* Library:
|
||||
Input:
|
||||
- dependencies (other libraries)
|
||||
- headers: include path & files
|
||||
- sources
|
||||
- generated sources
|
||||
- resources
|
||||
- generated resources
|
||||
Production:
|
||||
- Static library
|
||||
- Dynamic library
|
||||
- Naming rule
|
||||
Life-cycle:
|
||||
- Library compilation
|
||||
- Compilation as a dependencies
|
||||
- Run-time
|
||||
- Packaging
|
||||
Identity:
|
||||
- Name
|
||||
- Version
|
||||
* Binary:
|
||||
Input:
|
||||
- dependencies (other libraries)
|
||||
- headers: include path & files (usually empty)
|
||||
- sources
|
||||
- generated sources
|
||||
- resources
|
||||
- generated resources
|
||||
- supported variant (optimized/debug, dll/static...)
|
||||
Production:
|
||||
- Binary executable
|
||||
- Manifest [on some platforms]
|
||||
- Debug symbol [on some platforms]
|
||||
Life-cycle:
|
||||
- Compilation
|
||||
- Run-time
|
||||
- Packaging
|
||||
Identity:
|
||||
- Name
|
||||
- Version
|
||||
* Documentation:
|
||||
Input:
|
||||
- dependencies (libraries, binaries)
|
||||
- additional sources
|
||||
- generated sources
|
||||
- resources
|
||||
- generated resources
|
||||
- supported variant (public/internal)
|
||||
Production:
|
||||
- HTML documentation
|
||||
- PDF documentation
|
||||
- CHM documentation
|
||||
Life-cycle:
|
||||
- Documentation
|
||||
- Packaging
|
||||
- Test
|
||||
Identity:
|
||||
- Name
|
||||
- Version
|
||||
"""
|
||||
|
||||
|
||||
|
||||
import os
|
||||
import os.path
|
||||
import sys
|
||||
|
||||
JSONCPP_VERSION = '0.2'
|
||||
DIST_DIR = '#dist'
|
||||
|
||||
options = Variables()
|
||||
options.Add( EnumVariable('platform',
|
||||
'Platform (compiler/stl) used to build the project',
|
||||
'msvc71',
|
||||
allowed_values='suncc vacpp mingw msvc6 msvc7 msvc71 msvc80 linux-gcc'.split(),
|
||||
ignorecase=2) )
|
||||
|
||||
try:
|
||||
platform = ARGUMENTS['platform']
|
||||
if platform == 'linux-gcc':
|
||||
CXX = 'g++' # not quite right, but env is not yet available.
|
||||
import commands
|
||||
version = commands.getoutput('%s -dumpversion' %CXX)
|
||||
platform = 'linux-gcc-%s' %version
|
||||
print "Using platform '%s'" %platform
|
||||
LD_LIBRARY_PATH = os.environ.get('LD_LIBRARY_PATH', '')
|
||||
LD_LIBRARY_PATH = "%s:libs/%s" %(LD_LIBRARY_PATH, platform)
|
||||
os.environ['LD_LIBRARY_PATH'] = LD_LIBRARY_PATH
|
||||
print "LD_LIBRARY_PATH =", LD_LIBRARY_PATH
|
||||
except KeyError:
|
||||
print 'You must specify a "platform"'
|
||||
sys.exit(2)
|
||||
|
||||
print "Building using PLATFORM =", platform
|
||||
|
||||
rootbuild_dir = Dir('#buildscons')
|
||||
build_dir = os.path.join( '#buildscons', platform )
|
||||
bin_dir = os.path.join( '#bin', platform )
|
||||
lib_dir = os.path.join( '#libs', platform )
|
||||
sconsign_dir_path = Dir(build_dir).abspath
|
||||
sconsign_path = os.path.join( sconsign_dir_path, '.sconsign.dbm' )
|
||||
|
||||
# Ensure build directory exist (SConsignFile fail otherwise!)
|
||||
if not os.path.exists( sconsign_dir_path ):
|
||||
os.makedirs( sconsign_dir_path )
|
||||
|
||||
# Store all dependencies signature in a database
|
||||
SConsignFile( sconsign_path )
|
||||
|
||||
def make_environ_vars():
|
||||
"""Returns a dictionnary with environment variable to use when compiling."""
|
||||
# PATH is required to find the compiler
|
||||
# TEMP is required for at least mingw
|
||||
vars = {}
|
||||
for name in ('PATH', 'TEMP', 'TMP'):
|
||||
if name in os.environ:
|
||||
vars[name] = os.environ[name]
|
||||
return vars
|
||||
|
||||
|
||||
env = Environment( ENV = make_environ_vars(),
|
||||
toolpath = ['scons-tools'],
|
||||
tools=[] ) #, tools=['default'] )
|
||||
|
||||
if platform == 'suncc':
|
||||
env.Tool( 'sunc++' )
|
||||
env.Tool( 'sunlink' )
|
||||
env.Tool( 'sunar' )
|
||||
env.Append( CCFLAGS = ['-mt'] )
|
||||
elif platform == 'vacpp':
|
||||
env.Tool( 'default' )
|
||||
env.Tool( 'aixcc' )
|
||||
env['CXX'] = 'xlC_r' #scons does not pick-up the correct one !
|
||||
# using xlC_r ensure multi-threading is enabled:
|
||||
# http://publib.boulder.ibm.com/infocenter/pseries/index.jsp?topic=/com.ibm.vacpp7a.doc/compiler/ref/cuselect.htm
|
||||
env.Append( CCFLAGS = '-qrtti=all',
|
||||
LINKFLAGS='-bh:5' ) # -bh:5 remove duplicate symbol warning
|
||||
elif platform == 'msvc6':
|
||||
env['MSVS_VERSION']='6.0'
|
||||
for tool in ['msvc', 'msvs', 'mslink', 'masm', 'mslib']:
|
||||
env.Tool( tool )
|
||||
env['CXXFLAGS']='-GR -GX /nologo /MT'
|
||||
elif platform == 'msvc70':
|
||||
env['MSVS_VERSION']='7.0'
|
||||
for tool in ['msvc', 'msvs', 'mslink', 'masm', 'mslib']:
|
||||
env.Tool( tool )
|
||||
env['CXXFLAGS']='-GR -GX /nologo /MT'
|
||||
elif platform == 'msvc71':
|
||||
env['MSVS_VERSION']='7.1'
|
||||
for tool in ['msvc', 'msvs', 'mslink', 'masm', 'mslib']:
|
||||
env.Tool( tool )
|
||||
env['CXXFLAGS']='-GR -GX /nologo /MT'
|
||||
elif platform == 'msvc80':
|
||||
env['MSVS_VERSION']='8.0'
|
||||
for tool in ['msvc', 'msvs', 'mslink', 'masm', 'mslib']:
|
||||
env.Tool( tool )
|
||||
env['CXXFLAGS']='-GR -EHsc /nologo /MT'
|
||||
elif platform == 'mingw':
|
||||
env.Tool( 'mingw' )
|
||||
env.Append( CPPDEFINES=[ "WIN32", "NDEBUG", "_MT" ] )
|
||||
elif platform.startswith('linux-gcc'):
|
||||
env.Tool( 'default' )
|
||||
env.Append( LIBS = ['pthread'], CCFLAGS = "-Wall" )
|
||||
env['SHARED_LIB_ENABLED'] = True
|
||||
else:
|
||||
print "UNSUPPORTED PLATFORM."
|
||||
env.Exit(1)
|
||||
|
||||
env.Tool('doxygen')
|
||||
env.Tool('substinfile')
|
||||
env.Tool('targz')
|
||||
env.Tool('srcdist')
|
||||
env.Tool('globtool')
|
||||
|
||||
env.Append( CPPPATH = ['#include'],
|
||||
LIBPATH = lib_dir )
|
||||
short_platform = platform
|
||||
if short_platform.startswith('msvc'):
|
||||
short_platform = short_platform[2:]
|
||||
# Notes: on Windows you need to rebuild the source for each variant
|
||||
# Build script does not support that yet so we only build static libraries.
|
||||
# This also fails on AIX because both dynamic and static library ends with
|
||||
# extension .a.
|
||||
env['SHARED_LIB_ENABLED'] = env.get('SHARED_LIB_ENABLED', False)
|
||||
env['LIB_PLATFORM'] = short_platform
|
||||
env['LIB_LINK_TYPE'] = 'lib' # static
|
||||
env['LIB_CRUNTIME'] = 'mt'
|
||||
env['LIB_NAME_SUFFIX'] = '${LIB_PLATFORM}_${LIB_LINK_TYPE}${LIB_CRUNTIME}' # must match autolink naming convention
|
||||
env['JSONCPP_VERSION'] = JSONCPP_VERSION
|
||||
env['BUILD_DIR'] = env.Dir(build_dir)
|
||||
env['ROOTBUILD_DIR'] = env.Dir(rootbuild_dir)
|
||||
env['DIST_DIR'] = DIST_DIR
|
||||
if 'TarGz' in env['BUILDERS']:
|
||||
class SrcDistAdder:
|
||||
def __init__( self, env ):
|
||||
self.env = env
|
||||
def __call__( self, *args, **kw ):
|
||||
apply( self.env.SrcDist, (self.env['SRCDIST_TARGET'],) + args, kw )
|
||||
env['SRCDIST_BUILDER'] = env.TarGz
|
||||
else: # If tarfile module is missing
|
||||
class SrcDistAdder:
|
||||
def __init__( self, env ):
|
||||
pass
|
||||
def __call__( self, *args, **kw ):
|
||||
pass
|
||||
env['SRCDIST_ADD'] = SrcDistAdder( env )
|
||||
env['SRCDIST_TARGET'] = os.path.join( DIST_DIR, 'jsoncpp-src-%s.tar.gz' % env['JSONCPP_VERSION'] )
|
||||
|
||||
env_testing = env.Clone( )
|
||||
env_testing.Append( LIBS = ['json_${LIB_NAME_SUFFIX}'] )
|
||||
|
||||
def buildJSONExample( env, target_sources, target_name ):
|
||||
env = env.Clone()
|
||||
env.Append( CPPPATH = ['#'] )
|
||||
exe = env.Program( target=target_name,
|
||||
source=target_sources )
|
||||
env['SRCDIST_ADD']( source=[target_sources] )
|
||||
global bin_dir
|
||||
return env.Install( bin_dir, exe )
|
||||
|
||||
def buildJSONTests( env, target_sources, target_name ):
|
||||
jsontests_node = buildJSONExample( env, target_sources, target_name )
|
||||
check_alias_target = env.Alias( 'check', jsontests_node, RunJSONTests( jsontests_node, jsontests_node ) )
|
||||
env.AlwaysBuild( check_alias_target )
|
||||
|
||||
def buildUnitTests( env, target_sources, target_name ):
|
||||
jsontests_node = buildJSONExample( env, target_sources, target_name )
|
||||
check_alias_target = env.Alias( 'check', jsontests_node,
|
||||
RunUnitTests( jsontests_node, jsontests_node ) )
|
||||
env.AlwaysBuild( check_alias_target )
|
||||
|
||||
def buildLibrary( env, target_sources, target_name ):
|
||||
static_lib = env.StaticLibrary( target=target_name + '_${LIB_NAME_SUFFIX}',
|
||||
source=target_sources )
|
||||
global lib_dir
|
||||
env.Install( lib_dir, static_lib )
|
||||
if env['SHARED_LIB_ENABLED']:
|
||||
shared_lib = env.SharedLibrary( target=target_name + '_${LIB_NAME_SUFFIX}',
|
||||
source=target_sources )
|
||||
env.Install( lib_dir, shared_lib )
|
||||
env['SRCDIST_ADD']( source=[target_sources] )
|
||||
|
||||
Export( 'env env_testing buildJSONExample buildLibrary buildJSONTests buildUnitTests' )
|
||||
|
||||
def buildProjectInDirectory( target_directory ):
|
||||
global build_dir
|
||||
target_build_dir = os.path.join( build_dir, target_directory )
|
||||
target = os.path.join( target_directory, 'sconscript' )
|
||||
SConscript( target, build_dir=target_build_dir, duplicate=0 )
|
||||
env['SRCDIST_ADD']( source=[target] )
|
||||
|
||||
|
||||
def runJSONTests_action( target, source = None, env = None ):
|
||||
# Add test scripts to python path
|
||||
jsontest_path = Dir( '#test' ).abspath
|
||||
sys.path.insert( 0, jsontest_path )
|
||||
data_path = os.path.join( jsontest_path, 'data' )
|
||||
import runjsontests
|
||||
return runjsontests.runAllTests( os.path.abspath(source[0].path), data_path )
|
||||
|
||||
def runJSONTests_string( target, source = None, env = None ):
|
||||
return 'RunJSONTests("%s")' % source[0]
|
||||
|
||||
import SCons.Action
|
||||
ActionFactory = SCons.Action.ActionFactory
|
||||
RunJSONTests = ActionFactory(runJSONTests_action, runJSONTests_string )
|
||||
|
||||
def runUnitTests_action( target, source = None, env = None ):
|
||||
# Add test scripts to python path
|
||||
jsontest_path = Dir( '#test' ).abspath
|
||||
sys.path.insert( 0, jsontest_path )
|
||||
import rununittests
|
||||
return rununittests.runAllTests( os.path.abspath(source[0].path) )
|
||||
|
||||
def runUnitTests_string( target, source = None, env = None ):
|
||||
return 'RunUnitTests("%s")' % source[0]
|
||||
|
||||
RunUnitTests = ActionFactory(runUnitTests_action, runUnitTests_string )
|
||||
|
||||
env.Alias( 'check' )
|
||||
|
||||
srcdist_cmd = env['SRCDIST_ADD']( source = """
|
||||
AUTHORS README.txt SConstruct
|
||||
""".split() )
|
||||
env.Alias( 'src-dist', srcdist_cmd )
|
||||
|
||||
buildProjectInDirectory( 'src/jsontestrunner' )
|
||||
buildProjectInDirectory( 'src/lib_json' )
|
||||
buildProjectInDirectory( 'src/test_lib_json' )
|
||||
buildProjectInDirectory( 'doc' )
|
||||
#print env.Dump()
|
||||
|
17
SECURITY.md
Normal file
17
SECURITY.md
Normal file
@ -0,0 +1,17 @@
|
||||
# Security Policy
|
||||
|
||||
If you have discovered a security vulnerability in this project, please report it
|
||||
privately. **Do not disclose it as a public issue.** This gives us time to work with you
|
||||
to fix the issue before public exposure, reducing the chance that the exploit will be
|
||||
used before a patch is released.
|
||||
|
||||
Please submit the report by filling out
|
||||
[this form](https://github.com/open-source-parsers/jsoncpp/security/advisories/new).
|
||||
|
||||
Please provide the following information in your report:
|
||||
|
||||
- A description of the vulnerability and its impact
|
||||
- How to reproduce the issue
|
||||
|
||||
This project is maintained by volunteers on a reasonable-effort basis. As such,
|
||||
we ask that you give us 90 days to work on a fix before public exposure.
|
161
amalgamate.py
Executable file
161
amalgamate.py
Executable file
@ -0,0 +1,161 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""Amalgamate json-cpp library sources into a single source and header file.
|
||||
|
||||
Works with python2.6+ and python3.4+.
|
||||
|
||||
Example of invocation (must be invoked from json-cpp top directory):
|
||||
python amalgamate.py
|
||||
"""
|
||||
import os
|
||||
import os.path
|
||||
import sys
|
||||
|
||||
INCLUDE_PATH = "include/json"
|
||||
SRC_PATH = "src/lib_json"
|
||||
|
||||
class AmalgamationFile:
|
||||
def __init__(self, top_dir):
|
||||
self.top_dir = top_dir
|
||||
self.blocks = []
|
||||
|
||||
def add_text(self, text):
|
||||
if not text.endswith("\n"):
|
||||
text += "\n"
|
||||
self.blocks.append(text)
|
||||
|
||||
def add_file(self, relative_input_path, wrap_in_comment=False):
|
||||
def add_marker(prefix):
|
||||
self.add_text("")
|
||||
self.add_text("// " + "/"*70)
|
||||
self.add_text("// %s of content of file: %s" % (prefix, relative_input_path.replace("\\","/")))
|
||||
self.add_text("// " + "/"*70)
|
||||
self.add_text("")
|
||||
add_marker("Beginning")
|
||||
f = open(os.path.join(self.top_dir, relative_input_path), "rt")
|
||||
content = f.read()
|
||||
if wrap_in_comment:
|
||||
content = "/*\n" + content + "\n*/"
|
||||
self.add_text(content)
|
||||
f.close()
|
||||
add_marker("End")
|
||||
self.add_text("\n\n\n\n")
|
||||
|
||||
def get_value(self):
|
||||
return "".join(self.blocks).replace("\r\n","\n")
|
||||
|
||||
def write_to(self, output_path):
|
||||
output_dir = os.path.dirname(output_path)
|
||||
if output_dir and not os.path.isdir(output_dir):
|
||||
os.makedirs(output_dir)
|
||||
f = open(output_path, "wb")
|
||||
f.write(str.encode(self.get_value(), 'UTF-8'))
|
||||
f.close()
|
||||
|
||||
def amalgamate_source(source_top_dir=None,
|
||||
target_source_path=None,
|
||||
header_include_path=None):
|
||||
"""Produces amalgamated source.
|
||||
Parameters:
|
||||
source_top_dir: top-directory
|
||||
target_source_path: output .cpp path
|
||||
header_include_path: generated header path relative to target_source_path.
|
||||
"""
|
||||
print("Amalgamating header...")
|
||||
header = AmalgamationFile(source_top_dir)
|
||||
header.add_text("/// Json-cpp amalgamated header (https://github.com/open-source-parsers/jsoncpp/).")
|
||||
header.add_text('/// It is intended to be used with #include "%s"' % header_include_path)
|
||||
header.add_file("LICENSE", wrap_in_comment=True)
|
||||
header.add_text("#ifndef JSON_AMALGAMATED_H_INCLUDED")
|
||||
header.add_text("# define JSON_AMALGAMATED_H_INCLUDED")
|
||||
header.add_text("/// If defined, indicates that the source file is amalgamated")
|
||||
header.add_text("/// to prevent private header inclusion.")
|
||||
header.add_text("#define JSON_IS_AMALGAMATION")
|
||||
header.add_file(os.path.join(INCLUDE_PATH, "version.h"))
|
||||
header.add_file(os.path.join(INCLUDE_PATH, "allocator.h"))
|
||||
header.add_file(os.path.join(INCLUDE_PATH, "config.h"))
|
||||
header.add_file(os.path.join(INCLUDE_PATH, "forwards.h"))
|
||||
header.add_file(os.path.join(INCLUDE_PATH, "json_features.h"))
|
||||
header.add_file(os.path.join(INCLUDE_PATH, "value.h"))
|
||||
header.add_file(os.path.join(INCLUDE_PATH, "reader.h"))
|
||||
header.add_file(os.path.join(INCLUDE_PATH, "writer.h"))
|
||||
header.add_file(os.path.join(INCLUDE_PATH, "assertions.h"))
|
||||
header.add_text("#endif //ifndef JSON_AMALGAMATED_H_INCLUDED")
|
||||
|
||||
target_header_path = os.path.join(os.path.dirname(target_source_path), header_include_path)
|
||||
print("Writing amalgamated header to %r" % target_header_path)
|
||||
header.write_to(target_header_path)
|
||||
|
||||
base, ext = os.path.splitext(header_include_path)
|
||||
forward_header_include_path = base + "-forwards" + ext
|
||||
print("Amalgamating forward header...")
|
||||
header = AmalgamationFile(source_top_dir)
|
||||
header.add_text("/// Json-cpp amalgamated forward header (https://github.com/open-source-parsers/jsoncpp/).")
|
||||
header.add_text('/// It is intended to be used with #include "%s"' % forward_header_include_path)
|
||||
header.add_text("/// This header provides forward declaration for all JsonCpp types.")
|
||||
header.add_file("LICENSE", wrap_in_comment=True)
|
||||
header.add_text("#ifndef JSON_FORWARD_AMALGAMATED_H_INCLUDED")
|
||||
header.add_text("# define JSON_FORWARD_AMALGAMATED_H_INCLUDED")
|
||||
header.add_text("/// If defined, indicates that the source file is amalgamated")
|
||||
header.add_text("/// to prevent private header inclusion.")
|
||||
header.add_text("#define JSON_IS_AMALGAMATION")
|
||||
header.add_file(os.path.join(INCLUDE_PATH, "version.h"))
|
||||
header.add_file(os.path.join(INCLUDE_PATH, "allocator.h"))
|
||||
header.add_file(os.path.join(INCLUDE_PATH, "config.h"))
|
||||
header.add_file(os.path.join(INCLUDE_PATH, "forwards.h"))
|
||||
header.add_text("#endif //ifndef JSON_FORWARD_AMALGAMATED_H_INCLUDED")
|
||||
|
||||
target_forward_header_path = os.path.join(os.path.dirname(target_source_path),
|
||||
forward_header_include_path)
|
||||
print("Writing amalgamated forward header to %r" % target_forward_header_path)
|
||||
header.write_to(target_forward_header_path)
|
||||
|
||||
print("Amalgamating source...")
|
||||
source = AmalgamationFile(source_top_dir)
|
||||
source.add_text("/// Json-cpp amalgamated source (https://github.com/open-source-parsers/jsoncpp/).")
|
||||
source.add_text('/// It is intended to be used with #include "%s"' % header_include_path)
|
||||
source.add_file("LICENSE", wrap_in_comment=True)
|
||||
source.add_text("")
|
||||
source.add_text('#include "%s"' % header_include_path)
|
||||
source.add_text("""
|
||||
#ifndef JSON_IS_AMALGAMATION
|
||||
#error "Compile with -I PATH_TO_JSON_DIRECTORY"
|
||||
#endif
|
||||
""")
|
||||
source.add_text("")
|
||||
source.add_file(os.path.join(SRC_PATH, "json_tool.h"))
|
||||
source.add_file(os.path.join(SRC_PATH, "json_reader.cpp"))
|
||||
source.add_file(os.path.join(SRC_PATH, "json_valueiterator.inl"))
|
||||
source.add_file(os.path.join(SRC_PATH, "json_value.cpp"))
|
||||
source.add_file(os.path.join(SRC_PATH, "json_writer.cpp"))
|
||||
|
||||
print("Writing amalgamated source to %r" % target_source_path)
|
||||
source.write_to(target_source_path)
|
||||
|
||||
def main():
|
||||
usage = """%prog [options]
|
||||
Generate a single amalgamated source and header file from the sources.
|
||||
"""
|
||||
from optparse import OptionParser
|
||||
parser = OptionParser(usage=usage)
|
||||
parser.allow_interspersed_args = False
|
||||
parser.add_option("-s", "--source", dest="target_source_path", action="store", default="dist/jsoncpp.cpp",
|
||||
help="""Output .cpp source path. [Default: %default]""")
|
||||
parser.add_option("-i", "--include", dest="header_include_path", action="store", default="json/json.h",
|
||||
help="""Header include path. Used to include the header from the amalgamated source file. [Default: %default]""")
|
||||
parser.add_option("-t", "--top-dir", dest="top_dir", action="store", default=os.getcwd(),
|
||||
help="""Source top-directory. [Default: %default]""")
|
||||
parser.enable_interspersed_args()
|
||||
options, args = parser.parse_args()
|
||||
|
||||
msg = amalgamate_source(source_top_dir=options.top_dir,
|
||||
target_source_path=options.target_source_path,
|
||||
header_include_path=options.header_include_path)
|
||||
if msg:
|
||||
sys.stderr.write(msg + "\n")
|
||||
sys.exit(1)
|
||||
else:
|
||||
print("Source successfully amalgamated")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
37
appveyor.yml
Normal file
37
appveyor.yml
Normal file
@ -0,0 +1,37 @@
|
||||
clone_folder: c:\projects\jsoncpp
|
||||
|
||||
environment:
|
||||
|
||||
matrix:
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
CMAKE_GENERATOR: Visual Studio 14 2015
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
CMAKE_GENERATOR: Visual Studio 14 2015 Win64
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
CMAKE_GENERATOR: Visual Studio 15 2017
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
CMAKE_GENERATOR: Visual Studio 15 2017 Win64
|
||||
|
||||
build_script:
|
||||
- cmake --version
|
||||
# The build script starts in root.
|
||||
- set JSONCPP_FOLDER=%cd%
|
||||
- set JSONCPP_BUILD_FOLDER=%JSONCPP_FOLDER%\build\release
|
||||
- mkdir -p %JSONCPP_BUILD_FOLDER%
|
||||
- cd %JSONCPP_BUILD_FOLDER%
|
||||
- cmake -G "%CMAKE_GENERATOR%" -DCMAKE_INSTALL_PREFIX:PATH=%CD:\=/%/install -DBUILD_SHARED_LIBS:BOOL=ON %JSONCPP_FOLDER%
|
||||
# Use ctest to make a dashboard build:
|
||||
# - ctest -D Experimental(Start|Update|Configure|Build|Test|Coverage|MemCheck|Submit)
|
||||
# NOTE: Testing on windows is not yet finished:
|
||||
# - ctest -C Release -D ExperimentalStart -D ExperimentalConfigure -D ExperimentalBuild -D ExperimentalTest -D ExperimentalSubmit
|
||||
- ctest -C Release -D ExperimentalStart -D ExperimentalConfigure -D ExperimentalBuild -D ExperimentalSubmit
|
||||
# Final step is to verify that installation succeeds
|
||||
- cmake --build . --config Release --target install
|
||||
|
||||
deploy:
|
||||
provider: GitHub
|
||||
auth_token:
|
||||
secure: K2Tp1q8pIZ7rs0Ot24ZMWuwr12Ev6Tc6QkhMjGQxoQG3ng1pXtgPasiJ45IDXGdg
|
||||
on:
|
||||
branch: master
|
||||
appveyor_repo_tag: true
|
23
cmake/JoinPaths.cmake
Normal file
23
cmake/JoinPaths.cmake
Normal file
@ -0,0 +1,23 @@
|
||||
# This module provides a function for joining paths
|
||||
# known from most languages
|
||||
#
|
||||
# SPDX-License-Identifier: (MIT OR CC0-1.0)
|
||||
# Copyright 2020 Jan Tojnar
|
||||
# https://github.com/jtojnar/cmake-snips
|
||||
#
|
||||
# Modelled after Python’s os.path.join
|
||||
# https://docs.python.org/3.7/library/os.path.html#os.path.join
|
||||
# Windows not supported
|
||||
function(join_paths joined_path first_path_segment)
|
||||
set(temp_path "${first_path_segment}")
|
||||
foreach(current_segment IN LISTS ARGN)
|
||||
if(NOT ("${current_segment}" STREQUAL ""))
|
||||
if(IS_ABSOLUTE "${current_segment}")
|
||||
set(temp_path "${current_segment}")
|
||||
else()
|
||||
set(temp_path "${temp_path}/${current_segment}")
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
set(${joined_path} "${temp_path}" PARENT_SCOPE)
|
||||
endfunction()
|
37
dev.makefile
Normal file
37
dev.makefile
Normal file
@ -0,0 +1,37 @@
|
||||
# This is only for jsoncpp developers/contributors.
|
||||
# We use this to sign releases, generate documentation, etc.
|
||||
VER?=$(shell cat version)
|
||||
|
||||
default:
|
||||
@echo "VER=${VER}"
|
||||
update-version:
|
||||
perl get_version.pl meson.build >| version
|
||||
sign: jsoncpp-${VER}.tar.gz
|
||||
gpg --armor --detach-sign $<
|
||||
gpg --verify $<.asc
|
||||
# Then upload .asc to the release.
|
||||
jsoncpp-%.tar.gz:
|
||||
curl https://github.com/open-source-parsers/jsoncpp/archive/$*.tar.gz -o $@
|
||||
dox:
|
||||
python doxybuild.py --doxygen=$$(which doxygen) --in doc/web_doxyfile.in
|
||||
rsync -va -c --delete dist/doxygen/jsoncpp-api-html-${VER}/ ../jsoncpp-docs/doxygen/
|
||||
# Then 'git add -A' and 'git push' in jsoncpp-docs.
|
||||
build:
|
||||
mkdir -p build/debug
|
||||
cd build/debug; cmake -DCMAKE_BUILD_TYPE=debug -DBUILD_SHARED_LIBS=ON -G "Unix Makefiles" ../..
|
||||
make -C build/debug
|
||||
|
||||
# Currently, this depends on include/json/version.h generated
|
||||
# by cmake.
|
||||
test-amalgamate:
|
||||
python2.7 amalgamate.py
|
||||
python3.4 amalgamate.py
|
||||
cd dist; gcc -I. -c jsoncpp.cpp
|
||||
|
||||
valgrind:
|
||||
valgrind --error-exitcode=42 --leak-check=full ./build/debug/src/test_lib_json/jsoncpp_test
|
||||
|
||||
clean:
|
||||
\rm -rf *.gz *.asc dist/
|
||||
|
||||
.PHONY: build
|
6
devtools/__init__.py
Normal file
6
devtools/__init__.py
Normal file
@ -0,0 +1,6 @@
|
||||
# Copyright 2010 Baptiste Lepilleur and The JsonCpp Authors
|
||||
# Distributed under MIT license, or public domain if desired and
|
||||
# recognized in your jurisdiction.
|
||||
# See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||
|
||||
# module
|
33
devtools/agent_vmw7.json
Normal file
33
devtools/agent_vmw7.json
Normal file
@ -0,0 +1,33 @@
|
||||
{
|
||||
"cmake_variants" : [
|
||||
{"name": "generator",
|
||||
"generators": [
|
||||
{"generator": [
|
||||
"Visual Studio 7 .NET 2003",
|
||||
"Visual Studio 9 2008",
|
||||
"Visual Studio 9 2008 Win64",
|
||||
"Visual Studio 10",
|
||||
"Visual Studio 10 Win64",
|
||||
"Visual Studio 11",
|
||||
"Visual Studio 11 Win64"
|
||||
]
|
||||
},
|
||||
{"generator": ["MinGW Makefiles"],
|
||||
"env_prepend": [{"path": "c:/wut/prg/MinGW/bin"}]
|
||||
}
|
||||
]
|
||||
},
|
||||
{"name": "shared_dll",
|
||||
"variables": [
|
||||
["BUILD_SHARED_LIBS=true"],
|
||||
["BUILD_SHARED_LIBS=false"]
|
||||
]
|
||||
},
|
||||
{"name": "build_type",
|
||||
"build_types": [
|
||||
"debug",
|
||||
"release"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
26
devtools/agent_vmxp.json
Normal file
26
devtools/agent_vmxp.json
Normal file
@ -0,0 +1,26 @@
|
||||
{
|
||||
"cmake_variants" : [
|
||||
{"name": "generator",
|
||||
"generators": [
|
||||
{"generator": [
|
||||
"Visual Studio 6",
|
||||
"Visual Studio 7",
|
||||
"Visual Studio 8 2005"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{"name": "shared_dll",
|
||||
"variables": [
|
||||
["BUILD_SHARED_LIBS=true"],
|
||||
["BUILD_SHARED_LIBS=false"]
|
||||
]
|
||||
},
|
||||
{"name": "build_type",
|
||||
"build_types": [
|
||||
"debug",
|
||||
"release"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
205
devtools/antglob.py
Normal file
205
devtools/antglob.py
Normal file
@ -0,0 +1,205 @@
|
||||
#!/usr/bin/env python
|
||||
# encoding: utf-8
|
||||
# Copyright 2009 Baptiste Lepilleur and The JsonCpp Authors
|
||||
# Distributed under MIT license, or public domain if desired and
|
||||
# recognized in your jurisdiction.
|
||||
# See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||
|
||||
from __future__ import print_function
|
||||
from dircache import listdir
|
||||
import re
|
||||
import fnmatch
|
||||
import os.path
|
||||
|
||||
|
||||
# These fnmatch expressions are used by default to prune the directory tree
|
||||
# while doing the recursive traversal in the glob_impl method of glob function.
|
||||
prune_dirs = '.git .bzr .hg .svn _MTN _darcs CVS SCCS '
|
||||
|
||||
# These fnmatch expressions are used by default to exclude files and dirs
|
||||
# while doing the recursive traversal in the glob_impl method of glob function.
|
||||
##exclude_pats = prune_pats + '*~ #*# .#* %*% ._* .gitignore .cvsignore vssver.scc .DS_Store'.split()
|
||||
|
||||
# These ant_glob expressions are used by default to exclude files and dirs and also prune the directory tree
|
||||
# while doing the recursive traversal in the glob_impl method of glob function.
|
||||
default_excludes = '''
|
||||
**/*~
|
||||
**/#*#
|
||||
**/.#*
|
||||
**/%*%
|
||||
**/._*
|
||||
**/CVS
|
||||
**/CVS/**
|
||||
**/.cvsignore
|
||||
**/SCCS
|
||||
**/SCCS/**
|
||||
**/vssver.scc
|
||||
**/.svn
|
||||
**/.svn/**
|
||||
**/.git
|
||||
**/.git/**
|
||||
**/.gitignore
|
||||
**/.bzr
|
||||
**/.bzr/**
|
||||
**/.hg
|
||||
**/.hg/**
|
||||
**/_MTN
|
||||
**/_MTN/**
|
||||
**/_darcs
|
||||
**/_darcs/**
|
||||
**/.DS_Store '''
|
||||
|
||||
DIR = 1
|
||||
FILE = 2
|
||||
DIR_LINK = 4
|
||||
FILE_LINK = 8
|
||||
LINKS = DIR_LINK | FILE_LINK
|
||||
ALL_NO_LINK = DIR | FILE
|
||||
ALL = DIR | FILE | LINKS
|
||||
|
||||
_ANT_RE = re.compile(r'(/\*\*/)|(\*\*/)|(/\*\*)|(\*)|(/)|([^\*/]*)')
|
||||
|
||||
def ant_pattern_to_re(ant_pattern):
|
||||
"""Generates a regular expression from the ant pattern.
|
||||
Matching convention:
|
||||
**/a: match 'a', 'dir/a', 'dir1/dir2/a'
|
||||
a/**/b: match 'a/b', 'a/c/b', 'a/d/c/b'
|
||||
*.py: match 'script.py' but not 'a/script.py'
|
||||
"""
|
||||
rex = ['^']
|
||||
next_pos = 0
|
||||
sep_rex = r'(?:/|%s)' % re.escape(os.path.sep)
|
||||
## print 'Converting', ant_pattern
|
||||
for match in _ANT_RE.finditer(ant_pattern):
|
||||
## print 'Matched', match.group()
|
||||
## print match.start(0), next_pos
|
||||
if match.start(0) != next_pos:
|
||||
raise ValueError("Invalid ant pattern")
|
||||
if match.group(1): # /**/
|
||||
rex.append(sep_rex + '(?:.*%s)?' % sep_rex)
|
||||
elif match.group(2): # **/
|
||||
rex.append('(?:.*%s)?' % sep_rex)
|
||||
elif match.group(3): # /**
|
||||
rex.append(sep_rex + '.*')
|
||||
elif match.group(4): # *
|
||||
rex.append('[^/%s]*' % re.escape(os.path.sep))
|
||||
elif match.group(5): # /
|
||||
rex.append(sep_rex)
|
||||
else: # somepath
|
||||
rex.append(re.escape(match.group(6)))
|
||||
next_pos = match.end()
|
||||
rex.append('$')
|
||||
return re.compile(''.join(rex))
|
||||
|
||||
def _as_list(l):
|
||||
if isinstance(l, basestring):
|
||||
return l.split()
|
||||
return l
|
||||
|
||||
def glob(dir_path,
|
||||
includes = '**/*',
|
||||
excludes = default_excludes,
|
||||
entry_type = FILE,
|
||||
prune_dirs = prune_dirs,
|
||||
max_depth = 25):
|
||||
include_filter = [ant_pattern_to_re(p) for p in _as_list(includes)]
|
||||
exclude_filter = [ant_pattern_to_re(p) for p in _as_list(excludes)]
|
||||
prune_dirs = [p.replace('/',os.path.sep) for p in _as_list(prune_dirs)]
|
||||
dir_path = dir_path.replace('/',os.path.sep)
|
||||
entry_type_filter = entry_type
|
||||
|
||||
def is_pruned_dir(dir_name):
|
||||
for pattern in prune_dirs:
|
||||
if fnmatch.fnmatch(dir_name, pattern):
|
||||
return True
|
||||
return False
|
||||
|
||||
def apply_filter(full_path, filter_rexs):
|
||||
"""Return True if at least one of the filter regular expression match full_path."""
|
||||
for rex in filter_rexs:
|
||||
if rex.match(full_path):
|
||||
return True
|
||||
return False
|
||||
|
||||
def glob_impl(root_dir_path):
|
||||
child_dirs = [root_dir_path]
|
||||
while child_dirs:
|
||||
dir_path = child_dirs.pop()
|
||||
for entry in listdir(dir_path):
|
||||
full_path = os.path.join(dir_path, entry)
|
||||
## print 'Testing:', full_path,
|
||||
is_dir = os.path.isdir(full_path)
|
||||
if is_dir and not is_pruned_dir(entry): # explore child directory ?
|
||||
## print '===> marked for recursion',
|
||||
child_dirs.append(full_path)
|
||||
included = apply_filter(full_path, include_filter)
|
||||
rejected = apply_filter(full_path, exclude_filter)
|
||||
if not included or rejected: # do not include entry ?
|
||||
## print '=> not included or rejected'
|
||||
continue
|
||||
link = os.path.islink(full_path)
|
||||
is_file = os.path.isfile(full_path)
|
||||
if not is_file and not is_dir:
|
||||
## print '=> unknown entry type'
|
||||
continue
|
||||
if link:
|
||||
entry_type = is_file and FILE_LINK or DIR_LINK
|
||||
else:
|
||||
entry_type = is_file and FILE or DIR
|
||||
## print '=> type: %d' % entry_type,
|
||||
if (entry_type & entry_type_filter) != 0:
|
||||
## print ' => KEEP'
|
||||
yield os.path.join(dir_path, entry)
|
||||
## else:
|
||||
## print ' => TYPE REJECTED'
|
||||
return list(glob_impl(dir_path))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import unittest
|
||||
|
||||
class AntPatternToRETest(unittest.TestCase):
|
||||
## def test_conversion(self):
|
||||
## self.assertEqual('^somepath$', ant_pattern_to_re('somepath').pattern)
|
||||
|
||||
def test_matching(self):
|
||||
test_cases = [ ('path',
|
||||
['path'],
|
||||
['somepath', 'pathsuffix', '/path', '/path']),
|
||||
('*.py',
|
||||
['source.py', 'source.ext.py', '.py'],
|
||||
['path/source.py', '/.py', 'dir.py/z', 'z.pyc', 'z.c']),
|
||||
('**/path',
|
||||
['path', '/path', '/a/path', 'c:/a/path', '/a/b/path', '//a/path', '/a/path/b/path'],
|
||||
['path/', 'a/path/b', 'dir.py/z', 'somepath', 'pathsuffix', 'a/somepath']),
|
||||
('path/**',
|
||||
['path/a', 'path/path/a', 'path//'],
|
||||
['path', 'somepath/a', 'a/path', 'a/path/a', 'pathsuffix/a']),
|
||||
('/**/path',
|
||||
['/path', '/a/path', '/a/b/path/path', '/path/path'],
|
||||
['path', 'path/', 'a/path', '/pathsuffix', '/somepath']),
|
||||
('a/b',
|
||||
['a/b'],
|
||||
['somea/b', 'a/bsuffix', 'a/b/c']),
|
||||
('**/*.py',
|
||||
['script.py', 'src/script.py', 'a/b/script.py', '/a/b/script.py'],
|
||||
['script.pyc', 'script.pyo', 'a.py/b']),
|
||||
('src/**/*.py',
|
||||
['src/a.py', 'src/dir/a.py'],
|
||||
['a/src/a.py', '/src/a.py']),
|
||||
]
|
||||
for ant_pattern, accepted_matches, rejected_matches in list(test_cases):
|
||||
def local_path(paths):
|
||||
return [ p.replace('/',os.path.sep) for p in paths ]
|
||||
test_cases.append((ant_pattern, local_path(accepted_matches), local_path(rejected_matches)))
|
||||
for ant_pattern, accepted_matches, rejected_matches in test_cases:
|
||||
rex = ant_pattern_to_re(ant_pattern)
|
||||
print('ant_pattern:', ant_pattern, ' => ', rex.pattern)
|
||||
for accepted_match in accepted_matches:
|
||||
print('Accepted?:', accepted_match)
|
||||
self.assertTrue(rex.match(accepted_match) is not None)
|
||||
for rejected_match in rejected_matches:
|
||||
print('Rejected?:', rejected_match)
|
||||
self.assertTrue(rex.match(rejected_match) is None)
|
||||
|
||||
unittest.main()
|
278
devtools/batchbuild.py
Normal file
278
devtools/batchbuild.py
Normal file
@ -0,0 +1,278 @@
|
||||
from __future__ import print_function
|
||||
import collections
|
||||
import itertools
|
||||
import json
|
||||
import os
|
||||
import os.path
|
||||
import re
|
||||
import shutil
|
||||
import string
|
||||
import subprocess
|
||||
import sys
|
||||
import html
|
||||
|
||||
class BuildDesc:
|
||||
def __init__(self, prepend_envs=None, variables=None, build_type=None, generator=None):
|
||||
self.prepend_envs = prepend_envs or [] # [ { "var": "value" } ]
|
||||
self.variables = variables or []
|
||||
self.build_type = build_type
|
||||
self.generator = generator
|
||||
|
||||
def merged_with(self, build_desc):
|
||||
"""Returns a new BuildDesc by merging field content.
|
||||
Prefer build_desc fields to self fields for single valued field.
|
||||
"""
|
||||
return BuildDesc(self.prepend_envs + build_desc.prepend_envs,
|
||||
self.variables + build_desc.variables,
|
||||
build_desc.build_type or self.build_type,
|
||||
build_desc.generator or self.generator)
|
||||
|
||||
def env(self):
|
||||
environ = os.environ.copy()
|
||||
for values_by_name in self.prepend_envs:
|
||||
for var, value in list(values_by_name.items()):
|
||||
var = var.upper()
|
||||
if type(value) is unicode:
|
||||
value = value.encode(sys.getdefaultencoding())
|
||||
if var in environ:
|
||||
environ[var] = value + os.pathsep + environ[var]
|
||||
else:
|
||||
environ[var] = value
|
||||
return environ
|
||||
|
||||
def cmake_args(self):
|
||||
args = ["-D%s" % var for var in self.variables]
|
||||
# skip build type for Visual Studio solution as it cause warning
|
||||
if self.build_type and 'Visual' not in self.generator:
|
||||
args.append("-DCMAKE_BUILD_TYPE=%s" % self.build_type)
|
||||
if self.generator:
|
||||
args.extend(['-G', self.generator])
|
||||
return args
|
||||
|
||||
def __repr__(self):
|
||||
return "BuildDesc(%s, build_type=%s)" % (" ".join(self.cmake_args()), self.build_type)
|
||||
|
||||
class BuildData:
|
||||
def __init__(self, desc, work_dir, source_dir):
|
||||
self.desc = desc
|
||||
self.work_dir = work_dir
|
||||
self.source_dir = source_dir
|
||||
self.cmake_log_path = os.path.join(work_dir, 'batchbuild_cmake.log')
|
||||
self.build_log_path = os.path.join(work_dir, 'batchbuild_build.log')
|
||||
self.cmake_succeeded = False
|
||||
self.build_succeeded = False
|
||||
|
||||
def execute_build(self):
|
||||
print('Build %s' % self.desc)
|
||||
self._make_new_work_dir()
|
||||
self.cmake_succeeded = self._generate_makefiles()
|
||||
if self.cmake_succeeded:
|
||||
self.build_succeeded = self._build_using_makefiles()
|
||||
return self.build_succeeded
|
||||
|
||||
def _generate_makefiles(self):
|
||||
print(' Generating makefiles: ', end=' ')
|
||||
cmd = ['cmake'] + self.desc.cmake_args() + [os.path.abspath(self.source_dir)]
|
||||
succeeded = self._execute_build_subprocess(cmd, self.desc.env(), self.cmake_log_path)
|
||||
print('done' if succeeded else 'FAILED')
|
||||
return succeeded
|
||||
|
||||
def _build_using_makefiles(self):
|
||||
print(' Building:', end=' ')
|
||||
cmd = ['cmake', '--build', self.work_dir]
|
||||
if self.desc.build_type:
|
||||
cmd += ['--config', self.desc.build_type]
|
||||
succeeded = self._execute_build_subprocess(cmd, self.desc.env(), self.build_log_path)
|
||||
print('done' if succeeded else 'FAILED')
|
||||
return succeeded
|
||||
|
||||
def _execute_build_subprocess(self, cmd, env, log_path):
|
||||
process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, cwd=self.work_dir,
|
||||
env=env)
|
||||
stdout, _ = process.communicate()
|
||||
succeeded = (process.returncode == 0)
|
||||
with open(log_path, 'wb') as flog:
|
||||
log = ' '.join(cmd) + '\n' + stdout + '\nExit code: %r\n' % process.returncode
|
||||
flog.write(fix_eol(log))
|
||||
return succeeded
|
||||
|
||||
def _make_new_work_dir(self):
|
||||
if os.path.isdir(self.work_dir):
|
||||
print(' Removing work directory', self.work_dir)
|
||||
shutil.rmtree(self.work_dir, ignore_errors=True)
|
||||
if not os.path.isdir(self.work_dir):
|
||||
os.makedirs(self.work_dir)
|
||||
|
||||
def fix_eol(stdout):
|
||||
"""Fixes wrong EOL produced by cmake --build on Windows (\r\r\n instead of \r\n).
|
||||
"""
|
||||
return re.sub('\r*\n', os.linesep, stdout)
|
||||
|
||||
def load_build_variants_from_config(config_path):
|
||||
with open(config_path, 'rb') as fconfig:
|
||||
data = json.load(fconfig)
|
||||
variants = data[ 'cmake_variants' ]
|
||||
build_descs_by_axis = collections.defaultdict(list)
|
||||
for axis in variants:
|
||||
axis_name = axis["name"]
|
||||
build_descs = []
|
||||
if "generators" in axis:
|
||||
for generator_data in axis["generators"]:
|
||||
for generator in generator_data["generator"]:
|
||||
build_desc = BuildDesc(generator=generator,
|
||||
prepend_envs=generator_data.get("env_prepend"))
|
||||
build_descs.append(build_desc)
|
||||
elif "variables" in axis:
|
||||
for variables in axis["variables"]:
|
||||
build_desc = BuildDesc(variables=variables)
|
||||
build_descs.append(build_desc)
|
||||
elif "build_types" in axis:
|
||||
for build_type in axis["build_types"]:
|
||||
build_desc = BuildDesc(build_type=build_type)
|
||||
build_descs.append(build_desc)
|
||||
build_descs_by_axis[axis_name].extend(build_descs)
|
||||
return build_descs_by_axis
|
||||
|
||||
def generate_build_variants(build_descs_by_axis):
|
||||
"""Returns a list of BuildDesc generated for the partial BuildDesc for each axis."""
|
||||
axis_names = list(build_descs_by_axis.keys())
|
||||
build_descs = []
|
||||
for axis_name, axis_build_descs in list(build_descs_by_axis.items()):
|
||||
if len(build_descs):
|
||||
# for each existing build_desc and each axis build desc, create a new build_desc
|
||||
new_build_descs = []
|
||||
for prototype_build_desc, axis_build_desc in itertools.product(build_descs, axis_build_descs):
|
||||
new_build_descs.append(prototype_build_desc.merged_with(axis_build_desc))
|
||||
build_descs = new_build_descs
|
||||
else:
|
||||
build_descs = axis_build_descs
|
||||
return build_descs
|
||||
|
||||
HTML_TEMPLATE = string.Template('''<html>
|
||||
<head>
|
||||
<title>$title</title>
|
||||
<style type="text/css">
|
||||
td.failed {background-color:#f08080;}
|
||||
td.ok {background-color:#c0eec0;}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<table border="1">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Variables</th>
|
||||
$th_vars
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Build type</th>
|
||||
$th_build_types
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
$tr_builds
|
||||
</tbody>
|
||||
</table>
|
||||
</body></html>''')
|
||||
|
||||
def generate_html_report(html_report_path, builds):
|
||||
report_dir = os.path.dirname(html_report_path)
|
||||
# Vertical axis: generator
|
||||
# Horizontal: variables, then build_type
|
||||
builds_by_generator = collections.defaultdict(list)
|
||||
variables = set()
|
||||
build_types_by_variable = collections.defaultdict(set)
|
||||
build_by_pos_key = {} # { (generator, var_key, build_type): build }
|
||||
for build in builds:
|
||||
builds_by_generator[build.desc.generator].append(build)
|
||||
var_key = tuple(sorted(build.desc.variables))
|
||||
variables.add(var_key)
|
||||
build_types_by_variable[var_key].add(build.desc.build_type)
|
||||
pos_key = (build.desc.generator, var_key, build.desc.build_type)
|
||||
build_by_pos_key[pos_key] = build
|
||||
variables = sorted(variables)
|
||||
th_vars = []
|
||||
th_build_types = []
|
||||
for variable in variables:
|
||||
build_types = sorted(build_types_by_variable[variable])
|
||||
nb_build_type = len(build_types_by_variable[variable])
|
||||
th_vars.append('<th colspan="%d">%s</th>' % (nb_build_type, html.escape(' '.join(variable))))
|
||||
for build_type in build_types:
|
||||
th_build_types.append('<th>%s</th>' % html.escape(build_type))
|
||||
tr_builds = []
|
||||
for generator in sorted(builds_by_generator):
|
||||
tds = [ '<td>%s</td>\n' % html.escape(generator) ]
|
||||
for variable in variables:
|
||||
build_types = sorted(build_types_by_variable[variable])
|
||||
for build_type in build_types:
|
||||
pos_key = (generator, variable, build_type)
|
||||
build = build_by_pos_key.get(pos_key)
|
||||
if build:
|
||||
cmake_status = 'ok' if build.cmake_succeeded else 'FAILED'
|
||||
build_status = 'ok' if build.build_succeeded else 'FAILED'
|
||||
cmake_log_url = os.path.relpath(build.cmake_log_path, report_dir)
|
||||
build_log_url = os.path.relpath(build.build_log_path, report_dir)
|
||||
td = '<td class="%s"><a href="%s" class="%s">CMake: %s</a>' % ( build_status.lower(), cmake_log_url, cmake_status.lower(), cmake_status)
|
||||
if build.cmake_succeeded:
|
||||
td += '<br><a href="%s" class="%s">Build: %s</a>' % ( build_log_url, build_status.lower(), build_status)
|
||||
td += '</td>'
|
||||
else:
|
||||
td = '<td></td>'
|
||||
tds.append(td)
|
||||
tr_builds.append('<tr>%s</tr>' % '\n'.join(tds))
|
||||
html = HTML_TEMPLATE.substitute( title='Batch build report',
|
||||
th_vars=' '.join(th_vars),
|
||||
th_build_types=' '.join(th_build_types),
|
||||
tr_builds='\n'.join(tr_builds))
|
||||
with open(html_report_path, 'wt') as fhtml:
|
||||
fhtml.write(html)
|
||||
print('HTML report generated in:', html_report_path)
|
||||
|
||||
def main():
|
||||
usage = r"""%prog WORK_DIR SOURCE_DIR CONFIG_JSON_PATH [CONFIG2_JSON_PATH...]
|
||||
Build a given CMake based project located in SOURCE_DIR with multiple generators/options.dry_run
|
||||
as described in CONFIG_JSON_PATH building in WORK_DIR.
|
||||
|
||||
Example of call:
|
||||
python devtools\batchbuild.py e:\buildbots\jsoncpp\build . devtools\agent_vmw7.json
|
||||
"""
|
||||
from optparse import OptionParser
|
||||
parser = OptionParser(usage=usage)
|
||||
parser.allow_interspersed_args = True
|
||||
# parser.add_option('-v', '--verbose', dest="verbose", action='store_true',
|
||||
# help="""Be verbose.""")
|
||||
parser.enable_interspersed_args()
|
||||
options, args = parser.parse_args()
|
||||
if len(args) < 3:
|
||||
parser.error("Missing one of WORK_DIR SOURCE_DIR CONFIG_JSON_PATH.")
|
||||
work_dir = args[0]
|
||||
source_dir = args[1].rstrip('/\\')
|
||||
config_paths = args[2:]
|
||||
for config_path in config_paths:
|
||||
if not os.path.isfile(config_path):
|
||||
parser.error("Can not read: %r" % config_path)
|
||||
|
||||
# generate build variants
|
||||
build_descs = []
|
||||
for config_path in config_paths:
|
||||
build_descs_by_axis = load_build_variants_from_config(config_path)
|
||||
build_descs.extend(generate_build_variants(build_descs_by_axis))
|
||||
print('Build variants (%d):' % len(build_descs))
|
||||
# assign build directory for each variant
|
||||
if not os.path.isdir(work_dir):
|
||||
os.makedirs(work_dir)
|
||||
builds = []
|
||||
with open(os.path.join(work_dir, 'matrix-dir-map.txt'), 'wt') as fmatrixmap:
|
||||
for index, build_desc in enumerate(build_descs):
|
||||
build_desc_work_dir = os.path.join(work_dir, '%03d' % (index+1))
|
||||
builds.append(BuildData(build_desc, build_desc_work_dir, source_dir))
|
||||
fmatrixmap.write('%s: %s\n' % (build_desc_work_dir, build_desc))
|
||||
for build in builds:
|
||||
build.execute_build()
|
||||
html_report_path = os.path.join(work_dir, 'batchbuild-report.html')
|
||||
generate_html_report(html_report_path, builds)
|
||||
print('Done')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
70
devtools/fixeol.py
Normal file
70
devtools/fixeol.py
Normal file
@ -0,0 +1,70 @@
|
||||
# Copyright 2010 Baptiste Lepilleur and The JsonCpp Authors
|
||||
# Distributed under MIT license, or public domain if desired and
|
||||
# recognized in your jurisdiction.
|
||||
# See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||
|
||||
from __future__ import print_function
|
||||
import os.path
|
||||
import sys
|
||||
|
||||
def fix_source_eol(path, is_dry_run = True, verbose = True, eol = '\n'):
|
||||
"""Makes sure that all sources have the specified eol sequence (default: unix)."""
|
||||
if not os.path.isfile(path):
|
||||
raise ValueError('Path "%s" is not a file' % path)
|
||||
try:
|
||||
f = open(path, 'rb')
|
||||
except IOError as msg:
|
||||
print("%s: I/O Error: %s" % (file, str(msg)), file=sys.stderr)
|
||||
return False
|
||||
try:
|
||||
raw_lines = f.readlines()
|
||||
finally:
|
||||
f.close()
|
||||
fixed_lines = [line.rstrip('\r\n') + eol for line in raw_lines]
|
||||
if raw_lines != fixed_lines:
|
||||
print('%s =>' % path, end=' ')
|
||||
if not is_dry_run:
|
||||
f = open(path, "wb")
|
||||
try:
|
||||
f.writelines(fixed_lines)
|
||||
finally:
|
||||
f.close()
|
||||
if verbose:
|
||||
print(is_dry_run and ' NEED FIX' or ' FIXED')
|
||||
return True
|
||||
##
|
||||
##
|
||||
##
|
||||
##def _do_fix(is_dry_run = True):
|
||||
## from waftools import antglob
|
||||
## python_sources = antglob.glob('.',
|
||||
## includes = '**/*.py **/wscript **/wscript_build',
|
||||
## excludes = antglob.default_excludes + './waf.py',
|
||||
## prune_dirs = antglob.prune_dirs + 'waf-* ./build')
|
||||
## for path in python_sources:
|
||||
## _fix_python_source(path, is_dry_run)
|
||||
##
|
||||
## cpp_sources = antglob.glob('.',
|
||||
## includes = '**/*.cpp **/*.h **/*.inl',
|
||||
## prune_dirs = antglob.prune_dirs + 'waf-* ./build')
|
||||
## for path in cpp_sources:
|
||||
## _fix_source_eol(path, is_dry_run)
|
||||
##
|
||||
##
|
||||
##def dry_fix(context):
|
||||
## _do_fix(is_dry_run = True)
|
||||
##
|
||||
##def fix(context):
|
||||
## _do_fix(is_dry_run = False)
|
||||
##
|
||||
##def shutdown():
|
||||
## pass
|
||||
##
|
||||
##def check(context):
|
||||
## # Unit tests are run when "check" target is used
|
||||
## ut = UnitTest.unit_test()
|
||||
## ut.change_to_testfile_dir = True
|
||||
## ut.want_to_see_test_output = True
|
||||
## ut.want_to_see_test_error = True
|
||||
## ut.run()
|
||||
## ut.print_results()
|
94
devtools/licenseupdater.py
Normal file
94
devtools/licenseupdater.py
Normal file
@ -0,0 +1,94 @@
|
||||
"""Updates the license text in source file.
|
||||
"""
|
||||
from __future__ import print_function
|
||||
|
||||
# An existing license is found if the file starts with the string below,
|
||||
# and ends with the first blank line.
|
||||
LICENSE_BEGIN = "// Copyright "
|
||||
|
||||
BRIEF_LICENSE = LICENSE_BEGIN + """2007-2010 Baptiste Lepilleur and The JsonCpp Authors
|
||||
// Distributed under MIT license, or public domain if desired and
|
||||
// recognized in your jurisdiction.
|
||||
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||
|
||||
""".replace('\r\n','\n')
|
||||
|
||||
def update_license(path, dry_run, show_diff):
|
||||
"""Update the license statement in the specified file.
|
||||
Parameters:
|
||||
path: path of the C++ source file to update.
|
||||
dry_run: if True, just print the path of the file that would be updated,
|
||||
but don't change it.
|
||||
show_diff: if True, print the path of the file that would be modified,
|
||||
as well as the change made to the file.
|
||||
"""
|
||||
with open(path, 'rt') as fin:
|
||||
original_text = fin.read().replace('\r\n','\n')
|
||||
newline = fin.newlines and fin.newlines[0] or '\n'
|
||||
if not original_text.startswith(LICENSE_BEGIN):
|
||||
# No existing license found => prepend it
|
||||
new_text = BRIEF_LICENSE + original_text
|
||||
else:
|
||||
license_end_index = original_text.index('\n\n') # search first blank line
|
||||
new_text = BRIEF_LICENSE + original_text[license_end_index+2:]
|
||||
if original_text != new_text:
|
||||
if not dry_run:
|
||||
with open(path, 'wb') as fout:
|
||||
fout.write(new_text.replace('\n', newline))
|
||||
print('Updated', path)
|
||||
if show_diff:
|
||||
import difflib
|
||||
print('\n'.join(difflib.unified_diff(original_text.split('\n'),
|
||||
new_text.split('\n'))))
|
||||
return True
|
||||
return False
|
||||
|
||||
def update_license_in_source_directories(source_dirs, dry_run, show_diff):
|
||||
"""Updates license text in C++ source files found in directory source_dirs.
|
||||
Parameters:
|
||||
source_dirs: list of directory to scan for C++ sources. Directories are
|
||||
scanned recursively.
|
||||
dry_run: if True, just print the path of the file that would be updated,
|
||||
but don't change it.
|
||||
show_diff: if True, print the path of the file that would be modified,
|
||||
as well as the change made to the file.
|
||||
"""
|
||||
from devtools import antglob
|
||||
prune_dirs = antglob.prune_dirs + 'scons-local* ./build* ./libs ./dist'
|
||||
for source_dir in source_dirs:
|
||||
cpp_sources = antglob.glob(source_dir,
|
||||
includes = '''**/*.h **/*.cpp **/*.inl''',
|
||||
prune_dirs = prune_dirs)
|
||||
for source in cpp_sources:
|
||||
update_license(source, dry_run, show_diff)
|
||||
|
||||
def main():
|
||||
usage = """%prog DIR [DIR2...]
|
||||
Updates license text in sources of the project in source files found
|
||||
in the directory specified on the command-line.
|
||||
|
||||
Example of call:
|
||||
python devtools\licenseupdater.py include src -n --diff
|
||||
=> Show change that would be made to the sources.
|
||||
|
||||
python devtools\licenseupdater.py include src
|
||||
=> Update license statement on all sources in directories include/ and src/.
|
||||
"""
|
||||
from optparse import OptionParser
|
||||
parser = OptionParser(usage=usage)
|
||||
parser.allow_interspersed_args = False
|
||||
parser.add_option('-n', '--dry-run', dest="dry_run", action='store_true', default=False,
|
||||
help="""Only show what files are updated, do not update the files""")
|
||||
parser.add_option('--diff', dest="show_diff", action='store_true', default=False,
|
||||
help="""On update, show change made to the file.""")
|
||||
parser.enable_interspersed_args()
|
||||
options, args = parser.parse_args()
|
||||
update_license_in_source_directories(args, options.dry_run, options.show_diff)
|
||||
print('Done')
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
import os.path
|
||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
main()
|
||||
|
52
devtools/tarball.py
Normal file
52
devtools/tarball.py
Normal file
@ -0,0 +1,52 @@
|
||||
# Copyright 2010 Baptiste Lepilleur and The JsonCpp Authors
|
||||
# Distributed under MIT license, or public domain if desired and
|
||||
# recognized in your jurisdiction.
|
||||
# See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||
|
||||
from contextlib import closing
|
||||
import os
|
||||
import tarfile
|
||||
|
||||
TARGZ_DEFAULT_COMPRESSION_LEVEL = 9
|
||||
|
||||
def make_tarball(tarball_path, sources, base_dir, prefix_dir=''):
|
||||
"""Parameters:
|
||||
tarball_path: output path of the .tar.gz file
|
||||
sources: list of sources to include in the tarball, relative to the current directory
|
||||
base_dir: if a source file is in a sub-directory of base_dir, then base_dir is stripped
|
||||
from path in the tarball.
|
||||
prefix_dir: all files stored in the tarball be sub-directory of prefix_dir. Set to ''
|
||||
to make them child of root.
|
||||
"""
|
||||
base_dir = os.path.normpath(os.path.abspath(base_dir))
|
||||
def archive_name(path):
|
||||
"""Makes path relative to base_dir."""
|
||||
path = os.path.normpath(os.path.abspath(path))
|
||||
common_path = os.path.commonprefix((base_dir, path))
|
||||
archive_name = path[len(common_path):]
|
||||
if os.path.isabs(archive_name):
|
||||
archive_name = archive_name[1:]
|
||||
return os.path.join(prefix_dir, archive_name)
|
||||
def visit(tar, dirname, names):
|
||||
for name in names:
|
||||
path = os.path.join(dirname, name)
|
||||
if os.path.isfile(path):
|
||||
path_in_tar = archive_name(path)
|
||||
tar.add(path, path_in_tar)
|
||||
compression = TARGZ_DEFAULT_COMPRESSION_LEVEL
|
||||
with closing(tarfile.TarFile.open(tarball_path, 'w:gz',
|
||||
compresslevel=compression)) as tar:
|
||||
for source in sources:
|
||||
source_path = source
|
||||
if os.path.isdir(source):
|
||||
for dirpath, dirnames, filenames in os.walk(source_path):
|
||||
visit(tar, dirpath, filenames)
|
||||
else:
|
||||
path_in_tar = archive_name(source_path)
|
||||
tar.add(source_path, path_in_tar) # filename, arcname
|
||||
|
||||
def decompress(tarball_path, base_dir):
|
||||
"""Decompress the gzipped tarball into directory base_dir.
|
||||
"""
|
||||
with closing(tarfile.TarFile.open(tarball_path)) as tar:
|
||||
tar.extractall(base_dir)
|
2170
doc/doxyfile.in
2170
doc/doxyfile.in
File diff suppressed because it is too large
Load Diff
@ -1,23 +1,21 @@
|
||||
<hr>
|
||||
<table width="100%">
|
||||
<tr>
|
||||
<td width="10%" align="left" valign="center">
|
||||
<a href="http://sourceforge.net">
|
||||
<img
|
||||
src="http://sourceforge.net/sflogo.php?group_id=144446"
|
||||
width="88" height="31" border="0" alt="SourceForge Logo"></a>
|
||||
</td>
|
||||
<td width="20%" align="left" valign="center">
|
||||
hosts this site.
|
||||
</td>
|
||||
<td>
|
||||
</td>
|
||||
<td align="right" valign="center">
|
||||
Send comments to:<br>
|
||||
<a href="mailto:jsoncpp-devel@lists.sourceforge.net">Json-cpp Developers</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<!-- HTML footer for doxygen 1.8.13-->
|
||||
<!-- start footer part -->
|
||||
<!--BEGIN GENERATE_TREEVIEW-->
|
||||
<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
|
||||
<ul>
|
||||
$navpath
|
||||
<li class="footer">$generatedby
|
||||
<a href="http://www.doxygen.org/index.html">
|
||||
<img class="footer" src="$relpath^doxygen.png" alt="doxygen"/></a> $doxygenversion </li>
|
||||
</ul>
|
||||
</div>
|
||||
<!--END GENERATE_TREEVIEW-->
|
||||
<!--BEGIN !GENERATE_TREEVIEW-->
|
||||
<hr class="footer"/><address class="footer"><small>
|
||||
$generatedby  <a href="http://www.doxygen.org/index.html">
|
||||
<img class="footer" src="$relpath^doxygen.png" alt="doxygen"/>
|
||||
</a> $doxygenversion
|
||||
</small></address>
|
||||
<!--END !GENERATE_TREEVIEW-->
|
||||
</body>
|
||||
</html>
|
||||
|
@ -1,24 +1,64 @@
|
||||
<html>
|
||||
<!-- HTML header for doxygen 1.8.13-->
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>
|
||||
JsonCpp - JSON data format manipulation library
|
||||
</title>
|
||||
<link href="doxygen.css" rel="stylesheet" type="text/css">
|
||||
<link href="tabs.css" rel="stylesheet" type="text/css">
|
||||
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
|
||||
<meta name="generator" content="Doxygen $doxygenversion"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
||||
<link href="$relpath^tabs.css" rel="stylesheet" type="text/css"/>
|
||||
<script type="text/javascript" src="$relpath^jquery.js"></script>
|
||||
<script type="text/javascript" src="$relpath^dynsections.js"></script>
|
||||
$treeview
|
||||
$search
|
||||
$mathjax
|
||||
<link href="$relpath^$stylesheet" rel="stylesheet" type="text/css" />
|
||||
$extrastylesheet
|
||||
</head>
|
||||
<body>
|
||||
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
|
||||
|
||||
<!--BEGIN TITLEAREA-->
|
||||
<div id="titlearea">
|
||||
<table cellspacing="0" cellpadding="0">
|
||||
<tbody>
|
||||
<tr style="height: 56px;">
|
||||
<!--BEGIN PROJECT_LOGO-->
|
||||
<td id="projectlogo"><img alt="Logo" src="$relpath^$projectlogo"/></td>
|
||||
<!--END PROJECT_LOGO-->
|
||||
<!--BEGIN DISABLE_INDEX-->
|
||||
<!--BEGIN SEARCHENGINE-->
|
||||
<td>$searchbox</td>
|
||||
<!--END SEARCHENGINE-->
|
||||
<!--END DISABLE_INDEX-->
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<!--END TITLEAREA-->
|
||||
<body bgcolor="#ffffff">
|
||||
<table width="100%">
|
||||
<tr>
|
||||
<td width="40%" align="left" valign="center">
|
||||
<a href="http://sourceforge.net/projects/jsoncpp">
|
||||
<td width="30%" align="left" valign="center">
|
||||
<a href="https://github.com/open-source-parsers/jsoncpp">
|
||||
JsonCpp project page
|
||||
</a>
|
||||
</td>
|
||||
<td width="40%" align="right" valign="center">
|
||||
<a href="http://jsoncpp.sourceforge.net">JsonCpp home page</a>
|
||||
<td width="20%" align="center" valign="center">
|
||||
<a href="hierarchy.html">
|
||||
Classes
|
||||
</a>
|
||||
</td>
|
||||
<td width="20%" align="center" valign="center">
|
||||
<a href="namespace_json.html">
|
||||
Namespace
|
||||
</a>
|
||||
</td>
|
||||
<td width="30%" align="right" valign="center">
|
||||
<a href="http://open-source-parsers.github.io/jsoncpp-docs/doxygen/">JsonCpp home page</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<hr>
|
||||
<!-- end header part -->
|
||||
|
173
doc/jsoncpp.dox
173
doc/jsoncpp.dox
@ -4,11 +4,21 @@
|
||||
|
||||
<a HREF="http://www.json.org/">JSON (JavaScript Object Notation)</a>
|
||||
is a lightweight data-interchange format.
|
||||
It can represents integer, real number, string, an ordered sequence of value, and
|
||||
a collection of name/value pairs.
|
||||
|
||||
Here is an example of JSON data:
|
||||
\verbatim
|
||||
{
|
||||
"encoding" : "UTF-8",
|
||||
"plug-ins" : [
|
||||
"python",
|
||||
"c++",
|
||||
"ruby"
|
||||
],
|
||||
"indent" : { "length" : 3, "use_space": true }
|
||||
}
|
||||
\endverbatim
|
||||
<b>JsonCpp</b> supports comments as <i>meta-data</i>:
|
||||
\code
|
||||
// Configuration options
|
||||
{
|
||||
// Default encoding for text
|
||||
@ -17,81 +27,138 @@ Here is an example of JSON data:
|
||||
// Plug-ins loaded at start-up
|
||||
"plug-ins" : [
|
||||
"python",
|
||||
"c++",
|
||||
"c++", // trailing comment
|
||||
"ruby"
|
||||
],
|
||||
|
||||
// Tab indent size
|
||||
"indent" : { "length" : 3, "use_space" = true }
|
||||
// (multi-line comment)
|
||||
"indent" : { /*embedded comment*/ "length" : 3, "use_space": true }
|
||||
}
|
||||
\endverbatim
|
||||
\endcode
|
||||
|
||||
\section _features Features
|
||||
- read and write JSON document
|
||||
- attach C++ style comments to element during parsing
|
||||
- rewrite JSON document preserving original comments
|
||||
|
||||
Notes: Comments used to be supported in JSON but were removed for
|
||||
portability (C like comments are not supported in Python). Since
|
||||
comments are useful in configuration/input file, this feature was
|
||||
preserved.
|
||||
|
||||
\section _example Code example
|
||||
|
||||
\code
|
||||
Json::Value root; // will contains the root value after parsing.
|
||||
Json::Reader reader;
|
||||
bool parsingSuccessful = reader.parse( config_doc, root );
|
||||
if ( !parsingSuccessful )
|
||||
{
|
||||
// report to the user the failure and their locations in the document.
|
||||
std::cout << "Failed to parse configuration\n"
|
||||
<< reader.getFormatedErrorMessages();
|
||||
return;
|
||||
}
|
||||
Json::Value root; // 'root' will contain the root value after parsing.
|
||||
std::cin >> root;
|
||||
|
||||
// Get the value of the member of root named 'encoding', return 'UTF-8' if there is no
|
||||
// such member.
|
||||
std::string encoding = root.get("encoding", "UTF-8" ).asString();
|
||||
// Get the value of the member of root named 'encoding', return a 'null' value if
|
||||
// there is no such member.
|
||||
const Json::Value plugins = root["plug-ins"];
|
||||
for ( int index = 0; index < plugins.size(); ++index ) // Iterates over the sequence elements.
|
||||
loadPlugIn( plugins[index].asString() );
|
||||
|
||||
setIndentLength( root["indent"].get("length", 3).asInt() );
|
||||
setIndentUseSpace( root["indent"].get("use_space", true).asBool() );
|
||||
|
||||
// ...
|
||||
// At application shutdown to make the new configuration document:
|
||||
// Since Json::Value has implicit constructor for all value types, it is not
|
||||
// necessary to explicitely construct the Json::Value object:
|
||||
root["encoding"] = getCurrentEncoding();
|
||||
root["indent"]["length"] = getCurrentIndentLength();
|
||||
root["indent"]["use_space"] = getCurrentIndentUseSpace();
|
||||
|
||||
Json::StyledWriter writer;
|
||||
// Make a new JSON document for the configuration. Preserve original comments.
|
||||
std::string outputConfig = writer.write( root );
|
||||
|
||||
// You can also use streams. This will put the contents of any JSON
|
||||
// stream at a particular sub-value, if you'd like.
|
||||
// You can also read into a particular sub-value.
|
||||
std::cin >> root["subtree"];
|
||||
|
||||
// And you can write to a stream, using the StyledWriter automatically.
|
||||
// Get the value of the member of root named 'encoding',
|
||||
// and return 'UTF-8' if there is no such member.
|
||||
std::string encoding = root.get("encoding", "UTF-8" ).asString();
|
||||
|
||||
// Get the value of the member of root named 'plug-ins'; return a 'null' value if
|
||||
// there is no such member.
|
||||
const Json::Value plugins = root["plug-ins"];
|
||||
|
||||
// Iterate over the sequence elements.
|
||||
for ( int index = 0; index < plugins.size(); ++index )
|
||||
loadPlugIn( plugins[index].asString() );
|
||||
|
||||
// Try other datatypes. Some are auto-convertible to others.
|
||||
foo::setIndentLength( root["indent"].get("length", 3).asInt() );
|
||||
foo::setIndentUseSpace( root["indent"].get("use_space", true).asBool() );
|
||||
|
||||
// Since Json::Value has an implicit constructor for all value types, it is not
|
||||
// necessary to explicitly construct the Json::Value object.
|
||||
root["encoding"] = foo::getCurrentEncoding();
|
||||
root["indent"]["length"] = foo::getCurrentIndentLength();
|
||||
root["indent"]["use_space"] = foo::getCurrentIndentUseSpace();
|
||||
|
||||
// If you like the defaults, you can insert directly into a stream.
|
||||
std::cout << root;
|
||||
// Of course, you can write to `std::ostringstream` if you prefer.
|
||||
|
||||
// If desired, remember to add a linefeed and flush.
|
||||
std::cout << std::endl;
|
||||
\endcode
|
||||
|
||||
\section _plinks Build instructions
|
||||
The build instruction are located in the file
|
||||
<a HREF="README.txt">README.txt</a> in the top-directory of the project.
|
||||
\section _advanced Advanced usage
|
||||
|
||||
Permanent link to the lastest revision of the file in subversion:
|
||||
<a HREF="http://svn.sourceforge.net/viewcvs.cgi/jsoncpp/README.txt?view=markup">lastest README.txt</a>
|
||||
Configure *builders* to create *readers* and *writers*. For
|
||||
configuration, we use our own `Json::Value` (rather than
|
||||
standard setters/getters) so that we can add
|
||||
features without losing binary-compatibility.
|
||||
|
||||
\section _plinks Project links
|
||||
- <a HREF="http://jsoncpp.sourceforge.net">json-cpp home</a>
|
||||
- <a HREF="http://www.sourceforge.net/projects/jsoncpp">json-cpp sourceforge project</a>
|
||||
\code
|
||||
// For convenience, use `writeString()` with a specialized builder.
|
||||
Json::StreamWriterBuilder wbuilder;
|
||||
wbuilder["indentation"] = "\t";
|
||||
std::string document = Json::writeString(wbuilder, root);
|
||||
|
||||
// Here, using a specialized Builder, we discard comments and
|
||||
// record errors as we parse.
|
||||
Json::CharReaderBuilder rbuilder;
|
||||
rbuilder["collectComments"] = false;
|
||||
std::string errs;
|
||||
bool ok = Json::parseFromStream(rbuilder, std::cin, &root, &errs);
|
||||
\endcode
|
||||
|
||||
Yes, compile-time configuration-checking would be helpful,
|
||||
but `Json::Value` lets you
|
||||
write and read the builder configuration, which is better! In other words,
|
||||
you can configure your JSON parser using JSON.
|
||||
|
||||
CharReaders and StreamWriters are not thread-safe, but they are re-usable.
|
||||
\code
|
||||
Json::CharReaderBuilder rbuilder;
|
||||
cfg >> rbuilder.settings_;
|
||||
std::unique_ptr<Json::CharReader> const reader(rbuilder.newCharReader());
|
||||
reader->parse(start, stop, &value1, &errs);
|
||||
// ...
|
||||
reader->parse(start, stop, &value2, &errs);
|
||||
// etc.
|
||||
\endcode
|
||||
|
||||
\section _pbuild Build instructions
|
||||
The build instructions are located in the file
|
||||
<a HREF="https://github.com/open-source-parsers/jsoncpp/blob/master/README.md">README.md</a> in the top-directory of the project.
|
||||
|
||||
The latest version of the source is available in the project's GitHub repository:
|
||||
<a HREF="https://github.com/open-source-parsers/jsoncpp/">
|
||||
jsoncpp</a>
|
||||
|
||||
\section _news What's New?
|
||||
The description of latest changes can be found in
|
||||
<a HREF="https://github.com/open-source-parsers/jsoncpp/wiki/NEWS">
|
||||
the NEWS wiki
|
||||
</a>.
|
||||
|
||||
\section _rlinks Related links
|
||||
- <a HREF="http://www.json.org/">JSON</a> Specification and alternate language implementations.
|
||||
- <a HREF="http://www.yaml.org/">YAML</a> A data format designed for human readability.
|
||||
- <a HREF="http://www.cl.cam.ac.uk/~mgk25/unicode.html">UTF-8 and Unicode FAQ</a>.
|
||||
|
||||
\section _license License
|
||||
The json-cpp library and this documentation are in Public Domain.
|
||||
\section _plinks Old project links
|
||||
- <a href="https://sourceforge.net/projects/jsoncpp/">https://sourceforge.net/projects/jsoncpp/</a>
|
||||
- <a href="http://jsoncpp.sourceforge.net">http://jsoncpp.sourceforge.net</a>
|
||||
- <a href="http://sourceforge.net/projects/jsoncpp/files/">http://sourceforge.net/projects/jsoncpp/files/</a>
|
||||
- <a href="http://jsoncpp.svn.sourceforge.net/svnroot/jsoncpp/trunk/">http://jsoncpp.svn.sourceforge.net/svnroot/jsoncpp/trunk/</a>
|
||||
- <a href="http://jsoncpp.sourceforge.net/old.html">http://jsoncpp.sourceforge.net/old.html</a>
|
||||
|
||||
\author Baptiste Lepilleur <blep@users.sourceforge.net>
|
||||
\section _license License
|
||||
See file <a href="https://github.com/open-source-parsers/jsoncpp/blob/master/LICENSE"><code>LICENSE</code></a> in the top-directory of the project.
|
||||
|
||||
Basically JsonCpp is licensed under MIT license, or public domain if desired
|
||||
and recognized in your jurisdiction.
|
||||
|
||||
\author Baptiste Lepilleur <blep@users.sourceforge.net> (originator)
|
||||
\author Christopher Dunn <cdunn2001@gmail.com> (primary maintainer)
|
||||
\version \include version
|
||||
We make strong guarantees about binary-compatibility, consistent with
|
||||
<a href="http://apr.apache.org/versioning.html">the Apache versioning scheme</a>.
|
||||
\sa version.h
|
||||
*/
|
||||
|
@ -1,32 +1,3 @@
|
||||
/*! \page roadmap JsonCpp roadmap
|
||||
\section ms_release Makes JsonCpp ready for release
|
||||
- Build system clean-up:
|
||||
- Fix build on Windows (shared-library build is broken)
|
||||
- Add enable/disable flag for static and shared library build
|
||||
- Enhance help
|
||||
- Platform portability check: (Notes: was ok on last check)
|
||||
- linux/gcc,
|
||||
- solaris/cc,
|
||||
- windows/msvc678,
|
||||
- aix/vacpp
|
||||
- Add JsonCpp version to header as numeric for use in preprocessor test
|
||||
- Remove buggy experimental hash stuff
|
||||
- Release on sourceforge download
|
||||
\section ms_strict Adds a strict mode to reader/parser
|
||||
Strict JSON support as specific in RFC 4627 (http://www.ietf.org/rfc/rfc4627.txt?number=4627).
|
||||
- Enforce only object or array as root element
|
||||
- Disable comment support
|
||||
- Get jsonchecker failing tests to pass in strict mode
|
||||
\section ms_separation Expose json reader/writer API that do not impose using Json::Value.
|
||||
Some typical use-case involve an application specific structure to/from a JSON document.
|
||||
- Event base parser to allow unserializing a Json document directly in datastructure instead of
|
||||
using the intermediate Json::Value.
|
||||
- "Stream" based parser to serialized a Json document without using Json::Value as input.
|
||||
- Performance oriented parser/writer:
|
||||
- Provides an event based parser. Should allow pulling & skipping events for ease of use.
|
||||
- Provides a JSON document builder: fast only.
|
||||
\section ms_perfo Performance tuning
|
||||
- Provides support for static property name definition avoiding allocation
|
||||
- Static property dictionnary can be provided to JSON reader
|
||||
- Performance scenario & benchmarking
|
||||
Moved to: https://github.com/open-source-parsers/jsoncpp/wiki/Roadmap
|
||||
*/
|
||||
|
@ -1,61 +0,0 @@
|
||||
Import( 'env' )
|
||||
import os.path
|
||||
|
||||
if 'doxygen' in env['TOOLS']:
|
||||
doc_topdir = str(env['ROOTBUILD_DIR'])
|
||||
html_dir = 'jsoncpp-api-doc'
|
||||
|
||||
doxygen_inputs = env.Glob( includes = '*.dox', dir = '#doc' ) \
|
||||
+ env.Glob( includes = '*.h', dir = '#include/json/' ) \
|
||||
+ env.Glob( includes = ('*.dox','*.h','*.inl','*.cpp'),
|
||||
dir = '#src/lib_json' )
|
||||
## for p in doxygen_inputs:
|
||||
## print p.abspath
|
||||
|
||||
top_dir = env.Dir('#').abspath
|
||||
include_top_dir = env.Dir('#include').abspath
|
||||
env['DOXYFILE_DICT'] = { 'PROJECT_NAME': 'JsonCpp',
|
||||
'PROJECT_NUMBER': env['JSONCPP_VERSION'],
|
||||
'STRIP_FROM_PATH': top_dir,
|
||||
'STRIP_FROM_INC_PATH': include_top_dir,
|
||||
'HTML_OUTPUT': html_dir,
|
||||
'HTML_HEADER': env.File('#doc/header.html').abspath,
|
||||
'HTML_FOOTER': env.File('#doc/footer.html').abspath,
|
||||
'INCLUDE_PATH': include_top_dir,
|
||||
'PREDEFINED': 'JSONCPP_DOC_EXCLUDE_IMPLEMENTATION JSON_VALUE_USE_INTERNAL_MAP'
|
||||
}
|
||||
env['DOXYFILE_FILE'] = 'doxyfile.in'
|
||||
doxfile_nodes = env.Doxyfile( os.path.join( doc_topdir, 'doxyfile' ), doxygen_inputs )
|
||||
html_doc_path = os.path.join( doc_topdir, html_dir )
|
||||
doc_nodes = env.Doxygen( source = doxfile_nodes,
|
||||
target = os.path.join( html_doc_path, 'index.html' ) )
|
||||
alias_doc_cmd = env.Alias('doc', doc_nodes )
|
||||
env.Alias('doc', env.Install( html_doc_path, '#README.txt' ) )
|
||||
if 'TarGz' in env['BUILDERS']:
|
||||
targz_path = os.path.join( env['DIST_DIR'], '%s.tar.gz' % html_dir )
|
||||
zip_doc_cmd = env.TarGz( targz_path, [env.Dir(html_doc_path)],
|
||||
TARGZ_BASEDIR = env['ROOTBUILD_DIR'] )
|
||||
env.Depends( zip_doc_cmd, alias_doc_cmd )
|
||||
env.Alias( 'doc-dist', zip_doc_cmd )
|
||||
##
|
||||
## doxyfile = env.SubstInFile( '#doc/doxyfile', 'doxyfile.in',
|
||||
## SUBST_DICT = {
|
||||
## '%JSONCPP_VERSION%' : env['JSONCPP_VERSION'],
|
||||
## '%TOPDIR%' : env.Dir('#').abspath,
|
||||
## '%DOC_TOPDIR%' : str(doc_topdir) } )
|
||||
## doc_cmd = env.Doxygen( doxyfile )
|
||||
## alias_doc_cmd = env.Alias('doc', doc_cmd )
|
||||
## env.AlwaysBuild(alias_doc_cmd)
|
||||
##
|
||||
## for dir in doc_cmd:
|
||||
## env.Alias('doc', env.Install( '#' + dir.path, '#README.txt' ) )
|
||||
## filename = os.path.split(dir.path)[1]
|
||||
## targz_path = os.path.join( env['DIST_DIR'], '%s.tar.gz' % filename )
|
||||
## zip_doc_cmd = env.TarGz( targz_path, [env.Dir(dir)],
|
||||
## TARGZ_BASEDIR = doc_topdir )
|
||||
## env.Depends( zip_doc_cmd, alias_doc_cmd )
|
||||
## env.Alias( 'doc-dist', zip_doc_cmd )
|
||||
##
|
||||
## # When doxyfile gets updated, I get errors on the first pass.
|
||||
## # I have to run scons twice. Something is wrong with the dependencies
|
||||
## # here, but I avoid it by running "scons doc/doxyfile" first.
|
2290
doc/web_doxyfile.in
Normal file
2290
doc/web_doxyfile.in
Normal file
File diff suppressed because it is too large
Load Diff
189
doxybuild.py
Normal file
189
doxybuild.py
Normal file
@ -0,0 +1,189 @@
|
||||
"""Script to generate doxygen documentation.
|
||||
"""
|
||||
from __future__ import print_function
|
||||
from __future__ import unicode_literals
|
||||
from devtools import tarball
|
||||
from contextlib import contextmanager
|
||||
import subprocess
|
||||
import traceback
|
||||
import re
|
||||
import os
|
||||
import sys
|
||||
import shutil
|
||||
|
||||
@contextmanager
|
||||
def cd(newdir):
|
||||
"""
|
||||
http://stackoverflow.com/questions/431684/how-do-i-cd-in-python
|
||||
"""
|
||||
prevdir = os.getcwd()
|
||||
os.chdir(newdir)
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
os.chdir(prevdir)
|
||||
|
||||
def find_program(*filenames):
|
||||
"""find a program in folders path_lst, and sets env[var]
|
||||
@param filenames: a list of possible names of the program to search for
|
||||
@return: the full path of the filename if found, or '' if filename could not be found
|
||||
"""
|
||||
paths = os.environ.get('PATH', '').split(os.pathsep)
|
||||
suffixes = ('win32' in sys.platform) and '.exe .com .bat .cmd' or ''
|
||||
for filename in filenames:
|
||||
for name in [filename+ext for ext in suffixes.split(' ')]:
|
||||
for directory in paths:
|
||||
full_path = os.path.join(directory, name)
|
||||
if os.path.isfile(full_path):
|
||||
return full_path
|
||||
return ''
|
||||
|
||||
def do_subst_in_file(targetfile, sourcefile, dict):
|
||||
"""Replace all instances of the keys of dict with their values.
|
||||
For example, if dict is {'%VERSION%': '1.2345', '%BASE%': 'MyProg'},
|
||||
then all instances of %VERSION% in the file will be replaced with 1.2345 etc.
|
||||
"""
|
||||
with open(sourcefile, 'r') as f:
|
||||
contents = f.read()
|
||||
for (k,v) in list(dict.items()):
|
||||
v = v.replace('\\','\\\\')
|
||||
contents = re.sub(k, v, contents)
|
||||
with open(targetfile, 'w') as f:
|
||||
f.write(contents)
|
||||
|
||||
def getstatusoutput(cmd):
|
||||
"""cmd is a list.
|
||||
"""
|
||||
try:
|
||||
process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||
output, _ = process.communicate()
|
||||
status = process.returncode
|
||||
except:
|
||||
status = -1
|
||||
output = traceback.format_exc()
|
||||
return status, output
|
||||
|
||||
def run_cmd(cmd, silent=False):
|
||||
"""Raise exception on failure.
|
||||
"""
|
||||
info = 'Running: %r in %r' %(' '.join(cmd), os.getcwd())
|
||||
print(info)
|
||||
sys.stdout.flush()
|
||||
if silent:
|
||||
status, output = getstatusoutput(cmd)
|
||||
else:
|
||||
status, output = subprocess.call(cmd), ''
|
||||
if status:
|
||||
msg = 'Error while %s ...\n\terror=%d, output="""%s"""' %(info, status, output)
|
||||
raise Exception(msg)
|
||||
|
||||
def assert_is_exe(path):
|
||||
if not path:
|
||||
raise Exception('path is empty.')
|
||||
if not os.path.isfile(path):
|
||||
raise Exception('%r is not a file.' %path)
|
||||
if not os.access(path, os.X_OK):
|
||||
raise Exception('%r is not executable by this user.' %path)
|
||||
|
||||
def run_doxygen(doxygen_path, config_file, working_dir, is_silent):
|
||||
assert_is_exe(doxygen_path)
|
||||
config_file = os.path.abspath(config_file)
|
||||
with cd(working_dir):
|
||||
cmd = [doxygen_path, config_file]
|
||||
run_cmd(cmd, is_silent)
|
||||
|
||||
def build_doc(options, make_release=False):
|
||||
if make_release:
|
||||
options.make_tarball = True
|
||||
options.with_dot = True
|
||||
options.with_html_help = True
|
||||
options.with_uml_look = True
|
||||
options.open = False
|
||||
options.silent = True
|
||||
|
||||
version = open('version', 'rt').read().strip()
|
||||
output_dir = 'dist/doxygen' # relative to doc/doxyfile location.
|
||||
if not os.path.isdir(output_dir):
|
||||
os.makedirs(output_dir)
|
||||
top_dir = os.path.abspath('.')
|
||||
html_output_dirname = 'jsoncpp-api-html-' + version
|
||||
tarball_path = os.path.join('dist', html_output_dirname + '.tar.gz')
|
||||
warning_log_path = os.path.join(output_dir, '../jsoncpp-doxygen-warning.log')
|
||||
html_output_path = os.path.join(output_dir, html_output_dirname)
|
||||
def yesno(bool):
|
||||
return bool and 'YES' or 'NO'
|
||||
subst_keys = {
|
||||
'%JSONCPP_VERSION%': version,
|
||||
'%DOC_TOPDIR%': '',
|
||||
'%TOPDIR%': top_dir,
|
||||
'%HTML_OUTPUT%': os.path.join('..', output_dir, html_output_dirname),
|
||||
'%HAVE_DOT%': yesno(options.with_dot),
|
||||
'%DOT_PATH%': os.path.split(options.dot_path)[0],
|
||||
'%HTML_HELP%': yesno(options.with_html_help),
|
||||
'%UML_LOOK%': yesno(options.with_uml_look),
|
||||
'%WARNING_LOG_PATH%': os.path.join('..', warning_log_path)
|
||||
}
|
||||
|
||||
if os.path.isdir(output_dir):
|
||||
print('Deleting directory:', output_dir)
|
||||
shutil.rmtree(output_dir)
|
||||
if not os.path.isdir(output_dir):
|
||||
os.makedirs(output_dir)
|
||||
|
||||
do_subst_in_file('doc/doxyfile', options.doxyfile_input_path, subst_keys)
|
||||
run_doxygen(options.doxygen_path, 'doc/doxyfile', 'doc', is_silent=options.silent)
|
||||
if not options.silent:
|
||||
print(open(warning_log_path, 'r').read())
|
||||
index_path = os.path.abspath(os.path.join('doc', subst_keys['%HTML_OUTPUT%'], 'index.html'))
|
||||
print('Generated documentation can be found in:')
|
||||
print(index_path)
|
||||
if options.open:
|
||||
import webbrowser
|
||||
webbrowser.open('file://' + index_path)
|
||||
if options.make_tarball:
|
||||
print('Generating doc tarball to', tarball_path)
|
||||
tarball_sources = [
|
||||
output_dir,
|
||||
'README.md',
|
||||
'LICENSE',
|
||||
'NEWS.txt',
|
||||
'version'
|
||||
]
|
||||
tarball_basedir = os.path.join(output_dir, html_output_dirname)
|
||||
tarball.make_tarball(tarball_path, tarball_sources, tarball_basedir, html_output_dirname)
|
||||
return tarball_path, html_output_dirname
|
||||
|
||||
def main():
|
||||
usage = """%prog
|
||||
Generates doxygen documentation in build/doxygen.
|
||||
Optionally makes a tarball of the documentation to dist/.
|
||||
|
||||
Must be started in the project top directory.
|
||||
"""
|
||||
from optparse import OptionParser
|
||||
parser = OptionParser(usage=usage)
|
||||
parser.allow_interspersed_args = False
|
||||
parser.add_option('--with-dot', dest="with_dot", action='store_true', default=False,
|
||||
help="""Enable usage of DOT to generate collaboration diagram""")
|
||||
parser.add_option('--dot', dest="dot_path", action='store', default=find_program('dot'),
|
||||
help="""Path to GraphViz dot tool. Must be full qualified path. [Default: %default]""")
|
||||
parser.add_option('--doxygen', dest="doxygen_path", action='store', default=find_program('doxygen'),
|
||||
help="""Path to Doxygen tool. [Default: %default]""")
|
||||
parser.add_option('--in', dest="doxyfile_input_path", action='store', default='doc/doxyfile.in',
|
||||
help="""Path to doxygen inputs. [Default: %default]""")
|
||||
parser.add_option('--with-html-help', dest="with_html_help", action='store_true', default=False,
|
||||
help="""Enable generation of Microsoft HTML HELP""")
|
||||
parser.add_option('--no-uml-look', dest="with_uml_look", action='store_false', default=True,
|
||||
help="""Generates DOT graph without UML look [Default: False]""")
|
||||
parser.add_option('--open', dest="open", action='store_true', default=False,
|
||||
help="""Open the HTML index in the web browser after generation""")
|
||||
parser.add_option('--tarball', dest="make_tarball", action='store_true', default=False,
|
||||
help="""Generates a tarball of the documentation in dist/ directory""")
|
||||
parser.add_option('-s', '--silent', dest="silent", action='store_true', default=False,
|
||||
help="""Hides doxygen output""")
|
||||
parser.enable_interspersed_args()
|
||||
options, args = parser.parse_args()
|
||||
build_doc(options)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
33
example/BUILD.bazel
Normal file
33
example/BUILD.bazel
Normal file
@ -0,0 +1,33 @@
|
||||
cc_binary(
|
||||
name = "readFromStream_ok",
|
||||
srcs = ["readFromStream/readFromStream.cpp"],
|
||||
deps = ["//:jsoncpp"],
|
||||
args = ["$(location :readFromStream/withComment.json)"],
|
||||
data = ["readFromStream/withComment.json"],
|
||||
)
|
||||
|
||||
cc_binary(
|
||||
name = "readFromStream_err",
|
||||
srcs = ["readFromStream/readFromStream.cpp"],
|
||||
deps = ["//:jsoncpp"],
|
||||
args = ["$(location :readFromStream/errorFormat.json)"],
|
||||
data = ["readFromStream/errorFormat.json"],
|
||||
)
|
||||
|
||||
cc_binary(
|
||||
name = "readFromString",
|
||||
srcs = ["readFromString/readFromString.cpp"],
|
||||
deps = ["//:jsoncpp"],
|
||||
)
|
||||
|
||||
cc_binary(
|
||||
name = "streamWrite",
|
||||
srcs = ["streamWrite/streamWrite.cpp"],
|
||||
deps = ["//:jsoncpp"],
|
||||
)
|
||||
|
||||
cc_binary(
|
||||
name = "stringWrite",
|
||||
srcs = ["stringWrite/stringWrite.cpp"],
|
||||
deps = ["//:jsoncpp"],
|
||||
)
|
27
example/CMakeLists.txt
Normal file
27
example/CMakeLists.txt
Normal file
@ -0,0 +1,27 @@
|
||||
#vim: et ts =4 sts = 4 sw = 4 tw = 0
|
||||
set(EXAMPLES
|
||||
readFromString
|
||||
readFromStream
|
||||
stringWrite
|
||||
streamWrite
|
||||
)
|
||||
add_definitions(-D_GLIBCXX_USE_CXX11_ABI)
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||
add_compile_options(-Wall -Wextra)
|
||||
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
||||
add_definitions(
|
||||
-D_SCL_SECURE_NO_WARNINGS
|
||||
-D_CRT_SECURE_NO_WARNINGS
|
||||
-D_WIN32_WINNT=0x601
|
||||
-D_WINSOCK_DEPRECATED_NO_WARNINGS
|
||||
)
|
||||
endif()
|
||||
|
||||
foreach(example ${EXAMPLES})
|
||||
add_executable(${example} ${example}/${example}.cpp)
|
||||
target_include_directories(${example} PUBLIC ${CMAKE_SOURCE_DIR}/include)
|
||||
target_link_libraries(${example} jsoncpp_lib)
|
||||
endforeach()
|
||||
|
||||
add_custom_target(examples ALL DEPENDS ${EXAMPLES})
|
13
example/README.md
Normal file
13
example/README.md
Normal file
@ -0,0 +1,13 @@
|
||||
***NOTE***
|
||||
|
||||
If you get linker errors about undefined references to symbols that involve types in the `std::__cxx11` namespace or the tag
|
||||
`[abi:cxx11]` then it probably indicates that you are trying to link together object files that were compiled with different
|
||||
values for the _GLIBCXX_USE_CXX11_ABI marco. This commonly happens when linking to a third-party library that was compiled with
|
||||
an older version of GCC. If the third-party library cannot be rebuilt with the new ABI, then you need to recompile your code with
|
||||
the old ABI,just like:
|
||||
**g++ stringWrite.cpp -ljsoncpp -std=c++11 -D_GLIBCXX_USE_CXX11_ABI=0 -o stringWrite**
|
||||
|
||||
Not all of uses of the new ABI will cause changes in symbol names, for example a class with a `std::string` member variable will
|
||||
have the same mangled name whether compiled with the older or new ABI. In order to detect such problems, the new types and functions
|
||||
are annotated with the abi_tag attribute, allowing the compiler to warn about potential ABI incompatibilities in code using them.
|
||||
Those warnings can be enabled with the `-Wabi-tag` option.
|
3
example/readFromStream/errorFormat.json
Normal file
3
example/readFromStream/errorFormat.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
1: "value"
|
||||
}
|
30
example/readFromStream/readFromStream.cpp
Normal file
30
example/readFromStream/readFromStream.cpp
Normal file
@ -0,0 +1,30 @@
|
||||
#include "json/json.h"
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
/** \brief Parse from stream, collect comments and capture error info.
|
||||
* Example Usage:
|
||||
* $g++ readFromStream.cpp -ljsoncpp -std=c++11 -o readFromStream
|
||||
* $./readFromStream
|
||||
* // comment head
|
||||
* {
|
||||
* // comment before
|
||||
* "key" : "value"
|
||||
* }
|
||||
* // comment after
|
||||
* // comment tail
|
||||
*/
|
||||
int main(int argc, char* argv[]) {
|
||||
Json::Value root;
|
||||
std::ifstream ifs;
|
||||
ifs.open(argv[1]);
|
||||
|
||||
Json::CharReaderBuilder builder;
|
||||
builder["collectComments"] = true;
|
||||
JSONCPP_STRING errs;
|
||||
if (!parseFromStream(builder, ifs, &root, &errs)) {
|
||||
std::cout << errs << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
std::cout << root << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
6
example/readFromStream/withComment.json
Normal file
6
example/readFromStream/withComment.json
Normal file
@ -0,0 +1,6 @@
|
||||
// comment head
|
||||
{
|
||||
// comment before
|
||||
"key" : "value"
|
||||
// comment after
|
||||
}// comment tail
|
38
example/readFromString/readFromString.cpp
Normal file
38
example/readFromString/readFromString.cpp
Normal file
@ -0,0 +1,38 @@
|
||||
#include "json/json.h"
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
/**
|
||||
* \brief Parse a raw string into Value object using the CharReaderBuilder
|
||||
* class, or the legacy Reader class.
|
||||
* Example Usage:
|
||||
* $g++ readFromString.cpp -ljsoncpp -std=c++11 -o readFromString
|
||||
* $./readFromString
|
||||
* colin
|
||||
* 20
|
||||
*/
|
||||
int main() {
|
||||
const std::string rawJson = R"({"Age": 20, "Name": "colin"})";
|
||||
const auto rawJsonLength = static_cast<int>(rawJson.length());
|
||||
constexpr bool shouldUseOldWay = false;
|
||||
JSONCPP_STRING err;
|
||||
Json::Value root;
|
||||
|
||||
if (shouldUseOldWay) {
|
||||
Json::Reader reader;
|
||||
reader.parse(rawJson, root);
|
||||
} else {
|
||||
Json::CharReaderBuilder builder;
|
||||
const std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
|
||||
if (!reader->parse(rawJson.c_str(), rawJson.c_str() + rawJsonLength, &root,
|
||||
&err)) {
|
||||
std::cout << "error: " << err << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
const std::string name = root["Name"].asString();
|
||||
const int age = root["Age"].asInt();
|
||||
|
||||
std::cout << name << std::endl;
|
||||
std::cout << age << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
23
example/streamWrite/streamWrite.cpp
Normal file
23
example/streamWrite/streamWrite.cpp
Normal file
@ -0,0 +1,23 @@
|
||||
#include "json/json.h"
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
/** \brief Write the Value object to a stream.
|
||||
* Example Usage:
|
||||
* $g++ streamWrite.cpp -ljsoncpp -std=c++11 -o streamWrite
|
||||
* $./streamWrite
|
||||
* {
|
||||
* "Age" : 20,
|
||||
* "Name" : "robin"
|
||||
* }
|
||||
*/
|
||||
int main() {
|
||||
Json::Value root;
|
||||
Json::StreamWriterBuilder builder;
|
||||
const std::unique_ptr<Json::StreamWriter> writer(builder.newStreamWriter());
|
||||
|
||||
root["Name"] = "robin";
|
||||
root["Age"] = 20;
|
||||
writer->write(root, &std::cout);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
33
example/stringWrite/stringWrite.cpp
Normal file
33
example/stringWrite/stringWrite.cpp
Normal file
@ -0,0 +1,33 @@
|
||||
#include "json/json.h"
|
||||
#include <iostream>
|
||||
/** \brief Write a Value object to a string.
|
||||
* Example Usage:
|
||||
* $g++ stringWrite.cpp -ljsoncpp -std=c++11 -o stringWrite
|
||||
* $./stringWrite
|
||||
* {
|
||||
* "action" : "run",
|
||||
* "data" :
|
||||
* {
|
||||
* "number" : 1
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
int main() {
|
||||
Json::Value root;
|
||||
Json::Value data;
|
||||
constexpr bool shouldUseOldWay = false;
|
||||
root["action"] = "run";
|
||||
data["number"] = 1;
|
||||
root["data"] = data;
|
||||
|
||||
if (shouldUseOldWay) {
|
||||
Json::FastWriter writer;
|
||||
const std::string json_file = writer.write(root);
|
||||
std::cout << json_file << std::endl;
|
||||
} else {
|
||||
Json::StreamWriterBuilder builder;
|
||||
const std::string json_file = Json::writeString(builder, root);
|
||||
std::cout << json_file << std::endl;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
5
get_version.pl
Normal file
5
get_version.pl
Normal file
@ -0,0 +1,5 @@
|
||||
while (<>) {
|
||||
if (/version : '(.+)',/) {
|
||||
print "$1";
|
||||
}
|
||||
}
|
5
include/CMakeLists.txt
Normal file
5
include/CMakeLists.txt
Normal file
@ -0,0 +1,5 @@
|
||||
file(GLOB INCLUDE_FILES "json/*.h")
|
||||
install(FILES
|
||||
${INCLUDE_FILES}
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/json)
|
||||
|
9
include/PreventInBuildInstalls.cmake
Normal file
9
include/PreventInBuildInstalls.cmake
Normal file
@ -0,0 +1,9 @@
|
||||
string(TOLOWER "${CMAKE_INSTALL_PREFIX}" _PREFIX)
|
||||
string(TOLOWER "${ITK_BINARY_DIR}" _BUILD)
|
||||
if("${_PREFIX}" STREQUAL "${_BUILD}")
|
||||
message(FATAL_ERROR
|
||||
"The current CMAKE_INSTALL_PREFIX points at the build tree:\n"
|
||||
" ${CMAKE_INSTALL_PREFIX}\n"
|
||||
"This is not supported."
|
||||
)
|
||||
endif()
|
45
include/PreventInSourceBuilds.cmake
Normal file
45
include/PreventInSourceBuilds.cmake
Normal file
@ -0,0 +1,45 @@
|
||||
#
|
||||
# This function will prevent in-source builds
|
||||
function(AssureOutOfSourceBuilds)
|
||||
# make sure the user doesn't play dirty with symlinks
|
||||
get_filename_component(srcdir "${CMAKE_CURRENT_SOURCE_DIR}" REALPATH)
|
||||
get_filename_component(bindir "${CMAKE_CURRENT_BINARY_DIR}" REALPATH)
|
||||
|
||||
# disallow in-source builds
|
||||
if("${srcdir}" STREQUAL "${bindir}")
|
||||
message("######################################################")
|
||||
message("# jsoncpp should not be configured & built in the jsoncpp source directory")
|
||||
message("# You must run cmake in a build directory.")
|
||||
message("# For example:")
|
||||
message("# mkdir jsoncpp-Sandbox ; cd jsoncpp-sandbox")
|
||||
message("# git clone https://github.com/open-source-parsers/jsoncpp.git # or download & unpack the source tarball")
|
||||
message("# mkdir jsoncpp-build")
|
||||
message("# this will create the following directory structure")
|
||||
message("#")
|
||||
message("# jsoncpp-Sandbox")
|
||||
message("# +--jsoncpp")
|
||||
message("# +--jsoncpp-build")
|
||||
message("#")
|
||||
message("# Then you can proceed to configure and build")
|
||||
message("# by using the following commands")
|
||||
message("#")
|
||||
message("# cd jsoncpp-build")
|
||||
message("# cmake ../jsoncpp # or ccmake, or cmake-gui ")
|
||||
message("# make")
|
||||
message("#")
|
||||
message("# NOTE: Given that you already tried to make an in-source build")
|
||||
message("# CMake have already created several files & directories")
|
||||
message("# in your source tree. run 'git status' to find them and")
|
||||
message("# remove them by doing:")
|
||||
message("#")
|
||||
message("# cd jsoncpp-Sandbox/jsoncpp")
|
||||
message("# git clean -n -d")
|
||||
message("# git clean -f -d")
|
||||
message("# git checkout --")
|
||||
message("#")
|
||||
message("######################################################")
|
||||
message(FATAL_ERROR "Quitting configuration")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
AssureOutOfSourceBuilds()
|
100
include/json/allocator.h
Normal file
100
include/json/allocator.h
Normal file
@ -0,0 +1,100 @@
|
||||
// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
|
||||
// Distributed under MIT license, or public domain if desired and
|
||||
// recognized in your jurisdiction.
|
||||
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||
|
||||
#ifndef JSON_ALLOCATOR_H_INCLUDED
|
||||
#define JSON_ALLOCATOR_H_INCLUDED
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
|
||||
#pragma pack(push)
|
||||
#pragma pack()
|
||||
|
||||
namespace Json {
|
||||
template <typename T> class SecureAllocator {
|
||||
public:
|
||||
// Type definitions
|
||||
using value_type = T;
|
||||
using pointer = T*;
|
||||
using const_pointer = const T*;
|
||||
using reference = T&;
|
||||
using const_reference = const T&;
|
||||
using size_type = std::size_t;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
|
||||
/**
|
||||
* Allocate memory for N items using the standard allocator.
|
||||
*/
|
||||
pointer allocate(size_type n) {
|
||||
// allocate using "global operator new"
|
||||
return static_cast<pointer>(::operator new(n * sizeof(T)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Release memory which was allocated for N items at pointer P.
|
||||
*
|
||||
* The memory block is filled with zeroes before being released.
|
||||
*/
|
||||
void deallocate(pointer p, size_type n) {
|
||||
// These constructs will not be removed by the compiler during optimization,
|
||||
// unlike memset.
|
||||
#if defined(HAVE_MEMSET_S)
|
||||
memset_s(p, n * sizeof(T), 0, n * sizeof(T));
|
||||
#elif defined(_WIN32)
|
||||
RtlSecureZeroMemory(p, n * sizeof(T));
|
||||
#else
|
||||
std::fill_n(reinterpret_cast<volatile unsigned char*>(p), n, 0);
|
||||
#endif
|
||||
|
||||
// free using "global operator delete"
|
||||
::operator delete(p);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an item in-place at pointer P.
|
||||
*/
|
||||
template <typename... Args> void construct(pointer p, Args&&... args) {
|
||||
// construct using "placement new" and "perfect forwarding"
|
||||
::new (static_cast<void*>(p)) T(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
size_type max_size() const { return size_t(-1) / sizeof(T); }
|
||||
|
||||
pointer address(reference x) const { return std::addressof(x); }
|
||||
|
||||
const_pointer address(const_reference x) const { return std::addressof(x); }
|
||||
|
||||
/**
|
||||
* Destroy an item in-place at pointer P.
|
||||
*/
|
||||
void destroy(pointer p) {
|
||||
// destroy using "explicit destructor"
|
||||
p->~T();
|
||||
}
|
||||
|
||||
// Boilerplate
|
||||
SecureAllocator() {}
|
||||
template <typename U> SecureAllocator(const SecureAllocator<U>&) {}
|
||||
template <typename U> struct rebind {
|
||||
using other = SecureAllocator<U>;
|
||||
};
|
||||
};
|
||||
|
||||
template <typename T, typename U>
|
||||
bool operator==(const SecureAllocator<T>&, const SecureAllocator<U>&) {
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
bool operator!=(const SecureAllocator<T>&, const SecureAllocator<U>&) {
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace Json
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
#endif // JSON_ALLOCATOR_H_INCLUDED
|
61
include/json/assertions.h
Normal file
61
include/json/assertions.h
Normal file
@ -0,0 +1,61 @@
|
||||
// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
|
||||
// Distributed under MIT license, or public domain if desired and
|
||||
// recognized in your jurisdiction.
|
||||
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||
|
||||
#ifndef JSON_ASSERTIONS_H_INCLUDED
|
||||
#define JSON_ASSERTIONS_H_INCLUDED
|
||||
|
||||
#include <cstdlib>
|
||||
#include <sstream>
|
||||
|
||||
#if !defined(JSON_IS_AMALGAMATION)
|
||||
#include "config.h"
|
||||
#endif // if !defined(JSON_IS_AMALGAMATION)
|
||||
|
||||
/** It should not be possible for a maliciously designed file to
|
||||
* cause an abort() or seg-fault, so these macros are used only
|
||||
* for pre-condition violations and internal logic errors.
|
||||
*/
|
||||
#if JSON_USE_EXCEPTION
|
||||
|
||||
// @todo <= add detail about condition in exception
|
||||
#define JSON_ASSERT(condition) \
|
||||
do { \
|
||||
if (!(condition)) { \
|
||||
Json::throwLogicError("assert json failed"); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define JSON_FAIL_MESSAGE(message) \
|
||||
do { \
|
||||
OStringStream oss; \
|
||||
oss << message; \
|
||||
Json::throwLogicError(oss.str()); \
|
||||
abort(); \
|
||||
} while (0)
|
||||
|
||||
#else // JSON_USE_EXCEPTION
|
||||
|
||||
#define JSON_ASSERT(condition) assert(condition)
|
||||
|
||||
// The call to assert() will show the failure message in debug builds. In
|
||||
// release builds we abort, for a core-dump or debugger.
|
||||
#define JSON_FAIL_MESSAGE(message) \
|
||||
{ \
|
||||
OStringStream oss; \
|
||||
oss << message; \
|
||||
assert(false && oss.str().c_str()); \
|
||||
abort(); \
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#define JSON_ASSERT_MESSAGE(condition, message) \
|
||||
do { \
|
||||
if (!(condition)) { \
|
||||
JSON_FAIL_MESSAGE(message); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#endif // JSON_ASSERTIONS_H_INCLUDED
|
@ -1,19 +0,0 @@
|
||||
#ifndef JSON_AUTOLINK_H_INCLUDED
|
||||
# define JSON_AUTOLINK_H_INCLUDED
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# ifdef JSON_IN_CPPTL
|
||||
# include <cpptl/cpptl_autolink.h>
|
||||
# endif
|
||||
|
||||
# if !defined(JSON_NO_AUTOLINK) && !defined(JSON_DLL_BUILD) && !defined(JSON_IN_CPPTL)
|
||||
# define CPPTL_AUTOLINK_NAME "json"
|
||||
# undef CPPTL_AUTOLINK_DLL
|
||||
# ifdef JSON_DLL
|
||||
# define CPPTL_AUTOLINK_DLL
|
||||
# endif
|
||||
# include "autolink.h"
|
||||
# endif
|
||||
|
||||
#endif // JSON_AUTOLINK_H_INCLUDED
|
@ -1,43 +1,150 @@
|
||||
// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
|
||||
// Distributed under MIT license, or public domain if desired and
|
||||
// recognized in your jurisdiction.
|
||||
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||
|
||||
#ifndef JSON_CONFIG_H_INCLUDED
|
||||
# define JSON_CONFIG_H_INCLUDED
|
||||
#define JSON_CONFIG_H_INCLUDED
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <istream>
|
||||
#include <memory>
|
||||
#include <ostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
/// If defined, indicates that json library is embedded in CppTL library.
|
||||
//# define JSON_IN_CPPTL 1
|
||||
// If non-zero, the library uses exceptions to report bad input instead of C
|
||||
// assertion macros. The default is to use exceptions.
|
||||
#ifndef JSON_USE_EXCEPTION
|
||||
#define JSON_USE_EXCEPTION 1
|
||||
#endif
|
||||
|
||||
/// If defined, indicates that json may leverage CppTL library
|
||||
//# define JSON_USE_CPPTL 1
|
||||
/// If defined, indicates that cpptl vector based map should be used instead of std::map
|
||||
/// as Value container.
|
||||
//# define JSON_USE_CPPTL_SMALLMAP 1
|
||||
/// If defined, indicates that Json specific container should be used
|
||||
/// (hash table & simple deque container with customizable allocator).
|
||||
/// THIS FEATURE IS STILL EXPERIMENTAL!
|
||||
//# define JSON_VALUE_USE_INTERNAL_MAP 1
|
||||
/// Force usage of standard new/malloc based allocator instead of memory pool based allocator.
|
||||
/// The memory pools allocator used optimization (initializing Value and ValueInternalLink
|
||||
/// as if it was a POD) that may cause some validation tool to report errors.
|
||||
/// Only has effects if JSON_VALUE_USE_INTERNAL_MAP is defined.
|
||||
//# define JSON_USE_SIMPLE_INTERNAL_ALLOCATOR 1
|
||||
// Temporary, tracked for removal with issue #982.
|
||||
#ifndef JSON_USE_NULLREF
|
||||
#define JSON_USE_NULLREF 1
|
||||
#endif
|
||||
|
||||
/// If defined, indicates that Json use exception to report invalid type manipulation
|
||||
/// instead of C assert macro.
|
||||
# define JSON_USE_EXCEPTION 1
|
||||
/// If defined, indicates that the source file is amalgamated
|
||||
/// to prevent private header inclusion.
|
||||
/// Remarks: it is automatically defined in the generated amalgamated header.
|
||||
// #define JSON_IS_AMALGAMATION
|
||||
|
||||
# ifdef JSON_IN_CPPTL
|
||||
# include <cpptl/config.h>
|
||||
# ifndef JSON_USE_CPPTL
|
||||
# define JSON_USE_CPPTL 1
|
||||
# endif
|
||||
# endif
|
||||
// Export macros for DLL visibility
|
||||
#if defined(JSON_DLL_BUILD)
|
||||
#if defined(_MSC_VER) || defined(__MINGW32__)
|
||||
#define JSON_API __declspec(dllexport)
|
||||
#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
|
||||
#elif defined(__GNUC__) || defined(__clang__)
|
||||
#define JSON_API __attribute__((visibility("default")))
|
||||
#endif // if defined(_MSC_VER)
|
||||
|
||||
# ifdef JSON_IN_CPPTL
|
||||
# define JSON_API CPPTL_API
|
||||
# elif defined(JSON_DLL_BUILD)
|
||||
# define JSON_API __declspec(dllexport)
|
||||
# elif defined(JSON_DLL)
|
||||
# define JSON_API __declspec(dllimport)
|
||||
# else
|
||||
# define JSON_API
|
||||
# endif
|
||||
#elif defined(JSON_DLL)
|
||||
#if defined(_MSC_VER) || defined(__MINGW32__)
|
||||
#define JSON_API __declspec(dllimport)
|
||||
#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
|
||||
#endif // if defined(_MSC_VER)
|
||||
#endif // ifdef JSON_DLL_BUILD
|
||||
|
||||
#if !defined(JSON_API)
|
||||
#define JSON_API
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1800
|
||||
#error \
|
||||
"ERROR: Visual Studio 12 (2013) with _MSC_VER=1800 is the oldest supported compiler with sufficient C++11 capabilities"
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1900
|
||||
// As recommended at
|
||||
// https://stackoverflow.com/questions/2915672/snprintf-and-visual-studio-2010
|
||||
extern JSON_API int msvc_pre1900_c99_snprintf(char* outBuf, size_t size,
|
||||
const char* format, ...);
|
||||
#define jsoncpp_snprintf msvc_pre1900_c99_snprintf
|
||||
#else
|
||||
#define jsoncpp_snprintf std::snprintf
|
||||
#endif
|
||||
|
||||
// If JSON_NO_INT64 is defined, then Json only support C++ "int" type for
|
||||
// integer
|
||||
// Storages, and 64 bits integer support is disabled.
|
||||
// #define JSON_NO_INT64 1
|
||||
|
||||
// JSONCPP_OVERRIDE is maintained for backwards compatibility of external tools.
|
||||
// C++11 should be used directly in JSONCPP.
|
||||
#define JSONCPP_OVERRIDE override
|
||||
|
||||
#ifdef __clang__
|
||||
#if __has_extension(attribute_deprecated_with_message)
|
||||
#define JSONCPP_DEPRECATED(message) __attribute__((deprecated(message)))
|
||||
#endif
|
||||
#elif defined(__GNUC__) // not clang (gcc comes later since clang emulates gcc)
|
||||
#if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5))
|
||||
#define JSONCPP_DEPRECATED(message) __attribute__((deprecated(message)))
|
||||
#elif (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
|
||||
#define JSONCPP_DEPRECATED(message) __attribute__((__deprecated__))
|
||||
#endif // GNUC version
|
||||
#elif defined(_MSC_VER) // MSVC (after clang because clang on Windows emulates
|
||||
// MSVC)
|
||||
#define JSONCPP_DEPRECATED(message) __declspec(deprecated(message))
|
||||
#endif // __clang__ || __GNUC__ || _MSC_VER
|
||||
|
||||
#if !defined(JSONCPP_DEPRECATED)
|
||||
#define JSONCPP_DEPRECATED(message)
|
||||
#endif // if !defined(JSONCPP_DEPRECATED)
|
||||
|
||||
#if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ >= 6))
|
||||
#define JSON_USE_INT64_DOUBLE_CONVERSION 1
|
||||
#endif
|
||||
|
||||
#if !defined(JSON_IS_AMALGAMATION)
|
||||
|
||||
#include "allocator.h"
|
||||
#include "version.h"
|
||||
|
||||
#endif // if !defined(JSON_IS_AMALGAMATION)
|
||||
|
||||
namespace Json {
|
||||
using Int = int;
|
||||
using UInt = unsigned int;
|
||||
#if defined(JSON_NO_INT64)
|
||||
using LargestInt = int;
|
||||
using LargestUInt = unsigned int;
|
||||
#undef JSON_HAS_INT64
|
||||
#else // if defined(JSON_NO_INT64)
|
||||
// For Microsoft Visual use specific types as long long is not supported
|
||||
#if defined(_MSC_VER) // Microsoft Visual Studio
|
||||
using Int64 = __int64;
|
||||
using UInt64 = unsigned __int64;
|
||||
#else // if defined(_MSC_VER) // Other platforms, use long long
|
||||
using Int64 = int64_t;
|
||||
using UInt64 = uint64_t;
|
||||
#endif // if defined(_MSC_VER)
|
||||
using LargestInt = Int64;
|
||||
using LargestUInt = UInt64;
|
||||
#define JSON_HAS_INT64
|
||||
#endif // if defined(JSON_NO_INT64)
|
||||
|
||||
template <typename T>
|
||||
using Allocator =
|
||||
typename std::conditional<JSONCPP_USE_SECURE_MEMORY, SecureAllocator<T>,
|
||||
std::allocator<T>>::type;
|
||||
using String = std::basic_string<char, std::char_traits<char>, Allocator<char>>;
|
||||
using IStringStream =
|
||||
std::basic_istringstream<String::value_type, String::traits_type,
|
||||
String::allocator_type>;
|
||||
using OStringStream =
|
||||
std::basic_ostringstream<String::value_type, String::traits_type,
|
||||
String::allocator_type>;
|
||||
using IStream = std::istream;
|
||||
using OStream = std::ostream;
|
||||
} // namespace Json
|
||||
|
||||
// Legacy names (formerly macros).
|
||||
using JSONCPP_STRING = Json::String;
|
||||
using JSONCPP_ISTRINGSTREAM = Json::IStringStream;
|
||||
using JSONCPP_OSTRINGSTREAM = Json::OStringStream;
|
||||
using JSONCPP_ISTREAM = Json::IStream;
|
||||
using JSONCPP_OSTREAM = Json::OStream;
|
||||
|
||||
#endif // JSON_CONFIG_H_INCLUDED
|
||||
|
@ -1,42 +0,0 @@
|
||||
#ifndef CPPTL_JSON_FEATURES_H_INCLUDED
|
||||
# define CPPTL_JSON_FEATURES_H_INCLUDED
|
||||
|
||||
# include "forwards.h"
|
||||
|
||||
namespace Json {
|
||||
|
||||
/** \brief Configuration passed to reader and writer.
|
||||
* This configuration object can be used to force the Reader or Writer
|
||||
* to behave in a standard conforming way.
|
||||
*/
|
||||
class JSON_API Features
|
||||
{
|
||||
public:
|
||||
/** \brief A configuration that allows all features and assumes all strings are UTF-8.
|
||||
* - C & C++ comments are allowed
|
||||
* - Root object can be any JSON value
|
||||
* - Assumes Value strings are encoded in UTF-8
|
||||
*/
|
||||
static Features all();
|
||||
|
||||
/** \brief A configuration that is strictly compatible with the JSON specification.
|
||||
* - Comments are forbidden.
|
||||
* - Root object must be either an array or an object value.
|
||||
* - Assumes Value strings are encoded in UTF-8
|
||||
*/
|
||||
static Features strictMode();
|
||||
|
||||
/** \brief Initialize the configuration like JsonConfig::allFeatures;
|
||||
*/
|
||||
Features();
|
||||
|
||||
/// \c true if comments are allowed. Default: \c true.
|
||||
bool allowComments_;
|
||||
|
||||
/// \c true if root must be either an array or an object value. Default: \c false.
|
||||
bool strictRoot_;
|
||||
};
|
||||
|
||||
} // namespace Json
|
||||
|
||||
#endif // CPPTL_JSON_FEATURES_H_INCLUDED
|
@ -1,39 +1,43 @@
|
||||
#ifndef JSON_FORWARDS_H_INCLUDED
|
||||
# define JSON_FORWARDS_H_INCLUDED
|
||||
// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
|
||||
// Distributed under MIT license, or public domain if desired and
|
||||
// recognized in your jurisdiction.
|
||||
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||
|
||||
# include "config.h"
|
||||
#ifndef JSON_FORWARDS_H_INCLUDED
|
||||
#define JSON_FORWARDS_H_INCLUDED
|
||||
|
||||
#if !defined(JSON_IS_AMALGAMATION)
|
||||
#include "config.h"
|
||||
#endif // if !defined(JSON_IS_AMALGAMATION)
|
||||
|
||||
namespace Json {
|
||||
|
||||
// writer.h
|
||||
class FastWriter;
|
||||
class StyledWriter;
|
||||
// writer.h
|
||||
class StreamWriter;
|
||||
class StreamWriterBuilder;
|
||||
class Writer;
|
||||
class FastWriter;
|
||||
class StyledWriter;
|
||||
class StyledStreamWriter;
|
||||
|
||||
// reader.h
|
||||
class Reader;
|
||||
// reader.h
|
||||
class Reader;
|
||||
class CharReader;
|
||||
class CharReaderBuilder;
|
||||
|
||||
// features.h
|
||||
class Features;
|
||||
// json_features.h
|
||||
class Features;
|
||||
|
||||
// value.h
|
||||
typedef int Int;
|
||||
typedef unsigned int UInt;
|
||||
class StaticString;
|
||||
class Path;
|
||||
class PathArgument;
|
||||
class Value;
|
||||
class ValueIteratorBase;
|
||||
class ValueIterator;
|
||||
class ValueConstIterator;
|
||||
#ifdef JSON_VALUE_USE_INTERNAL_MAP
|
||||
class ValueAllocator;
|
||||
class ValueMapAllocator;
|
||||
class ValueInternalLink;
|
||||
class ValueInternalArray;
|
||||
class ValueInternalMap;
|
||||
#endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP
|
||||
// value.h
|
||||
using ArrayIndex = unsigned int;
|
||||
class StaticString;
|
||||
class Path;
|
||||
class PathArgument;
|
||||
class Value;
|
||||
class ValueIteratorBase;
|
||||
class ValueIterator;
|
||||
class ValueConstIterator;
|
||||
|
||||
} // namespace Json
|
||||
|
||||
|
||||
#endif // JSON_FORWARDS_H_INCLUDED
|
||||
|
@ -1,10 +1,15 @@
|
||||
#ifndef JSON_JSON_H_INCLUDED
|
||||
# define JSON_JSON_H_INCLUDED
|
||||
// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
|
||||
// Distributed under MIT license, or public domain if desired and
|
||||
// recognized in your jurisdiction.
|
||||
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||
|
||||
# include "autolink.h"
|
||||
# include "value.h"
|
||||
# include "reader.h"
|
||||
# include "writer.h"
|
||||
# include "features.h"
|
||||
#ifndef JSON_JSON_H_INCLUDED
|
||||
#define JSON_JSON_H_INCLUDED
|
||||
|
||||
#include "config.h"
|
||||
#include "json_features.h"
|
||||
#include "reader.h"
|
||||
#include "value.h"
|
||||
#include "writer.h"
|
||||
|
||||
#endif // JSON_JSON_H_INCLUDED
|
||||
|
62
include/json/json_features.h
Normal file
62
include/json/json_features.h
Normal file
@ -0,0 +1,62 @@
|
||||
// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
|
||||
// Distributed under MIT license, or public domain if desired and
|
||||
// recognized in your jurisdiction.
|
||||
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||
|
||||
#ifndef JSON_FEATURES_H_INCLUDED
|
||||
#define JSON_FEATURES_H_INCLUDED
|
||||
|
||||
#if !defined(JSON_IS_AMALGAMATION)
|
||||
#include "forwards.h"
|
||||
#endif // if !defined(JSON_IS_AMALGAMATION)
|
||||
|
||||
#pragma pack(push)
|
||||
#pragma pack()
|
||||
|
||||
namespace Json {
|
||||
|
||||
/** \brief Configuration passed to reader and writer.
|
||||
* This configuration object can be used to force the Reader or Writer
|
||||
* to behave in a standard conforming way.
|
||||
*/
|
||||
class JSON_API Features {
|
||||
public:
|
||||
/** \brief A configuration that allows all features and assumes all strings
|
||||
* are UTF-8.
|
||||
* - C & C++ comments are allowed
|
||||
* - Root object can be any JSON value
|
||||
* - Assumes Value strings are encoded in UTF-8
|
||||
*/
|
||||
static Features all();
|
||||
|
||||
/** \brief A configuration that is strictly compatible with the JSON
|
||||
* specification.
|
||||
* - Comments are forbidden.
|
||||
* - Root object must be either an array or an object value.
|
||||
* - Assumes Value strings are encoded in UTF-8
|
||||
*/
|
||||
static Features strictMode();
|
||||
|
||||
/** \brief Initialize the configuration like JsonConfig::allFeatures;
|
||||
*/
|
||||
Features();
|
||||
|
||||
/// \c true if comments are allowed. Default: \c true.
|
||||
bool allowComments_{true};
|
||||
|
||||
/// \c true if root must be either an array or an object value. Default: \c
|
||||
/// false.
|
||||
bool strictRoot_{false};
|
||||
|
||||
/// \c true if dropped null placeholders are allowed. Default: \c false.
|
||||
bool allowDroppedNullPlaceholders_{false};
|
||||
|
||||
/// \c true if numeric object key are allowed. Default: \c false.
|
||||
bool allowNumericKeys_{false};
|
||||
};
|
||||
|
||||
} // namespace Json
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
#endif // JSON_FEATURES_H_INCLUDED
|
@ -1,196 +1,437 @@
|
||||
#ifndef CPPTL_JSON_READER_H_INCLUDED
|
||||
# define CPPTL_JSON_READER_H_INCLUDED
|
||||
// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
|
||||
// Distributed under MIT license, or public domain if desired and
|
||||
// recognized in your jurisdiction.
|
||||
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||
|
||||
# include "features.h"
|
||||
# include "value.h"
|
||||
# include <deque>
|
||||
# include <stack>
|
||||
# include <string>
|
||||
# include <iostream>
|
||||
#ifndef JSON_READER_H_INCLUDED
|
||||
#define JSON_READER_H_INCLUDED
|
||||
|
||||
#if !defined(JSON_IS_AMALGAMATION)
|
||||
#include "json_features.h"
|
||||
#include "value.h"
|
||||
#endif // if !defined(JSON_IS_AMALGAMATION)
|
||||
#include <deque>
|
||||
#include <iosfwd>
|
||||
#include <istream>
|
||||
#include <stack>
|
||||
#include <string>
|
||||
|
||||
// Disable warning C4251: <data member>: <type> needs to have dll-interface to
|
||||
// be used by...
|
||||
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4251)
|
||||
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
||||
|
||||
#pragma pack(push)
|
||||
#pragma pack()
|
||||
|
||||
namespace Json {
|
||||
|
||||
/** \brief Unserialize a <a HREF="http://www.json.org">JSON</a> document into a Value.
|
||||
*
|
||||
*/
|
||||
class JSON_API Reader
|
||||
{
|
||||
public:
|
||||
typedef char Char;
|
||||
typedef const Char *Location;
|
||||
/** \brief Unserialize a <a HREF="http://www.json.org">JSON</a> document into a
|
||||
* Value.
|
||||
*
|
||||
* \deprecated Use CharReader and CharReaderBuilder.
|
||||
*/
|
||||
|
||||
/** \brief Constructs a Reader allowing all features
|
||||
* for parsing.
|
||||
*/
|
||||
Reader();
|
||||
class JSON_API Reader {
|
||||
public:
|
||||
using Char = char;
|
||||
using Location = const Char*;
|
||||
|
||||
/** \brief Constructs a Reader allowing the specified feature set
|
||||
* for parsing.
|
||||
*/
|
||||
Reader( const Features &features );
|
||||
|
||||
/** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a> document.
|
||||
* \param document UTF-8 encoded string containing the document to read.
|
||||
* \param root [out] Contains the root value of the document if it was
|
||||
* successfully parsed.
|
||||
* \param collectComments \c true to collect comment and allow writing them back during
|
||||
* serialization, \c false to discard comments.
|
||||
* This parameter is ignored if Features::allowComments_
|
||||
* is \c false.
|
||||
* \return \c true if the document was successfully parsed, \c false if an error occurred.
|
||||
*/
|
||||
bool parse( const std::string &document,
|
||||
Value &root,
|
||||
bool collectComments = true );
|
||||
|
||||
/** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a> document.
|
||||
* \param document UTF-8 encoded string containing the document to read.
|
||||
* \param root [out] Contains the root value of the document if it was
|
||||
* successfully parsed.
|
||||
* \param collectComments \c true to collect comment and allow writing them back during
|
||||
* serialization, \c false to discard comments.
|
||||
* This parameter is ignored if Features::allowComments_
|
||||
* is \c false.
|
||||
* \return \c true if the document was successfully parsed, \c false if an error occurred.
|
||||
*/
|
||||
bool parse( const char *beginDoc, const char *endDoc,
|
||||
Value &root,
|
||||
bool collectComments = true );
|
||||
|
||||
/// \brief Parse from input stream.
|
||||
/// \see Json::operator>>(std::istream&, Json::Value&).
|
||||
bool parse( std::istream &is,
|
||||
Value &root,
|
||||
bool collectComments = true );
|
||||
|
||||
/** \brief Returns a user friendly string that list errors in the parsed document.
|
||||
* \return Formatted error message with the list of errors with their location in
|
||||
* the parsed document. An empty string is returned if no error occurred
|
||||
* during parsing.
|
||||
*/
|
||||
std::string getFormatedErrorMessages() const;
|
||||
|
||||
private:
|
||||
enum TokenType
|
||||
{
|
||||
tokenEndOfStream = 0,
|
||||
tokenObjectBegin,
|
||||
tokenObjectEnd,
|
||||
tokenArrayBegin,
|
||||
tokenArrayEnd,
|
||||
tokenString,
|
||||
tokenNumber,
|
||||
tokenTrue,
|
||||
tokenFalse,
|
||||
tokenNull,
|
||||
tokenArraySeparator,
|
||||
tokenMemberSeparator,
|
||||
tokenComment,
|
||||
tokenError
|
||||
};
|
||||
|
||||
class Token
|
||||
{
|
||||
public:
|
||||
TokenType type_;
|
||||
Location start_;
|
||||
Location end_;
|
||||
};
|
||||
|
||||
class ErrorInfo
|
||||
{
|
||||
public:
|
||||
Token token_;
|
||||
std::string message_;
|
||||
Location extra_;
|
||||
};
|
||||
|
||||
typedef std::deque<ErrorInfo> Errors;
|
||||
|
||||
bool expectToken( TokenType type, Token &token, const char *message );
|
||||
bool readToken( Token &token );
|
||||
void skipSpaces();
|
||||
bool match( Location pattern,
|
||||
int patternLength );
|
||||
bool readComment();
|
||||
bool readCStyleComment();
|
||||
bool readCppStyleComment();
|
||||
bool readString();
|
||||
void readNumber();
|
||||
bool readValue();
|
||||
bool readObject( Token &token );
|
||||
bool readArray( Token &token );
|
||||
bool decodeNumber( Token &token );
|
||||
bool decodeString( Token &token );
|
||||
bool decodeString( Token &token, std::string &decoded );
|
||||
bool decodeDouble( Token &token );
|
||||
bool decodeUnicodeCodePoint( Token &token,
|
||||
Location ¤t,
|
||||
Location end,
|
||||
unsigned int &unicode );
|
||||
bool decodeUnicodeEscapeSequence( Token &token,
|
||||
Location ¤t,
|
||||
Location end,
|
||||
unsigned int &unicode );
|
||||
bool addError( const std::string &message,
|
||||
Token &token,
|
||||
Location extra = 0 );
|
||||
bool recoverFromError( TokenType skipUntilToken );
|
||||
bool addErrorAndRecover( const std::string &message,
|
||||
Token &token,
|
||||
TokenType skipUntilToken );
|
||||
void skipUntilSpace();
|
||||
Value ¤tValue();
|
||||
Char getNextChar();
|
||||
void getLocationLineAndColumn( Location location,
|
||||
int &line,
|
||||
int &column ) const;
|
||||
std::string getLocationLineAndColumn( Location location ) const;
|
||||
void addComment( Location begin,
|
||||
Location end,
|
||||
CommentPlacement placement );
|
||||
void skipCommentTokens( Token &token );
|
||||
|
||||
typedef std::stack<Value *> Nodes;
|
||||
Nodes nodes_;
|
||||
Errors errors_;
|
||||
std::string document_;
|
||||
Location begin_;
|
||||
Location end_;
|
||||
Location current_;
|
||||
Location lastValueEnd_;
|
||||
Value *lastValue_;
|
||||
std::string commentsBefore_;
|
||||
Features features_;
|
||||
bool collectComments_;
|
||||
};
|
||||
|
||||
/** \brief Read from 'sin' into 'root'.
|
||||
|
||||
Always keep comments from the input JSON.
|
||||
|
||||
This can be used to read a file into a particular sub-object.
|
||||
For example:
|
||||
\code
|
||||
Json::Value root;
|
||||
cin >> root["dir"]["file"];
|
||||
cout << root;
|
||||
\endcode
|
||||
Result:
|
||||
\verbatim
|
||||
{
|
||||
"dir": {
|
||||
"file": {
|
||||
// The input stream JSON would be nested here.
|
||||
}
|
||||
}
|
||||
}
|
||||
\endverbatim
|
||||
\throw std::exception on parse error.
|
||||
\see Json::operator<<()
|
||||
/** \brief An error tagged with where in the JSON text it was encountered.
|
||||
*
|
||||
* The offsets give the [start, limit) range of bytes within the text. Note
|
||||
* that this is bytes, not codepoints.
|
||||
*/
|
||||
std::istream& operator>>( std::istream&, Value& );
|
||||
struct StructuredError {
|
||||
ptrdiff_t offset_start;
|
||||
ptrdiff_t offset_limit;
|
||||
String message;
|
||||
};
|
||||
|
||||
/** \brief Constructs a Reader allowing all features for parsing.
|
||||
* \deprecated Use CharReader and CharReaderBuilder.
|
||||
*/
|
||||
Reader();
|
||||
|
||||
/** \brief Constructs a Reader allowing the specified feature set for parsing.
|
||||
* \deprecated Use CharReader and CharReaderBuilder.
|
||||
*/
|
||||
Reader(const Features& features);
|
||||
|
||||
/** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
|
||||
* document.
|
||||
*
|
||||
* \param document UTF-8 encoded string containing the document
|
||||
* to read.
|
||||
* \param[out] root Contains the root value of the document if it
|
||||
* was successfully parsed.
|
||||
* \param collectComments \c true to collect comment and allow writing
|
||||
* them back during serialization, \c false to
|
||||
* discard comments. This parameter is ignored
|
||||
* if Features::allowComments_ is \c false.
|
||||
* \return \c true if the document was successfully parsed, \c false if an
|
||||
* error occurred.
|
||||
*/
|
||||
bool parse(const std::string& document, Value& root,
|
||||
bool collectComments = true);
|
||||
|
||||
/** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
|
||||
* document.
|
||||
*
|
||||
* \param beginDoc Pointer on the beginning of the UTF-8 encoded
|
||||
* string of the document to read.
|
||||
* \param endDoc Pointer on the end of the UTF-8 encoded string
|
||||
* of the document to read. Must be >= beginDoc.
|
||||
* \param[out] root Contains the root value of the document if it
|
||||
* was successfully parsed.
|
||||
* \param collectComments \c true to collect comment and allow writing
|
||||
* them back during serialization, \c false to
|
||||
* discard comments. This parameter is ignored
|
||||
* if Features::allowComments_ is \c false.
|
||||
* \return \c true if the document was successfully parsed, \c false if an
|
||||
* error occurred.
|
||||
*/
|
||||
bool parse(const char* beginDoc, const char* endDoc, Value& root,
|
||||
bool collectComments = true);
|
||||
|
||||
/// \brief Parse from input stream.
|
||||
/// \see Json::operator>>(std::istream&, Json::Value&).
|
||||
bool parse(IStream& is, Value& root, bool collectComments = true);
|
||||
|
||||
/** \brief Returns a user friendly string that list errors in the parsed
|
||||
* document.
|
||||
*
|
||||
* \return Formatted error message with the list of errors with their
|
||||
* location in the parsed document. An empty string is returned if no error
|
||||
* occurred during parsing.
|
||||
* \deprecated Use getFormattedErrorMessages() instead (typo fix).
|
||||
*/
|
||||
JSONCPP_DEPRECATED("Use getFormattedErrorMessages() instead.")
|
||||
String getFormatedErrorMessages() const;
|
||||
|
||||
/** \brief Returns a user friendly string that list errors in the parsed
|
||||
* document.
|
||||
*
|
||||
* \return Formatted error message with the list of errors with their
|
||||
* location in the parsed document. An empty string is returned if no error
|
||||
* occurred during parsing.
|
||||
*/
|
||||
String getFormattedErrorMessages() const;
|
||||
|
||||
/** \brief Returns a vector of structured errors encountered while parsing.
|
||||
*
|
||||
* \return A (possibly empty) vector of StructuredError objects. Currently
|
||||
* only one error can be returned, but the caller should tolerate multiple
|
||||
* errors. This can occur if the parser recovers from a non-fatal parse
|
||||
* error and then encounters additional errors.
|
||||
*/
|
||||
std::vector<StructuredError> getStructuredErrors() const;
|
||||
|
||||
/** \brief Add a semantic error message.
|
||||
*
|
||||
* \param value JSON Value location associated with the error
|
||||
* \param message The error message.
|
||||
* \return \c true if the error was successfully added, \c false if the Value
|
||||
* offset exceeds the document size.
|
||||
*/
|
||||
bool pushError(const Value& value, const String& message);
|
||||
|
||||
/** \brief Add a semantic error message with extra context.
|
||||
*
|
||||
* \param value JSON Value location associated with the error
|
||||
* \param message The error message.
|
||||
* \param extra Additional JSON Value location to contextualize the error
|
||||
* \return \c true if the error was successfully added, \c false if either
|
||||
* Value offset exceeds the document size.
|
||||
*/
|
||||
bool pushError(const Value& value, const String& message, const Value& extra);
|
||||
|
||||
/** \brief Return whether there are any errors.
|
||||
*
|
||||
* \return \c true if there are no errors to report \c false if errors have
|
||||
* occurred.
|
||||
*/
|
||||
bool good() const;
|
||||
|
||||
private:
|
||||
enum TokenType {
|
||||
tokenEndOfStream = 0,
|
||||
tokenObjectBegin,
|
||||
tokenObjectEnd,
|
||||
tokenArrayBegin,
|
||||
tokenArrayEnd,
|
||||
tokenString,
|
||||
tokenNumber,
|
||||
tokenTrue,
|
||||
tokenFalse,
|
||||
tokenNull,
|
||||
tokenArraySeparator,
|
||||
tokenMemberSeparator,
|
||||
tokenComment,
|
||||
tokenError
|
||||
};
|
||||
|
||||
class Token {
|
||||
public:
|
||||
TokenType type_;
|
||||
Location start_;
|
||||
Location end_;
|
||||
};
|
||||
|
||||
class ErrorInfo {
|
||||
public:
|
||||
Token token_;
|
||||
String message_;
|
||||
Location extra_;
|
||||
};
|
||||
|
||||
using Errors = std::deque<ErrorInfo>;
|
||||
|
||||
bool readToken(Token& token);
|
||||
bool readTokenSkippingComments(Token& token);
|
||||
void skipSpaces();
|
||||
bool match(const Char* pattern, int patternLength);
|
||||
bool readComment();
|
||||
bool readCStyleComment();
|
||||
bool readCppStyleComment();
|
||||
bool readString();
|
||||
void readNumber();
|
||||
bool readValue();
|
||||
bool readObject(Token& token);
|
||||
bool readArray(Token& token);
|
||||
bool decodeNumber(Token& token);
|
||||
bool decodeNumber(Token& token, Value& decoded);
|
||||
bool decodeString(Token& token);
|
||||
bool decodeString(Token& token, String& decoded);
|
||||
bool decodeDouble(Token& token);
|
||||
bool decodeDouble(Token& token, Value& decoded);
|
||||
bool decodeUnicodeCodePoint(Token& token, Location& current, Location end,
|
||||
unsigned int& unicode);
|
||||
bool decodeUnicodeEscapeSequence(Token& token, Location& current,
|
||||
Location end, unsigned int& unicode);
|
||||
bool addError(const String& message, Token& token, Location extra = nullptr);
|
||||
bool recoverFromError(TokenType skipUntilToken);
|
||||
bool addErrorAndRecover(const String& message, Token& token,
|
||||
TokenType skipUntilToken);
|
||||
void skipUntilSpace();
|
||||
Value& currentValue();
|
||||
Char getNextChar();
|
||||
void getLocationLineAndColumn(Location location, int& line,
|
||||
int& column) const;
|
||||
String getLocationLineAndColumn(Location location) const;
|
||||
void addComment(Location begin, Location end, CommentPlacement placement);
|
||||
|
||||
static bool containsNewLine(Location begin, Location end);
|
||||
static String normalizeEOL(Location begin, Location end);
|
||||
|
||||
using Nodes = std::stack<Value*>;
|
||||
Nodes nodes_;
|
||||
Errors errors_;
|
||||
String document_;
|
||||
Location begin_{};
|
||||
Location end_{};
|
||||
Location current_{};
|
||||
Location lastValueEnd_{};
|
||||
Value* lastValue_{};
|
||||
String commentsBefore_;
|
||||
Features features_;
|
||||
bool collectComments_{};
|
||||
}; // Reader
|
||||
|
||||
/** Interface for reading JSON from a char array.
|
||||
*/
|
||||
class JSON_API CharReader {
|
||||
public:
|
||||
struct JSON_API StructuredError {
|
||||
ptrdiff_t offset_start;
|
||||
ptrdiff_t offset_limit;
|
||||
String message;
|
||||
};
|
||||
|
||||
virtual ~CharReader() = default;
|
||||
/** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
|
||||
* document. The document must be a UTF-8 encoded string containing the
|
||||
* document to read.
|
||||
*
|
||||
* \param beginDoc Pointer on the beginning of the UTF-8 encoded string
|
||||
* of the document to read.
|
||||
* \param endDoc Pointer on the end of the UTF-8 encoded string of the
|
||||
* document to read. Must be >= beginDoc.
|
||||
* \param[out] root Contains the root value of the document if it was
|
||||
* successfully parsed.
|
||||
* \param[out] errs Formatted error messages (if not NULL) a user
|
||||
* friendly string that lists errors in the parsed
|
||||
* document.
|
||||
* \return \c true if the document was successfully parsed, \c false if an
|
||||
* error occurred.
|
||||
*/
|
||||
virtual bool parse(char const* beginDoc, char const* endDoc, Value* root,
|
||||
String* errs);
|
||||
|
||||
/** \brief Returns a vector of structured errors encountered while parsing.
|
||||
* Each parse call resets the stored list of errors.
|
||||
*/
|
||||
std::vector<StructuredError> getStructuredErrors() const;
|
||||
|
||||
class JSON_API Factory {
|
||||
public:
|
||||
virtual ~Factory() = default;
|
||||
/** \brief Allocate a CharReader via operator new().
|
||||
* \throw std::exception if something goes wrong (e.g. invalid settings)
|
||||
*/
|
||||
virtual CharReader* newCharReader() const = 0;
|
||||
}; // Factory
|
||||
|
||||
protected:
|
||||
class Impl {
|
||||
public:
|
||||
virtual ~Impl() = default;
|
||||
virtual bool parse(char const* beginDoc, char const* endDoc, Value* root,
|
||||
String* errs) = 0;
|
||||
virtual std::vector<StructuredError> getStructuredErrors() const = 0;
|
||||
};
|
||||
|
||||
explicit CharReader(std::unique_ptr<Impl> impl) : _impl(std::move(impl)) {}
|
||||
|
||||
private:
|
||||
std::unique_ptr<Impl> _impl;
|
||||
}; // CharReader
|
||||
|
||||
/** \brief Build a CharReader implementation.
|
||||
*
|
||||
* Usage:
|
||||
* \code
|
||||
* using namespace Json;
|
||||
* CharReaderBuilder builder;
|
||||
* builder["collectComments"] = false;
|
||||
* Value value;
|
||||
* String errs;
|
||||
* bool ok = parseFromStream(builder, std::cin, &value, &errs);
|
||||
* \endcode
|
||||
*/
|
||||
class JSON_API CharReaderBuilder : public CharReader::Factory {
|
||||
public:
|
||||
// Note: We use a Json::Value so that we can add data-members to this class
|
||||
// without a major version bump.
|
||||
/** Configuration of this builder.
|
||||
* These are case-sensitive.
|
||||
* Available settings (case-sensitive):
|
||||
* - `"collectComments": false or true`
|
||||
* - true to collect comment and allow writing them back during
|
||||
* serialization, false to discard comments. This parameter is ignored
|
||||
* if allowComments is false.
|
||||
* - `"allowComments": false or true`
|
||||
* - true if comments are allowed.
|
||||
* - `"allowTrailingCommas": false or true`
|
||||
* - true if trailing commas in objects and arrays are allowed.
|
||||
* - `"strictRoot": false or true`
|
||||
* - true if root must be either an array or an object value
|
||||
* - `"allowDroppedNullPlaceholders": false or true`
|
||||
* - true if dropped null placeholders are allowed. (See
|
||||
* StreamWriterBuilder.)
|
||||
* - `"allowNumericKeys": false or true`
|
||||
* - true if numeric object keys are allowed.
|
||||
* - `"allowSingleQuotes": false or true`
|
||||
* - true if '' are allowed for strings (both keys and values)
|
||||
* - `"stackLimit": integer`
|
||||
* - Exceeding stackLimit (recursive depth of `readValue()`) will cause an
|
||||
* exception.
|
||||
* - This is a security issue (seg-faults caused by deeply nested JSON), so
|
||||
* the default is low.
|
||||
* - `"failIfExtra": false or true`
|
||||
* - If true, `parse()` returns false when extra non-whitespace trails the
|
||||
* JSON value in the input string.
|
||||
* - `"rejectDupKeys": false or true`
|
||||
* - If true, `parse()` returns false when a key is duplicated within an
|
||||
* object.
|
||||
* - `"allowSpecialFloats": false or true`
|
||||
* - If true, special float values (NaNs and infinities) are allowed and
|
||||
* their values are lossfree restorable.
|
||||
* - `"skipBom": false or true`
|
||||
* - If true, if the input starts with the Unicode byte order mark (BOM),
|
||||
* it is skipped.
|
||||
*
|
||||
* You can examine 'settings_` yourself to see the defaults. You can also
|
||||
* write and read them just like any JSON Value.
|
||||
* \sa setDefaults()
|
||||
*/
|
||||
Json::Value settings_;
|
||||
|
||||
CharReaderBuilder();
|
||||
~CharReaderBuilder() override;
|
||||
|
||||
CharReader* newCharReader() const override;
|
||||
|
||||
/** \return true if 'settings' are legal and consistent;
|
||||
* otherwise, indicate bad settings via 'invalid'.
|
||||
*/
|
||||
bool validate(Json::Value* invalid) const;
|
||||
|
||||
/** A simple way to update a specific setting.
|
||||
*/
|
||||
Value& operator[](const String& key);
|
||||
|
||||
/** Called by ctor, but you can use this to reset settings_.
|
||||
* \pre 'settings' != NULL (but Json::null is fine)
|
||||
* \remark Defaults:
|
||||
* \snippet src/lib_json/json_reader.cpp CharReaderBuilderDefaults
|
||||
*/
|
||||
static void setDefaults(Json::Value* settings);
|
||||
/** Same as old Features::strictMode().
|
||||
* \pre 'settings' != NULL (but Json::null is fine)
|
||||
* \remark Defaults:
|
||||
* \snippet src/lib_json/json_reader.cpp CharReaderBuilderStrictMode
|
||||
*/
|
||||
static void strictMode(Json::Value* settings);
|
||||
/** ECMA-404 mode.
|
||||
* \pre 'settings' != NULL (but Json::null is fine)
|
||||
* \remark Defaults:
|
||||
* \snippet src/lib_json/json_reader.cpp CharReaderBuilderECMA404Mode
|
||||
*/
|
||||
static void ecma404Mode(Json::Value* settings);
|
||||
};
|
||||
|
||||
/** Consume entire stream and use its begin/end.
|
||||
* Someday we might have a real StreamReader, but for now this
|
||||
* is convenient.
|
||||
*/
|
||||
bool JSON_API parseFromStream(CharReader::Factory const&, IStream&, Value* root,
|
||||
String* errs);
|
||||
|
||||
/** \brief Read from 'sin' into 'root'.
|
||||
*
|
||||
* Always keep comments from the input JSON.
|
||||
*
|
||||
* This can be used to read a file into a particular sub-object.
|
||||
* For example:
|
||||
* \code
|
||||
* Json::Value root;
|
||||
* cin >> root["dir"]["file"];
|
||||
* cout << root;
|
||||
* \endcode
|
||||
* Result:
|
||||
* \verbatim
|
||||
* {
|
||||
* "dir": {
|
||||
* "file": {
|
||||
* // The input stream JSON would be nested here.
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* \endverbatim
|
||||
* \throw std::exception on parse error.
|
||||
* \see Json::operator<<()
|
||||
*/
|
||||
JSON_API IStream& operator>>(IStream&, Value&);
|
||||
|
||||
} // namespace Json
|
||||
|
||||
#endif // CPPTL_JSON_READER_H_INCLUDED
|
||||
#pragma pack(pop)
|
||||
|
||||
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
||||
#pragma warning(pop)
|
||||
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
||||
|
||||
#endif // JSON_READER_H_INCLUDED
|
||||
|
1950
include/json/value.h
1950
include/json/value.h
File diff suppressed because it is too large
Load Diff
28
include/json/version.h
Normal file
28
include/json/version.h
Normal file
@ -0,0 +1,28 @@
|
||||
#ifndef JSON_VERSION_H_INCLUDED
|
||||
#define JSON_VERSION_H_INCLUDED
|
||||
|
||||
// Note: version must be updated in four places when doing a release. This
|
||||
// annoying process ensures that amalgamate, CMake, and meson all report the
|
||||
// correct version.
|
||||
// 1. /meson.build
|
||||
// 2. /include/json/version.h
|
||||
// 3. /CMakeLists.txt
|
||||
// 4. /MODULE.bazel
|
||||
// IMPORTANT: also update the SOVERSION!!
|
||||
|
||||
#define JSONCPP_VERSION_STRING "1.9.7"
|
||||
#define JSONCPP_VERSION_MAJOR 1
|
||||
#define JSONCPP_VERSION_MINOR 9
|
||||
#define JSONCPP_VERSION_PATCH 7
|
||||
#define JSONCPP_VERSION_QUALIFIER
|
||||
#define JSONCPP_VERSION_HEXA \
|
||||
((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | \
|
||||
(JSONCPP_VERSION_PATCH << 8))
|
||||
|
||||
#if !defined(JSONCPP_USE_SECURE_MEMORY)
|
||||
#define JSONCPP_USE_SECURE_MEMORY 0
|
||||
#endif
|
||||
// If non-zero, the library zeroes any memory that it has allocated before
|
||||
// it frees its memory.
|
||||
|
||||
#endif // JSON_VERSION_H_INCLUDED
|
@ -1,174 +1,368 @@
|
||||
#ifndef JSON_WRITER_H_INCLUDED
|
||||
# define JSON_WRITER_H_INCLUDED
|
||||
// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
|
||||
// Distributed under MIT license, or public domain if desired and
|
||||
// recognized in your jurisdiction.
|
||||
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||
|
||||
# include "value.h"
|
||||
# include <vector>
|
||||
# include <string>
|
||||
# include <iostream>
|
||||
#ifndef JSON_WRITER_H_INCLUDED
|
||||
#define JSON_WRITER_H_INCLUDED
|
||||
|
||||
#if !defined(JSON_IS_AMALGAMATION)
|
||||
#include "value.h"
|
||||
#endif // if !defined(JSON_IS_AMALGAMATION)
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
// Disable warning C4251: <data member>: <type> needs to have dll-interface to
|
||||
// be used by...
|
||||
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) && defined(_MSC_VER)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4251)
|
||||
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
||||
|
||||
#pragma pack(push)
|
||||
#pragma pack()
|
||||
|
||||
namespace Json {
|
||||
|
||||
class Value;
|
||||
class Value;
|
||||
|
||||
/** \brief Abstract class for writers.
|
||||
*/
|
||||
class JSON_API Writer
|
||||
{
|
||||
public:
|
||||
virtual ~Writer();
|
||||
/**
|
||||
*
|
||||
* Usage:
|
||||
* \code
|
||||
* using namespace Json;
|
||||
* void writeToStdout(StreamWriter::Factory const& factory, Value const& value)
|
||||
* { std::unique_ptr<StreamWriter> const writer( factory.newStreamWriter());
|
||||
* writer->write(value, &std::cout);
|
||||
* std::cout << std::endl; // add lf and flush
|
||||
* }
|
||||
* \endcode
|
||||
*/
|
||||
class JSON_API StreamWriter {
|
||||
protected:
|
||||
OStream* sout_; // not owned; will not delete
|
||||
public:
|
||||
StreamWriter();
|
||||
virtual ~StreamWriter();
|
||||
/** Write Value into document as configured in sub-class.
|
||||
* Do not take ownership of sout, but maintain a reference during function.
|
||||
* \pre sout != NULL
|
||||
* \return zero on success (For now, we always return zero, so check the
|
||||
* stream instead.) \throw std::exception possibly, depending on
|
||||
* configuration
|
||||
*/
|
||||
virtual int write(Value const& root, OStream* sout) = 0;
|
||||
|
||||
virtual std::string write( const Value &root ) = 0;
|
||||
};
|
||||
/** \brief A simple abstract factory.
|
||||
*/
|
||||
class JSON_API Factory {
|
||||
public:
|
||||
virtual ~Factory();
|
||||
/** \brief Allocate a CharReader via operator new().
|
||||
* \throw std::exception if something goes wrong (e.g. invalid settings)
|
||||
*/
|
||||
virtual StreamWriter* newStreamWriter() const = 0;
|
||||
}; // Factory
|
||||
}; // StreamWriter
|
||||
|
||||
/** \brief Outputs a Value in <a HREF="http://www.json.org">JSON</a> format without formatting (not human friendly).
|
||||
*
|
||||
* The JSON document is written in a single line. It is not intended for 'human' consumption,
|
||||
* but may be usefull to support feature such as RPC where bandwith is limited.
|
||||
* \sa Reader, Value
|
||||
*/
|
||||
class JSON_API FastWriter : public Writer
|
||||
{
|
||||
public:
|
||||
FastWriter();
|
||||
virtual ~FastWriter(){}
|
||||
/** \brief Write into stringstream, then return string, for convenience.
|
||||
* A StreamWriter will be created from the factory, used, and then deleted.
|
||||
*/
|
||||
String JSON_API writeString(StreamWriter::Factory const& factory,
|
||||
Value const& root);
|
||||
|
||||
void enableYAMLCompatibility();
|
||||
/** \brief Build a StreamWriter implementation.
|
||||
|
||||
public: // overridden from Writer
|
||||
virtual std::string write( const Value &root );
|
||||
* Usage:
|
||||
* \code
|
||||
* using namespace Json;
|
||||
* Value value = ...;
|
||||
* StreamWriterBuilder builder;
|
||||
* builder["commentStyle"] = "None";
|
||||
* builder["indentation"] = " "; // or whatever you like
|
||||
* std::unique_ptr<Json::StreamWriter> writer(
|
||||
* builder.newStreamWriter());
|
||||
* writer->write(value, &std::cout);
|
||||
* std::cout << std::endl; // add lf and flush
|
||||
* \endcode
|
||||
*/
|
||||
class JSON_API StreamWriterBuilder : public StreamWriter::Factory {
|
||||
public:
|
||||
// Note: We use a Json::Value so that we can add data-members to this class
|
||||
// without a major version bump.
|
||||
/** Configuration of this builder.
|
||||
* Available settings (case-sensitive):
|
||||
* - "commentStyle": "None" or "All"
|
||||
* - "indentation": "<anything>".
|
||||
* - Setting this to an empty string also omits newline characters.
|
||||
* - "enableYAMLCompatibility": false or true
|
||||
* - slightly change the whitespace around colons
|
||||
* - "dropNullPlaceholders": false or true
|
||||
* - Drop the "null" string from the writer's output for nullValues.
|
||||
* Strictly speaking, this is not valid JSON. But when the output is being
|
||||
* fed to a browser's JavaScript, it makes for smaller output and the
|
||||
* browser can handle the output just fine.
|
||||
* - "useSpecialFloats": false or true
|
||||
* - If true, outputs non-finite floating point values in the following way:
|
||||
* NaN values as "NaN", positive infinity as "Infinity", and negative
|
||||
* infinity as "-Infinity".
|
||||
* - "precision": int
|
||||
* - Number of precision digits for formatting of real values.
|
||||
* - "precisionType": "significant"(default) or "decimal"
|
||||
* - Type of precision for formatting of real values.
|
||||
* - "emitUTF8": false or true
|
||||
* - If true, outputs raw UTF8 strings instead of escaping them.
|
||||
|
||||
private:
|
||||
void writeValue( const Value &value );
|
||||
* You can examine 'settings_` yourself
|
||||
* to see the defaults. You can also write and read them just like any
|
||||
* JSON Value.
|
||||
* \sa setDefaults()
|
||||
*/
|
||||
Json::Value settings_;
|
||||
|
||||
std::string document_;
|
||||
bool yamlCompatiblityEnabled_;
|
||||
};
|
||||
StreamWriterBuilder();
|
||||
~StreamWriterBuilder() override;
|
||||
|
||||
/** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a human friendly way.
|
||||
*
|
||||
* The rules for line break and indent are as follow:
|
||||
* - Object value:
|
||||
* - if empty then print {} without indent and line break
|
||||
* - if not empty the print '{', line break & indent, print one value per line
|
||||
* and then unindent and line break and print '}'.
|
||||
* - Array value:
|
||||
* - if empty then print [] without indent and line break
|
||||
* - if the array contains no object value, empty array or some other value types,
|
||||
* and all the values fit on one lines, then print the array on a single line.
|
||||
* - otherwise, it the values do not fit on one line, or the array contains
|
||||
* object or non empty array, then print one value per line.
|
||||
*
|
||||
* If the Value have comments then they are outputed according to their #CommentPlacement.
|
||||
*
|
||||
* \sa Reader, Value, Value::setComment()
|
||||
*/
|
||||
class JSON_API StyledWriter: public Writer
|
||||
{
|
||||
public:
|
||||
StyledWriter();
|
||||
virtual ~StyledWriter(){}
|
||||
/**
|
||||
* \throw std::exception if something goes wrong (e.g. invalid settings)
|
||||
*/
|
||||
StreamWriter* newStreamWriter() const override;
|
||||
|
||||
public: // overridden from Writer
|
||||
/** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
|
||||
* \param root Value to serialize.
|
||||
* \return String containing the JSON document that represents the root value.
|
||||
*/
|
||||
virtual std::string write( const Value &root );
|
||||
/** \return true if 'settings' are legal and consistent;
|
||||
* otherwise, indicate bad settings via 'invalid'.
|
||||
*/
|
||||
bool validate(Json::Value* invalid) const;
|
||||
/** A simple way to update a specific setting.
|
||||
*/
|
||||
Value& operator[](const String& key);
|
||||
|
||||
private:
|
||||
void writeValue( const Value &value );
|
||||
void writeArrayValue( const Value &value );
|
||||
bool isMultineArray( const Value &value );
|
||||
void pushValue( const std::string &value );
|
||||
void writeIndent();
|
||||
void writeWithIndent( const std::string &value );
|
||||
void indent();
|
||||
void unindent();
|
||||
void writeCommentBeforeValue( const Value &root );
|
||||
void writeCommentAfterValueOnSameLine( const Value &root );
|
||||
bool hasCommentForValue( const Value &value );
|
||||
static std::string normalizeEOL( const std::string &text );
|
||||
/** Called by ctor, but you can use this to reset settings_.
|
||||
* \pre 'settings' != NULL (but Json::null is fine)
|
||||
* \remark Defaults:
|
||||
* \snippet src/lib_json/json_writer.cpp StreamWriterBuilderDefaults
|
||||
*/
|
||||
static void setDefaults(Json::Value* settings);
|
||||
};
|
||||
|
||||
typedef std::vector<std::string> ChildValues;
|
||||
/** \brief Abstract class for writers.
|
||||
* \deprecated Use StreamWriter. (And really, this is an implementation detail.)
|
||||
*/
|
||||
class JSON_API Writer {
|
||||
public:
|
||||
virtual ~Writer();
|
||||
|
||||
ChildValues childValues_;
|
||||
std::string document_;
|
||||
std::string indentString_;
|
||||
int rightMargin_;
|
||||
int indentSize_;
|
||||
bool addChildValues_;
|
||||
};
|
||||
virtual String write(const Value& root) = 0;
|
||||
};
|
||||
|
||||
/** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a human friendly way,
|
||||
to a stream rather than to a string.
|
||||
*
|
||||
* The rules for line break and indent are as follow:
|
||||
* - Object value:
|
||||
* - if empty then print {} without indent and line break
|
||||
* - if not empty the print '{', line break & indent, print one value per line
|
||||
* and then unindent and line break and print '}'.
|
||||
* - Array value:
|
||||
* - if empty then print [] without indent and line break
|
||||
* - if the array contains no object value, empty array or some other value types,
|
||||
* and all the values fit on one lines, then print the array on a single line.
|
||||
* - otherwise, it the values do not fit on one line, or the array contains
|
||||
* object or non empty array, then print one value per line.
|
||||
*
|
||||
* If the Value have comments then they are outputed according to their #CommentPlacement.
|
||||
*
|
||||
* \param indentation Each level will be indented by this amount extra.
|
||||
* \sa Reader, Value, Value::setComment()
|
||||
*/
|
||||
class JSON_API StyledStreamWriter
|
||||
{
|
||||
public:
|
||||
StyledStreamWriter( std::string indentation="\t" );
|
||||
~StyledStreamWriter(){}
|
||||
/** \brief Outputs a Value in <a HREF="http://www.json.org">JSON</a> format
|
||||
*without formatting (not human friendly).
|
||||
*
|
||||
* The JSON document is written in a single line. It is not intended for 'human'
|
||||
*consumption,
|
||||
* but may be useful to support feature such as RPC where bandwidth is limited.
|
||||
* \sa Reader, Value
|
||||
* \deprecated Use StreamWriterBuilder.
|
||||
*/
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4996) // Deriving from deprecated class
|
||||
#endif
|
||||
class JSON_API FastWriter : public Writer {
|
||||
public:
|
||||
FastWriter();
|
||||
~FastWriter() override = default;
|
||||
|
||||
public:
|
||||
/** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
|
||||
* \param out Stream to write to. (Can be ostringstream, e.g.)
|
||||
* \param root Value to serialize.
|
||||
* \note There is no point in deriving from Writer, since write() should not return a value.
|
||||
*/
|
||||
void write( std::ostream &out, const Value &root );
|
||||
void enableYAMLCompatibility();
|
||||
|
||||
private:
|
||||
void writeValue( const Value &value );
|
||||
void writeArrayValue( const Value &value );
|
||||
bool isMultineArray( const Value &value );
|
||||
void pushValue( const std::string &value );
|
||||
void writeIndent();
|
||||
void writeWithIndent( const std::string &value );
|
||||
void indent();
|
||||
void unindent();
|
||||
void writeCommentBeforeValue( const Value &root );
|
||||
void writeCommentAfterValueOnSameLine( const Value &root );
|
||||
bool hasCommentForValue( const Value &value );
|
||||
static std::string normalizeEOL( const std::string &text );
|
||||
/** \brief Drop the "null" string from the writer's output for nullValues.
|
||||
* Strictly speaking, this is not valid JSON. But when the output is being
|
||||
* fed to a browser's JavaScript, it makes for smaller output and the
|
||||
* browser can handle the output just fine.
|
||||
*/
|
||||
void dropNullPlaceholders();
|
||||
|
||||
typedef std::vector<std::string> ChildValues;
|
||||
void omitEndingLineFeed();
|
||||
|
||||
ChildValues childValues_;
|
||||
std::ostream* document_;
|
||||
std::string indentString_;
|
||||
int rightMargin_;
|
||||
std::string indentation_;
|
||||
bool addChildValues_;
|
||||
};
|
||||
public: // overridden from Writer
|
||||
String write(const Value& root) override;
|
||||
|
||||
std::string JSON_API valueToString( Int value );
|
||||
std::string JSON_API valueToString( UInt value );
|
||||
std::string JSON_API valueToString( double value );
|
||||
std::string JSON_API valueToString( bool value );
|
||||
std::string JSON_API valueToQuotedString( const char *value );
|
||||
private:
|
||||
void writeValue(const Value& value);
|
||||
|
||||
/// \brief Output using the StyledStreamWriter.
|
||||
/// \see Json::operator>>()
|
||||
std::ostream& operator<<( std::ostream&, const Value &root );
|
||||
String document_;
|
||||
bool yamlCompatibilityEnabled_{false};
|
||||
bool dropNullPlaceholders_{false};
|
||||
bool omitEndingLineFeed_{false};
|
||||
};
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
/** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a
|
||||
*human friendly way.
|
||||
*
|
||||
* The rules for line break and indent are as follow:
|
||||
* - Object value:
|
||||
* - if empty then print {} without indent and line break
|
||||
* - if not empty the print '{', line break & indent, print one value per
|
||||
*line
|
||||
* and then unindent and line break and print '}'.
|
||||
* - Array value:
|
||||
* - if empty then print [] without indent and line break
|
||||
* - if the array contains no object value, empty array or some other value
|
||||
*types,
|
||||
* and all the values fit on one lines, then print the array on a single
|
||||
*line.
|
||||
* - otherwise, it the values do not fit on one line, or the array contains
|
||||
* object or non empty array, then print one value per line.
|
||||
*
|
||||
* If the Value have comments then they are outputted according to their
|
||||
*#CommentPlacement.
|
||||
*
|
||||
* \sa Reader, Value, Value::setComment()
|
||||
* \deprecated Use StreamWriterBuilder.
|
||||
*/
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4996) // Deriving from deprecated class
|
||||
#endif
|
||||
class JSON_API StyledWriter : public Writer {
|
||||
public:
|
||||
StyledWriter();
|
||||
~StyledWriter() override = default;
|
||||
|
||||
public: // overridden from Writer
|
||||
/** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
|
||||
* \param root Value to serialize.
|
||||
* \return String containing the JSON document that represents the root value.
|
||||
*/
|
||||
String write(const Value& root) override;
|
||||
|
||||
private:
|
||||
void writeValue(const Value& value);
|
||||
void writeArrayValue(const Value& value);
|
||||
bool isMultilineArray(const Value& value);
|
||||
void pushValue(const String& value);
|
||||
void writeIndent();
|
||||
void writeWithIndent(const String& value);
|
||||
void indent();
|
||||
void unindent();
|
||||
void writeCommentBeforeValue(const Value& root);
|
||||
void writeCommentAfterValueOnSameLine(const Value& root);
|
||||
static bool hasCommentForValue(const Value& value);
|
||||
static String normalizeEOL(const String& text);
|
||||
|
||||
using ChildValues = std::vector<String>;
|
||||
|
||||
ChildValues childValues_;
|
||||
String document_;
|
||||
String indentString_;
|
||||
unsigned int rightMargin_{74};
|
||||
unsigned int indentSize_{3};
|
||||
bool addChildValues_{false};
|
||||
};
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
/** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a
|
||||
human friendly way,
|
||||
to a stream rather than to a string.
|
||||
*
|
||||
* The rules for line break and indent are as follow:
|
||||
* - Object value:
|
||||
* - if empty then print {} without indent and line break
|
||||
* - if not empty the print '{', line break & indent, print one value per
|
||||
line
|
||||
* and then unindent and line break and print '}'.
|
||||
* - Array value:
|
||||
* - if empty then print [] without indent and line break
|
||||
* - if the array contains no object value, empty array or some other value
|
||||
types,
|
||||
* and all the values fit on one lines, then print the array on a single
|
||||
line.
|
||||
* - otherwise, it the values do not fit on one line, or the array contains
|
||||
* object or non empty array, then print one value per line.
|
||||
*
|
||||
* If the Value have comments then they are outputted according to their
|
||||
#CommentPlacement.
|
||||
*
|
||||
* \sa Reader, Value, Value::setComment()
|
||||
* \deprecated Use StreamWriterBuilder.
|
||||
*/
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4996) // Deriving from deprecated class
|
||||
#endif
|
||||
class JSON_API StyledStreamWriter {
|
||||
public:
|
||||
/**
|
||||
* \param indentation Each level will be indented by this amount extra.
|
||||
*/
|
||||
StyledStreamWriter(String indentation = "\t");
|
||||
~StyledStreamWriter() = default;
|
||||
|
||||
public:
|
||||
/** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
|
||||
* \param out Stream to write to. (Can be ostringstream, e.g.)
|
||||
* \param root Value to serialize.
|
||||
* \note There is no point in deriving from Writer, since write() should not
|
||||
* return a value.
|
||||
*/
|
||||
void write(OStream& out, const Value& root);
|
||||
|
||||
private:
|
||||
void writeValue(const Value& value);
|
||||
void writeArrayValue(const Value& value);
|
||||
bool isMultilineArray(const Value& value);
|
||||
void pushValue(const String& value);
|
||||
void writeIndent();
|
||||
void writeWithIndent(const String& value);
|
||||
void indent();
|
||||
void unindent();
|
||||
void writeCommentBeforeValue(const Value& root);
|
||||
void writeCommentAfterValueOnSameLine(const Value& root);
|
||||
static bool hasCommentForValue(const Value& value);
|
||||
static String normalizeEOL(const String& text);
|
||||
|
||||
using ChildValues = std::vector<String>;
|
||||
|
||||
ChildValues childValues_;
|
||||
OStream* document_;
|
||||
String indentString_;
|
||||
unsigned int rightMargin_{74};
|
||||
String indentation_;
|
||||
bool addChildValues_ : 1;
|
||||
bool indented_ : 1;
|
||||
};
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#if defined(JSON_HAS_INT64)
|
||||
String JSON_API valueToString(Int value);
|
||||
String JSON_API valueToString(UInt value);
|
||||
#endif // if defined(JSON_HAS_INT64)
|
||||
String JSON_API valueToString(LargestInt value);
|
||||
String JSON_API valueToString(LargestUInt value);
|
||||
String JSON_API valueToString(
|
||||
double value, unsigned int precision = Value::defaultRealPrecision,
|
||||
PrecisionType precisionType = PrecisionType::significantDigits);
|
||||
String JSON_API valueToString(bool value);
|
||||
String JSON_API valueToQuotedString(const char* value);
|
||||
String JSON_API valueToQuotedString(const char* value, size_t length);
|
||||
|
||||
/// \brief Output using the StyledStreamWriter.
|
||||
/// \see Json::operator>>()
|
||||
JSON_API OStream& operator<<(OStream&, const Value& root);
|
||||
|
||||
} // namespace Json
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
||||
#pragma warning(pop)
|
||||
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
||||
|
||||
#endif // JSON_WRITER_H_INCLUDED
|
||||
|
9
jsoncpp-namespaced-targets.cmake
Normal file
9
jsoncpp-namespaced-targets.cmake
Normal file
@ -0,0 +1,9 @@
|
||||
if (NOT TARGET JsonCpp::JsonCpp)
|
||||
if (TARGET jsoncpp_static)
|
||||
add_library(JsonCpp::JsonCpp INTERFACE IMPORTED)
|
||||
set_target_properties(JsonCpp::JsonCpp PROPERTIES INTERFACE_LINK_LIBRARIES "jsoncpp_static")
|
||||
elseif (TARGET jsoncpp_lib)
|
||||
add_library(JsonCpp::JsonCpp INTERFACE IMPORTED)
|
||||
set_target_properties(JsonCpp::JsonCpp PROPERTIES INTERFACE_LINK_LIBRARIES "jsoncpp_lib")
|
||||
endif ()
|
||||
endif ()
|
11
jsoncppConfig.cmake.in
Normal file
11
jsoncppConfig.cmake.in
Normal file
@ -0,0 +1,11 @@
|
||||
cmake_policy(PUSH)
|
||||
cmake_policy(VERSION 3.0...3.26)
|
||||
|
||||
@PACKAGE_INIT@
|
||||
|
||||
include ( "${CMAKE_CURRENT_LIST_DIR}/jsoncpp-targets.cmake" )
|
||||
include ( "${CMAKE_CURRENT_LIST_DIR}/jsoncpp-namespaced-targets.cmake" )
|
||||
|
||||
check_required_components(JsonCpp)
|
||||
|
||||
cmake_policy(POP)
|
6
jsoncppConfig.cmake.meson.in
Normal file
6
jsoncppConfig.cmake.meson.in
Normal file
@ -0,0 +1,6 @@
|
||||
@PACKAGE_INIT@
|
||||
|
||||
@MESON_SHARED_TARGET@
|
||||
@MESON_STATIC_TARGET@
|
||||
|
||||
include ( "${CMAKE_CURRENT_LIST_DIR}/jsoncpp-namespaced-targets.cmake" )
|
@ -1,46 +0,0 @@
|
||||
Microsoft Visual Studio Solution File, Format Version 8.00
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lib_json", "lib_json.vcproj", "{B84F7231-16CE-41D8-8C08-7B523FF4225B}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jsontest", "jsontest.vcproj", "{25AF2DD2-D396-4668-B188-488C33B8E620}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{B84F7231-16CE-41D8-8C08-7B523FF4225B} = {B84F7231-16CE-41D8-8C08-7B523FF4225B}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_lib_json", "test_lib_json.vcproj", "{B7A96B78-2782-40D2-8F37-A2DEF2B9C26D}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{B84F7231-16CE-41D8-8C08-7B523FF4225B} = {B84F7231-16CE-41D8-8C08-7B523FF4225B}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfiguration) = preSolution
|
||||
Debug = Debug
|
||||
dummy = dummy
|
||||
Release = Release
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfiguration) = postSolution
|
||||
{B84F7231-16CE-41D8-8C08-7B523FF4225B}.Debug.ActiveCfg = Debug|Win32
|
||||
{B84F7231-16CE-41D8-8C08-7B523FF4225B}.Debug.Build.0 = Debug|Win32
|
||||
{B84F7231-16CE-41D8-8C08-7B523FF4225B}.dummy.ActiveCfg = dummy|Win32
|
||||
{B84F7231-16CE-41D8-8C08-7B523FF4225B}.dummy.Build.0 = dummy|Win32
|
||||
{B84F7231-16CE-41D8-8C08-7B523FF4225B}.Release.ActiveCfg = Release|Win32
|
||||
{B84F7231-16CE-41D8-8C08-7B523FF4225B}.Release.Build.0 = Release|Win32
|
||||
{25AF2DD2-D396-4668-B188-488C33B8E620}.Debug.ActiveCfg = Debug|Win32
|
||||
{25AF2DD2-D396-4668-B188-488C33B8E620}.Debug.Build.0 = Debug|Win32
|
||||
{25AF2DD2-D396-4668-B188-488C33B8E620}.dummy.ActiveCfg = Debug|Win32
|
||||
{25AF2DD2-D396-4668-B188-488C33B8E620}.dummy.Build.0 = Debug|Win32
|
||||
{25AF2DD2-D396-4668-B188-488C33B8E620}.Release.ActiveCfg = Release|Win32
|
||||
{25AF2DD2-D396-4668-B188-488C33B8E620}.Release.Build.0 = Release|Win32
|
||||
{B7A96B78-2782-40D2-8F37-A2DEF2B9C26D}.Debug.ActiveCfg = Debug|Win32
|
||||
{B7A96B78-2782-40D2-8F37-A2DEF2B9C26D}.Debug.Build.0 = Debug|Win32
|
||||
{B7A96B78-2782-40D2-8F37-A2DEF2B9C26D}.dummy.ActiveCfg = Debug|Win32
|
||||
{B7A96B78-2782-40D2-8F37-A2DEF2B9C26D}.dummy.Build.0 = Debug|Win32
|
||||
{B7A96B78-2782-40D2-8F37-A2DEF2B9C26D}.Release.ActiveCfg = Release|Win32
|
||||
{B7A96B78-2782-40D2-8F37-A2DEF2B9C26D}.Release.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityAddIns) = postSolution
|
||||
EndGlobalSection
|
||||
EndGlobal
|
@ -1,119 +0,0 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="7.10"
|
||||
Name="jsontest"
|
||||
ProjectGUID="{25AF2DD2-D396-4668-B188-488C33B8E620}"
|
||||
Keyword="Win32Proj">
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"/>
|
||||
</Platforms>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="../../build/vs71/debug/jsontest"
|
||||
IntermediateDirectory="../../build/vs71/debug/jsontest"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="../../include"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
|
||||
MinimalRebuild="TRUE"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="4"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
OutputFile="$(OutDir)/jsontest.exe"
|
||||
LinkIncremental="2"
|
||||
GenerateDebugInformation="TRUE"
|
||||
ProgramDatabaseFile="$(OutDir)/jsontest.pdb"
|
||||
SubSystem="1"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="../../build/vs71/release/jsontest"
|
||||
IntermediateDirectory="../../build/vs71/release/jsontest"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories="../../include"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
|
||||
RuntimeLibrary="0"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="3"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
OutputFile="$(OutDir)/jsontest.exe"
|
||||
LinkIncremental="1"
|
||||
GenerateDebugInformation="TRUE"
|
||||
SubSystem="1"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<File
|
||||
RelativePath="..\..\src\jsontestrunner\main.cpp">
|
||||
</File>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
@ -1,214 +0,0 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="7.10"
|
||||
Name="lib_json"
|
||||
ProjectGUID="{B84F7231-16CE-41D8-8C08-7B523FF4225B}"
|
||||
Keyword="Win32Proj">
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"/>
|
||||
</Platforms>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="../../build/vs71/debug/lib_json"
|
||||
IntermediateDirectory="../../build/vs71/debug/lib_json"
|
||||
ConfigurationType="4"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="../../include"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
|
||||
StringPooling="TRUE"
|
||||
MinimalRebuild="TRUE"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
EnableFunctionLevelLinking="TRUE"
|
||||
DisableLanguageExtensions="TRUE"
|
||||
ForceConformanceInForLoopScope="FALSE"
|
||||
RuntimeTypeInfo="TRUE"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="4"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
OutputFile="$(OutDir)/json_vc71_libmtd.lib"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="../../build/vs71/release/lib_json"
|
||||
IntermediateDirectory="../../build/vs71/release/lib_json"
|
||||
ConfigurationType="4"
|
||||
CharacterSet="2"
|
||||
WholeProgramOptimization="TRUE">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
GlobalOptimizations="TRUE"
|
||||
EnableIntrinsicFunctions="TRUE"
|
||||
AdditionalIncludeDirectories="../../include"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
|
||||
StringPooling="TRUE"
|
||||
RuntimeLibrary="0"
|
||||
EnableFunctionLevelLinking="TRUE"
|
||||
DisableLanguageExtensions="TRUE"
|
||||
ForceConformanceInForLoopScope="FALSE"
|
||||
RuntimeTypeInfo="TRUE"
|
||||
UsePrecompiledHeader="0"
|
||||
AssemblerOutput="4"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="3"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
OutputFile="$(OutDir)/json_vc71_libmt.lib"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="dummy|Win32"
|
||||
OutputDirectory="$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="2"
|
||||
WholeProgramOptimization="TRUE">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
GlobalOptimizations="TRUE"
|
||||
EnableIntrinsicFunctions="TRUE"
|
||||
AdditionalIncludeDirectories="../../include"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
|
||||
StringPooling="TRUE"
|
||||
RuntimeLibrary="4"
|
||||
EnableFunctionLevelLinking="TRUE"
|
||||
DisableLanguageExtensions="TRUE"
|
||||
ForceConformanceInForLoopScope="FALSE"
|
||||
RuntimeTypeInfo="TRUE"
|
||||
UsePrecompiledHeader="0"
|
||||
AssemblerOutput="4"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="3"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
GenerateDebugInformation="TRUE"
|
||||
SubSystem="2"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<File
|
||||
RelativePath="..\..\include\json\autolink.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\include\json\config.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\include\json\features.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\include\json\forwards.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\include\json\json.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\lib_json\json_batchallocator.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\lib_json\json_internalarray.inl">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\lib_json\json_internalmap.inl">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\lib_json\json_reader.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\lib_json\json_value.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\lib_json\json_valueiterator.inl">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\lib_json\json_writer.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\include\json\reader.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\include\json\value.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\include\json\writer.h">
|
||||
</File>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
@ -1,130 +0,0 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="7.10"
|
||||
Name="test_lib_json"
|
||||
ProjectGUID="{B7A96B78-2782-40D2-8F37-A2DEF2B9C26D}"
|
||||
RootNamespace="test_lib_json"
|
||||
Keyword="Win32Proj">
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"/>
|
||||
</Platforms>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="../../build/vs71/debug/test_lib_json"
|
||||
IntermediateDirectory="../../build/vs71/debug/test_lib_json"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="../../include"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
|
||||
MinimalRebuild="TRUE"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="4"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
OutputFile="$(OutDir)/test_lib_json.exe"
|
||||
LinkIncremental="2"
|
||||
GenerateDebugInformation="TRUE"
|
||||
ProgramDatabaseFile="$(OutDir)/test_lib_json.pdb"
|
||||
SubSystem="1"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
Description="Running all unit tests"
|
||||
CommandLine="$(TargetPath)"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="../../build/vs71/release/test_lib_json"
|
||||
IntermediateDirectory="../../build/vs71/release/test_lib_json"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories="../../include"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
|
||||
RuntimeLibrary="0"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="3"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
OutputFile="$(OutDir)/test_lib_json.exe"
|
||||
LinkIncremental="1"
|
||||
GenerateDebugInformation="TRUE"
|
||||
SubSystem="1"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
Description="Running all unit tests"
|
||||
CommandLine="$(TargetPath)"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<File
|
||||
RelativePath="..\..\src\test_lib_json\jsontest.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\test_lib_json\jsontest.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\test_lib_json\main.cpp">
|
||||
</File>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
157
meson.build
Normal file
157
meson.build
Normal file
@ -0,0 +1,157 @@
|
||||
project(
|
||||
'jsoncpp',
|
||||
'cpp',
|
||||
|
||||
# Note: version must be updated in four places when doing a release. This
|
||||
# annoying process ensures that amalgamate, CMake, and meson all report the
|
||||
# correct version.
|
||||
# 1. /meson.build
|
||||
# 2. /include/json/version.h
|
||||
# 3. /CMakeLists.txt
|
||||
# 4. /MODULE.bazel
|
||||
# IMPORTANT: also update the SOVERSION!!
|
||||
version : '1.9.7',
|
||||
default_options : [
|
||||
'buildtype=release',
|
||||
'cpp_std=c++11',
|
||||
'warning_level=1'],
|
||||
license : 'Public Domain',
|
||||
meson_version : '>= 0.54.0')
|
||||
|
||||
|
||||
jsoncpp_headers = files([
|
||||
'include/json/allocator.h',
|
||||
'include/json/assertions.h',
|
||||
'include/json/config.h',
|
||||
'include/json/json_features.h',
|
||||
'include/json/forwards.h',
|
||||
'include/json/json.h',
|
||||
'include/json/reader.h',
|
||||
'include/json/value.h',
|
||||
'include/json/version.h',
|
||||
'include/json/writer.h',
|
||||
])
|
||||
jsoncpp_include_directories = include_directories('include')
|
||||
|
||||
install_headers(
|
||||
jsoncpp_headers,
|
||||
subdir : 'json')
|
||||
|
||||
if get_option('default_library') == 'shared' and meson.get_compiler('cpp').get_id() == 'msvc'
|
||||
dll_export_flag = '-DJSON_DLL_BUILD'
|
||||
dll_import_flag = '-DJSON_DLL'
|
||||
else
|
||||
dll_export_flag = []
|
||||
dll_import_flag = []
|
||||
endif
|
||||
|
||||
jsoncpp_lib = library(
|
||||
'jsoncpp', files([
|
||||
'src/lib_json/json_reader.cpp',
|
||||
'src/lib_json/json_value.cpp',
|
||||
'src/lib_json/json_writer.cpp',
|
||||
]),
|
||||
soversion : 27,
|
||||
install : true,
|
||||
include_directories : jsoncpp_include_directories,
|
||||
cpp_args: dll_export_flag)
|
||||
|
||||
import('pkgconfig').generate(
|
||||
libraries : jsoncpp_lib,
|
||||
version : meson.project_version(),
|
||||
name : 'jsoncpp',
|
||||
filebase : 'jsoncpp',
|
||||
description : 'A C++ library for interacting with JSON')
|
||||
|
||||
cmakeconf = configuration_data()
|
||||
cmakeconf.set('MESON_LIB_DIR', get_option('libdir'))
|
||||
cmakeconf.set('MESON_INCLUDE_DIR', get_option('includedir'))
|
||||
|
||||
fs = import('fs')
|
||||
if get_option('default_library') == 'shared'
|
||||
shared_name = fs.name(jsoncpp_lib.full_path())
|
||||
endif
|
||||
if get_option('default_library') == 'static'
|
||||
static_name = fs.name(jsoncpp_lib.full_path())
|
||||
endif
|
||||
if get_option('default_library') == 'both'
|
||||
shared_name = fs.name(jsoncpp_lib.get_shared_lib().full_path())
|
||||
static_name = fs.name(jsoncpp_lib.get_static_lib().full_path())
|
||||
endif
|
||||
|
||||
if get_option('default_library') == 'shared' or get_option('default_library') == 'both'
|
||||
cmakeconf.set('MESON_SHARED_TARGET', '''
|
||||
add_library(jsoncpp_lib IMPORTED SHARED)
|
||||
set_target_properties(jsoncpp_lib PROPERTIES
|
||||
IMPORTED_LOCATION "''' + join_paths('${PACKAGE_PREFIX_DIR}', get_option('libdir'), shared_name) + '''"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "''' + join_paths('${PACKAGE_PREFIX_DIR}', get_option('includedir')) + '")')
|
||||
endif
|
||||
if get_option('default_library') == 'static' or get_option('default_library') == 'both'
|
||||
cmakeconf.set('MESON_STATIC_TARGET', '''
|
||||
add_library(jsoncpp_static IMPORTED STATIC)
|
||||
set_target_properties(jsoncpp_static PROPERTIES
|
||||
IMPORTED_LOCATION "''' + join_paths('${PACKAGE_PREFIX_DIR}', get_option('libdir'), static_name) + '''"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "''' + join_paths('${PACKAGE_PREFIX_DIR}', get_option('includedir')) + '")')
|
||||
endif
|
||||
|
||||
import('cmake').configure_package_config_file(
|
||||
name: 'jsoncpp',
|
||||
input: 'jsoncppConfig.cmake.meson.in',
|
||||
configuration: cmakeconf)
|
||||
install_data('jsoncpp-namespaced-targets.cmake', install_dir : join_paths(get_option('libdir'), 'cmake', jsoncpp_lib.name()))
|
||||
|
||||
# for libraries bundling jsoncpp
|
||||
jsoncpp_dep = declare_dependency(
|
||||
include_directories : jsoncpp_include_directories,
|
||||
link_with : jsoncpp_lib,
|
||||
version : meson.project_version())
|
||||
|
||||
# tests
|
||||
if meson.is_subproject() or not get_option('tests')
|
||||
subdir_done()
|
||||
endif
|
||||
|
||||
python = find_program('python3')
|
||||
|
||||
jsoncpp_test = executable(
|
||||
'jsoncpp_test', files([
|
||||
'src/test_lib_json/jsontest.cpp',
|
||||
'src/test_lib_json/main.cpp',
|
||||
'src/test_lib_json/fuzz.cpp',
|
||||
]),
|
||||
include_directories : jsoncpp_include_directories,
|
||||
link_with : jsoncpp_lib,
|
||||
install : false,
|
||||
cpp_args: dll_import_flag)
|
||||
test(
|
||||
'unittest_jsoncpp_test',
|
||||
jsoncpp_test)
|
||||
|
||||
jsontestrunner = executable(
|
||||
'jsontestrunner',
|
||||
'src/jsontestrunner/main.cpp',
|
||||
include_directories : jsoncpp_include_directories,
|
||||
link_with : jsoncpp_lib,
|
||||
install : false,
|
||||
cpp_args: dll_import_flag)
|
||||
test(
|
||||
'unittest_jsontestrunner',
|
||||
python,
|
||||
args : [
|
||||
'-B',
|
||||
join_paths(meson.current_source_dir(), 'test/runjsontests.py'),
|
||||
jsontestrunner,
|
||||
join_paths(meson.current_source_dir(), 'test/data')],
|
||||
)
|
||||
test(
|
||||
'jsonchecker_jsontestrunner',
|
||||
python,
|
||||
is_parallel : false,
|
||||
args : [
|
||||
'-B',
|
||||
join_paths(meson.current_source_dir(), 'test/runjsontests.py'),
|
||||
'--with-json-checker',
|
||||
jsontestrunner,
|
||||
join_paths(meson.current_source_dir(), 'test/data')],
|
||||
workdir : join_paths(meson.current_source_dir(), 'test/data'),
|
||||
)
|
5
meson_options.txt
Normal file
5
meson_options.txt
Normal file
@ -0,0 +1,5 @@
|
||||
option(
|
||||
'tests',
|
||||
type : 'boolean',
|
||||
value : true,
|
||||
description : 'Enable building tests')
|
11
pkg-config/jsoncpp.pc.in
Normal file
11
pkg-config/jsoncpp.pc.in
Normal file
@ -0,0 +1,11 @@
|
||||
prefix=@CMAKE_INSTALL_PREFIX@
|
||||
exec_prefix=@CMAKE_INSTALL_PREFIX@
|
||||
libdir=@libdir_for_pc_file@
|
||||
includedir=@includedir_for_pc_file@
|
||||
|
||||
Name: jsoncpp
|
||||
Description: A C++ library for interacting with JSON
|
||||
Version: @PROJECT_VERSION@
|
||||
URL: https://github.com/open-source-parsers/jsoncpp
|
||||
Libs: -L${libdir} -ljsoncpp
|
||||
Cflags: -I${includedir}
|
1
reformat.sh
Executable file
1
reformat.sh
Executable file
@ -0,0 +1 @@
|
||||
find src -name '*.cpp' -or -name '*.h' | xargs clang-format -i
|
@ -1,116 +0,0 @@
|
||||
# Big issue:
|
||||
# emitter depends on doxyfile which is generated from doxyfile.in.
|
||||
# build fails after cleaning and relaunching the build.
|
||||
|
||||
# Todo:
|
||||
# Add helper function to environment like for glob
|
||||
# Easier passage of header/footer
|
||||
# Automatic deduction of index.html path based on custom parameters passed to doxyfile
|
||||
|
||||
import os
|
||||
import os.path
|
||||
from fnmatch import fnmatch
|
||||
import SCons
|
||||
|
||||
def Doxyfile_emitter(target, source, env):
|
||||
"""
|
||||
Modify the target and source lists to use the defaults if nothing
|
||||
else has been specified.
|
||||
|
||||
Dependencies on external HTML documentation references are also
|
||||
appended to the source list.
|
||||
"""
|
||||
doxyfile_template = env.File(env['DOXYFILE_FILE'])
|
||||
source.insert(0, doxyfile_template)
|
||||
|
||||
return target, source
|
||||
|
||||
def Doxyfile_Builder(target, source, env):
|
||||
"""Input:
|
||||
DOXYFILE_FILE
|
||||
Path of the template file for the output doxyfile
|
||||
|
||||
DOXYFILE_DICT
|
||||
A dictionnary of parameter to append to the generated doxyfile
|
||||
"""
|
||||
subdir = os.path.split(source[0].abspath)[0]
|
||||
doc_top_dir = os.path.split(target[0].abspath)[0]
|
||||
doxyfile_path = source[0].abspath
|
||||
doxy_file = file( target[0].abspath, 'wt' )
|
||||
try:
|
||||
# First, output the template file
|
||||
try:
|
||||
f = file(doxyfile_path, 'rt')
|
||||
doxy_file.write( f.read() )
|
||||
f.close()
|
||||
doxy_file.write( '\n' )
|
||||
doxy_file.write( '# Generated content:\n' )
|
||||
except:
|
||||
raise SCons.Errors.UserError, "Can't read doxygen template file '%s'" % doxyfile_path
|
||||
# Then, the input files
|
||||
doxy_file.write( 'INPUT = \\\n' )
|
||||
for source in source:
|
||||
if source.abspath != doxyfile_path: # skip doxyfile path, which is the first source
|
||||
doxy_file.write( '"%s" \\\n' % source.abspath )
|
||||
doxy_file.write( '\n' )
|
||||
# Dot...
|
||||
values_dict = { 'HAVE_DOT': env.get('DOT') and 'YES' or 'NO',
|
||||
'DOT_PATH': env.get('DOT') and os.path.split(env['DOT'])[0] or '',
|
||||
'OUTPUT_DIRECTORY': doc_top_dir,
|
||||
'WARN_LOGFILE': target[0].abspath + '-warning.log'}
|
||||
values_dict.update( env['DOXYFILE_DICT'] )
|
||||
# Finally, output user dictionary values which override any of the previously set parameters.
|
||||
for key, value in values_dict.iteritems():
|
||||
doxy_file.write ('%s = "%s"\n' % (key, str(value)))
|
||||
finally:
|
||||
doxy_file.close()
|
||||
|
||||
def generate(env):
|
||||
"""
|
||||
Add builders and construction variables for the
|
||||
Doxygen tool.
|
||||
"""
|
||||
## Doxyfile builder
|
||||
def doxyfile_message (target, source, env):
|
||||
return "creating Doxygen config file '%s'" % target[0]
|
||||
|
||||
doxyfile_variables = [
|
||||
'DOXYFILE_DICT',
|
||||
'DOXYFILE_FILE'
|
||||
]
|
||||
|
||||
#doxyfile_action = SCons.Action.Action( Doxyfile_Builder, doxyfile_message,
|
||||
# doxyfile_variables )
|
||||
doxyfile_action = SCons.Action.Action( Doxyfile_Builder, doxyfile_message)
|
||||
|
||||
doxyfile_builder = SCons.Builder.Builder( action = doxyfile_action,
|
||||
emitter = Doxyfile_emitter )
|
||||
|
||||
env['BUILDERS']['Doxyfile'] = doxyfile_builder
|
||||
env['DOXYFILE_DICT'] = {}
|
||||
env['DOXYFILE_FILE'] = 'doxyfile.in'
|
||||
|
||||
## Doxygen builder
|
||||
def Doxygen_emitter(target, source, env):
|
||||
output_dir = str( source[0].dir )
|
||||
if str(target[0]) == str(source[0]):
|
||||
target = env.File( os.path.join( output_dir, 'html', 'index.html' ) )
|
||||
return target, source
|
||||
|
||||
doxygen_action = SCons.Action.Action( [ '$DOXYGEN_COM'] )
|
||||
doxygen_builder = SCons.Builder.Builder( action = doxygen_action,
|
||||
emitter = Doxygen_emitter )
|
||||
env['BUILDERS']['Doxygen'] = doxygen_builder
|
||||
env['DOXYGEN_COM'] = '$DOXYGEN $DOXYGEN_FLAGS $SOURCE'
|
||||
env['DOXYGEN_FLAGS'] = ''
|
||||
env['DOXYGEN'] = 'doxygen'
|
||||
|
||||
dot_path = env.WhereIs("dot")
|
||||
if dot_path:
|
||||
env['DOT'] = dot_path
|
||||
|
||||
def exists(env):
|
||||
"""
|
||||
Make sure doxygen exists.
|
||||
"""
|
||||
return env.Detect("doxygen")
|
@ -1,53 +0,0 @@
|
||||
import fnmatch
|
||||
import os
|
||||
|
||||
def generate( env ):
|
||||
def Glob( env, includes = None, excludes = None, dir = '.' ):
|
||||
"""Adds Glob( includes = Split( '*' ), excludes = None, dir = '.')
|
||||
helper function to environment.
|
||||
|
||||
Glob both the file-system files.
|
||||
|
||||
includes: list of file name pattern included in the return list when matched.
|
||||
excludes: list of file name pattern exluced from the return list.
|
||||
|
||||
Example:
|
||||
sources = env.Glob( ("*.cpp", '*.h'), "~*.cpp", "#src" )
|
||||
"""
|
||||
def filterFilename(path):
|
||||
abs_path = os.path.join( dir, path )
|
||||
if not os.path.isfile(abs_path):
|
||||
return 0
|
||||
fn = os.path.basename(path)
|
||||
match = 0
|
||||
for include in includes:
|
||||
if fnmatch.fnmatchcase( fn, include ):
|
||||
match = 1
|
||||
break
|
||||
if match == 1 and not excludes is None:
|
||||
for exclude in excludes:
|
||||
if fnmatch.fnmatchcase( fn, exclude ):
|
||||
match = 0
|
||||
break
|
||||
return match
|
||||
if includes is None:
|
||||
includes = ('*',)
|
||||
elif type(includes) in ( type(''), type(u'') ):
|
||||
includes = (includes,)
|
||||
if type(excludes) in ( type(''), type(u'') ):
|
||||
excludes = (excludes,)
|
||||
dir = env.Dir(dir).abspath
|
||||
paths = os.listdir( dir )
|
||||
def makeAbsFileNode( path ):
|
||||
return env.File( os.path.join( dir, path ) )
|
||||
nodes = filter( filterFilename, paths )
|
||||
return map( makeAbsFileNode, nodes )
|
||||
|
||||
from SCons.Script import Environment
|
||||
Environment.Glob = Glob
|
||||
|
||||
def exists(env):
|
||||
"""
|
||||
Tool always exists.
|
||||
"""
|
||||
return True
|
@ -1,179 +0,0 @@
|
||||
import os
|
||||
import os.path
|
||||
from fnmatch import fnmatch
|
||||
import targz
|
||||
|
||||
##def DoxyfileParse(file_contents):
|
||||
## """
|
||||
## Parse a Doxygen source file and return a dictionary of all the values.
|
||||
## Values will be strings and lists of strings.
|
||||
## """
|
||||
## data = {}
|
||||
##
|
||||
## import shlex
|
||||
## lex = shlex.shlex(instream = file_contents, posix = True)
|
||||
## lex.wordchars += "*+./-:"
|
||||
## lex.whitespace = lex.whitespace.replace("\n", "")
|
||||
## lex.escape = ""
|
||||
##
|
||||
## lineno = lex.lineno
|
||||
## last_backslash_lineno = lineno
|
||||
## token = lex.get_token()
|
||||
## key = token # the first token should be a key
|
||||
## last_token = ""
|
||||
## key_token = False
|
||||
## next_key = False
|
||||
## new_data = True
|
||||
##
|
||||
## def append_data(data, key, new_data, token):
|
||||
## if new_data or len(data[key]) == 0:
|
||||
## data[key].append(token)
|
||||
## else:
|
||||
## data[key][-1] += token
|
||||
##
|
||||
## while token:
|
||||
## if token in ['\n']:
|
||||
## if last_token not in ['\\']:
|
||||
## key_token = True
|
||||
## elif token in ['\\']:
|
||||
## pass
|
||||
## elif key_token:
|
||||
## key = token
|
||||
## key_token = False
|
||||
## else:
|
||||
## if token == "+=":
|
||||
## if not data.has_key(key):
|
||||
## data[key] = list()
|
||||
## elif token == "=":
|
||||
## data[key] = list()
|
||||
## else:
|
||||
## append_data( data, key, new_data, token )
|
||||
## new_data = True
|
||||
##
|
||||
## last_token = token
|
||||
## token = lex.get_token()
|
||||
##
|
||||
## if last_token == '\\' and token != '\n':
|
||||
## new_data = False
|
||||
## append_data( data, key, new_data, '\\' )
|
||||
##
|
||||
## # compress lists of len 1 into single strings
|
||||
## for (k, v) in data.items():
|
||||
## if len(v) == 0:
|
||||
## data.pop(k)
|
||||
##
|
||||
## # items in the following list will be kept as lists and not converted to strings
|
||||
## if k in ["INPUT", "FILE_PATTERNS", "EXCLUDE_PATTERNS"]:
|
||||
## continue
|
||||
##
|
||||
## if len(v) == 1:
|
||||
## data[k] = v[0]
|
||||
##
|
||||
## return data
|
||||
##
|
||||
##def DoxySourceScan(node, env, path):
|
||||
## """
|
||||
## Doxygen Doxyfile source scanner. This should scan the Doxygen file and add
|
||||
## any files used to generate docs to the list of source files.
|
||||
## """
|
||||
## default_file_patterns = [
|
||||
## '*.c', '*.cc', '*.cxx', '*.cpp', '*.c++', '*.java', '*.ii', '*.ixx',
|
||||
## '*.ipp', '*.i++', '*.inl', '*.h', '*.hh ', '*.hxx', '*.hpp', '*.h++',
|
||||
## '*.idl', '*.odl', '*.cs', '*.php', '*.php3', '*.inc', '*.m', '*.mm',
|
||||
## '*.py',
|
||||
## ]
|
||||
##
|
||||
## default_exclude_patterns = [
|
||||
## '*~',
|
||||
## ]
|
||||
##
|
||||
## sources = []
|
||||
##
|
||||
## data = DoxyfileParse(node.get_contents())
|
||||
##
|
||||
## if data.get("RECURSIVE", "NO") == "YES":
|
||||
## recursive = True
|
||||
## else:
|
||||
## recursive = False
|
||||
##
|
||||
## file_patterns = data.get("FILE_PATTERNS", default_file_patterns)
|
||||
## exclude_patterns = data.get("EXCLUDE_PATTERNS", default_exclude_patterns)
|
||||
##
|
||||
## for node in data.get("INPUT", []):
|
||||
## if os.path.isfile(node):
|
||||
## sources.add(node)
|
||||
## elif os.path.isdir(node):
|
||||
## if recursive:
|
||||
## for root, dirs, files in os.walk(node):
|
||||
## for f in files:
|
||||
## filename = os.path.join(root, f)
|
||||
##
|
||||
## pattern_check = reduce(lambda x, y: x or bool(fnmatch(filename, y)), file_patterns, False)
|
||||
## exclude_check = reduce(lambda x, y: x and fnmatch(filename, y), exclude_patterns, True)
|
||||
##
|
||||
## if pattern_check and not exclude_check:
|
||||
## sources.append(filename)
|
||||
## else:
|
||||
## for pattern in file_patterns:
|
||||
## sources.extend(glob.glob("/".join([node, pattern])))
|
||||
## sources = map( lambda path: env.File(path), sources )
|
||||
## return sources
|
||||
##
|
||||
##
|
||||
##def DoxySourceScanCheck(node, env):
|
||||
## """Check if we should scan this file"""
|
||||
## return os.path.isfile(node.path)
|
||||
|
||||
def srcDistEmitter(source, target, env):
|
||||
## """Doxygen Doxyfile emitter"""
|
||||
## # possible output formats and their default values and output locations
|
||||
## output_formats = {
|
||||
## "HTML": ("YES", "html"),
|
||||
## "LATEX": ("YES", "latex"),
|
||||
## "RTF": ("NO", "rtf"),
|
||||
## "MAN": ("YES", "man"),
|
||||
## "XML": ("NO", "xml"),
|
||||
## }
|
||||
##
|
||||
## data = DoxyfileParse(source[0].get_contents())
|
||||
##
|
||||
## targets = []
|
||||
## out_dir = data.get("OUTPUT_DIRECTORY", ".")
|
||||
##
|
||||
## # add our output locations
|
||||
## for (k, v) in output_formats.items():
|
||||
## if data.get("GENERATE_" + k, v[0]) == "YES":
|
||||
## targets.append(env.Dir( os.path.join(out_dir, data.get(k + "_OUTPUT", v[1]))) )
|
||||
##
|
||||
## # don't clobber targets
|
||||
## for node in targets:
|
||||
## env.Precious(node)
|
||||
##
|
||||
## # set up cleaning stuff
|
||||
## for node in targets:
|
||||
## env.Clean(node, node)
|
||||
##
|
||||
## return (targets, source)
|
||||
return (target,source)
|
||||
|
||||
def generate(env):
|
||||
"""
|
||||
Add builders and construction variables for the
|
||||
SrcDist tool.
|
||||
"""
|
||||
## doxyfile_scanner = env.Scanner(
|
||||
## DoxySourceScan,
|
||||
## "DoxySourceScan",
|
||||
## scan_check = DoxySourceScanCheck,
|
||||
## )
|
||||
|
||||
if targz.exists(env):
|
||||
srcdist_builder = targz.makeBuilder( srcDistEmitter )
|
||||
|
||||
env['BUILDERS']['SrcDist'] = srcdist_builder
|
||||
|
||||
def exists(env):
|
||||
"""
|
||||
Make sure srcdist exists.
|
||||
"""
|
||||
return targz.exists(env)
|
@ -1,79 +0,0 @@
|
||||
import re
|
||||
from SCons.Script import * # the usual scons stuff you get in a SConscript
|
||||
|
||||
def generate(env):
|
||||
"""
|
||||
Add builders and construction variables for the
|
||||
SubstInFile tool.
|
||||
|
||||
Adds SubstInFile builder, which substitutes the keys->values of SUBST_DICT
|
||||
from the source to the target.
|
||||
The values of SUBST_DICT first have any construction variables expanded
|
||||
(its keys are not expanded).
|
||||
If a value of SUBST_DICT is a python callable function, it is called and
|
||||
the result is expanded as the value.
|
||||
If there's more than one source and more than one target, each target gets
|
||||
substituted from the corresponding source.
|
||||
"""
|
||||
def do_subst_in_file(targetfile, sourcefile, dict):
|
||||
"""Replace all instances of the keys of dict with their values.
|
||||
For example, if dict is {'%VERSION%': '1.2345', '%BASE%': 'MyProg'},
|
||||
then all instances of %VERSION% in the file will be replaced with 1.2345 etc.
|
||||
"""
|
||||
try:
|
||||
f = open(sourcefile, 'rb')
|
||||
contents = f.read()
|
||||
f.close()
|
||||
except:
|
||||
raise SCons.Errors.UserError, "Can't read source file %s"%sourcefile
|
||||
for (k,v) in dict.items():
|
||||
contents = re.sub(k, v, contents)
|
||||
try:
|
||||
f = open(targetfile, 'wb')
|
||||
f.write(contents)
|
||||
f.close()
|
||||
except:
|
||||
raise SCons.Errors.UserError, "Can't write target file %s"%targetfile
|
||||
return 0 # success
|
||||
|
||||
def subst_in_file(target, source, env):
|
||||
if not env.has_key('SUBST_DICT'):
|
||||
raise SCons.Errors.UserError, "SubstInFile requires SUBST_DICT to be set."
|
||||
d = dict(env['SUBST_DICT']) # copy it
|
||||
for (k,v) in d.items():
|
||||
if callable(v):
|
||||
d[k] = env.subst(v()).replace('\\','\\\\')
|
||||
elif SCons.Util.is_String(v):
|
||||
d[k] = env.subst(v).replace('\\','\\\\')
|
||||
else:
|
||||
raise SCons.Errors.UserError, "SubstInFile: key %s: %s must be a string or callable"%(k, repr(v))
|
||||
for (t,s) in zip(target, source):
|
||||
return do_subst_in_file(str(t), str(s), d)
|
||||
|
||||
def subst_in_file_string(target, source, env):
|
||||
"""This is what gets printed on the console."""
|
||||
return '\n'.join(['Substituting vars from %s into %s'%(str(s), str(t))
|
||||
for (t,s) in zip(target, source)])
|
||||
|
||||
def subst_emitter(target, source, env):
|
||||
"""Add dependency from substituted SUBST_DICT to target.
|
||||
Returns original target, source tuple unchanged.
|
||||
"""
|
||||
d = env['SUBST_DICT'].copy() # copy it
|
||||
for (k,v) in d.items():
|
||||
if callable(v):
|
||||
d[k] = env.subst(v())
|
||||
elif SCons.Util.is_String(v):
|
||||
d[k]=env.subst(v)
|
||||
Depends(target, SCons.Node.Python.Value(d))
|
||||
return target, source
|
||||
|
||||
## env.Append(TOOLS = 'substinfile') # this should be automaticaly done by Scons ?!?
|
||||
subst_action = SCons.Action.Action( subst_in_file, subst_in_file_string )
|
||||
env['BUILDERS']['SubstInFile'] = Builder(action=subst_action, emitter=subst_emitter)
|
||||
|
||||
def exists(env):
|
||||
"""
|
||||
Make sure tool exists.
|
||||
"""
|
||||
return True
|
@ -1,82 +0,0 @@
|
||||
"""tarball
|
||||
|
||||
Tool-specific initialization for tarball.
|
||||
|
||||
"""
|
||||
|
||||
## Commands to tackle a command based implementation:
|
||||
##to unpack on the fly...
|
||||
##gunzip < FILE.tar.gz | tar xvf -
|
||||
##to pack on the fly...
|
||||
##tar cvf - FILE-LIST | gzip -c > FILE.tar.gz
|
||||
|
||||
import os.path
|
||||
|
||||
import SCons.Builder
|
||||
import SCons.Node.FS
|
||||
import SCons.Util
|
||||
|
||||
try:
|
||||
import gzip
|
||||
import tarfile
|
||||
internal_targz = 1
|
||||
except ImportError:
|
||||
internal_targz = 0
|
||||
|
||||
TARGZ_DEFAULT_COMPRESSION_LEVEL = 9
|
||||
|
||||
if internal_targz:
|
||||
def targz(target, source, env):
|
||||
def archive_name( path ):
|
||||
path = os.path.normpath( os.path.abspath( path ) )
|
||||
common_path = os.path.commonprefix( (base_dir, path) )
|
||||
archive_name = path[len(common_path):]
|
||||
return archive_name
|
||||
|
||||
def visit(tar, dirname, names):
|
||||
for name in names:
|
||||
path = os.path.join(dirname, name)
|
||||
if os.path.isfile(path):
|
||||
tar.add(path, archive_name(path) )
|
||||
compression = env.get('TARGZ_COMPRESSION_LEVEL',TARGZ_DEFAULT_COMPRESSION_LEVEL)
|
||||
base_dir = os.path.normpath( env.get('TARGZ_BASEDIR', env.Dir('.')).abspath )
|
||||
target_path = str(target[0])
|
||||
fileobj = gzip.GzipFile( target_path, 'wb', compression )
|
||||
tar = tarfile.TarFile(os.path.splitext(target_path)[0], 'w', fileobj)
|
||||
for source in source:
|
||||
source_path = str(source)
|
||||
if source.isdir():
|
||||
os.path.walk(source_path, visit, tar)
|
||||
else:
|
||||
tar.add(source_path, archive_name(source_path) ) # filename, arcname
|
||||
tar.close()
|
||||
|
||||
targzAction = SCons.Action.Action(targz, varlist=['TARGZ_COMPRESSION_LEVEL','TARGZ_BASEDIR'])
|
||||
|
||||
def makeBuilder( emitter = None ):
|
||||
return SCons.Builder.Builder(action = SCons.Action.Action('$TARGZ_COM', '$TARGZ_COMSTR'),
|
||||
source_factory = SCons.Node.FS.Entry,
|
||||
source_scanner = SCons.Defaults.DirScanner,
|
||||
suffix = '$TARGZ_SUFFIX',
|
||||
multi = 1)
|
||||
TarGzBuilder = makeBuilder()
|
||||
|
||||
def generate(env):
|
||||
"""Add Builders and construction variables for zip to an Environment.
|
||||
The following environnement variables may be set:
|
||||
TARGZ_COMPRESSION_LEVEL: integer, [0-9]. 0: no compression, 9: best compression (same as gzip compression level).
|
||||
TARGZ_BASEDIR: base-directory used to determine archive name (this allow archive name to be relative
|
||||
to something other than top-dir).
|
||||
"""
|
||||
env['BUILDERS']['TarGz'] = TarGzBuilder
|
||||
env['TARGZ_COM'] = targzAction
|
||||
env['TARGZ_COMPRESSION_LEVEL'] = TARGZ_DEFAULT_COMPRESSION_LEVEL # range 0-9
|
||||
env['TARGZ_SUFFIX'] = '.tar.gz'
|
||||
env['TARGZ_BASEDIR'] = env.Dir('.') # Sources archive name are made relative to that directory.
|
||||
else:
|
||||
def generate(env):
|
||||
pass
|
||||
|
||||
|
||||
def exists(env):
|
||||
return internal_targz
|
5
src/CMakeLists.txt
Normal file
5
src/CMakeLists.txt
Normal file
@ -0,0 +1,5 @@
|
||||
add_subdirectory(lib_json)
|
||||
if(JSONCPP_WITH_TESTS)
|
||||
add_subdirectory(jsontestrunner)
|
||||
add_subdirectory(test_lib_json)
|
||||
endif()
|
51
src/jsontestrunner/CMakeLists.txt
Normal file
51
src/jsontestrunner/CMakeLists.txt
Normal file
@ -0,0 +1,51 @@
|
||||
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
|
||||
# The new Python3 module is much more robust than the previous PythonInterp
|
||||
find_package(Python3 COMPONENTS Interpreter)
|
||||
# Set variables for backwards compatibility with cmake < 3.12.0
|
||||
set(PYTHONINTERP_FOUND ${Python3_Interpreter_FOUND})
|
||||
set(PYTHON_EXECUTABLE ${Python3_EXECUTABLE})
|
||||
else()
|
||||
set(Python_ADDITIONAL_VERSIONS 3.8)
|
||||
find_package(PythonInterp 3)
|
||||
endif()
|
||||
|
||||
add_executable(jsontestrunner_exe
|
||||
main.cpp
|
||||
)
|
||||
|
||||
if(BUILD_SHARED_LIBS)
|
||||
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
|
||||
add_compile_definitions( JSON_DLL )
|
||||
else()
|
||||
add_definitions(-DJSON_DLL)
|
||||
endif()
|
||||
target_link_libraries(jsontestrunner_exe jsoncpp_lib)
|
||||
else()
|
||||
target_link_libraries(jsontestrunner_exe jsoncpp_static)
|
||||
endif()
|
||||
|
||||
set_target_properties(jsontestrunner_exe PROPERTIES OUTPUT_NAME jsontestrunner_exe)
|
||||
|
||||
if(PYTHONINTERP_FOUND)
|
||||
# Run end to end parser/writer tests
|
||||
set(TEST_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../test)
|
||||
set(RUNJSONTESTS_PATH ${TEST_DIR}/runjsontests.py)
|
||||
|
||||
# Run unit tests in post-build
|
||||
# (default cmake workflow hides away the test result into a file, resulting in poor dev workflow?!?)
|
||||
add_custom_target(jsoncpp_readerwriter_tests
|
||||
"${PYTHON_EXECUTABLE}" -B "${RUNJSONTESTS_PATH}" $<TARGET_FILE:jsontestrunner_exe> "${TEST_DIR}/data"
|
||||
DEPENDS jsontestrunner_exe jsoncpp_test
|
||||
)
|
||||
add_custom_target(jsoncpp_check DEPENDS jsoncpp_readerwriter_tests)
|
||||
|
||||
## Create tests for dashboard submission, allows easy review of CI results https://my.cdash.org/index.php?project=jsoncpp
|
||||
add_test(NAME jsoncpp_readerwriter
|
||||
COMMAND "${PYTHON_EXECUTABLE}" -B "${RUNJSONTESTS_PATH}" $<TARGET_FILE:jsontestrunner_exe> "${TEST_DIR}/data"
|
||||
WORKING_DIRECTORY "${TEST_DIR}/data"
|
||||
)
|
||||
add_test(NAME jsoncpp_readerwriter_json_checker
|
||||
COMMAND "${PYTHON_EXECUTABLE}" -B "${RUNJSONTESTS_PATH}" --with-json-checker $<TARGET_FILE:jsontestrunner_exe> "${TEST_DIR}/data"
|
||||
WORKING_DIRECTORY "${TEST_DIR}/data"
|
||||
)
|
||||
endif()
|
@ -1,233 +1,346 @@
|
||||
#include <json/json.h>
|
||||
#include <algorithm> // sort
|
||||
#include <stdio.h>
|
||||
// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
|
||||
// Distributed under MIT license, or public domain if desired and
|
||||
// recognized in your jurisdiction.
|
||||
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1310
|
||||
# pragma warning( disable: 4996 ) // disable fopen deprecation warning
|
||||
#if defined(__GNUC__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
#elif defined(_MSC_VER)
|
||||
#pragma warning(disable : 4996)
|
||||
#endif
|
||||
|
||||
static std::string
|
||||
readInputTestFile( const char *path )
|
||||
{
|
||||
FILE *file = fopen( path, "rb" );
|
||||
if ( !file )
|
||||
return std::string("");
|
||||
fseek( file, 0, SEEK_END );
|
||||
long size = ftell( file );
|
||||
fseek( file, 0, SEEK_SET );
|
||||
std::string text;
|
||||
char *buffer = new char[size+1];
|
||||
buffer[size] = 0;
|
||||
if ( fread( buffer, 1, size, file ) == (unsigned long)size )
|
||||
text = buffer;
|
||||
fclose( file );
|
||||
delete[] buffer;
|
||||
return text;
|
||||
/* This executable is used for testing parser/writer using real JSON files.
|
||||
*/
|
||||
|
||||
#include <algorithm> // sort
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
#include <json/json.h>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
|
||||
struct Options {
|
||||
Json::String path;
|
||||
Json::Features features;
|
||||
bool parseOnly;
|
||||
using writeFuncType = Json::String (*)(Json::Value const&);
|
||||
writeFuncType write;
|
||||
};
|
||||
|
||||
static Json::String normalizeFloatingPointStr(double value) {
|
||||
char buffer[32];
|
||||
jsoncpp_snprintf(buffer, sizeof(buffer), "%.16g", value);
|
||||
buffer[sizeof(buffer) - 1] = 0;
|
||||
Json::String s(buffer);
|
||||
Json::String::size_type index = s.find_last_of("eE");
|
||||
if (index != Json::String::npos) {
|
||||
Json::String::size_type hasSign =
|
||||
(s[index + 1] == '+' || s[index + 1] == '-') ? 1 : 0;
|
||||
Json::String::size_type exponentStartIndex = index + 1 + hasSign;
|
||||
Json::String normalized = s.substr(0, exponentStartIndex);
|
||||
Json::String::size_type indexDigit =
|
||||
s.find_first_not_of('0', exponentStartIndex);
|
||||
Json::String exponent = "0";
|
||||
if (indexDigit != Json::String::npos) // There is an exponent different
|
||||
// from 0
|
||||
{
|
||||
exponent = s.substr(indexDigit);
|
||||
}
|
||||
return normalized + exponent;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
printValueTree( FILE *fout, Json::Value &value, const std::string &path = "." )
|
||||
{
|
||||
switch ( value.type() )
|
||||
{
|
||||
case Json::nullValue:
|
||||
fprintf( fout, "%s=null\n", path.c_str() );
|
||||
break;
|
||||
case Json::intValue:
|
||||
fprintf( fout, "%s=%d\n", path.c_str(), value.asInt() );
|
||||
break;
|
||||
case Json::uintValue:
|
||||
fprintf( fout, "%s=%u\n", path.c_str(), value.asUInt() );
|
||||
break;
|
||||
case Json::realValue:
|
||||
fprintf( fout, "%s=%.16g\n", path.c_str(), value.asDouble() );
|
||||
break;
|
||||
case Json::stringValue:
|
||||
fprintf( fout, "%s=\"%s\"\n", path.c_str(), value.asString().c_str() );
|
||||
break;
|
||||
case Json::booleanValue:
|
||||
fprintf( fout, "%s=%s\n", path.c_str(), value.asBool() ? "true" : "false" );
|
||||
break;
|
||||
case Json::arrayValue:
|
||||
{
|
||||
fprintf( fout, "%s=[]\n", path.c_str() );
|
||||
int size = value.size();
|
||||
for ( int index =0; index < size; ++index )
|
||||
{
|
||||
static char buffer[16];
|
||||
sprintf( buffer, "[%d]", index );
|
||||
printValueTree( fout, value[index], path + buffer );
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Json::objectValue:
|
||||
{
|
||||
fprintf( fout, "%s={}\n", path.c_str() );
|
||||
Json::Value::Members members( value.getMemberNames() );
|
||||
std::sort( members.begin(), members.end() );
|
||||
std::string suffix = *(path.end()-1) == '.' ? "" : ".";
|
||||
for ( Json::Value::Members::iterator it = members.begin();
|
||||
it != members.end();
|
||||
++it )
|
||||
{
|
||||
const std::string &name = *it;
|
||||
printValueTree( fout, value[name], path + suffix + name );
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
static Json::String readInputTestFile(const char* path) {
|
||||
FILE* file = fopen(path, "rb");
|
||||
if (!file)
|
||||
return "";
|
||||
fseek(file, 0, SEEK_END);
|
||||
auto const size = ftell(file);
|
||||
auto const usize = static_cast<size_t>(size);
|
||||
fseek(file, 0, SEEK_SET);
|
||||
auto buffer = new char[size + 1];
|
||||
buffer[size] = 0;
|
||||
Json::String text;
|
||||
if (fread(buffer, 1, usize, file) == usize)
|
||||
text = buffer;
|
||||
fclose(file);
|
||||
delete[] buffer;
|
||||
return text;
|
||||
}
|
||||
|
||||
static void printValueTree(FILE* fout, Json::Value& value,
|
||||
const Json::String& path = ".") {
|
||||
if (value.hasComment(Json::commentBefore)) {
|
||||
fprintf(fout, "%s\n", value.getComment(Json::commentBefore).c_str());
|
||||
}
|
||||
switch (value.type()) {
|
||||
case Json::nullValue:
|
||||
fprintf(fout, "%s=null\n", path.c_str());
|
||||
break;
|
||||
case Json::intValue:
|
||||
fprintf(fout, "%s=%s\n", path.c_str(),
|
||||
Json::valueToString(value.asLargestInt()).c_str());
|
||||
break;
|
||||
case Json::uintValue:
|
||||
fprintf(fout, "%s=%s\n", path.c_str(),
|
||||
Json::valueToString(value.asLargestUInt()).c_str());
|
||||
break;
|
||||
case Json::realValue:
|
||||
fprintf(fout, "%s=%s\n", path.c_str(),
|
||||
normalizeFloatingPointStr(value.asDouble()).c_str());
|
||||
break;
|
||||
case Json::stringValue:
|
||||
fprintf(fout, "%s=\"%s\"\n", path.c_str(), value.asString().c_str());
|
||||
break;
|
||||
case Json::booleanValue:
|
||||
fprintf(fout, "%s=%s\n", path.c_str(), value.asBool() ? "true" : "false");
|
||||
break;
|
||||
case Json::arrayValue: {
|
||||
fprintf(fout, "%s=[]\n", path.c_str());
|
||||
Json::ArrayIndex size = value.size();
|
||||
for (Json::ArrayIndex index = 0; index < size; ++index) {
|
||||
static char buffer[16];
|
||||
jsoncpp_snprintf(buffer, sizeof(buffer), "[%u]", index);
|
||||
printValueTree(fout, value[index], path + buffer);
|
||||
}
|
||||
} break;
|
||||
case Json::objectValue: {
|
||||
fprintf(fout, "%s={}\n", path.c_str());
|
||||
Json::Value::Members members(value.getMemberNames());
|
||||
std::sort(members.begin(), members.end());
|
||||
Json::String suffix = *(path.end() - 1) == '.' ? "" : ".";
|
||||
for (const auto& name : members) {
|
||||
printValueTree(fout, value[name], path + suffix + name);
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
static int
|
||||
parseAndSaveValueTree( const std::string &input,
|
||||
const std::string &actual,
|
||||
const std::string &kind,
|
||||
Json::Value &root,
|
||||
const Json::Features &features,
|
||||
bool parseOnly )
|
||||
{
|
||||
Json::Reader reader( features );
|
||||
bool parsingSuccessful = reader.parse( input, root );
|
||||
if ( !parsingSuccessful )
|
||||
{
|
||||
printf( "Failed to parse %s file: \n%s\n",
|
||||
kind.c_str(),
|
||||
reader.getFormatedErrorMessages().c_str() );
|
||||
if (value.hasComment(Json::commentAfter)) {
|
||||
fprintf(fout, "%s\n", value.getComment(Json::commentAfter).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
static int parseAndSaveValueTree(const Json::String& input,
|
||||
const Json::String& actual,
|
||||
const Json::String& kind,
|
||||
const Json::Features& features, bool parseOnly,
|
||||
Json::Value* root, bool use_legacy) {
|
||||
if (!use_legacy) {
|
||||
Json::CharReaderBuilder builder;
|
||||
|
||||
builder.settings_["allowComments"] = features.allowComments_;
|
||||
builder.settings_["strictRoot"] = features.strictRoot_;
|
||||
builder.settings_["allowDroppedNullPlaceholders"] =
|
||||
features.allowDroppedNullPlaceholders_;
|
||||
builder.settings_["allowNumericKeys"] = features.allowNumericKeys_;
|
||||
|
||||
std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
|
||||
Json::String errors;
|
||||
const bool parsingSuccessful =
|
||||
reader->parse(input.data(), input.data() + input.size(), root, &errors);
|
||||
|
||||
if (!parsingSuccessful) {
|
||||
std::cerr << "Failed to parse " << kind << " file: " << std::endl
|
||||
<< errors << std::endl;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !parseOnly )
|
||||
{
|
||||
FILE *factual = fopen( actual.c_str(), "wt" );
|
||||
if ( !factual )
|
||||
{
|
||||
printf( "Failed to create %s actual file.\n", kind.c_str() );
|
||||
return 2;
|
||||
}
|
||||
printValueTree( factual, root );
|
||||
fclose( factual );
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
// We may instead check the legacy implementation (to ensure it doesn't
|
||||
// randomly get broken).
|
||||
} else {
|
||||
Json::Reader reader(features);
|
||||
const bool parsingSuccessful =
|
||||
reader.parse(input.data(), input.data() + input.size(), *root);
|
||||
if (!parsingSuccessful) {
|
||||
std::cerr << "Failed to parse " << kind << " file: " << std::endl
|
||||
<< reader.getFormatedErrorMessages() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
rewriteValueTree( const std::string &rewritePath,
|
||||
const Json::Value &root,
|
||||
std::string &rewrite )
|
||||
{
|
||||
//Json::FastWriter writer;
|
||||
//writer.enableYAMLCompatibility();
|
||||
Json::StyledWriter writer;
|
||||
rewrite = writer.write( root );
|
||||
FILE *fout = fopen( rewritePath.c_str(), "wt" );
|
||||
if ( !fout )
|
||||
{
|
||||
printf( "Failed to create rewrite file: %s\n", rewritePath.c_str() );
|
||||
if (!parseOnly) {
|
||||
FILE* factual = fopen(actual.c_str(), "wt");
|
||||
if (!factual) {
|
||||
std::cerr << "Failed to create '" << kind << "' actual file."
|
||||
<< std::endl;
|
||||
return 2;
|
||||
}
|
||||
fprintf( fout, "%s\n", rewrite.c_str() );
|
||||
fclose( fout );
|
||||
return 0;
|
||||
}
|
||||
printValueTree(factual, *root);
|
||||
fclose(factual);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
// static Json::String useFastWriter(Json::Value const& root) {
|
||||
// Json::FastWriter writer;
|
||||
// writer.enableYAMLCompatibility();
|
||||
// return writer.write(root);
|
||||
// }
|
||||
static Json::String useStyledWriter(Json::Value const& root) {
|
||||
Json::StyledWriter writer;
|
||||
return writer.write(root);
|
||||
}
|
||||
static Json::String useStyledStreamWriter(Json::Value const& root) {
|
||||
Json::StyledStreamWriter writer;
|
||||
Json::OStringStream sout;
|
||||
writer.write(sout, root);
|
||||
return sout.str();
|
||||
}
|
||||
static Json::String useBuiltStyledStreamWriter(Json::Value const& root) {
|
||||
Json::StreamWriterBuilder builder;
|
||||
return Json::writeString(builder, root);
|
||||
}
|
||||
static int rewriteValueTree(const Json::String& rewritePath,
|
||||
const Json::Value& root,
|
||||
Options::writeFuncType write,
|
||||
Json::String* rewrite) {
|
||||
*rewrite = write(root);
|
||||
FILE* fout = fopen(rewritePath.c_str(), "wt");
|
||||
if (!fout) {
|
||||
std::cerr << "Failed to create rewrite file: " << rewritePath << std::endl;
|
||||
return 2;
|
||||
}
|
||||
fprintf(fout, "%s\n", rewrite->c_str());
|
||||
fclose(fout);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static std::string
|
||||
removeSuffix( const std::string &path,
|
||||
const std::string &extension )
|
||||
{
|
||||
if ( extension.length() >= path.length() )
|
||||
return std::string("");
|
||||
std::string suffix = path.substr( path.length() - extension.length() );
|
||||
if ( suffix != extension )
|
||||
return std::string("");
|
||||
return path.substr( 0, path.length() - extension.length() );
|
||||
static Json::String removeSuffix(const Json::String& path,
|
||||
const Json::String& extension) {
|
||||
if (extension.length() >= path.length())
|
||||
return Json::String("");
|
||||
Json::String suffix = path.substr(path.length() - extension.length());
|
||||
if (suffix != extension)
|
||||
return Json::String("");
|
||||
return path.substr(0, path.length() - extension.length());
|
||||
}
|
||||
|
||||
static int
|
||||
printUsage( const char *argv[] )
|
||||
{
|
||||
printf( "Usage: %s [--strict] input-json-file", argv[0] );
|
||||
return 3;
|
||||
static void printConfig() {
|
||||
// Print the configuration used to compile JsonCpp
|
||||
#if defined(JSON_NO_INT64)
|
||||
std::cout << "JSON_NO_INT64=1" << std::endl;
|
||||
#else
|
||||
std::cout << "JSON_NO_INT64=0" << std::endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
parseCommandLine( int argc, const char *argv[],
|
||||
Json::Features &features, std::string &path,
|
||||
bool &parseOnly )
|
||||
{
|
||||
parseOnly = false;
|
||||
if ( argc < 2 )
|
||||
{
|
||||
return printUsage( argv );
|
||||
}
|
||||
|
||||
int index = 1;
|
||||
if ( std::string(argv[1]) == "--json-checker" )
|
||||
{
|
||||
features = Json::Features::strictMode();
|
||||
parseOnly = true;
|
||||
++index;
|
||||
}
|
||||
|
||||
if ( index == argc || index + 1 < argc )
|
||||
{
|
||||
return printUsage( argv );
|
||||
}
|
||||
|
||||
path = argv[index];
|
||||
return 0;
|
||||
static int printUsage(const char* argv[]) {
|
||||
std::cout << "Usage: " << argv[0] << " [--strict] input-json-file"
|
||||
<< std::endl;
|
||||
return 3;
|
||||
}
|
||||
|
||||
static int parseCommandLine(int argc, const char* argv[], Options* opts) {
|
||||
opts->parseOnly = false;
|
||||
opts->write = &useStyledWriter;
|
||||
if (argc < 2) {
|
||||
return printUsage(argv);
|
||||
}
|
||||
int index = 1;
|
||||
if (Json::String(argv[index]) == "--parse-only") {
|
||||
opts->parseOnly = true;
|
||||
++index;
|
||||
}
|
||||
if (Json::String(argv[index]) == "--strict") {
|
||||
opts->features = Json::Features::strictMode();
|
||||
++index;
|
||||
}
|
||||
if (Json::String(argv[index]) == "--json-config") {
|
||||
printConfig();
|
||||
return 3;
|
||||
}
|
||||
if (Json::String(argv[index]) == "--json-writer") {
|
||||
++index;
|
||||
Json::String const writerName(argv[index++]);
|
||||
if (writerName == "StyledWriter") {
|
||||
opts->write = &useStyledWriter;
|
||||
} else if (writerName == "StyledStreamWriter") {
|
||||
opts->write = &useStyledStreamWriter;
|
||||
} else if (writerName == "BuiltStyledStreamWriter") {
|
||||
opts->write = &useBuiltStyledStreamWriter;
|
||||
} else {
|
||||
std::cerr << "Unknown '--json-writer' " << writerName << std::endl;
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
if (index == argc || index + 1 < argc) {
|
||||
return printUsage(argv);
|
||||
}
|
||||
opts->path = argv[index];
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main( int argc, const char *argv[] )
|
||||
{
|
||||
std::string path;
|
||||
Json::Features features;
|
||||
bool parseOnly;
|
||||
int exitCode = parseCommandLine( argc, argv, features, path, parseOnly );
|
||||
if ( exitCode != 0 )
|
||||
{
|
||||
static int runTest(Options const& opts, bool use_legacy) {
|
||||
int exitCode = 0;
|
||||
|
||||
Json::String input = readInputTestFile(opts.path.c_str());
|
||||
if (input.empty()) {
|
||||
std::cerr << "Invalid input file: " << opts.path << std::endl;
|
||||
return 3;
|
||||
}
|
||||
|
||||
Json::String basePath = removeSuffix(opts.path, ".json");
|
||||
if (!opts.parseOnly && basePath.empty()) {
|
||||
std::cerr << "Bad input path '" << opts.path
|
||||
<< "'. Must end with '.expected'" << std::endl;
|
||||
return 3;
|
||||
}
|
||||
|
||||
Json::String const actualPath = basePath + ".actual";
|
||||
Json::String const rewritePath = basePath + ".rewrite";
|
||||
Json::String const rewriteActualPath = basePath + ".actual-rewrite";
|
||||
|
||||
Json::Value root;
|
||||
exitCode = parseAndSaveValueTree(input, actualPath, "input", opts.features,
|
||||
opts.parseOnly, &root, use_legacy);
|
||||
if (exitCode || opts.parseOnly) {
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
Json::String rewrite;
|
||||
exitCode = rewriteValueTree(rewritePath, root, opts.write, &rewrite);
|
||||
if (exitCode) {
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
Json::Value rewriteRoot;
|
||||
exitCode = parseAndSaveValueTree(rewrite, rewriteActualPath, "rewrite",
|
||||
opts.features, opts.parseOnly, &rewriteRoot,
|
||||
use_legacy);
|
||||
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
int main(int argc, const char* argv[]) {
|
||||
Options opts;
|
||||
try {
|
||||
int exitCode = parseCommandLine(argc, argv, &opts);
|
||||
if (exitCode != 0) {
|
||||
std::cerr << "Failed to parse command-line." << std::endl;
|
||||
return exitCode;
|
||||
}
|
||||
}
|
||||
|
||||
std::string input = readInputTestFile( path.c_str() );
|
||||
if ( input.empty() )
|
||||
{
|
||||
printf( "Failed to read input or empty input: %s\n", path.c_str() );
|
||||
return 3;
|
||||
}
|
||||
const int modern_return_code = runTest(opts, false);
|
||||
if (modern_return_code) {
|
||||
return modern_return_code;
|
||||
}
|
||||
|
||||
std::string basePath = removeSuffix( argv[1], ".json" );
|
||||
if ( !parseOnly && basePath.empty() )
|
||||
{
|
||||
printf( "Bad input path. Path does not end with '.expected':\n%s\n", path.c_str() );
|
||||
return 3;
|
||||
}
|
||||
|
||||
std::string actualPath = basePath + ".actual";
|
||||
std::string rewritePath = basePath + ".rewrite";
|
||||
std::string rewriteActualPath = basePath + ".actual-rewrite";
|
||||
|
||||
Json::Value root;
|
||||
exitCode = parseAndSaveValueTree( input, actualPath, "input", root, features, parseOnly );
|
||||
if ( exitCode == 0 && !parseOnly )
|
||||
{
|
||||
std::string rewrite;
|
||||
exitCode = rewriteValueTree( rewritePath, root, rewrite );
|
||||
if ( exitCode == 0 )
|
||||
{
|
||||
Json::Value rewriteRoot;
|
||||
exitCode = parseAndSaveValueTree( rewrite, rewriteActualPath,
|
||||
"rewrite", rewriteRoot, features, parseOnly );
|
||||
}
|
||||
}
|
||||
|
||||
return exitCode;
|
||||
const std::string filename =
|
||||
opts.path.substr(opts.path.find_last_of("\\/") + 1);
|
||||
const bool should_run_legacy = (filename.rfind("legacy_", 0) == 0);
|
||||
if (should_run_legacy) {
|
||||
return runTest(opts, true);
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr << "Unhandled exception:" << std::endl << e.what() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
@ -1,9 +0,0 @@
|
||||
Import( 'env_testing buildJSONTests' )
|
||||
|
||||
buildJSONTests( env_testing, Split( """
|
||||
main.cpp
|
||||
""" ),
|
||||
'jsontestrunner' )
|
||||
|
||||
# For 'check' to work, 'libs' must be built first.
|
||||
env_testing.Depends('jsontestrunner', '#libs')
|
205
src/lib_json/CMakeLists.txt
Normal file
205
src/lib_json/CMakeLists.txt
Normal file
@ -0,0 +1,205 @@
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.1.2)
|
||||
#-Werror=* was introduced -after- GCC 4.1.2
|
||||
add_compile_options("-Werror=strict-aliasing")
|
||||
endif()
|
||||
|
||||
include(CheckIncludeFileCXX)
|
||||
include(CheckTypeSize)
|
||||
include(CheckStructHasMember)
|
||||
include(CheckCXXSymbolExists)
|
||||
|
||||
check_include_file_cxx(clocale HAVE_CLOCALE)
|
||||
check_cxx_symbol_exists(localeconv clocale HAVE_LOCALECONV)
|
||||
|
||||
set(CMAKE_EXTRA_INCLUDE_FILES clocale)
|
||||
check_type_size(lconv LCONV_SIZE LANGUAGE CXX)
|
||||
unset(CMAKE_EXTRA_INCLUDE_FILES)
|
||||
check_struct_has_member(lconv decimal_point clocale HAVE_DECIMAL_POINT LANGUAGE CXX)
|
||||
|
||||
if(NOT (HAVE_CLOCALE AND HAVE_LCONV_SIZE AND HAVE_DECIMAL_POINT AND HAVE_LOCALECONV))
|
||||
message(WARNING "Locale functionality is not supported")
|
||||
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
|
||||
add_compile_definitions(JSONCPP_NO_LOCALE_SUPPORT)
|
||||
else()
|
||||
add_definitions(-DJSONCPP_NO_LOCALE_SUPPORT)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(JSONCPP_INCLUDE_DIR ../../include)
|
||||
|
||||
set(PUBLIC_HEADERS
|
||||
${JSONCPP_INCLUDE_DIR}/json/config.h
|
||||
${JSONCPP_INCLUDE_DIR}/json/forwards.h
|
||||
${JSONCPP_INCLUDE_DIR}/json/json_features.h
|
||||
${JSONCPP_INCLUDE_DIR}/json/value.h
|
||||
${JSONCPP_INCLUDE_DIR}/json/reader.h
|
||||
${JSONCPP_INCLUDE_DIR}/json/version.h
|
||||
${JSONCPP_INCLUDE_DIR}/json/writer.h
|
||||
${JSONCPP_INCLUDE_DIR}/json/assertions.h
|
||||
)
|
||||
|
||||
source_group("Public API" FILES ${PUBLIC_HEADERS})
|
||||
|
||||
set(JSONCPP_SOURCES
|
||||
json_tool.h
|
||||
json_reader.cpp
|
||||
json_valueiterator.inl
|
||||
json_value.cpp
|
||||
json_writer.cpp
|
||||
)
|
||||
|
||||
# Install instructions for this target
|
||||
if(JSONCPP_WITH_CMAKE_PACKAGE)
|
||||
set(INSTALL_EXPORT EXPORT jsoncpp)
|
||||
else()
|
||||
set(INSTALL_EXPORT)
|
||||
endif()
|
||||
|
||||
# Specify compiler features required when compiling a given target.
|
||||
# See https://cmake.org/cmake/help/v3.1/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.html#prop_gbl:CMAKE_CXX_KNOWN_FEATURES
|
||||
# for complete list of features available
|
||||
list(APPEND REQUIRED_FEATURES
|
||||
cxx_std_11 # Compiler mode is aware of C++ 11.
|
||||
#MSVC 1900 cxx_alignas # Alignment control alignas, as defined in N2341.
|
||||
#MSVC 1900 cxx_alignof # Alignment control alignof, as defined in N2341.
|
||||
#MSVC 1900 cxx_attributes # Generic attributes, as defined in N2761.
|
||||
cxx_auto_type # Automatic type deduction, as defined in N1984.
|
||||
#MSVC 1900 cxx_constexpr # Constant expressions, as defined in N2235.
|
||||
cxx_decltype # Decltype, as defined in N2343.
|
||||
cxx_default_function_template_args # Default template arguments for function templates, as defined in DR226
|
||||
cxx_defaulted_functions # Defaulted functions, as defined in N2346.
|
||||
#MSVC 1900 cxx_defaulted_move_initializers # Defaulted move initializers, as defined in N3053.
|
||||
cxx_delegating_constructors # Delegating constructors, as defined in N1986.
|
||||
#MSVC 1900 cxx_deleted_functions # Deleted functions, as defined in N2346.
|
||||
cxx_enum_forward_declarations # Enum forward declarations, as defined in N2764.
|
||||
cxx_explicit_conversions # Explicit conversion operators, as defined in N2437.
|
||||
cxx_extended_friend_declarations # Extended friend declarations, as defined in N1791.
|
||||
cxx_extern_templates # Extern templates, as defined in N1987.
|
||||
cxx_final # Override control final keyword, as defined in N2928, N3206 and N3272.
|
||||
#MSVC 1900 cxx_func_identifier # Predefined __func__ identifier, as defined in N2340.
|
||||
#MSVC 1900 cxx_generalized_initializers # Initializer lists, as defined in N2672.
|
||||
#MSVC 1900 cxx_inheriting_constructors # Inheriting constructors, as defined in N2540.
|
||||
#MSVC 1900 cxx_inline_namespaces # Inline namespaces, as defined in N2535.
|
||||
cxx_lambdas # Lambda functions, as defined in N2927.
|
||||
#MSVC 1900 cxx_local_type_template_args # Local and unnamed types as template arguments, as defined in N2657.
|
||||
cxx_long_long_type # long long type, as defined in N1811.
|
||||
#MSVC 1900 cxx_noexcept # Exception specifications, as defined in N3050.
|
||||
#MSVC 1900 cxx_nonstatic_member_init # Non-static data member initialization, as defined in N2756.
|
||||
cxx_nullptr # Null pointer, as defined in N2431.
|
||||
cxx_override # Override control override keyword, as defined in N2928, N3206 and N3272.
|
||||
cxx_range_for # Range-based for, as defined in N2930.
|
||||
cxx_raw_string_literals # Raw string literals, as defined in N2442.
|
||||
#MSVC 1900 cxx_reference_qualified_functions # Reference qualified functions, as defined in N2439.
|
||||
cxx_right_angle_brackets # Right angle bracket parsing, as defined in N1757.
|
||||
cxx_rvalue_references # R-value references, as defined in N2118.
|
||||
#MSVC 1900 cxx_sizeof_member # Size of non-static data members, as defined in N2253.
|
||||
cxx_static_assert # Static assert, as defined in N1720.
|
||||
cxx_strong_enums # Strongly typed enums, as defined in N2347.
|
||||
#MSVC 1900 cxx_thread_local # Thread-local variables, as defined in N2659.
|
||||
cxx_trailing_return_types # Automatic function return type, as defined in N2541.
|
||||
#MSVC 1900 cxx_unicode_literals # Unicode string literals, as defined in N2442.
|
||||
cxx_uniform_initialization # Uniform initialization, as defined in N2640.
|
||||
#MSVC 1900 cxx_unrestricted_unions # Unrestricted unions, as defined in N2544.
|
||||
#MSVC 1900 cxx_user_literals # User-defined literals, as defined in N2765.
|
||||
cxx_variadic_macros # Variadic macros, as defined in N1653.
|
||||
cxx_variadic_templates # Variadic templates, as defined in N2242.
|
||||
)
|
||||
|
||||
|
||||
if(BUILD_SHARED_LIBS)
|
||||
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
|
||||
add_compile_definitions(JSON_DLL_BUILD)
|
||||
else()
|
||||
add_definitions(-DJSON_DLL_BUILD)
|
||||
endif()
|
||||
|
||||
set(SHARED_LIB ${PROJECT_NAME}_lib)
|
||||
add_library(${SHARED_LIB} SHARED ${PUBLIC_HEADERS} ${JSONCPP_SOURCES})
|
||||
set_target_properties(${SHARED_LIB} PROPERTIES
|
||||
OUTPUT_NAME jsoncpp
|
||||
VERSION ${PROJECT_VERSION}
|
||||
SOVERSION ${PROJECT_SOVERSION}
|
||||
POSITION_INDEPENDENT_CODE ${BUILD_SHARED_LIBS}
|
||||
)
|
||||
|
||||
# Set library's runtime search path on OSX
|
||||
if(APPLE)
|
||||
set_target_properties(${SHARED_LIB} PROPERTIES INSTALL_RPATH "@loader_path/.")
|
||||
endif()
|
||||
|
||||
target_compile_features(${SHARED_LIB} PUBLIC ${REQUIRED_FEATURES})
|
||||
|
||||
target_include_directories(${SHARED_LIB} PUBLIC
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/${JSONCPP_INCLUDE_DIR}>
|
||||
)
|
||||
|
||||
list(APPEND CMAKE_TARGETS ${SHARED_LIB})
|
||||
endif()
|
||||
|
||||
if(BUILD_STATIC_LIBS)
|
||||
set(STATIC_LIB ${PROJECT_NAME}_static)
|
||||
add_library(${STATIC_LIB} STATIC ${PUBLIC_HEADERS} ${JSONCPP_SOURCES})
|
||||
|
||||
# avoid name clashes on windows as the shared import lib is also named jsoncpp.lib
|
||||
if(NOT DEFINED STATIC_SUFFIX AND BUILD_SHARED_LIBS)
|
||||
if (MSVC OR ("${CMAKE_C_SIMULATE_ID}" STREQUAL "MSVC"))
|
||||
set(STATIC_SUFFIX "_static")
|
||||
else()
|
||||
set(STATIC_SUFFIX "")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set_target_properties(${STATIC_LIB} PROPERTIES
|
||||
OUTPUT_NAME jsoncpp${STATIC_SUFFIX}
|
||||
VERSION ${PROJECT_VERSION}
|
||||
)
|
||||
|
||||
# Set library's runtime search path on OSX
|
||||
if(APPLE)
|
||||
set_target_properties(${STATIC_LIB} PROPERTIES INSTALL_RPATH "@loader_path/.")
|
||||
endif()
|
||||
|
||||
target_compile_features(${STATIC_LIB} PUBLIC ${REQUIRED_FEATURES})
|
||||
|
||||
target_include_directories(${STATIC_LIB} PUBLIC
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/${JSONCPP_INCLUDE_DIR}>
|
||||
)
|
||||
|
||||
list(APPEND CMAKE_TARGETS ${STATIC_LIB})
|
||||
endif()
|
||||
|
||||
if(BUILD_OBJECT_LIBS)
|
||||
set(OBJECT_LIB ${PROJECT_NAME}_object)
|
||||
add_library(${OBJECT_LIB} OBJECT ${PUBLIC_HEADERS} ${JSONCPP_SOURCES})
|
||||
|
||||
set_target_properties(${OBJECT_LIB} PROPERTIES
|
||||
OUTPUT_NAME jsoncpp
|
||||
VERSION ${PROJECT_VERSION}
|
||||
SOVERSION ${PROJECT_SOVERSION}
|
||||
POSITION_INDEPENDENT_CODE ${BUILD_SHARED_LIBS}
|
||||
)
|
||||
|
||||
# Set library's runtime search path on OSX
|
||||
if(APPLE)
|
||||
set_target_properties(${OBJECT_LIB} PROPERTIES INSTALL_RPATH "@loader_path/.")
|
||||
endif()
|
||||
|
||||
target_compile_features(${OBJECT_LIB} PUBLIC ${REQUIRED_FEATURES})
|
||||
|
||||
target_include_directories(${OBJECT_LIB} PUBLIC
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/${JSONCPP_INCLUDE_DIR}>
|
||||
)
|
||||
|
||||
list(APPEND CMAKE_TARGETS ${OBJECT_LIB})
|
||||
endif()
|
||||
|
||||
install(TARGETS ${CMAKE_TARGETS} ${INSTALL_EXPORT}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
OBJECTS DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
)
|
||||
|
@ -1,125 +0,0 @@
|
||||
#ifndef JSONCPP_BATCHALLOCATOR_H_INCLUDED
|
||||
# define JSONCPP_BATCHALLOCATOR_H_INCLUDED
|
||||
|
||||
# include <stdlib.h>
|
||||
# include <assert.h>
|
||||
|
||||
# ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
|
||||
|
||||
namespace Json {
|
||||
|
||||
/* Fast memory allocator.
|
||||
*
|
||||
* This memory allocator allocates memory for a batch of object (specified by
|
||||
* the page size, the number of object in each page).
|
||||
*
|
||||
* It does not allow the destruction of a single object. All the allocated objects
|
||||
* can be destroyed at once. The memory can be either released or reused for future
|
||||
* allocation.
|
||||
*
|
||||
* The in-place new operator must be used to construct the object using the pointer
|
||||
* returned by allocate.
|
||||
*/
|
||||
template<typename AllocatedType
|
||||
,const unsigned int objectPerAllocation>
|
||||
class BatchAllocator
|
||||
{
|
||||
public:
|
||||
typedef AllocatedType Type;
|
||||
|
||||
BatchAllocator( unsigned int objectsPerPage = 255 )
|
||||
: freeHead_( 0 )
|
||||
, objectsPerPage_( objectsPerPage )
|
||||
{
|
||||
// printf( "Size: %d => %s\n", sizeof(AllocatedType), typeid(AllocatedType).name() );
|
||||
assert( sizeof(AllocatedType) * objectPerAllocation >= sizeof(AllocatedType *) ); // We must be able to store a slist in the object free space.
|
||||
assert( objectsPerPage >= 16 );
|
||||
batches_ = allocateBatch( 0 ); // allocated a dummy page
|
||||
currentBatch_ = batches_;
|
||||
}
|
||||
|
||||
~BatchAllocator()
|
||||
{
|
||||
for ( BatchInfo *batch = batches_; batch; )
|
||||
{
|
||||
BatchInfo *nextBatch = batch->next_;
|
||||
free( batch );
|
||||
batch = nextBatch;
|
||||
}
|
||||
}
|
||||
|
||||
/// allocate space for an array of objectPerAllocation object.
|
||||
/// @warning it is the responsability of the caller to call objects constructors.
|
||||
AllocatedType *allocate()
|
||||
{
|
||||
if ( freeHead_ ) // returns node from free list.
|
||||
{
|
||||
AllocatedType *object = freeHead_;
|
||||
freeHead_ = *(AllocatedType **)object;
|
||||
return object;
|
||||
}
|
||||
if ( currentBatch_->used_ == currentBatch_->end_ )
|
||||
{
|
||||
currentBatch_ = currentBatch_->next_;
|
||||
while ( currentBatch_ && currentBatch_->used_ == currentBatch_->end_ )
|
||||
currentBatch_ = currentBatch_->next_;
|
||||
|
||||
if ( !currentBatch_ ) // no free batch found, allocate a new one
|
||||
{
|
||||
currentBatch_ = allocateBatch( objectsPerPage_ );
|
||||
currentBatch_->next_ = batches_; // insert at the head of the list
|
||||
batches_ = currentBatch_;
|
||||
}
|
||||
}
|
||||
AllocatedType *allocated = currentBatch_->used_;
|
||||
currentBatch_->used_ += objectPerAllocation;
|
||||
return allocated;
|
||||
}
|
||||
|
||||
/// Release the object.
|
||||
/// @warning it is the responsability of the caller to actually destruct the object.
|
||||
void release( AllocatedType *object )
|
||||
{
|
||||
assert( object != 0 );
|
||||
*(AllocatedType **)object = freeHead_;
|
||||
freeHead_ = object;
|
||||
}
|
||||
|
||||
private:
|
||||
struct BatchInfo
|
||||
{
|
||||
BatchInfo *next_;
|
||||
AllocatedType *used_;
|
||||
AllocatedType *end_;
|
||||
AllocatedType buffer_[objectPerAllocation];
|
||||
};
|
||||
|
||||
// disabled copy constructor and assignement operator.
|
||||
BatchAllocator( const BatchAllocator & );
|
||||
void operator =( const BatchAllocator &);
|
||||
|
||||
static BatchInfo *allocateBatch( unsigned int objectsPerPage )
|
||||
{
|
||||
const unsigned int mallocSize = sizeof(BatchInfo) - sizeof(AllocatedType)* objectPerAllocation
|
||||
+ sizeof(AllocatedType) * objectPerAllocation * objectsPerPage;
|
||||
BatchInfo *batch = static_cast<BatchInfo*>( malloc( mallocSize ) );
|
||||
batch->next_ = 0;
|
||||
batch->used_ = batch->buffer_;
|
||||
batch->end_ = batch->buffer_ + objectsPerPage;
|
||||
return batch;
|
||||
}
|
||||
|
||||
BatchInfo *batches_;
|
||||
BatchInfo *currentBatch_;
|
||||
/// Head of a single linked list within the allocated space of freeed object
|
||||
AllocatedType *freeHead_;
|
||||
unsigned int objectsPerPage_;
|
||||
};
|
||||
|
||||
|
||||
} // namespace Json
|
||||
|
||||
# endif // ifndef JSONCPP_DOC_INCLUDE_IMPLEMENTATION
|
||||
|
||||
#endif // JSONCPP_BATCHALLOCATOR_H_INCLUDED
|
||||
|
@ -1,448 +0,0 @@
|
||||
// included by json_value.cpp
|
||||
// everything is within Json namespace
|
||||
|
||||
// //////////////////////////////////////////////////////////////////
|
||||
// //////////////////////////////////////////////////////////////////
|
||||
// //////////////////////////////////////////////////////////////////
|
||||
// class ValueInternalArray
|
||||
// //////////////////////////////////////////////////////////////////
|
||||
// //////////////////////////////////////////////////////////////////
|
||||
// //////////////////////////////////////////////////////////////////
|
||||
|
||||
ValueArrayAllocator::~ValueArrayAllocator()
|
||||
{
|
||||
}
|
||||
|
||||
// //////////////////////////////////////////////////////////////////
|
||||
// class DefaultValueArrayAllocator
|
||||
// //////////////////////////////////////////////////////////////////
|
||||
#ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
|
||||
class DefaultValueArrayAllocator : public ValueArrayAllocator
|
||||
{
|
||||
public: // overridden from ValueArrayAllocator
|
||||
virtual ~DefaultValueArrayAllocator()
|
||||
{
|
||||
}
|
||||
|
||||
virtual ValueInternalArray *newArray()
|
||||
{
|
||||
return new ValueInternalArray();
|
||||
}
|
||||
|
||||
virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other )
|
||||
{
|
||||
return new ValueInternalArray( other );
|
||||
}
|
||||
|
||||
virtual void destructArray( ValueInternalArray *array )
|
||||
{
|
||||
delete array;
|
||||
}
|
||||
|
||||
virtual void reallocateArrayPageIndex( Value **&indexes,
|
||||
ValueInternalArray::PageIndex &indexCount,
|
||||
ValueInternalArray::PageIndex minNewIndexCount )
|
||||
{
|
||||
ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1;
|
||||
if ( minNewIndexCount > newIndexCount )
|
||||
newIndexCount = minNewIndexCount;
|
||||
void *newIndexes = realloc( indexes, sizeof(Value*) * newIndexCount );
|
||||
if ( !newIndexes )
|
||||
throw std::bad_alloc();
|
||||
indexCount = newIndexCount;
|
||||
indexes = static_cast<Value **>( newIndexes );
|
||||
}
|
||||
virtual void releaseArrayPageIndex( Value **indexes,
|
||||
ValueInternalArray::PageIndex indexCount )
|
||||
{
|
||||
if ( indexes )
|
||||
free( indexes );
|
||||
}
|
||||
|
||||
virtual Value *allocateArrayPage()
|
||||
{
|
||||
return static_cast<Value *>( malloc( sizeof(Value) * ValueInternalArray::itemsPerPage ) );
|
||||
}
|
||||
|
||||
virtual void releaseArrayPage( Value *value )
|
||||
{
|
||||
if ( value )
|
||||
free( value );
|
||||
}
|
||||
};
|
||||
|
||||
#else // #ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
|
||||
/// @todo make this thread-safe (lock when accessign batch allocator)
|
||||
class DefaultValueArrayAllocator : public ValueArrayAllocator
|
||||
{
|
||||
public: // overridden from ValueArrayAllocator
|
||||
virtual ~DefaultValueArrayAllocator()
|
||||
{
|
||||
}
|
||||
|
||||
virtual ValueInternalArray *newArray()
|
||||
{
|
||||
ValueInternalArray *array = arraysAllocator_.allocate();
|
||||
new (array) ValueInternalArray(); // placement new
|
||||
return array;
|
||||
}
|
||||
|
||||
virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other )
|
||||
{
|
||||
ValueInternalArray *array = arraysAllocator_.allocate();
|
||||
new (array) ValueInternalArray( other ); // placement new
|
||||
return array;
|
||||
}
|
||||
|
||||
virtual void destructArray( ValueInternalArray *array )
|
||||
{
|
||||
if ( array )
|
||||
{
|
||||
array->~ValueInternalArray();
|
||||
arraysAllocator_.release( array );
|
||||
}
|
||||
}
|
||||
|
||||
virtual void reallocateArrayPageIndex( Value **&indexes,
|
||||
ValueInternalArray::PageIndex &indexCount,
|
||||
ValueInternalArray::PageIndex minNewIndexCount )
|
||||
{
|
||||
ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1;
|
||||
if ( minNewIndexCount > newIndexCount )
|
||||
newIndexCount = minNewIndexCount;
|
||||
void *newIndexes = realloc( indexes, sizeof(Value*) * newIndexCount );
|
||||
if ( !newIndexes )
|
||||
throw std::bad_alloc();
|
||||
indexCount = newIndexCount;
|
||||
indexes = static_cast<Value **>( newIndexes );
|
||||
}
|
||||
virtual void releaseArrayPageIndex( Value **indexes,
|
||||
ValueInternalArray::PageIndex indexCount )
|
||||
{
|
||||
if ( indexes )
|
||||
free( indexes );
|
||||
}
|
||||
|
||||
virtual Value *allocateArrayPage()
|
||||
{
|
||||
return static_cast<Value *>( pagesAllocator_.allocate() );
|
||||
}
|
||||
|
||||
virtual void releaseArrayPage( Value *value )
|
||||
{
|
||||
if ( value )
|
||||
pagesAllocator_.release( value );
|
||||
}
|
||||
private:
|
||||
BatchAllocator<ValueInternalArray,1> arraysAllocator_;
|
||||
BatchAllocator<Value,ValueInternalArray::itemsPerPage> pagesAllocator_;
|
||||
};
|
||||
#endif // #ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
|
||||
|
||||
static ValueArrayAllocator *&arrayAllocator()
|
||||
{
|
||||
static DefaultValueArrayAllocator defaultAllocator;
|
||||
static ValueArrayAllocator *arrayAllocator = &defaultAllocator;
|
||||
return arrayAllocator;
|
||||
}
|
||||
|
||||
static struct DummyArrayAllocatorInitializer {
|
||||
DummyArrayAllocatorInitializer()
|
||||
{
|
||||
arrayAllocator(); // ensure arrayAllocator() statics are initialized before main().
|
||||
}
|
||||
} dummyArrayAllocatorInitializer;
|
||||
|
||||
// //////////////////////////////////////////////////////////////////
|
||||
// class ValueInternalArray
|
||||
// //////////////////////////////////////////////////////////////////
|
||||
bool
|
||||
ValueInternalArray::equals( const IteratorState &x,
|
||||
const IteratorState &other )
|
||||
{
|
||||
return x.array_ == other.array_
|
||||
&& x.currentItemIndex_ == other.currentItemIndex_
|
||||
&& x.currentPageIndex_ == other.currentPageIndex_;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ValueInternalArray::increment( IteratorState &it )
|
||||
{
|
||||
JSON_ASSERT_MESSAGE( it.array_ &&
|
||||
(it.currentPageIndex_ - it.array_->pages_)*itemsPerPage + it.currentItemIndex_
|
||||
!= it.array_->size_,
|
||||
"ValueInternalArray::increment(): moving iterator beyond end" );
|
||||
++(it.currentItemIndex_);
|
||||
if ( it.currentItemIndex_ == itemsPerPage )
|
||||
{
|
||||
it.currentItemIndex_ = 0;
|
||||
++(it.currentPageIndex_);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ValueInternalArray::decrement( IteratorState &it )
|
||||
{
|
||||
JSON_ASSERT_MESSAGE( it.array_ && it.currentPageIndex_ == it.array_->pages_
|
||||
&& it.currentItemIndex_ == 0,
|
||||
"ValueInternalArray::decrement(): moving iterator beyond end" );
|
||||
if ( it.currentItemIndex_ == 0 )
|
||||
{
|
||||
it.currentItemIndex_ = itemsPerPage-1;
|
||||
--(it.currentPageIndex_);
|
||||
}
|
||||
else
|
||||
{
|
||||
--(it.currentItemIndex_);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Value &
|
||||
ValueInternalArray::unsafeDereference( const IteratorState &it )
|
||||
{
|
||||
return (*(it.currentPageIndex_))[it.currentItemIndex_];
|
||||
}
|
||||
|
||||
|
||||
Value &
|
||||
ValueInternalArray::dereference( const IteratorState &it )
|
||||
{
|
||||
JSON_ASSERT_MESSAGE( it.array_ &&
|
||||
(it.currentPageIndex_ - it.array_->pages_)*itemsPerPage + it.currentItemIndex_
|
||||
< it.array_->size_,
|
||||
"ValueInternalArray::dereference(): dereferencing invalid iterator" );
|
||||
return unsafeDereference( it );
|
||||
}
|
||||
|
||||
void
|
||||
ValueInternalArray::makeBeginIterator( IteratorState &it ) const
|
||||
{
|
||||
it.array_ = const_cast<ValueInternalArray *>( this );
|
||||
it.currentItemIndex_ = 0;
|
||||
it.currentPageIndex_ = pages_;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ValueInternalArray::makeIterator( IteratorState &it, ArrayIndex index ) const
|
||||
{
|
||||
it.array_ = const_cast<ValueInternalArray *>( this );
|
||||
it.currentItemIndex_ = index % itemsPerPage;
|
||||
it.currentPageIndex_ = pages_ + index / itemsPerPage;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ValueInternalArray::makeEndIterator( IteratorState &it ) const
|
||||
{
|
||||
makeIterator( it, size_ );
|
||||
}
|
||||
|
||||
|
||||
ValueInternalArray::ValueInternalArray()
|
||||
: pages_( 0 )
|
||||
, size_( 0 )
|
||||
, pageCount_( 0 )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ValueInternalArray::ValueInternalArray( const ValueInternalArray &other )
|
||||
: pages_( 0 )
|
||||
, pageCount_( 0 )
|
||||
, size_( other.size_ )
|
||||
{
|
||||
PageIndex minNewPages = other.size_ / itemsPerPage;
|
||||
arrayAllocator()->reallocateArrayPageIndex( pages_, pageCount_, minNewPages );
|
||||
JSON_ASSERT_MESSAGE( pageCount_ >= minNewPages,
|
||||
"ValueInternalArray::reserve(): bad reallocation" );
|
||||
IteratorState itOther;
|
||||
other.makeBeginIterator( itOther );
|
||||
Value *value;
|
||||
for ( ArrayIndex index = 0; index < size_; ++index, increment(itOther) )
|
||||
{
|
||||
if ( index % itemsPerPage == 0 )
|
||||
{
|
||||
PageIndex pageIndex = index / itemsPerPage;
|
||||
value = arrayAllocator()->allocateArrayPage();
|
||||
pages_[pageIndex] = value;
|
||||
}
|
||||
new (value) Value( dereference( itOther ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ValueInternalArray &
|
||||
ValueInternalArray::operator =( const ValueInternalArray &other )
|
||||
{
|
||||
ValueInternalArray temp( other );
|
||||
swap( temp );
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
ValueInternalArray::~ValueInternalArray()
|
||||
{
|
||||
// destroy all constructed items
|
||||
IteratorState it;
|
||||
IteratorState itEnd;
|
||||
makeBeginIterator( it);
|
||||
makeEndIterator( itEnd );
|
||||
for ( ; !equals(it,itEnd); increment(it) )
|
||||
{
|
||||
Value *value = &dereference(it);
|
||||
value->~Value();
|
||||
}
|
||||
// release all pages
|
||||
PageIndex lastPageIndex = size_ / itemsPerPage;
|
||||
for ( PageIndex pageIndex = 0; pageIndex < lastPageIndex; ++pageIndex )
|
||||
arrayAllocator()->releaseArrayPage( pages_[pageIndex] );
|
||||
// release pages index
|
||||
arrayAllocator()->releaseArrayPageIndex( pages_, pageCount_ );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ValueInternalArray::swap( ValueInternalArray &other )
|
||||
{
|
||||
Value **tempPages = pages_;
|
||||
pages_ = other.pages_;
|
||||
other.pages_ = tempPages;
|
||||
ArrayIndex tempSize = size_;
|
||||
size_ = other.size_;
|
||||
other.size_ = tempSize;
|
||||
PageIndex tempPageCount = pageCount_;
|
||||
pageCount_ = other.pageCount_;
|
||||
other.pageCount_ = tempPageCount;
|
||||
}
|
||||
|
||||
void
|
||||
ValueInternalArray::clear()
|
||||
{
|
||||
ValueInternalArray dummy;
|
||||
swap( dummy );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ValueInternalArray::resize( ArrayIndex newSize )
|
||||
{
|
||||
if ( newSize == 0 )
|
||||
clear();
|
||||
else if ( newSize < size_ )
|
||||
{
|
||||
IteratorState it;
|
||||
IteratorState itEnd;
|
||||
makeIterator( it, newSize );
|
||||
makeIterator( itEnd, size_ );
|
||||
for ( ; !equals(it,itEnd); increment(it) )
|
||||
{
|
||||
Value *value = &dereference(it);
|
||||
value->~Value();
|
||||
}
|
||||
PageIndex pageIndex = (newSize + itemsPerPage - 1) / itemsPerPage;
|
||||
PageIndex lastPageIndex = size_ / itemsPerPage;
|
||||
for ( ; pageIndex < lastPageIndex; ++pageIndex )
|
||||
arrayAllocator()->releaseArrayPage( pages_[pageIndex] );
|
||||
size_ = newSize;
|
||||
}
|
||||
else if ( newSize > size_ )
|
||||
resolveReference( newSize );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ValueInternalArray::makeIndexValid( ArrayIndex index )
|
||||
{
|
||||
// Need to enlarge page index ?
|
||||
if ( index >= pageCount_ * itemsPerPage )
|
||||
{
|
||||
PageIndex minNewPages = (index + 1) / itemsPerPage;
|
||||
arrayAllocator()->reallocateArrayPageIndex( pages_, pageCount_, minNewPages );
|
||||
JSON_ASSERT_MESSAGE( pageCount_ >= minNewPages, "ValueInternalArray::reserve(): bad reallocation" );
|
||||
}
|
||||
|
||||
// Need to allocate new pages ?
|
||||
ArrayIndex nextPageIndex =
|
||||
(size_ % itemsPerPage) != 0 ? size_ - (size_%itemsPerPage) + itemsPerPage
|
||||
: size_;
|
||||
if ( nextPageIndex <= index )
|
||||
{
|
||||
PageIndex pageIndex = nextPageIndex / itemsPerPage;
|
||||
PageIndex pageToAllocate = (index - nextPageIndex) / itemsPerPage + 1;
|
||||
for ( ; pageToAllocate-- > 0; ++pageIndex )
|
||||
pages_[pageIndex] = arrayAllocator()->allocateArrayPage();
|
||||
}
|
||||
|
||||
// Initialize all new entries
|
||||
IteratorState it;
|
||||
IteratorState itEnd;
|
||||
makeIterator( it, size_ );
|
||||
size_ = index + 1;
|
||||
makeIterator( itEnd, size_ );
|
||||
for ( ; !equals(it,itEnd); increment(it) )
|
||||
{
|
||||
Value *value = &dereference(it);
|
||||
new (value) Value(); // Construct a default value using placement new
|
||||
}
|
||||
}
|
||||
|
||||
Value &
|
||||
ValueInternalArray::resolveReference( ArrayIndex index )
|
||||
{
|
||||
if ( index >= size_ )
|
||||
makeIndexValid( index );
|
||||
return pages_[index/itemsPerPage][index%itemsPerPage];
|
||||
}
|
||||
|
||||
Value *
|
||||
ValueInternalArray::find( ArrayIndex index ) const
|
||||
{
|
||||
if ( index >= size_ )
|
||||
return 0;
|
||||
return &(pages_[index/itemsPerPage][index%itemsPerPage]);
|
||||
}
|
||||
|
||||
ValueInternalArray::ArrayIndex
|
||||
ValueInternalArray::size() const
|
||||
{
|
||||
return size_;
|
||||
}
|
||||
|
||||
int
|
||||
ValueInternalArray::distance( const IteratorState &x, const IteratorState &y )
|
||||
{
|
||||
return indexOf(y) - indexOf(x);
|
||||
}
|
||||
|
||||
|
||||
ValueInternalArray::ArrayIndex
|
||||
ValueInternalArray::indexOf( const IteratorState &iterator )
|
||||
{
|
||||
if ( !iterator.array_ )
|
||||
return ArrayIndex(-1);
|
||||
return ArrayIndex(
|
||||
(iterator.currentPageIndex_ - iterator.array_->pages_) * itemsPerPage
|
||||
+ iterator.currentItemIndex_ );
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
ValueInternalArray::compare( const ValueInternalArray &other ) const
|
||||
{
|
||||
int sizeDiff( size_ - other.size_ );
|
||||
if ( sizeDiff != 0 )
|
||||
return sizeDiff;
|
||||
|
||||
for ( ArrayIndex index =0; index < size_; ++index )
|
||||
{
|
||||
int diff = pages_[index/itemsPerPage][index%itemsPerPage].compare(
|
||||
other.pages_[index/itemsPerPage][index%itemsPerPage] );
|
||||
if ( diff != 0 )
|
||||
return diff;
|
||||
}
|
||||
return 0;
|
||||
}
|
@ -1,607 +0,0 @@
|
||||
// included by json_value.cpp
|
||||
// everything is within Json namespace
|
||||
|
||||
// //////////////////////////////////////////////////////////////////
|
||||
// //////////////////////////////////////////////////////////////////
|
||||
// //////////////////////////////////////////////////////////////////
|
||||
// class ValueInternalMap
|
||||
// //////////////////////////////////////////////////////////////////
|
||||
// //////////////////////////////////////////////////////////////////
|
||||
// //////////////////////////////////////////////////////////////////
|
||||
|
||||
/** \internal MUST be safely initialized using memset( this, 0, sizeof(ValueInternalLink) );
|
||||
* This optimization is used by the fast allocator.
|
||||
*/
|
||||
ValueInternalLink::ValueInternalLink()
|
||||
: previous_( 0 )
|
||||
, next_( 0 )
|
||||
{
|
||||
}
|
||||
|
||||
ValueInternalLink::~ValueInternalLink()
|
||||
{
|
||||
for ( int index =0; index < itemPerLink; ++index )
|
||||
{
|
||||
if ( !items_[index].isItemAvailable() )
|
||||
{
|
||||
if ( !items_[index].isMemberNameStatic() )
|
||||
free( keys_[index] );
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
ValueMapAllocator::~ValueMapAllocator()
|
||||
{
|
||||
}
|
||||
|
||||
#ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
|
||||
class DefaultValueMapAllocator : public ValueMapAllocator
|
||||
{
|
||||
public: // overridden from ValueMapAllocator
|
||||
virtual ValueInternalMap *newMap()
|
||||
{
|
||||
return new ValueInternalMap();
|
||||
}
|
||||
|
||||
virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other )
|
||||
{
|
||||
return new ValueInternalMap( other );
|
||||
}
|
||||
|
||||
virtual void destructMap( ValueInternalMap *map )
|
||||
{
|
||||
delete map;
|
||||
}
|
||||
|
||||
virtual ValueInternalLink *allocateMapBuckets( unsigned int size )
|
||||
{
|
||||
return new ValueInternalLink[size];
|
||||
}
|
||||
|
||||
virtual void releaseMapBuckets( ValueInternalLink *links )
|
||||
{
|
||||
delete [] links;
|
||||
}
|
||||
|
||||
virtual ValueInternalLink *allocateMapLink()
|
||||
{
|
||||
return new ValueInternalLink();
|
||||
}
|
||||
|
||||
virtual void releaseMapLink( ValueInternalLink *link )
|
||||
{
|
||||
delete link;
|
||||
}
|
||||
};
|
||||
#else
|
||||
/// @todo make this thread-safe (lock when accessign batch allocator)
|
||||
class DefaultValueMapAllocator : public ValueMapAllocator
|
||||
{
|
||||
public: // overridden from ValueMapAllocator
|
||||
virtual ValueInternalMap *newMap()
|
||||
{
|
||||
ValueInternalMap *map = mapsAllocator_.allocate();
|
||||
new (map) ValueInternalMap(); // placement new
|
||||
return map;
|
||||
}
|
||||
|
||||
virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other )
|
||||
{
|
||||
ValueInternalMap *map = mapsAllocator_.allocate();
|
||||
new (map) ValueInternalMap( other ); // placement new
|
||||
return map;
|
||||
}
|
||||
|
||||
virtual void destructMap( ValueInternalMap *map )
|
||||
{
|
||||
if ( map )
|
||||
{
|
||||
map->~ValueInternalMap();
|
||||
mapsAllocator_.release( map );
|
||||
}
|
||||
}
|
||||
|
||||
virtual ValueInternalLink *allocateMapBuckets( unsigned int size )
|
||||
{
|
||||
return new ValueInternalLink[size];
|
||||
}
|
||||
|
||||
virtual void releaseMapBuckets( ValueInternalLink *links )
|
||||
{
|
||||
delete [] links;
|
||||
}
|
||||
|
||||
virtual ValueInternalLink *allocateMapLink()
|
||||
{
|
||||
ValueInternalLink *link = linksAllocator_.allocate();
|
||||
memset( link, 0, sizeof(ValueInternalLink) );
|
||||
return link;
|
||||
}
|
||||
|
||||
virtual void releaseMapLink( ValueInternalLink *link )
|
||||
{
|
||||
link->~ValueInternalLink();
|
||||
linksAllocator_.release( link );
|
||||
}
|
||||
private:
|
||||
BatchAllocator<ValueInternalMap,1> mapsAllocator_;
|
||||
BatchAllocator<ValueInternalLink,1> linksAllocator_;
|
||||
};
|
||||
#endif
|
||||
|
||||
static ValueMapAllocator *&mapAllocator()
|
||||
{
|
||||
static DefaultValueMapAllocator defaultAllocator;
|
||||
static ValueMapAllocator *mapAllocator = &defaultAllocator;
|
||||
return mapAllocator;
|
||||
}
|
||||
|
||||
static struct DummyMapAllocatorInitializer {
|
||||
DummyMapAllocatorInitializer()
|
||||
{
|
||||
mapAllocator(); // ensure mapAllocator() statics are initialized before main().
|
||||
}
|
||||
} dummyMapAllocatorInitializer;
|
||||
|
||||
|
||||
|
||||
// h(K) = value * K >> w ; with w = 32 & K prime w.r.t. 2^32.
|
||||
|
||||
/*
|
||||
use linked list hash map.
|
||||
buckets array is a container.
|
||||
linked list element contains 6 key/values. (memory = (16+4) * 6 + 4 = 124)
|
||||
value have extra state: valid, available, deleted
|
||||
*/
|
||||
|
||||
|
||||
ValueInternalMap::ValueInternalMap()
|
||||
: buckets_( 0 )
|
||||
, tailLink_( 0 )
|
||||
, bucketsSize_( 0 )
|
||||
, itemCount_( 0 )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ValueInternalMap::ValueInternalMap( const ValueInternalMap &other )
|
||||
: buckets_( 0 )
|
||||
, tailLink_( 0 )
|
||||
, bucketsSize_( 0 )
|
||||
, itemCount_( 0 )
|
||||
{
|
||||
reserve( other.itemCount_ );
|
||||
IteratorState it;
|
||||
IteratorState itEnd;
|
||||
other.makeBeginIterator( it );
|
||||
other.makeEndIterator( itEnd );
|
||||
for ( ; !equals(it,itEnd); increment(it) )
|
||||
{
|
||||
bool isStatic;
|
||||
const char *memberName = key( it, isStatic );
|
||||
const Value &aValue = value( it );
|
||||
resolveReference(memberName, isStatic) = aValue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ValueInternalMap &
|
||||
ValueInternalMap::operator =( const ValueInternalMap &other )
|
||||
{
|
||||
ValueInternalMap dummy( other );
|
||||
swap( dummy );
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
ValueInternalMap::~ValueInternalMap()
|
||||
{
|
||||
if ( buckets_ )
|
||||
{
|
||||
for ( BucketIndex bucketIndex =0; bucketIndex < bucketsSize_; ++bucketIndex )
|
||||
{
|
||||
ValueInternalLink *link = buckets_[bucketIndex].next_;
|
||||
while ( link )
|
||||
{
|
||||
ValueInternalLink *linkToRelease = link;
|
||||
link = link->next_;
|
||||
mapAllocator()->releaseMapLink( linkToRelease );
|
||||
}
|
||||
}
|
||||
mapAllocator()->releaseMapBuckets( buckets_ );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ValueInternalMap::swap( ValueInternalMap &other )
|
||||
{
|
||||
ValueInternalLink *tempBuckets = buckets_;
|
||||
buckets_ = other.buckets_;
|
||||
other.buckets_ = tempBuckets;
|
||||
ValueInternalLink *tempTailLink = tailLink_;
|
||||
tailLink_ = other.tailLink_;
|
||||
other.tailLink_ = tempTailLink;
|
||||
BucketIndex tempBucketsSize = bucketsSize_;
|
||||
bucketsSize_ = other.bucketsSize_;
|
||||
other.bucketsSize_ = tempBucketsSize;
|
||||
BucketIndex tempItemCount = itemCount_;
|
||||
itemCount_ = other.itemCount_;
|
||||
other.itemCount_ = tempItemCount;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ValueInternalMap::clear()
|
||||
{
|
||||
ValueInternalMap dummy;
|
||||
swap( dummy );
|
||||
}
|
||||
|
||||
|
||||
ValueInternalMap::BucketIndex
|
||||
ValueInternalMap::size() const
|
||||
{
|
||||
return itemCount_;
|
||||
}
|
||||
|
||||
bool
|
||||
ValueInternalMap::reserveDelta( BucketIndex growth )
|
||||
{
|
||||
return reserve( itemCount_ + growth );
|
||||
}
|
||||
|
||||
bool
|
||||
ValueInternalMap::reserve( BucketIndex newItemCount )
|
||||
{
|
||||
if ( !buckets_ && newItemCount > 0 )
|
||||
{
|
||||
buckets_ = mapAllocator()->allocateMapBuckets( 1 );
|
||||
bucketsSize_ = 1;
|
||||
tailLink_ = &buckets_[0];
|
||||
}
|
||||
// BucketIndex idealBucketCount = (newItemCount + ValueInternalLink::itemPerLink) / ValueInternalLink::itemPerLink;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
const Value *
|
||||
ValueInternalMap::find( const char *key ) const
|
||||
{
|
||||
if ( !bucketsSize_ )
|
||||
return 0;
|
||||
HashKey hashedKey = hash( key );
|
||||
BucketIndex bucketIndex = hashedKey % bucketsSize_;
|
||||
for ( const ValueInternalLink *current = &buckets_[bucketIndex];
|
||||
current != 0;
|
||||
current = current->next_ )
|
||||
{
|
||||
for ( BucketIndex index=0; index < ValueInternalLink::itemPerLink; ++index )
|
||||
{
|
||||
if ( current->items_[index].isItemAvailable() )
|
||||
return 0;
|
||||
if ( strcmp( key, current->keys_[index] ) == 0 )
|
||||
return ¤t->items_[index];
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Value *
|
||||
ValueInternalMap::find( const char *key )
|
||||
{
|
||||
const ValueInternalMap *constThis = this;
|
||||
return const_cast<Value *>( constThis->find( key ) );
|
||||
}
|
||||
|
||||
|
||||
Value &
|
||||
ValueInternalMap::resolveReference( const char *key,
|
||||
bool isStatic )
|
||||
{
|
||||
HashKey hashedKey = hash( key );
|
||||
if ( bucketsSize_ )
|
||||
{
|
||||
BucketIndex bucketIndex = hashedKey % bucketsSize_;
|
||||
ValueInternalLink **previous = 0;
|
||||
BucketIndex index;
|
||||
for ( ValueInternalLink *current = &buckets_[bucketIndex];
|
||||
current != 0;
|
||||
previous = ¤t->next_, current = current->next_ )
|
||||
{
|
||||
for ( index=0; index < ValueInternalLink::itemPerLink; ++index )
|
||||
{
|
||||
if ( current->items_[index].isItemAvailable() )
|
||||
return setNewItem( key, isStatic, current, index );
|
||||
if ( strcmp( key, current->keys_[index] ) == 0 )
|
||||
return current->items_[index];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
reserveDelta( 1 );
|
||||
return unsafeAdd( key, isStatic, hashedKey );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ValueInternalMap::remove( const char *key )
|
||||
{
|
||||
HashKey hashedKey = hash( key );
|
||||
if ( !bucketsSize_ )
|
||||
return;
|
||||
BucketIndex bucketIndex = hashedKey % bucketsSize_;
|
||||
for ( ValueInternalLink *link = &buckets_[bucketIndex];
|
||||
link != 0;
|
||||
link = link->next_ )
|
||||
{
|
||||
BucketIndex index;
|
||||
for ( index =0; index < ValueInternalLink::itemPerLink; ++index )
|
||||
{
|
||||
if ( link->items_[index].isItemAvailable() )
|
||||
return;
|
||||
if ( strcmp( key, link->keys_[index] ) == 0 )
|
||||
{
|
||||
doActualRemove( link, index, bucketIndex );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ValueInternalMap::doActualRemove( ValueInternalLink *link,
|
||||
BucketIndex index,
|
||||
BucketIndex bucketIndex )
|
||||
{
|
||||
// find last item of the bucket and swap it with the 'removed' one.
|
||||
// set removed items flags to 'available'.
|
||||
// if last page only contains 'available' items, then desallocate it (it's empty)
|
||||
ValueInternalLink *&lastLink = getLastLinkInBucket( index );
|
||||
BucketIndex lastItemIndex = 1; // a link can never be empty, so start at 1
|
||||
for ( ;
|
||||
lastItemIndex < ValueInternalLink::itemPerLink;
|
||||
++lastItemIndex ) // may be optimized with dicotomic search
|
||||
{
|
||||
if ( lastLink->items_[lastItemIndex].isItemAvailable() )
|
||||
break;
|
||||
}
|
||||
|
||||
BucketIndex lastUsedIndex = lastItemIndex - 1;
|
||||
Value *valueToDelete = &link->items_[index];
|
||||
Value *valueToPreserve = &lastLink->items_[lastUsedIndex];
|
||||
if ( valueToDelete != valueToPreserve )
|
||||
valueToDelete->swap( *valueToPreserve );
|
||||
if ( lastUsedIndex == 0 ) // page is now empty
|
||||
{ // remove it from bucket linked list and delete it.
|
||||
ValueInternalLink *linkPreviousToLast = lastLink->previous_;
|
||||
if ( linkPreviousToLast != 0 ) // can not deleted bucket link.
|
||||
{
|
||||
mapAllocator()->releaseMapLink( lastLink );
|
||||
linkPreviousToLast->next_ = 0;
|
||||
lastLink = linkPreviousToLast;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Value dummy;
|
||||
valueToPreserve->swap( dummy ); // restore deleted to default Value.
|
||||
valueToPreserve->setItemUsed( false );
|
||||
}
|
||||
--itemCount_;
|
||||
}
|
||||
|
||||
|
||||
ValueInternalLink *&
|
||||
ValueInternalMap::getLastLinkInBucket( BucketIndex bucketIndex )
|
||||
{
|
||||
if ( bucketIndex == bucketsSize_ - 1 )
|
||||
return tailLink_;
|
||||
ValueInternalLink *&previous = buckets_[bucketIndex+1].previous_;
|
||||
if ( !previous )
|
||||
previous = &buckets_[bucketIndex];
|
||||
return previous;
|
||||
}
|
||||
|
||||
|
||||
Value &
|
||||
ValueInternalMap::setNewItem( const char *key,
|
||||
bool isStatic,
|
||||
ValueInternalLink *link,
|
||||
BucketIndex index )
|
||||
{
|
||||
char *duplicatedKey = valueAllocator()->makeMemberName( key );
|
||||
++itemCount_;
|
||||
link->keys_[index] = duplicatedKey;
|
||||
link->items_[index].setItemUsed();
|
||||
link->items_[index].setMemberNameIsStatic( isStatic );
|
||||
return link->items_[index]; // items already default constructed.
|
||||
}
|
||||
|
||||
|
||||
Value &
|
||||
ValueInternalMap::unsafeAdd( const char *key,
|
||||
bool isStatic,
|
||||
HashKey hashedKey )
|
||||
{
|
||||
JSON_ASSERT_MESSAGE( bucketsSize_ > 0, "ValueInternalMap::unsafeAdd(): internal logic error." );
|
||||
BucketIndex bucketIndex = hashedKey % bucketsSize_;
|
||||
ValueInternalLink *&previousLink = getLastLinkInBucket( bucketIndex );
|
||||
ValueInternalLink *link = previousLink;
|
||||
BucketIndex index;
|
||||
for ( index =0; index < ValueInternalLink::itemPerLink; ++index )
|
||||
{
|
||||
if ( link->items_[index].isItemAvailable() )
|
||||
break;
|
||||
}
|
||||
if ( index == ValueInternalLink::itemPerLink ) // need to add a new page
|
||||
{
|
||||
ValueInternalLink *newLink = mapAllocator()->allocateMapLink();
|
||||
index = 0;
|
||||
link->next_ = newLink;
|
||||
previousLink = newLink;
|
||||
link = newLink;
|
||||
}
|
||||
return setNewItem( key, isStatic, link, index );
|
||||
}
|
||||
|
||||
|
||||
ValueInternalMap::HashKey
|
||||
ValueInternalMap::hash( const char *key ) const
|
||||
{
|
||||
HashKey hash = 0;
|
||||
while ( *key )
|
||||
hash += *key++ * 37;
|
||||
return hash;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
ValueInternalMap::compare( const ValueInternalMap &other ) const
|
||||
{
|
||||
int sizeDiff( itemCount_ - other.itemCount_ );
|
||||
if ( sizeDiff != 0 )
|
||||
return sizeDiff;
|
||||
// Strict order guaranty is required. Compare all keys FIRST, then compare values.
|
||||
IteratorState it;
|
||||
IteratorState itEnd;
|
||||
makeBeginIterator( it );
|
||||
makeEndIterator( itEnd );
|
||||
for ( ; !equals(it,itEnd); increment(it) )
|
||||
{
|
||||
if ( !other.find( key( it ) ) )
|
||||
return 1;
|
||||
}
|
||||
|
||||
// All keys are equals, let's compare values
|
||||
makeBeginIterator( it );
|
||||
for ( ; !equals(it,itEnd); increment(it) )
|
||||
{
|
||||
const Value *otherValue = other.find( key( it ) );
|
||||
int valueDiff = value(it).compare( *otherValue );
|
||||
if ( valueDiff != 0 )
|
||||
return valueDiff;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ValueInternalMap::makeBeginIterator( IteratorState &it ) const
|
||||
{
|
||||
it.map_ = const_cast<ValueInternalMap *>( this );
|
||||
it.bucketIndex_ = 0;
|
||||
it.itemIndex_ = 0;
|
||||
it.link_ = buckets_;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ValueInternalMap::makeEndIterator( IteratorState &it ) const
|
||||
{
|
||||
it.map_ = const_cast<ValueInternalMap *>( this );
|
||||
it.bucketIndex_ = bucketsSize_;
|
||||
it.itemIndex_ = 0;
|
||||
it.link_ = 0;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
ValueInternalMap::equals( const IteratorState &x, const IteratorState &other )
|
||||
{
|
||||
return x.map_ == other.map_
|
||||
&& x.bucketIndex_ == other.bucketIndex_
|
||||
&& x.link_ == other.link_
|
||||
&& x.itemIndex_ == other.itemIndex_;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ValueInternalMap::incrementBucket( IteratorState &iterator )
|
||||
{
|
||||
++iterator.bucketIndex_;
|
||||
JSON_ASSERT_MESSAGE( iterator.bucketIndex_ <= iterator.map_->bucketsSize_,
|
||||
"ValueInternalMap::increment(): attempting to iterate beyond end." );
|
||||
if ( iterator.bucketIndex_ == iterator.map_->bucketsSize_ )
|
||||
iterator.link_ = 0;
|
||||
else
|
||||
iterator.link_ = &(iterator.map_->buckets_[iterator.bucketIndex_]);
|
||||
iterator.itemIndex_ = 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ValueInternalMap::increment( IteratorState &iterator )
|
||||
{
|
||||
JSON_ASSERT_MESSAGE( iterator.map_, "Attempting to iterator using invalid iterator." );
|
||||
++iterator.itemIndex_;
|
||||
if ( iterator.itemIndex_ == ValueInternalLink::itemPerLink )
|
||||
{
|
||||
JSON_ASSERT_MESSAGE( iterator.link_ != 0,
|
||||
"ValueInternalMap::increment(): attempting to iterate beyond end." );
|
||||
iterator.link_ = iterator.link_->next_;
|
||||
if ( iterator.link_ == 0 )
|
||||
incrementBucket( iterator );
|
||||
}
|
||||
else if ( iterator.link_->items_[iterator.itemIndex_].isItemAvailable() )
|
||||
{
|
||||
incrementBucket( iterator );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ValueInternalMap::decrement( IteratorState &iterator )
|
||||
{
|
||||
if ( iterator.itemIndex_ == 0 )
|
||||
{
|
||||
JSON_ASSERT_MESSAGE( iterator.map_, "Attempting to iterate using invalid iterator." );
|
||||
if ( iterator.link_ == &iterator.map_->buckets_[iterator.bucketIndex_] )
|
||||
{
|
||||
JSON_ASSERT_MESSAGE( iterator.bucketIndex_ > 0, "Attempting to iterate beyond beginning." );
|
||||
--(iterator.bucketIndex_);
|
||||
}
|
||||
iterator.link_ = iterator.link_->previous_;
|
||||
iterator.itemIndex_ = ValueInternalLink::itemPerLink - 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const char *
|
||||
ValueInternalMap::key( const IteratorState &iterator )
|
||||
{
|
||||
JSON_ASSERT_MESSAGE( iterator.link_, "Attempting to iterate using invalid iterator." );
|
||||
return iterator.link_->keys_[iterator.itemIndex_];
|
||||
}
|
||||
|
||||
const char *
|
||||
ValueInternalMap::key( const IteratorState &iterator, bool &isStatic )
|
||||
{
|
||||
JSON_ASSERT_MESSAGE( iterator.link_, "Attempting to iterate using invalid iterator." );
|
||||
isStatic = iterator.link_->items_[iterator.itemIndex_].isMemberNameStatic();
|
||||
return iterator.link_->keys_[iterator.itemIndex_];
|
||||
}
|
||||
|
||||
|
||||
Value &
|
||||
ValueInternalMap::value( const IteratorState &iterator )
|
||||
{
|
||||
JSON_ASSERT_MESSAGE( iterator.link_, "Attempting to iterate using invalid iterator." );
|
||||
return iterator.link_->items_[iterator.itemIndex_];
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
ValueInternalMap::distance( const IteratorState &x, const IteratorState &y )
|
||||
{
|
||||
int offset = 0;
|
||||
IteratorState it = x;
|
||||
while ( !equals( it, y ) )
|
||||
increment( it );
|
||||
return offset;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
138
src/lib_json/json_tool.h
Normal file
138
src/lib_json/json_tool.h
Normal file
@ -0,0 +1,138 @@
|
||||
// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
|
||||
// Distributed under MIT license, or public domain if desired and
|
||||
// recognized in your jurisdiction.
|
||||
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||
|
||||
#ifndef LIB_JSONCPP_JSON_TOOL_H_INCLUDED
|
||||
#define LIB_JSONCPP_JSON_TOOL_H_INCLUDED
|
||||
|
||||
#if !defined(JSON_IS_AMALGAMATION)
|
||||
#include <json/config.h>
|
||||
#endif
|
||||
|
||||
// Also support old flag NO_LOCALE_SUPPORT
|
||||
#ifdef NO_LOCALE_SUPPORT
|
||||
#define JSONCPP_NO_LOCALE_SUPPORT
|
||||
#endif
|
||||
|
||||
#ifndef JSONCPP_NO_LOCALE_SUPPORT
|
||||
#include <clocale>
|
||||
#endif
|
||||
|
||||
/* This header provides common string manipulation support, such as UTF-8,
|
||||
* portable conversion from/to string...
|
||||
*
|
||||
* It is an internal header that must not be exposed.
|
||||
*/
|
||||
|
||||
namespace Json {
|
||||
static inline char getDecimalPoint() {
|
||||
#ifdef JSONCPP_NO_LOCALE_SUPPORT
|
||||
return '\0';
|
||||
#else
|
||||
struct lconv* lc = localeconv();
|
||||
return lc ? *(lc->decimal_point) : '\0';
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Converts a unicode code-point to UTF-8.
|
||||
static inline String codePointToUTF8(unsigned int cp) {
|
||||
String result;
|
||||
|
||||
// based on description from http://en.wikipedia.org/wiki/UTF-8
|
||||
|
||||
if (cp <= 0x7f) {
|
||||
result.resize(1);
|
||||
result[0] = static_cast<char>(cp);
|
||||
} else if (cp <= 0x7FF) {
|
||||
result.resize(2);
|
||||
result[1] = static_cast<char>(0x80 | (0x3f & cp));
|
||||
result[0] = static_cast<char>(0xC0 | (0x1f & (cp >> 6)));
|
||||
} else if (cp <= 0xFFFF) {
|
||||
result.resize(3);
|
||||
result[2] = static_cast<char>(0x80 | (0x3f & cp));
|
||||
result[1] = static_cast<char>(0x80 | (0x3f & (cp >> 6)));
|
||||
result[0] = static_cast<char>(0xE0 | (0xf & (cp >> 12)));
|
||||
} else if (cp <= 0x10FFFF) {
|
||||
result.resize(4);
|
||||
result[3] = static_cast<char>(0x80 | (0x3f & cp));
|
||||
result[2] = static_cast<char>(0x80 | (0x3f & (cp >> 6)));
|
||||
result[1] = static_cast<char>(0x80 | (0x3f & (cp >> 12)));
|
||||
result[0] = static_cast<char>(0xF0 | (0x7 & (cp >> 18)));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
enum {
|
||||
/// Constant that specify the size of the buffer that must be passed to
|
||||
/// uintToString.
|
||||
uintToStringBufferSize = 3 * sizeof(LargestUInt) + 1
|
||||
};
|
||||
|
||||
// Defines a char buffer for use with uintToString().
|
||||
using UIntToStringBuffer = char[uintToStringBufferSize];
|
||||
|
||||
/** Converts an unsigned integer to string.
|
||||
* @param value Unsigned integer to convert to string
|
||||
* @param current Input/Output string buffer.
|
||||
* Must have at least uintToStringBufferSize chars free.
|
||||
*/
|
||||
static inline void uintToString(LargestUInt value, char*& current) {
|
||||
*--current = 0;
|
||||
do {
|
||||
*--current = static_cast<char>(value % 10U + static_cast<unsigned>('0'));
|
||||
value /= 10;
|
||||
} while (value != 0);
|
||||
}
|
||||
|
||||
/** Change ',' to '.' everywhere in buffer.
|
||||
*
|
||||
* We had a sophisticated way, but it did not work in WinCE.
|
||||
* @see https://github.com/open-source-parsers/jsoncpp/pull/9
|
||||
*/
|
||||
template <typename Iter> Iter fixNumericLocale(Iter begin, Iter end) {
|
||||
for (; begin != end; ++begin) {
|
||||
if (*begin == ',') {
|
||||
*begin = '.';
|
||||
}
|
||||
}
|
||||
return begin;
|
||||
}
|
||||
|
||||
template <typename Iter> void fixNumericLocaleInput(Iter begin, Iter end) {
|
||||
char decimalPoint = getDecimalPoint();
|
||||
if (decimalPoint == '\0' || decimalPoint == '.') {
|
||||
return;
|
||||
}
|
||||
for (; begin != end; ++begin) {
|
||||
if (*begin == '.') {
|
||||
*begin = decimalPoint;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return iterator that would be the new end of the range [begin,end), if we
|
||||
* were to delete zeros in the end of string, but not the last zero before '.'.
|
||||
*/
|
||||
template <typename Iter>
|
||||
Iter fixZerosInTheEnd(Iter begin, Iter end, unsigned int precision) {
|
||||
for (; begin != end; --end) {
|
||||
if (*(end - 1) != '0') {
|
||||
return end;
|
||||
}
|
||||
// Don't delete the last zero before the decimal point.
|
||||
if (begin != (end - 1) && begin != (end - 2) && *(end - 2) == '.') {
|
||||
if (precision) {
|
||||
return end;
|
||||
}
|
||||
return end - 2;
|
||||
}
|
||||
}
|
||||
return end;
|
||||
}
|
||||
|
||||
} // namespace Json
|
||||
|
||||
#endif // LIB_JSONCPP_JSON_TOOL_H_INCLUDED
|
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,11 @@
|
||||
// included by json_value.cpp
|
||||
// everything is within Json namespace
|
||||
// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
|
||||
// Distributed under MIT license, or public domain if desired and
|
||||
// recognized in your jurisdiction.
|
||||
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||
|
||||
// included by json_value.cpp
|
||||
|
||||
namespace Json {
|
||||
|
||||
// //////////////////////////////////////////////////////////////////
|
||||
// //////////////////////////////////////////////////////////////////
|
||||
@ -10,201 +15,95 @@
|
||||
// //////////////////////////////////////////////////////////////////
|
||||
// //////////////////////////////////////////////////////////////////
|
||||
|
||||
ValueIteratorBase::ValueIteratorBase()
|
||||
#ifndef JSON_VALUE_USE_INTERNAL_MAP
|
||||
: current_()
|
||||
, isNull_( true )
|
||||
{
|
||||
}
|
||||
#else
|
||||
: isArray_( true )
|
||||
, isNull_( true )
|
||||
{
|
||||
iterator_.array_ = ValueInternalArray::IteratorState();
|
||||
}
|
||||
#endif
|
||||
ValueIteratorBase::ValueIteratorBase() : current_() {}
|
||||
|
||||
ValueIteratorBase::ValueIteratorBase(
|
||||
const Value::ObjectValues::iterator& current)
|
||||
: current_(current), isNull_(false) {}
|
||||
|
||||
#ifndef JSON_VALUE_USE_INTERNAL_MAP
|
||||
ValueIteratorBase::ValueIteratorBase( const Value::ObjectValues::iterator ¤t )
|
||||
: current_( current )
|
||||
, isNull_( false )
|
||||
{
|
||||
}
|
||||
#else
|
||||
ValueIteratorBase::ValueIteratorBase( const ValueInternalArray::IteratorState &state )
|
||||
: isArray_( true )
|
||||
{
|
||||
iterator_.array_ = state;
|
||||
}
|
||||
Value& ValueIteratorBase::deref() { return current_->second; }
|
||||
const Value& ValueIteratorBase::deref() const { return current_->second; }
|
||||
|
||||
void ValueIteratorBase::increment() { ++current_; }
|
||||
|
||||
ValueIteratorBase::ValueIteratorBase( const ValueInternalMap::IteratorState &state )
|
||||
: isArray_( false )
|
||||
{
|
||||
iterator_.map_ = state;
|
||||
}
|
||||
#endif
|
||||
|
||||
Value &
|
||||
ValueIteratorBase::deref() const
|
||||
{
|
||||
#ifndef JSON_VALUE_USE_INTERNAL_MAP
|
||||
return current_->second;
|
||||
#else
|
||||
if ( isArray_ )
|
||||
return ValueInternalArray::dereference( iterator_.array_ );
|
||||
return ValueInternalMap::value( iterator_.map_ );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ValueIteratorBase::increment()
|
||||
{
|
||||
#ifndef JSON_VALUE_USE_INTERNAL_MAP
|
||||
++current_;
|
||||
#else
|
||||
if ( isArray_ )
|
||||
ValueInternalArray::increment( iterator_.array_ );
|
||||
ValueInternalMap::increment( iterator_.map_ );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ValueIteratorBase::decrement()
|
||||
{
|
||||
#ifndef JSON_VALUE_USE_INTERNAL_MAP
|
||||
--current_;
|
||||
#else
|
||||
if ( isArray_ )
|
||||
ValueInternalArray::decrement( iterator_.array_ );
|
||||
ValueInternalMap::decrement( iterator_.map_ );
|
||||
#endif
|
||||
}
|
||||
|
||||
void ValueIteratorBase::decrement() { --current_; }
|
||||
|
||||
ValueIteratorBase::difference_type
|
||||
ValueIteratorBase::computeDistance( const SelfType &other ) const
|
||||
{
|
||||
#ifndef JSON_VALUE_USE_INTERNAL_MAP
|
||||
# ifdef JSON_USE_CPPTL_SMALLMAP
|
||||
return current_ - other.current_;
|
||||
# else
|
||||
// Iterator for null value are initialized using the default
|
||||
// constructor, which initialize current_ to the default
|
||||
// std::map::iterator. As begin() and end() are two instance
|
||||
// of the default std::map::iterator, they can not be compared.
|
||||
// To allow this, we handle this comparison specifically.
|
||||
if ( isNull_ && other.isNull_ )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
ValueIteratorBase::computeDistance(const SelfType& other) const {
|
||||
// Iterator for null value are initialized using the default
|
||||
// constructor, which initialize current_ to the default
|
||||
// std::map::iterator. As begin() and end() are two instance
|
||||
// of the default std::map::iterator, they can not be compared.
|
||||
// To allow this, we handle this comparison specifically.
|
||||
if (isNull_ && other.isNull_) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// Usage of std::distance is not portable (does not compile with Sun Studio 12 RogueWave STL,
|
||||
// which is the one used by default).
|
||||
// Using a portable hand-made version for non random iterator instead:
|
||||
// return difference_type( std::distance( current_, other.current_ ) );
|
||||
difference_type myDistance = 0;
|
||||
for ( Value::ObjectValues::iterator it = current_; it != other.current_; ++it )
|
||||
{
|
||||
++myDistance;
|
||||
}
|
||||
return myDistance;
|
||||
# endif
|
||||
#else
|
||||
if ( isArray_ )
|
||||
return ValueInternalArray::distance( iterator_.array_, other.iterator_.array_ );
|
||||
return ValueInternalMap::distance( iterator_.map_, other.iterator_.map_ );
|
||||
#endif
|
||||
// Usage of std::distance is not portable (does not compile with Sun Studio 12
|
||||
// RogueWave STL,
|
||||
// which is the one used by default).
|
||||
// Using a portable hand-made version for non random iterator instead:
|
||||
// return difference_type( std::distance( current_, other.current_ ) );
|
||||
difference_type myDistance = 0;
|
||||
for (Value::ObjectValues::iterator it = current_; it != other.current_;
|
||||
++it) {
|
||||
++myDistance;
|
||||
}
|
||||
return myDistance;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
ValueIteratorBase::isEqual( const SelfType &other ) const
|
||||
{
|
||||
#ifndef JSON_VALUE_USE_INTERNAL_MAP
|
||||
if ( isNull_ )
|
||||
{
|
||||
return other.isNull_;
|
||||
}
|
||||
return current_ == other.current_;
|
||||
#else
|
||||
if ( isArray_ )
|
||||
return ValueInternalArray::equals( iterator_.array_, other.iterator_.array_ );
|
||||
return ValueInternalMap::equals( iterator_.map_, other.iterator_.map_ );
|
||||
#endif
|
||||
bool ValueIteratorBase::isEqual(const SelfType& other) const {
|
||||
if (isNull_) {
|
||||
return other.isNull_;
|
||||
}
|
||||
return current_ == other.current_;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ValueIteratorBase::copy( const SelfType &other )
|
||||
{
|
||||
#ifndef JSON_VALUE_USE_INTERNAL_MAP
|
||||
current_ = other.current_;
|
||||
#else
|
||||
if ( isArray_ )
|
||||
iterator_.array_ = other.iterator_.array_;
|
||||
iterator_.map_ = other.iterator_.map_;
|
||||
#endif
|
||||
void ValueIteratorBase::copy(const SelfType& other) {
|
||||
current_ = other.current_;
|
||||
isNull_ = other.isNull_;
|
||||
}
|
||||
|
||||
|
||||
Value
|
||||
ValueIteratorBase::key() const
|
||||
{
|
||||
#ifndef JSON_VALUE_USE_INTERNAL_MAP
|
||||
const Value::CZString czstring = (*current_).first;
|
||||
if ( czstring.c_str() )
|
||||
{
|
||||
if ( czstring.isStaticString() )
|
||||
return Value( StaticString( czstring.c_str() ) );
|
||||
return Value( czstring.c_str() );
|
||||
}
|
||||
return Value( czstring.index() );
|
||||
#else
|
||||
if ( isArray_ )
|
||||
return Value( ValueInternalArray::indexOf( iterator_.array_ ) );
|
||||
bool isStatic;
|
||||
const char *memberName = ValueInternalMap::key( iterator_.map_, isStatic );
|
||||
if ( isStatic )
|
||||
return Value( StaticString( memberName ) );
|
||||
return Value( memberName );
|
||||
#endif
|
||||
Value ValueIteratorBase::key() const {
|
||||
const Value::CZString czstring = (*current_).first;
|
||||
if (czstring.data()) {
|
||||
if (czstring.isStaticString())
|
||||
return Value(StaticString(czstring.data()));
|
||||
return Value(czstring.data(), czstring.data() + czstring.length());
|
||||
}
|
||||
return Value(czstring.index());
|
||||
}
|
||||
|
||||
|
||||
UInt
|
||||
ValueIteratorBase::index() const
|
||||
{
|
||||
#ifndef JSON_VALUE_USE_INTERNAL_MAP
|
||||
const Value::CZString czstring = (*current_).first;
|
||||
if ( !czstring.c_str() )
|
||||
return czstring.index();
|
||||
return Value::UInt( -1 );
|
||||
#else
|
||||
if ( isArray_ )
|
||||
return Value::UInt( ValueInternalArray::indexOf( iterator_.array_ ) );
|
||||
return Value::UInt( -1 );
|
||||
#endif
|
||||
UInt ValueIteratorBase::index() const {
|
||||
const Value::CZString czstring = (*current_).first;
|
||||
if (!czstring.data())
|
||||
return czstring.index();
|
||||
return Value::UInt(-1);
|
||||
}
|
||||
|
||||
|
||||
const char *
|
||||
ValueIteratorBase::memberName() const
|
||||
{
|
||||
#ifndef JSON_VALUE_USE_INTERNAL_MAP
|
||||
const char *name = (*current_).first.c_str();
|
||||
return name ? name : "";
|
||||
#else
|
||||
if ( !isArray_ )
|
||||
return ValueInternalMap::key( iterator_.map_ );
|
||||
return "";
|
||||
#endif
|
||||
String ValueIteratorBase::name() const {
|
||||
char const* keey;
|
||||
char const* end;
|
||||
keey = memberName(&end);
|
||||
if (!keey)
|
||||
return String();
|
||||
return String(keey, end);
|
||||
}
|
||||
|
||||
char const* ValueIteratorBase::memberName() const {
|
||||
const char* cname = (*current_).first.data();
|
||||
return cname ? cname : "";
|
||||
}
|
||||
|
||||
char const* ValueIteratorBase::memberName(char const** end) const {
|
||||
const char* cname = (*current_).first.data();
|
||||
if (!cname) {
|
||||
*end = nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
*end = cname + (*current_).first.length();
|
||||
return cname;
|
||||
}
|
||||
|
||||
// //////////////////////////////////////////////////////////////////
|
||||
// //////////////////////////////////////////////////////////////////
|
||||
@ -214,35 +113,20 @@ ValueIteratorBase::memberName() const
|
||||
// //////////////////////////////////////////////////////////////////
|
||||
// //////////////////////////////////////////////////////////////////
|
||||
|
||||
ValueConstIterator::ValueConstIterator()
|
||||
{
|
||||
}
|
||||
ValueConstIterator::ValueConstIterator() = default;
|
||||
|
||||
ValueConstIterator::ValueConstIterator(
|
||||
const Value::ObjectValues::iterator& current)
|
||||
: ValueIteratorBase(current) {}
|
||||
|
||||
#ifndef JSON_VALUE_USE_INTERNAL_MAP
|
||||
ValueConstIterator::ValueConstIterator( const Value::ObjectValues::iterator ¤t )
|
||||
: ValueIteratorBase( current )
|
||||
{
|
||||
}
|
||||
#else
|
||||
ValueConstIterator::ValueConstIterator( const ValueInternalArray::IteratorState &state )
|
||||
: ValueIteratorBase( state )
|
||||
{
|
||||
}
|
||||
ValueConstIterator::ValueConstIterator(ValueIterator const& other)
|
||||
: ValueIteratorBase(other) {}
|
||||
|
||||
ValueConstIterator::ValueConstIterator( const ValueInternalMap::IteratorState &state )
|
||||
: ValueIteratorBase( state )
|
||||
{
|
||||
ValueConstIterator& ValueConstIterator::
|
||||
operator=(const ValueIteratorBase& other) {
|
||||
copy(other);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
ValueConstIterator &
|
||||
ValueConstIterator::operator =( const ValueIteratorBase &other )
|
||||
{
|
||||
copy( other );
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
// //////////////////////////////////////////////////////////////////
|
||||
// //////////////////////////////////////////////////////////////////
|
||||
@ -252,41 +136,21 @@ ValueConstIterator::operator =( const ValueIteratorBase &other )
|
||||
// //////////////////////////////////////////////////////////////////
|
||||
// //////////////////////////////////////////////////////////////////
|
||||
|
||||
ValueIterator::ValueIterator()
|
||||
{
|
||||
ValueIterator::ValueIterator() = default;
|
||||
|
||||
ValueIterator::ValueIterator(const Value::ObjectValues::iterator& current)
|
||||
: ValueIteratorBase(current) {}
|
||||
|
||||
ValueIterator::ValueIterator(const ValueConstIterator& other)
|
||||
: ValueIteratorBase(other) {
|
||||
throwRuntimeError("ConstIterator to Iterator should never be allowed.");
|
||||
}
|
||||
|
||||
ValueIterator::ValueIterator(const ValueIterator& other) = default;
|
||||
|
||||
#ifndef JSON_VALUE_USE_INTERNAL_MAP
|
||||
ValueIterator::ValueIterator( const Value::ObjectValues::iterator ¤t )
|
||||
: ValueIteratorBase( current )
|
||||
{
|
||||
}
|
||||
#else
|
||||
ValueIterator::ValueIterator( const ValueInternalArray::IteratorState &state )
|
||||
: ValueIteratorBase( state )
|
||||
{
|
||||
ValueIterator& ValueIterator::operator=(const SelfType& other) {
|
||||
copy(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
ValueIterator::ValueIterator( const ValueInternalMap::IteratorState &state )
|
||||
: ValueIteratorBase( state )
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
ValueIterator::ValueIterator( const ValueConstIterator &other )
|
||||
: ValueIteratorBase( other )
|
||||
{
|
||||
}
|
||||
|
||||
ValueIterator::ValueIterator( const ValueIterator &other )
|
||||
: ValueIteratorBase( other )
|
||||
{
|
||||
}
|
||||
|
||||
ValueIterator &
|
||||
ValueIterator::operator =( const SelfType &other )
|
||||
{
|
||||
copy( other );
|
||||
return *this;
|
||||
}
|
||||
} // namespace Json
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,8 +0,0 @@
|
||||
Import( 'env buildLibrary' )
|
||||
|
||||
buildLibrary( env, Split( """
|
||||
json_reader.cpp
|
||||
json_value.cpp
|
||||
json_writer.cpp
|
||||
""" ),
|
||||
'json' )
|
39
src/test_lib_json/CMakeLists.txt
Normal file
39
src/test_lib_json/CMakeLists.txt
Normal file
@ -0,0 +1,39 @@
|
||||
# vim: et ts=4 sts=4 sw=4 tw=0
|
||||
|
||||
add_executable(jsoncpp_test
|
||||
jsontest.cpp
|
||||
jsontest.h
|
||||
fuzz.cpp
|
||||
fuzz.h
|
||||
main.cpp
|
||||
)
|
||||
|
||||
|
||||
if(BUILD_SHARED_LIBS)
|
||||
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
|
||||
add_compile_definitions( JSON_DLL )
|
||||
else()
|
||||
add_definitions( -DJSON_DLL )
|
||||
endif()
|
||||
target_link_libraries(jsoncpp_test jsoncpp_lib)
|
||||
else()
|
||||
target_link_libraries(jsoncpp_test jsoncpp_static)
|
||||
endif()
|
||||
|
||||
# another way to solve issue #90
|
||||
#set_target_properties(jsoncpp_test PROPERTIES COMPILE_FLAGS -ffloat-store)
|
||||
|
||||
## Create tests for dashboard submission, allows easy review of CI results https://my.cdash.org/index.php?project=jsoncpp
|
||||
add_test(NAME jsoncpp_test
|
||||
COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $<TARGET_FILE:jsoncpp_test>
|
||||
)
|
||||
set_target_properties(jsoncpp_test PROPERTIES OUTPUT_NAME jsoncpp_test)
|
||||
|
||||
# Run unit tests in post-build
|
||||
# (default cmake workflow hides away the test result into a file, resulting in poor dev workflow?!?)
|
||||
if(JSONCPP_WITH_POST_BUILD_UNITTEST)
|
||||
add_custom_command(TARGET jsoncpp_test
|
||||
POST_BUILD
|
||||
COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $<TARGET_FILE:jsoncpp_test>
|
||||
)
|
||||
endif()
|
54
src/test_lib_json/fuzz.cpp
Normal file
54
src/test_lib_json/fuzz.cpp
Normal file
@ -0,0 +1,54 @@
|
||||
// Copyright 2007-2019 The JsonCpp Authors
|
||||
// Distributed under MIT license, or public domain if desired and
|
||||
// recognized in your jurisdiction.
|
||||
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||
|
||||
#include "fuzz.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <json/config.h>
|
||||
#include <json/json.h>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace Json {
|
||||
class Exception;
|
||||
}
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
Json::CharReaderBuilder builder;
|
||||
|
||||
if (size < sizeof(uint32_t)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const uint32_t hash_settings = static_cast<uint32_t>(data[0]) |
|
||||
(static_cast<uint32_t>(data[1]) << 8) |
|
||||
(static_cast<uint32_t>(data[2]) << 16) |
|
||||
(static_cast<uint32_t>(data[3]) << 24);
|
||||
data += sizeof(uint32_t);
|
||||
size -= sizeof(uint32_t);
|
||||
|
||||
builder.settings_["failIfExtra"] = hash_settings & (1 << 0);
|
||||
builder.settings_["allowComments_"] = hash_settings & (1 << 1);
|
||||
builder.settings_["strictRoot_"] = hash_settings & (1 << 2);
|
||||
builder.settings_["allowDroppedNullPlaceholders_"] = hash_settings & (1 << 3);
|
||||
builder.settings_["allowNumericKeys_"] = hash_settings & (1 << 4);
|
||||
builder.settings_["allowSingleQuotes_"] = hash_settings & (1 << 5);
|
||||
builder.settings_["failIfExtra_"] = hash_settings & (1 << 6);
|
||||
builder.settings_["rejectDupKeys_"] = hash_settings & (1 << 7);
|
||||
builder.settings_["allowSpecialFloats_"] = hash_settings & (1 << 8);
|
||||
builder.settings_["collectComments"] = hash_settings & (1 << 9);
|
||||
builder.settings_["allowTrailingCommas_"] = hash_settings & (1 << 10);
|
||||
|
||||
std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
|
||||
|
||||
Json::Value root;
|
||||
const auto data_str = reinterpret_cast<const char*>(data);
|
||||
try {
|
||||
reader->parse(data_str, data_str + size, &root, nullptr);
|
||||
} catch (Json::Exception const&) {
|
||||
}
|
||||
// Whether it succeeded or not doesn't matter.
|
||||
return 0;
|
||||
}
|
54
src/test_lib_json/fuzz.dict
Normal file
54
src/test_lib_json/fuzz.dict
Normal file
@ -0,0 +1,54 @@
|
||||
#
|
||||
# AFL dictionary for JSON
|
||||
# -----------------------
|
||||
#
|
||||
# Just the very basics.
|
||||
#
|
||||
# Inspired by a dictionary by Jakub Wilk <jwilk@jwilk.net>
|
||||
#
|
||||
# https://github.com/rc0r/afl-fuzz/blob/master/dictionaries/json.dict
|
||||
#
|
||||
|
||||
"0"
|
||||
",0"
|
||||
":0"
|
||||
"0:"
|
||||
"-1.2e+3"
|
||||
|
||||
"true"
|
||||
"false"
|
||||
"null"
|
||||
|
||||
"\"\""
|
||||
",\"\""
|
||||
":\"\""
|
||||
"\"\":"
|
||||
|
||||
"{}"
|
||||
",{}"
|
||||
":{}"
|
||||
"{\"\":0}"
|
||||
"{{}}"
|
||||
|
||||
"[]"
|
||||
",[]"
|
||||
":[]"
|
||||
"[0]"
|
||||
"[[]]"
|
||||
|
||||
"''"
|
||||
"\\"
|
||||
"\\b"
|
||||
"\\f"
|
||||
"\\n"
|
||||
"\\r"
|
||||
"\\t"
|
||||
"\\u0000"
|
||||
"\\x00"
|
||||
"\\0"
|
||||
"\\uD800\\uDC00"
|
||||
"\\uDBFF\\uDFFF"
|
||||
|
||||
"\"\":0"
|
||||
"//"
|
||||
"/**/"
|
14
src/test_lib_json/fuzz.h
Normal file
14
src/test_lib_json/fuzz.h
Normal file
@ -0,0 +1,14 @@
|
||||
// Copyright 2007-2010 The JsonCpp Authors
|
||||
// Distributed under MIT license, or public domain if desired and
|
||||
// recognized in your jurisdiction.
|
||||
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||
|
||||
#ifndef FUZZ_H_INCLUDED
|
||||
#define FUZZ_H_INCLUDED
|
||||
|
||||
#include <cstddef>
|
||||
#include <stdint.h>
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size);
|
||||
|
||||
#endif // ifndef FUZZ_H_INCLUDED
|
@ -1,598 +1,430 @@
|
||||
// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
|
||||
// Distributed under MIT license, or public domain if desired and
|
||||
// recognized in your jurisdiction.
|
||||
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||
|
||||
#define _CRT_SECURE_NO_WARNINGS 1 // Prevents deprecation warning with MSVC
|
||||
#include "jsontest.h"
|
||||
#include <stdio.h>
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
// Used to install a report hook that prevent dialog on assertion and error.
|
||||
# include <crtdbg.h>
|
||||
#include <crtdbg.h>
|
||||
#endif // if defined(_MSC_VER)
|
||||
|
||||
#if defined(_WIN32)
|
||||
// Used to prevent dialog on memory fault.
|
||||
// Limits headers included by Windows.h
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# define NOSERVICE
|
||||
# define NOMCX
|
||||
# define NOIME
|
||||
# define NOSOUND
|
||||
# define NOCOMM
|
||||
# define NORPC
|
||||
# define NOGDI
|
||||
# define NOUSER
|
||||
# define NODRIVERS
|
||||
# define NOLOGERROR
|
||||
# define NOPROFILER
|
||||
# define NOMEMMGR
|
||||
# define NOLFILEIO
|
||||
# define NOOPENFILE
|
||||
# define NORESOURCE
|
||||
# define NOATOM
|
||||
# define NOLANGUAGE
|
||||
# define NOLSTRING
|
||||
# define NODBCS
|
||||
# define NOKEYBOARDINFO
|
||||
# define NOGDICAPMASKS
|
||||
# define NOCOLOR
|
||||
# define NOGDIOBJ
|
||||
# define NODRAWTEXT
|
||||
# define NOTEXTMETRIC
|
||||
# define NOSCALABLEFONT
|
||||
# define NOBITMAP
|
||||
# define NORASTEROPS
|
||||
# define NOMETAFILE
|
||||
# define NOSYSMETRICS
|
||||
# define NOSYSTEMPARAMSINFO
|
||||
# define NOMSG
|
||||
# define NOWINSTYLES
|
||||
# define NOWINOFFSETS
|
||||
# define NOSHOWWINDOW
|
||||
# define NODEFERWINDOWPOS
|
||||
# define NOVIRTUALKEYCODES
|
||||
# define NOKEYSTATES
|
||||
# define NOWH
|
||||
# define NOMENUS
|
||||
# define NOSCROLL
|
||||
# define NOCLIPBOARD
|
||||
# define NOICONS
|
||||
# define NOMB
|
||||
# define NOSYSCOMMANDS
|
||||
# define NOMDI
|
||||
# define NOCTLMGR
|
||||
# define NOWINMESSAGES
|
||||
# include <windows.h>
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define NOSERVICE
|
||||
#define NOMCX
|
||||
#define NOIME
|
||||
#define NOSOUND
|
||||
#define NOCOMM
|
||||
#define NORPC
|
||||
#define NOGDI
|
||||
#define NOUSER
|
||||
#define NODRIVERS
|
||||
#define NOLOGERROR
|
||||
#define NOPROFILER
|
||||
#define NOMEMMGR
|
||||
#define NOLFILEIO
|
||||
#define NOOPENFILE
|
||||
#define NORESOURCE
|
||||
#define NOATOM
|
||||
#define NOLANGUAGE
|
||||
#define NOLSTRING
|
||||
#define NODBCS
|
||||
#define NOKEYBOARDINFO
|
||||
#define NOGDICAPMASKS
|
||||
#define NOCOLOR
|
||||
#define NOGDIOBJ
|
||||
#define NODRAWTEXT
|
||||
#define NOTEXTMETRIC
|
||||
#define NOSCALABLEFONT
|
||||
#define NOBITMAP
|
||||
#define NORASTEROPS
|
||||
#define NOMETAFILE
|
||||
#define NOSYSMETRICS
|
||||
#define NOSYSTEMPARAMSINFO
|
||||
#define NOMSG
|
||||
#define NOWINSTYLES
|
||||
#define NOWINOFFSETS
|
||||
#define NOSHOWWINDOW
|
||||
#define NODEFERWINDOWPOS
|
||||
#define NOVIRTUALKEYCODES
|
||||
#define NOKEYSTATES
|
||||
#define NOWH
|
||||
#define NOMENUS
|
||||
#define NOSCROLL
|
||||
#define NOCLIPBOARD
|
||||
#define NOICONS
|
||||
#define NOMB
|
||||
#define NOSYSCOMMANDS
|
||||
#define NOMDI
|
||||
#define NOCTLMGR
|
||||
#define NOWINMESSAGES
|
||||
#include <windows.h>
|
||||
#endif // if defined(_WIN32)
|
||||
|
||||
namespace JsonTest {
|
||||
|
||||
|
||||
// class TestResult
|
||||
// //////////////////////////////////////////////////////////////////
|
||||
|
||||
TestResult::TestResult()
|
||||
: predicateId_( 1 )
|
||||
, lastUsedPredicateId_( 0 )
|
||||
, messageTarget_( 0 )
|
||||
{
|
||||
// The root predicate has id 0
|
||||
rootPredicateNode_.id_ = 0;
|
||||
rootPredicateNode_.next_ = 0;
|
||||
predicateStackTail_ = &rootPredicateNode_;
|
||||
TestResult::TestResult() {
|
||||
// The root predicate has id 0
|
||||
rootPredicateNode_.id_ = 0;
|
||||
rootPredicateNode_.next_ = nullptr;
|
||||
predicateStackTail_ = &rootPredicateNode_;
|
||||
}
|
||||
|
||||
void TestResult::setTestName(const Json::String& name) { name_ = name; }
|
||||
|
||||
void
|
||||
TestResult::setTestName( const std::string &name )
|
||||
{
|
||||
name_ = name;
|
||||
TestResult& TestResult::addFailure(const char* file, unsigned int line,
|
||||
const char* expr) {
|
||||
/// Walks the PredicateContext stack adding them to failures_ if not already
|
||||
/// added.
|
||||
unsigned int nestingLevel = 0;
|
||||
PredicateContext* lastNode = rootPredicateNode_.next_;
|
||||
for (; lastNode != nullptr; lastNode = lastNode->next_) {
|
||||
if (lastNode->id_ > lastUsedPredicateId_) // new PredicateContext
|
||||
{
|
||||
lastUsedPredicateId_ = lastNode->id_;
|
||||
addFailureInfo(lastNode->file_, lastNode->line_, lastNode->expr_,
|
||||
nestingLevel);
|
||||
// Link the PredicateContext to the failure for message target when
|
||||
// popping the PredicateContext.
|
||||
lastNode->failure_ = &(failures_.back());
|
||||
}
|
||||
++nestingLevel;
|
||||
}
|
||||
|
||||
// Adds the failed assertion
|
||||
addFailureInfo(file, line, expr, nestingLevel);
|
||||
messageTarget_ = &(failures_.back());
|
||||
return *this;
|
||||
}
|
||||
|
||||
TestResult &
|
||||
TestResult::addFailure( const char *file, unsigned int line,
|
||||
const char *expr )
|
||||
{
|
||||
/// Walks the PredicateContext stack adding them to failures_ if not already added.
|
||||
unsigned int nestingLevel = 0;
|
||||
PredicateContext *lastNode = rootPredicateNode_.next_;
|
||||
for ( ; lastNode != 0; lastNode = lastNode->next_ )
|
||||
{
|
||||
if ( lastNode->id_ > lastUsedPredicateId_ ) // new PredicateContext
|
||||
{
|
||||
lastUsedPredicateId_ = lastNode->id_;
|
||||
addFailureInfo( lastNode->file_, lastNode->line_, lastNode->expr_,
|
||||
nestingLevel );
|
||||
// Link the PredicateContext to the failure for message target when
|
||||
// popping the PredicateContext.
|
||||
lastNode->failure_ = &( failures_.back() );
|
||||
}
|
||||
++nestingLevel;
|
||||
}
|
||||
|
||||
// Adds the failed assertion
|
||||
addFailureInfo( file, line, expr, nestingLevel );
|
||||
messageTarget_ = &( failures_.back() );
|
||||
return *this;
|
||||
void TestResult::addFailureInfo(const char* file, unsigned int line,
|
||||
const char* expr, unsigned int nestingLevel) {
|
||||
Failure failure;
|
||||
failure.file_ = file;
|
||||
failure.line_ = line;
|
||||
if (expr) {
|
||||
failure.expr_ = expr;
|
||||
}
|
||||
failure.nestingLevel_ = nestingLevel;
|
||||
failures_.push_back(failure);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TestResult::addFailureInfo( const char *file, unsigned int line,
|
||||
const char *expr, unsigned int nestingLevel )
|
||||
{
|
||||
Failure failure;
|
||||
failure.file_ = file;
|
||||
failure.line_ = line;
|
||||
if ( expr )
|
||||
{
|
||||
failure.expr_ = expr;
|
||||
}
|
||||
failure.nestingLevel_ = nestingLevel;
|
||||
failures_.push_back( failure );
|
||||
TestResult& TestResult::popPredicateContext() {
|
||||
PredicateContext* lastNode = &rootPredicateNode_;
|
||||
while (lastNode->next_ != nullptr && lastNode->next_->next_ != nullptr) {
|
||||
lastNode = lastNode->next_;
|
||||
}
|
||||
// Set message target to popped failure
|
||||
PredicateContext* tail = lastNode->next_;
|
||||
if (tail != nullptr && tail->failure_ != nullptr) {
|
||||
messageTarget_ = tail->failure_;
|
||||
}
|
||||
// Remove tail from list
|
||||
predicateStackTail_ = lastNode;
|
||||
lastNode->next_ = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool TestResult::failed() const { return !failures_.empty(); }
|
||||
|
||||
TestResult &
|
||||
TestResult::popPredicateContext()
|
||||
{
|
||||
PredicateContext *lastNode = &rootPredicateNode_;
|
||||
while ( lastNode->next_ != 0 && lastNode->next_->next_ != 0 )
|
||||
{
|
||||
lastNode = lastNode->next_;
|
||||
}
|
||||
// Set message target to popped failure
|
||||
PredicateContext *tail = lastNode->next_;
|
||||
if ( tail != 0 && tail->failure_ != 0 )
|
||||
{
|
||||
messageTarget_ = tail->failure_;
|
||||
}
|
||||
// Remove tail from list
|
||||
predicateStackTail_ = lastNode;
|
||||
lastNode->next_ = 0;
|
||||
return *this;
|
||||
void TestResult::printFailure(bool printTestName) const {
|
||||
if (failures_.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (printTestName) {
|
||||
printf("* Detail of %s test failure:\n", name_.c_str());
|
||||
}
|
||||
|
||||
// Print in reverse to display the callstack in the right order
|
||||
for (const auto& failure : failures_) {
|
||||
Json::String indent(failure.nestingLevel_ * 2, ' ');
|
||||
if (failure.file_) {
|
||||
printf("%s%s(%u): ", indent.c_str(), failure.file_, failure.line_);
|
||||
}
|
||||
if (!failure.expr_.empty()) {
|
||||
printf("%s\n", failure.expr_.c_str());
|
||||
} else if (failure.file_) {
|
||||
printf("\n");
|
||||
}
|
||||
if (!failure.message_.empty()) {
|
||||
Json::String reindented = indentText(failure.message_, indent + " ");
|
||||
printf("%s\n", reindented.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
TestResult::failed() const
|
||||
{
|
||||
return !failures_.empty();
|
||||
Json::String TestResult::indentText(const Json::String& text,
|
||||
const Json::String& indent) {
|
||||
Json::String reindented;
|
||||
Json::String::size_type lastIndex = 0;
|
||||
while (lastIndex < text.size()) {
|
||||
Json::String::size_type nextIndex = text.find('\n', lastIndex);
|
||||
if (nextIndex == Json::String::npos) {
|
||||
nextIndex = text.size() - 1;
|
||||
}
|
||||
reindented += indent;
|
||||
reindented += text.substr(lastIndex, nextIndex - lastIndex + 1);
|
||||
lastIndex = nextIndex + 1;
|
||||
}
|
||||
return reindented;
|
||||
}
|
||||
|
||||
|
||||
unsigned int
|
||||
TestResult::getAssertionNestingLevel() const
|
||||
{
|
||||
unsigned int level = 0;
|
||||
const PredicateContext *lastNode = &rootPredicateNode_;
|
||||
while ( lastNode->next_ != 0 )
|
||||
{
|
||||
lastNode = lastNode->next_;
|
||||
++level;
|
||||
}
|
||||
return level;
|
||||
TestResult& TestResult::addToLastFailure(const Json::String& message) {
|
||||
if (messageTarget_ != nullptr) {
|
||||
messageTarget_->message_ += message;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TestResult::printFailure( bool printTestName ) const
|
||||
{
|
||||
if ( failures_.empty() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( printTestName )
|
||||
{
|
||||
printf( "* Detail of %s test failure:\n", name_.c_str() );
|
||||
}
|
||||
|
||||
// Print in reverse to display the callstack in the right order
|
||||
Failures::const_iterator itEnd = failures_.end();
|
||||
for ( Failures::const_iterator it = failures_.begin(); it != itEnd; ++it )
|
||||
{
|
||||
const Failure &failure = *it;
|
||||
std::string indent( failure.nestingLevel_ * 2, ' ' );
|
||||
if ( failure.file_ )
|
||||
{
|
||||
printf( "%s%s(%d): ", indent.c_str(), failure.file_, failure.line_ );
|
||||
}
|
||||
if ( !failure.expr_.empty() )
|
||||
{
|
||||
printf( "%s\n", failure.expr_.c_str() );
|
||||
}
|
||||
else if ( failure.file_ )
|
||||
{
|
||||
printf( "\n" );
|
||||
}
|
||||
if ( !failure.message_.empty() )
|
||||
{
|
||||
std::string reindented = indentText( failure.message_, indent + " " );
|
||||
printf( "%s\n", reindented.c_str() );
|
||||
}
|
||||
}
|
||||
TestResult& TestResult::operator<<(Json::Int64 value) {
|
||||
return addToLastFailure(Json::valueToString(value));
|
||||
}
|
||||
|
||||
|
||||
std::string
|
||||
TestResult::indentText( const std::string &text,
|
||||
const std::string &indent )
|
||||
{
|
||||
std::string reindented;
|
||||
std::string::size_type lastIndex = 0;
|
||||
while ( lastIndex < text.size() )
|
||||
{
|
||||
std::string::size_type nextIndex = text.find( '\n', lastIndex );
|
||||
if ( nextIndex == std::string::npos )
|
||||
{
|
||||
nextIndex = text.size() - 1;
|
||||
}
|
||||
reindented += indent;
|
||||
reindented += text.substr( lastIndex, nextIndex - lastIndex + 1 );
|
||||
lastIndex = nextIndex + 1;
|
||||
}
|
||||
return reindented;
|
||||
TestResult& TestResult::operator<<(Json::UInt64 value) {
|
||||
return addToLastFailure(Json::valueToString(value));
|
||||
}
|
||||
|
||||
|
||||
TestResult &
|
||||
TestResult::addToLastFailure( const std::string &message )
|
||||
{
|
||||
if ( messageTarget_ != 0 )
|
||||
{
|
||||
messageTarget_->message_ += message;
|
||||
}
|
||||
return *this;
|
||||
TestResult& TestResult::operator<<(bool value) {
|
||||
return addToLastFailure(value ? "true" : "false");
|
||||
}
|
||||
|
||||
|
||||
TestResult &
|
||||
TestResult::operator << ( bool value )
|
||||
{
|
||||
return addToLastFailure( value ? "true" : "false" );
|
||||
}
|
||||
|
||||
|
||||
TestResult &
|
||||
TestResult::operator << ( int value )
|
||||
{
|
||||
char buffer[32];
|
||||
sprintf( buffer, "%d", value );
|
||||
return addToLastFailure( buffer );
|
||||
}
|
||||
|
||||
|
||||
TestResult &
|
||||
TestResult::operator << ( unsigned int value )
|
||||
{
|
||||
char buffer[32];
|
||||
sprintf( buffer, "%u", value );
|
||||
return addToLastFailure( buffer );
|
||||
}
|
||||
|
||||
|
||||
TestResult &
|
||||
TestResult::operator << ( double value )
|
||||
{
|
||||
char buffer[32];
|
||||
sprintf( buffer, "%16g", value );
|
||||
return addToLastFailure( buffer );
|
||||
}
|
||||
|
||||
|
||||
TestResult &
|
||||
TestResult::operator << ( const char *value )
|
||||
{
|
||||
return addToLastFailure( value ? value
|
||||
: "<NULL>" );
|
||||
}
|
||||
|
||||
|
||||
TestResult &
|
||||
TestResult::operator << ( const std::string &value )
|
||||
{
|
||||
return addToLastFailure( value );
|
||||
}
|
||||
|
||||
|
||||
|
||||
// class TestCase
|
||||
// //////////////////////////////////////////////////////////////////
|
||||
|
||||
TestCase::TestCase()
|
||||
: result_( 0 )
|
||||
{
|
||||
TestCase::TestCase() = default;
|
||||
|
||||
TestCase::~TestCase() = default;
|
||||
|
||||
void TestCase::run(TestResult& result) {
|
||||
result_ = &result;
|
||||
runTestCase();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TestCase::run( TestResult &result )
|
||||
{
|
||||
result_ = &result;
|
||||
runTestCase();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// class Runner
|
||||
// //////////////////////////////////////////////////////////////////
|
||||
|
||||
Runner::Runner()
|
||||
{
|
||||
Runner::Runner() = default;
|
||||
|
||||
Runner& Runner::add(TestCaseFactory factory) {
|
||||
tests_.push_back(factory);
|
||||
return *this;
|
||||
}
|
||||
|
||||
size_t Runner::testCount() const { return tests_.size(); }
|
||||
|
||||
Runner &
|
||||
Runner::add( TestCaseFactory factory )
|
||||
{
|
||||
tests_.push_back( factory );
|
||||
return *this;
|
||||
Json::String Runner::testNameAt(size_t index) const {
|
||||
TestCase* test = tests_[index]();
|
||||
Json::String name = test->testName();
|
||||
delete test;
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
unsigned int
|
||||
Runner::testCount() const
|
||||
{
|
||||
return static_cast<unsigned int>( tests_.size() );
|
||||
}
|
||||
|
||||
|
||||
std::string
|
||||
Runner::testNameAt( unsigned int index ) const
|
||||
{
|
||||
TestCase *test = tests_[index]();
|
||||
std::string name = test->testName();
|
||||
delete test;
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Runner::runTestAt( unsigned int index, TestResult &result ) const
|
||||
{
|
||||
TestCase *test = tests_[index]();
|
||||
result.setTestName( test->testName() );
|
||||
printf( "Testing %s: ", test->testName() );
|
||||
fflush( stdout );
|
||||
void Runner::runTestAt(size_t index, TestResult& result) const {
|
||||
TestCase* test = tests_[index]();
|
||||
result.setTestName(test->testName());
|
||||
printf("Testing %s: ", test->testName());
|
||||
fflush(stdout);
|
||||
#if JSON_USE_EXCEPTION
|
||||
try
|
||||
{
|
||||
try {
|
||||
#endif // if JSON_USE_EXCEPTION
|
||||
test->run( result );
|
||||
test->run(result);
|
||||
#if JSON_USE_EXCEPTION
|
||||
}
|
||||
catch ( const std::exception &e )
|
||||
{
|
||||
result.addFailure( __FILE__, __LINE__,
|
||||
"Unexpected exception caugth:" ) << e.what();
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
result.addFailure(__FILE__, __LINE__, "Unexpected exception caught:")
|
||||
<< e.what();
|
||||
}
|
||||
#endif // if JSON_USE_EXCEPTION
|
||||
delete test;
|
||||
const char *status = result.failed() ? "FAILED"
|
||||
: "OK";
|
||||
printf( "%s\n", status );
|
||||
fflush( stdout );
|
||||
delete test;
|
||||
const char* status = result.failed() ? "FAILED" : "OK";
|
||||
printf("%s\n", status);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
bool Runner::runAllTest(bool printSummary) const {
|
||||
size_t const count = testCount();
|
||||
std::deque<TestResult> failures;
|
||||
for (size_t index = 0; index < count; ++index) {
|
||||
TestResult result;
|
||||
runTestAt(index, result);
|
||||
if (result.failed()) {
|
||||
failures.push_back(result);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
Runner::runAllTest( bool printSummary ) const
|
||||
{
|
||||
unsigned int count = testCount();
|
||||
std::deque<TestResult> failures;
|
||||
for ( unsigned int index = 0; index < count; ++index )
|
||||
{
|
||||
TestResult result;
|
||||
runTestAt( index, result );
|
||||
if ( result.failed() )
|
||||
{
|
||||
failures.push_back( result );
|
||||
}
|
||||
}
|
||||
if (failures.empty()) {
|
||||
if (printSummary) {
|
||||
printf("All %zu tests passed\n", count);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
for (auto& result : failures) {
|
||||
result.printFailure(count > 1);
|
||||
}
|
||||
|
||||
if ( failures.empty() )
|
||||
{
|
||||
if ( printSummary )
|
||||
{
|
||||
printf( "All %d tests passed\n", count );
|
||||
}
|
||||
if (printSummary) {
|
||||
size_t const failedCount = failures.size();
|
||||
size_t const passedCount = count - failedCount;
|
||||
printf("%zu/%zu tests passed (%zu failure(s))\n", passedCount, count,
|
||||
failedCount);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Runner::testIndex(const Json::String& testName, size_t& indexOut) const {
|
||||
const size_t count = testCount();
|
||||
for (size_t index = 0; index < count; ++index) {
|
||||
if (testNameAt(index) == testName) {
|
||||
indexOut = index;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( unsigned int index = 0; index < failures.size(); ++index )
|
||||
{
|
||||
TestResult &result = failures[index];
|
||||
result.printFailure( count > 1 );
|
||||
}
|
||||
|
||||
if ( printSummary )
|
||||
{
|
||||
unsigned int failedCount = static_cast<unsigned int>( failures.size() );
|
||||
unsigned int passedCount = count - failedCount;
|
||||
printf( "%d/%d tests passed (%d failure(s))\n", passedCount, count, failedCount );
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Runner::testIndex( const std::string &testName,
|
||||
unsigned int &indexOut ) const
|
||||
{
|
||||
unsigned int count = testCount();
|
||||
for ( unsigned int index = 0; index < count; ++index )
|
||||
{
|
||||
if ( testNameAt(index) == testName )
|
||||
{
|
||||
indexOut = index;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
void Runner::listTests() const {
|
||||
const size_t count = testCount();
|
||||
for (size_t index = 0; index < count; ++index) {
|
||||
printf("%s\n", testNameAt(index).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Runner::listTests() const
|
||||
{
|
||||
unsigned int count = testCount();
|
||||
for ( unsigned int index = 0; index < count; ++index )
|
||||
{
|
||||
printf( "%s\n", testNameAt( index ).c_str() );
|
||||
}
|
||||
int Runner::runCommandLine(int argc, const char* argv[]) const {
|
||||
// typedef std::deque<String> TestNames;
|
||||
Runner subrunner;
|
||||
for (int index = 1; index < argc; ++index) {
|
||||
Json::String opt = argv[index];
|
||||
if (opt == "--list-tests") {
|
||||
listTests();
|
||||
return 0;
|
||||
}
|
||||
if (opt == "--test-auto") {
|
||||
preventDialogOnCrash();
|
||||
} else if (opt == "--test") {
|
||||
++index;
|
||||
if (index < argc) {
|
||||
size_t testNameIndex;
|
||||
if (testIndex(argv[index], testNameIndex)) {
|
||||
subrunner.add(tests_[testNameIndex]);
|
||||
} else {
|
||||
fprintf(stderr, "Test '%s' does not exist!\n", argv[index]);
|
||||
return 2;
|
||||
}
|
||||
} else {
|
||||
printUsage(argv[0]);
|
||||
return 2;
|
||||
}
|
||||
} else {
|
||||
printUsage(argv[0]);
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
bool succeeded;
|
||||
if (subrunner.testCount() > 0) {
|
||||
succeeded = subrunner.runAllTest(subrunner.testCount() > 1);
|
||||
} else {
|
||||
succeeded = runAllTest(true);
|
||||
}
|
||||
return succeeded ? 0 : 1;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
Runner::runCommandLine( int argc, const char *argv[] ) const
|
||||
{
|
||||
typedef std::deque<std::string> TestNames;
|
||||
Runner subrunner;
|
||||
for ( int index = 1; index < argc; ++index )
|
||||
{
|
||||
std::string opt = argv[index];
|
||||
if ( opt == "--list-tests" )
|
||||
{
|
||||
listTests();
|
||||
return 0;
|
||||
}
|
||||
else if ( opt == "--test-auto" )
|
||||
{
|
||||
preventDialogOnCrash();
|
||||
}
|
||||
else if ( opt == "--test" )
|
||||
{
|
||||
++index;
|
||||
if ( index < argc )
|
||||
{
|
||||
unsigned int testNameIndex;
|
||||
if ( testIndex( argv[index], testNameIndex ) )
|
||||
{
|
||||
subrunner.add( tests_[testNameIndex] );
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf( stderr, "Test '%s' does not exist!\n", argv[index] );
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printUsage( argv[0] );
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printUsage( argv[0] );
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
bool succeeded;
|
||||
if ( subrunner.testCount() > 0 )
|
||||
{
|
||||
succeeded = subrunner.runAllTest( subrunner.testCount() > 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
succeeded = runAllTest( true );
|
||||
}
|
||||
return succeeded ? 0
|
||||
: 1;
|
||||
}
|
||||
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#if defined(_MSC_VER) && defined(_DEBUG)
|
||||
// Hook MSVCRT assertions to prevent dialog from appearing
|
||||
static int
|
||||
msvcrtSilentReportHook( int reportType, char *message, int *returnValue )
|
||||
{
|
||||
// The default CRT handling of error and assertion is to display
|
||||
// an error dialog to the user.
|
||||
// Instead, when an error or an assertion occurs, we force the
|
||||
// application to terminate using abort() after display
|
||||
// the message on stderr.
|
||||
if ( reportType == _CRT_ERROR ||
|
||||
reportType == _CRT_ASSERT )
|
||||
{
|
||||
// calling abort() cause the ReportHook to be called
|
||||
// The following is used to detect this case and let's the
|
||||
// error handler fallback on its default behaviour (
|
||||
// display a warning message)
|
||||
static volatile bool isAborting = false;
|
||||
if ( isAborting )
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
isAborting = true;
|
||||
static int msvcrtSilentReportHook(int reportType, char* message,
|
||||
int* /*returnValue*/) {
|
||||
// The default CRT handling of error and assertion is to display
|
||||
// an error dialog to the user.
|
||||
// Instead, when an error or an assertion occurs, we force the
|
||||
// application to terminate using abort() after display
|
||||
// the message on stderr.
|
||||
if (reportType == _CRT_ERROR || reportType == _CRT_ASSERT) {
|
||||
// calling abort() cause the ReportHook to be called
|
||||
// The following is used to detect this case and let's the
|
||||
// error handler fallback on its default behaviour (
|
||||
// display a warning message)
|
||||
static volatile bool isAborting = false;
|
||||
if (isAborting) {
|
||||
return TRUE;
|
||||
}
|
||||
isAborting = true;
|
||||
|
||||
fprintf( stderr, "CRT Error/Assert:\n%s\n", message );
|
||||
fflush( stderr );
|
||||
abort();
|
||||
}
|
||||
// Let's other reportType (_CRT_WARNING) be handled as they would by default
|
||||
return FALSE;
|
||||
fprintf(stderr, "CRT Error/Assert:\n%s\n", message);
|
||||
fflush(stderr);
|
||||
abort();
|
||||
}
|
||||
// Let's other reportType (_CRT_WARNING) be handled as they would by default
|
||||
return FALSE;
|
||||
}
|
||||
#endif // if defined(_MSC_VER)
|
||||
|
||||
|
||||
void
|
||||
Runner::preventDialogOnCrash()
|
||||
{
|
||||
#if defined(_MSC_VER)
|
||||
// Install a hook to prevent MSVCRT error and assertion from
|
||||
// popping a dialog.
|
||||
_CrtSetReportHook( &msvcrtSilentReportHook );
|
||||
void Runner::preventDialogOnCrash() {
|
||||
#if defined(_MSC_VER) && defined(_DEBUG)
|
||||
// Install a hook to prevent MSVCRT error and assertion from
|
||||
// popping a dialog
|
||||
// This function a NO-OP in release configuration
|
||||
// (which cause warning since msvcrtSilentReportHook is not referenced)
|
||||
_CrtSetReportHook(&msvcrtSilentReportHook);
|
||||
#endif // if defined(_MSC_VER)
|
||||
|
||||
// @todo investiguate this handler (for buffer overflow)
|
||||
// _set_security_error_handler
|
||||
// @todo investigate this handler (for buffer overflow)
|
||||
// _set_security_error_handler
|
||||
|
||||
#if defined(_WIN32)
|
||||
// Prevents the system from popping a dialog for debugging if the
|
||||
// application fails due to invalid memory access.
|
||||
SetErrorMode( SEM_FAILCRITICALERRORS
|
||||
| SEM_NOGPFAULTERRORBOX
|
||||
| SEM_NOOPENFILEERRORBOX );
|
||||
// Prevents the system from popping a dialog for debugging if the
|
||||
// application fails due to invalid memory access.
|
||||
SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX |
|
||||
SEM_NOOPENFILEERRORBOX);
|
||||
#endif // if defined(_WIN32)
|
||||
}
|
||||
|
||||
void
|
||||
Runner::printUsage( const char *appName )
|
||||
{
|
||||
printf(
|
||||
"Usage: %s [options]\n"
|
||||
"\n"
|
||||
"If --test is not specified, then all the test cases be run.\n"
|
||||
"\n"
|
||||
"Valid options:\n"
|
||||
"--list-tests: print the name of all test cases on the standard\n"
|
||||
" output and exit.\n"
|
||||
"--test TESTNAME: executes the test case with the specified name.\n"
|
||||
" May be repeated.\n"
|
||||
"--test-auto: prevent dialog prompting for debugging on crash.\n"
|
||||
, appName );
|
||||
void Runner::printUsage(const char* appName) {
|
||||
printf("Usage: %s [options]\n"
|
||||
"\n"
|
||||
"If --test is not specified, then all the test cases be run.\n"
|
||||
"\n"
|
||||
"Valid options:\n"
|
||||
"--list-tests: print the name of all test cases on the standard\n"
|
||||
" output and exit.\n"
|
||||
"--test TESTNAME: executes the test case with the specified name.\n"
|
||||
" May be repeated.\n"
|
||||
"--test-auto: prevent dialog prompting for debugging on crash.\n",
|
||||
appName);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Assertion functions
|
||||
// //////////////////////////////////////////////////////////////////
|
||||
|
||||
TestResult &
|
||||
checkStringEqual( TestResult &result,
|
||||
const std::string &expected, const std::string &actual,
|
||||
const char *file, unsigned int line, const char *expr )
|
||||
{
|
||||
if ( expected != actual )
|
||||
{
|
||||
result.addFailure( file, line, expr );
|
||||
result << "Expected: '" << expected << "'\n";
|
||||
result << "Actual : '" << actual << "'";
|
||||
}
|
||||
return result;
|
||||
Json::String ToJsonString(const char* toConvert) {
|
||||
return Json::String(toConvert);
|
||||
}
|
||||
|
||||
Json::String ToJsonString(Json::String in) { return in; }
|
||||
|
||||
#if JSONCPP_USE_SECURE_MEMORY
|
||||
Json::String ToJsonString(std::string in) {
|
||||
return Json::String(in.data(), in.data() + in.length());
|
||||
}
|
||||
#endif
|
||||
|
||||
TestResult& checkStringEqual(TestResult& result, const Json::String& expected,
|
||||
const Json::String& actual, const char* file,
|
||||
unsigned int line, const char* expr) {
|
||||
if (expected != actual) {
|
||||
result.addFailure(file, line, expr);
|
||||
result << "Expected: '" << expected << "'\n";
|
||||
result << "Actual : '" << actual << "'";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace JsonTest
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user