Compare commits
662
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
39e6e2139d | ||
|
|
9b0c3ae4f3 | ||
|
|
99f390a38c | ||
|
|
6f45e4dd2f | ||
|
|
47de5c60c8 | ||
|
|
871954bcc3 | ||
|
|
f41d85c224 | ||
|
|
18e7658445 | ||
|
|
ca522b7a23 | ||
|
|
32fccbfb69 | ||
|
|
27720a3127 | ||
|
|
6e3d1c7b8e | ||
|
|
625738b7b5 | ||
|
|
ef34d7efd8 | ||
|
|
40917782b0 | ||
|
|
e906bfec64 | ||
|
|
6b2845aa90 | ||
|
|
65fbea141d | ||
|
|
c6635005a1 | ||
|
|
72c21912a1 | ||
|
|
3142e62a10 | ||
|
|
1a82f5152e | ||
|
|
722ab02d2b | ||
|
|
6f352a5c95 | ||
|
|
ef3f7cc430 | ||
|
|
17b98adf74 | ||
|
|
809734eca8 | ||
|
|
ec87a2311d | ||
|
|
58bdb4e00d | ||
|
|
ee629278cf | ||
|
|
09ca8f504f | ||
|
|
fd6926eee8 | ||
|
|
5ae46fef77 | ||
|
|
07d12cbf94 | ||
|
|
e75dd34213 | ||
|
|
73294f1b76 | ||
|
|
1ca34db259 | ||
|
|
c35865a620 | ||
|
|
7a3804f1cd | ||
|
|
dd10feb286 | ||
|
|
f03b571f05 | ||
|
|
07aa53dffa | ||
|
|
68b42bdb01 | ||
|
|
2d7e6b1ec2 | ||
|
|
db0df50b53 | ||
|
|
bb6662a2c1 | ||
|
|
e1f98a3209 | ||
|
|
1f3b2c5cab | ||
|
|
cd1f4631dd | ||
|
|
4a1a7308dd | ||
|
|
7da668c136 | ||
|
|
304e669de2 | ||
|
|
9d86c85686 | ||
|
|
410680cadf | ||
|
|
64bd5eef4f | ||
|
|
3619d4b22c | ||
|
|
baa9dbfe76 | ||
|
|
11241b9b37 | ||
|
|
eb3fad64b0 | ||
|
|
cb97f26c89 | ||
|
|
5739f948b8 | ||
|
|
bdfb00aa22 | ||
|
|
50611fe4a3 | ||
|
|
4a193bd0e2 | ||
|
|
75907e2bd5 | ||
|
|
73d670c0dc | ||
|
|
688a6c8512 | ||
|
|
551430e256 | ||
|
|
c57312fb4d | ||
|
|
418201de6b | ||
|
|
5e1a83db8d | ||
|
|
e0ad6f72c0 | ||
|
|
8a22d7e318 | ||
|
|
856ba177aa | ||
|
|
54819d7d9b | ||
|
|
aaf9229f7e | ||
|
|
009a00c041 | ||
|
|
104742c9c0 | ||
|
|
1ea17a2a4e | ||
|
|
e68f6d5eb1 | ||
|
|
6bc397b497 | ||
|
|
343af5d8a3 | ||
|
|
ff8727b92d | ||
|
|
5d85dfa197 | ||
|
|
842740ceb3 | ||
|
|
79894864a0 | ||
|
|
f3021651eb | ||
|
|
459b808f4a | ||
|
|
49497c9be5 | ||
|
|
585524a8b2 | ||
|
|
c46771e8b6 | ||
|
|
244fc647fb | ||
|
|
57d7b4ba50 | ||
|
|
97e4276e20 | ||
|
|
d947882b0e | ||
|
|
61479c1198 | ||
|
|
1871358bde | ||
|
|
8bdf899da8 | ||
|
|
63c400543f | ||
|
|
6a339c273e | ||
|
|
16fc526b92 | ||
|
|
8f8e0a8b8e | ||
|
|
36fa0a8237 | ||
|
|
9abd1e68f2 | ||
|
|
de56bd3237 | ||
|
|
47712b704a | ||
|
|
6cf2b5fed2 | ||
|
|
e2fe3a04ce | ||
|
|
7aafc1b35e | ||
|
|
0165952b69 | ||
|
|
bc9e07a287 | ||
|
|
67a5f6fea2 | ||
|
|
5e374fcb56 | ||
|
|
639be9c210 | ||
|
|
62e82dbc42 | ||
|
|
6fa1aa036f | ||
|
|
92e825a73c | ||
|
|
f12fa9c524 | ||
|
|
a412f96701 | ||
|
|
ee4308cb73 | ||
|
|
5af3b094fa | ||
|
|
f18d00fd80 | ||
|
|
acb2bb7c1b | ||
|
|
56ca93c9d9 | ||
|
|
2c711a1224 | ||
|
|
12bffe1cd4 | ||
|
|
b6d7111f2d | ||
|
|
4113b02fb4 | ||
|
|
c050f764a7 | ||
|
|
065414cb2c | ||
|
|
c320fadffe | ||
|
|
6899d4ea28 | ||
|
|
4ce6c7930a | ||
|
|
9964d36689 | ||
|
|
d4da7a4e8f | ||
|
|
0c7ed9c384 | ||
|
|
e402b8ad83 | ||
|
|
b523ab22f0 | ||
|
|
2aa6ebac49 | ||
|
|
42f2727268 | ||
|
|
d3d79b5f2a | ||
|
|
44189a8371 | ||
|
|
a5bbb3b08e | ||
|
|
bc96653e77 | ||
|
|
5657fc81e3 | ||
|
|
4751372f9a | ||
|
|
0aaa6e18fd | ||
|
|
d68fe93422 | ||
|
|
9e294e7573 | ||
|
|
37ef7e6369 | ||
|
|
2d27abe4c3 | ||
|
|
2bb3a2b6b5 | ||
|
|
1443007f93 | ||
|
|
81b94a3857 | ||
|
|
2ee020d505 | ||
|
|
6b008ffd08 | ||
|
|
c76adbe257 | ||
|
|
09e3d00025 | ||
|
|
063ce5be73 | ||
|
|
eff9bb399f | ||
|
|
59afa2e2e1 | ||
|
|
38f6c71551 | ||
|
|
b303dfb80c | ||
|
|
de44f120af | ||
|
|
eb2c620ad2 | ||
|
|
276414f38f | ||
|
|
0248b73bde | ||
|
|
5722272435 | ||
|
|
d95ffbcedc | ||
|
|
d267cbbb73 | ||
|
|
1d2825c0ff | ||
|
|
b363a45374 | ||
|
|
f5a638bf8f | ||
|
|
be67f67abb | ||
|
|
1b9ce5f9b7 | ||
|
|
7fb411adce | ||
|
|
cac881ea1b | ||
|
|
07a72f6943 | ||
|
|
b6f64b4804 | ||
|
|
fa5cc6ab38 | ||
|
|
664424c91c | ||
|
|
0b463f4e65 | ||
|
|
ea0f1153e4 | ||
|
|
ff4bab71f3 | ||
|
|
c1fdc2e8be | ||
|
|
2ddb12212f | ||
|
|
06c694ea8a | ||
|
|
2cdea43eb5 | ||
|
|
10f105d48d | ||
|
|
fb69e75019 | ||
|
|
d3736df90f | ||
|
|
337828ff62 | ||
|
|
6ba4354e4c | ||
|
|
c5830493fe | ||
|
|
87c72d43dc | ||
|
|
47e70272d2 | ||
|
|
d04d711706 | ||
|
|
d77effe8e1 | ||
|
|
5606e690e6 | ||
|
|
8f50979f90 | ||
|
|
61e61e8bb8 | ||
|
|
b4baefb802 | ||
|
|
40c09084bd | ||
|
|
c0d622a02b | ||
|
|
99a17a81ff | ||
|
|
86c40fd487 | ||
|
|
e13dcaab58 | ||
|
|
4532c8644f | ||
|
|
cb97978fb0 | ||
|
|
3a13bb389a | ||
|
|
ddf7c89b61 | ||
|
|
3078dfda73 | ||
|
|
331d906a12 | ||
|
|
ef0ffdc243 | ||
|
|
97229a8f1a | ||
|
|
8c77499015 | ||
|
|
e1954f9ac9 | ||
|
|
a4a7ee384b | ||
|
|
5dfd2d96b5 | ||
|
|
d6b3f102de | ||
|
|
949b0b5b72 | ||
|
|
37e2d2ee13 | ||
|
|
bfdf6228be | ||
|
|
bc408c0c75 | ||
|
|
1486c1185c | ||
|
|
cb06d07eea | ||
|
|
c7205fcdd0 | ||
|
|
911347e080 | ||
|
|
a65eaf1cc4 | ||
|
|
fe2235bc8d | ||
|
|
2417b430fd | ||
|
|
be81e9af47 | ||
|
|
5e4858e860 | ||
|
|
9b82083a60 | ||
|
|
30f322a60a | ||
|
|
58015a396e | ||
|
|
939bdc5f56 | ||
|
|
2939cb601f | ||
|
|
2454f89ec4 | ||
|
|
df13b0c76f | ||
|
|
b4f87c21e0 | ||
|
|
9cfa28a91d | ||
|
|
6ade868afe | ||
|
|
1230424577 | ||
|
|
9bbada0740 | ||
|
|
44b3709c8f | ||
|
|
cabcd406f7 | ||
|
|
1c0026c108 | ||
|
|
11e862ae06 | ||
|
|
4deeacda4a | ||
|
|
9a0bf98b2c | ||
|
|
c286c3646b | ||
|
|
50596abce3 | ||
|
|
324a6031ba | ||
|
|
94591eee6d | ||
|
|
41390da06a | ||
|
|
9df9622ac2 | ||
|
|
4b965d1c3b | ||
|
|
d485621d21 | ||
|
|
b8678f6043 | ||
|
|
de15b0ea4b | ||
|
|
bd41e6cb52 | ||
|
|
f07b1f2e5f | ||
|
|
a232261df5 | ||
|
|
c3cd8cf543 | ||
|
|
95814d3dae | ||
|
|
c3ef18e649 | ||
|
|
feaf2cc6b4 | ||
|
|
e184c850d1 | ||
|
|
161fdfa463 | ||
|
|
9c184d7203 | ||
|
|
a2344e1494 | ||
|
|
cc153a1ced | ||
|
|
b19f720e42 | ||
|
|
51d934de27 | ||
|
|
23e47f1749 | ||
|
|
a5a905e20f | ||
|
|
1cecbe9276 | ||
|
|
edfc1fc0d7 | ||
|
|
cb43af0dd4 | ||
|
|
70616d4a09 | ||
|
|
6ec15d34a7 | ||
|
|
48b3852e6f | ||
|
|
595656f298 | ||
|
|
951d68e20c | ||
|
|
d64ddb3477 | ||
|
|
d937054f6f | ||
|
|
61affcf749 | ||
|
|
7270967181 | ||
|
|
008e84dcf0 | ||
|
|
9cc0108a01 | ||
|
|
6c1d1a43f5 | ||
|
|
d96b6da139 | ||
|
|
295300e7fa | ||
|
|
b35b9170e4 | ||
|
|
e57e401780 | ||
|
|
f5c333b84c | ||
|
|
60c784f371 | ||
|
|
68fe50f7e2 | ||
|
|
7ebafd8246 | ||
|
|
8f2e37d644 | ||
|
|
426b0daf61 | ||
|
|
5d71d7f01b | ||
|
|
1fa1dfa01e | ||
|
|
ec28e12a6f | ||
|
|
84b7e74bb6 | ||
|
|
64ffd3050f | ||
|
|
1f2f7dda09 | ||
|
|
60de12277b | ||
|
|
963a521a2c | ||
|
|
00ce3cdf37 | ||
|
|
fbdb4f112d | ||
|
|
2f9f20de06 | ||
|
|
c7b5b5df54 | ||
|
|
9342613501 | ||
|
|
0e893b9b5d | ||
|
|
0593ae0320 | ||
|
|
960149b9c5 | ||
|
|
b5f5f2f3d5 | ||
|
|
bd8c97244a | ||
|
|
cb187e6997 | ||
|
|
4004ed2267 | ||
|
|
a00347ac3f | ||
|
|
c4d08840bd | ||
|
|
84c0684b63 | ||
|
|
bca8df6d99 | ||
|
|
98f8e58f3f | ||
|
|
76f18f3443 | ||
|
|
b67d748ba1 | ||
|
|
0113721355 | ||
|
|
715f7f7c70 | ||
|
|
89955597c1 | ||
|
|
96d9aae048 | ||
|
|
f28d32946f | ||
|
|
924efb2c3f | ||
|
|
50abb1d784 | ||
|
|
b5ef39ee4b | ||
|
|
5b61b4fe69 | ||
|
|
2d8523ae67 | ||
|
|
f0eef447d3 | ||
|
|
8604d5672c | ||
|
|
30822fb1f1 | ||
|
|
826bbf76a9 | ||
|
|
eb8c97a1b7 | ||
|
|
5517c58724 | ||
|
|
e9bcdd0c65 | ||
|
|
83b37c6661 | ||
|
|
6163887cd3 | ||
|
|
214641aa1e | ||
|
|
06bc7af232 | ||
|
|
36b6168dec | ||
|
|
f9aa9dd982 | ||
|
|
22f1ab44f9 | ||
|
|
e4c87c267d | ||
|
|
86899a6ff0 | ||
|
|
2324fd3ad2 | ||
|
|
288b7712db | ||
|
|
8850bf4903 | ||
|
|
11112b41d1 | ||
|
|
2a98889b67 | ||
|
|
8060518a28 | ||
|
|
68440d3df3 | ||
|
|
7d775afc4c | ||
|
|
50c7764ef7 | ||
|
|
fb8b2d28f3 | ||
|
|
bcc2c4a514 | ||
|
|
9352298be0 | ||
|
|
180bd11740 | ||
|
|
57ea841381 | ||
|
|
7d9d176fa2 | ||
|
|
a8f4ec07c8 | ||
|
|
58c5be268f | ||
|
|
bf4859a2a9 | ||
|
|
db1cf93994 | ||
|
|
ecb1c4fea0 | ||
|
|
a513933044 | ||
|
|
764d65b595 | ||
|
|
bc0d606252 | ||
|
|
ceb8a68902 | ||
|
|
0b3183fd30 | ||
|
|
b6dbe37818 | ||
|
|
c78b8bc8e1 | ||
|
|
314f3e3715 | ||
|
|
26a1d5fc03 | ||
|
|
37e5003cf9 | ||
|
|
07f3868ffc | ||
|
|
46f0b17138 | ||
|
|
33a8e06a3a | ||
|
|
74afdde8de | ||
|
|
0a92ad2eb1 | ||
|
|
56d207c3f1 | ||
|
|
9172e752e3 | ||
|
|
adc9f2acfc | ||
|
|
41d17e67d2 | ||
|
|
5cacff073b | ||
|
|
c8da92c250 | ||
|
|
c4e76076e3 | ||
|
|
6a715b9a68 | ||
|
|
1f28940c95 | ||
|
|
ebff40b88f | ||
|
|
a6d14a3ac3 | ||
|
|
af96bcb9e3 | ||
|
|
619702cb04 | ||
|
|
5baec19aff | ||
|
|
39ef30c1e3 | ||
|
|
c2f2d28914 | ||
|
|
e06bc3bdf5 | ||
|
|
e19c19c013 | ||
|
|
8f324bc507 | ||
|
|
12107c42ce | ||
|
|
91c6fb4e52 | ||
|
|
7044355547 | ||
|
|
583ae65fb2 | ||
|
|
552fec0edc | ||
|
|
fcf6927fbf | ||
|
|
23f6d827d5 | ||
|
|
f083d0abab | ||
|
|
a895e36922 | ||
|
|
59d7a72288 | ||
|
|
7731f2f4d1 | ||
|
|
41ae5897c0 | ||
|
|
c7949ccfba | ||
|
|
567af79c7f | ||
|
|
6bb4a7b25c | ||
|
|
bc7cef4c34 | ||
|
|
ab9dc361d6 | ||
|
|
39da0a4dde | ||
|
|
44e864d697 | ||
|
|
0a02da3aba | ||
|
|
836771a7f0 | ||
|
|
f386badcfb | ||
|
|
1d43a484db | ||
|
|
91042cb41e | ||
|
|
10c0e4247d | ||
|
|
8e34264e6d | ||
|
|
0a840d256b | ||
|
|
8a69c51cac | ||
|
|
0262fd40bc | ||
|
|
859dfe3544 | ||
|
|
9c624a2f79 | ||
|
|
dec1061b40 | ||
|
|
be4895faa6 | ||
|
|
3c9755f0dd | ||
|
|
61ed847d7d | ||
|
|
fc9094fea8 | ||
|
|
e36c0efc4b | ||
|
|
4158a14cff | ||
|
|
201a45cba0 | ||
|
|
ab31b9b253 | ||
|
|
780ddc79a7 | ||
|
|
d5a2adaed6 | ||
|
|
008ab3f068 | ||
|
|
7d926f588d | ||
|
|
707cd07876 | ||
|
|
f7ecb9090c | ||
|
|
a19e8a7315 | ||
|
|
cf189ecf81 | ||
|
|
4405b7adcb | ||
|
|
e51ee7b7b9 | ||
|
|
dfaa74f426 | ||
|
|
1d2ce59009 | ||
|
|
3602cc05bb | ||
|
|
ac88a81ac6 | ||
|
|
01fa8e0c63 | ||
|
|
322c06bfbe | ||
|
|
b68fceb362 | ||
|
|
59547e0f37 | ||
|
|
3ce100a9cf | ||
|
|
6513fb0cd5 | ||
|
|
fd0fb1f760 | ||
|
|
5db586c4d3 | ||
|
|
31df1a3827 | ||
|
|
7e219aec7c | ||
|
|
37f8b98df9 | ||
|
|
f06beff22f | ||
|
|
6aa39a716a | ||
|
|
5088b5ebe0 | ||
|
|
010dd3a26f | ||
|
|
1a18755176 | ||
|
|
233e2576af | ||
|
|
543c655bca | ||
|
|
050e21e22b | ||
|
|
672ad6d237 | ||
|
|
0a8f6e866f | ||
|
|
b177ffef04 | ||
|
|
393f304be4 | ||
|
|
151816bf5e | ||
|
|
5cf7eacd82 | ||
|
|
87b6a2044c | ||
|
|
087d8ab8c9 | ||
|
|
b69b7b3350 | ||
|
|
5620f33524 | ||
|
|
f3e33fa390 | ||
|
|
3b631e0d5f | ||
|
|
f93d28ee76 | ||
|
|
23d7d3775d | ||
|
|
4940771166 | ||
|
|
c1967a8f6a | ||
|
|
8c797ee76b | ||
|
|
ce80957d07 | ||
|
|
c60018b59e | ||
|
|
3a27af87d1 | ||
|
|
068c1c6973 | ||
|
|
645a58c97d | ||
|
|
b7f455b29a | ||
|
|
4a2735839e | ||
|
|
d2e9fe8237 | ||
|
|
cfc60766d8 | ||
|
|
b03fec7f79 | ||
|
|
fb8e7c5b81 | ||
|
|
e44601d1b1 | ||
|
|
07bade53c0 | ||
|
|
fac0a9c25b | ||
|
|
1d1de3dd18 | ||
|
|
cfcbf004ba | ||
|
|
78c7dadbbe | ||
|
|
7b5a6031af | ||
|
|
c13a7782c8 | ||
|
|
45f02391d1 | ||
|
|
a3ca06addc | ||
|
|
32869e54ec | ||
|
|
ca73220a2e | ||
|
|
9fc3c2618e | ||
|
|
e72e0c0a30 | ||
|
|
a5bfc75278 | ||
|
|
261a184d25 | ||
|
|
54e96a06cb | ||
|
|
17e60df32b | ||
|
|
c99d5fe24c | ||
|
|
6049826e90 | ||
|
|
672149dd89 | ||
|
|
8c99147f04 | ||
|
|
4d4b0b7ae3 | ||
|
|
1a7955c1b1 | ||
|
|
f8fc2a1d96 | ||
|
|
9a7b3cb77c | ||
|
|
8a3e4edb4d | ||
|
|
e59183bb1e | ||
|
|
dd4d4e8dc6 | ||
|
|
f1744450ca | ||
|
|
3a7827a75b | ||
|
|
8d22e91c0d | ||
|
|
c425145fc9 | ||
|
|
4855935ae0 | ||
|
|
65f412ec9f | ||
|
|
40681c6093 | ||
|
|
ab2d36e523 | ||
|
|
b1ab3a66d2 | ||
|
|
5e7e7e8ef4 | ||
|
|
9291d30ae9 | ||
|
|
549708fcc2 | ||
|
|
1d5551f301 | ||
|
|
283db0f9ea | ||
|
|
9fb04b2db9 | ||
|
|
ceca96e10a | ||
|
|
fc48cc64af | ||
|
|
015d846941 | ||
|
|
e39108bbda | ||
|
|
6240d89a08 | ||
|
|
c76700e5e5 | ||
|
|
a8a0e8dea0 | ||
|
|
d65a2d6ed6 | ||
|
|
1824d5f9a4 | ||
|
|
d3eb29087b | ||
|
|
d6fae238f9 | ||
|
|
44b46033e3 | ||
|
|
5741ec9ab2 | ||
|
|
596975b309 | ||
|
|
9050318ceb | ||
|
|
7ee6933789 | ||
|
|
306c572b53 | ||
|
|
63306173b1 | ||
|
|
df1b45ca3e | ||
|
|
c31a1f1bf3 | ||
|
|
e95997ea17 | ||
|
|
12a070fd8d | ||
|
|
e0459c54fd | ||
|
|
15262a5a95 | ||
|
|
90ec64d25c | ||
|
|
061481419e | ||
|
|
8035255868 | ||
|
|
7feaf869dc | ||
|
|
7104e90fc9 | ||
|
|
52c1e500e6 | ||
|
|
07274f897a | ||
|
|
f626e53415 | ||
|
|
5a7b2965be | ||
|
|
0aab1628bc | ||
|
|
b9649e1d8e | ||
|
|
3bc9bf2207 | ||
|
|
888c06262b | ||
|
|
03e80dabcb | ||
|
|
54184d0875 | ||
|
|
90bcf5a455 | ||
|
|
d32d5ef40c | ||
|
|
2e0e0658c6 | ||
|
|
bbdb50a41e | ||
|
|
90705cac83 | ||
|
|
b91cdd6d91 | ||
|
|
64f2bd7a88 | ||
|
|
3e32f684e3 | ||
|
|
ff73756a55 | ||
|
|
1e64811d93 | ||
|
|
2488597cf2 | ||
|
|
2d8047ba80 | ||
|
|
3cb602b77e | ||
|
|
51e1005e79 | ||
|
|
ef7ea64973 | ||
|
|
0267c16e5a | ||
|
|
ca40e278ff | ||
|
|
1c5da7ad48 | ||
|
|
9bb3d5c569 | ||
|
|
92ba43bfad | ||
|
|
ddeb5e59f0 | ||
|
|
6b0b3e31cc | ||
|
|
3f6c904ccc | ||
|
|
d433919f1b | ||
|
|
75da9af39d | ||
|
|
22eff44926 | ||
|
|
cd6a052d0c | ||
|
|
3b6cf0b187 | ||
|
|
c170dd7a9e | ||
|
|
154775bc70 | ||
|
|
7f936f3ba9 | ||
|
|
9b30a947a8 | ||
|
|
2ee58d8f99 | ||
|
|
0537b3e9c7 | ||
|
|
8ae940bcbc | ||
|
|
966ccb5f2c | ||
|
|
fae9c3e59e | ||
|
|
cb1dfb257d | ||
|
|
76c3fe86c2 | ||
|
|
7e3b1de70f | ||
|
|
2a07e3cf3c | ||
|
|
6d0249825d | ||
|
|
63810e3966 | ||
|
|
4c013a8886 | ||
|
|
9509818978 | ||
|
|
4fdf3b8b60 | ||
|
|
ee9a58486d | ||
|
|
75d6939c8b | ||
|
|
fb1697b571 | ||
|
|
4080d606d8 | ||
|
|
7655fd47dd | ||
|
|
d029b0fce7 | ||
|
|
60df5b2a68 | ||
|
|
bada5dc961 | ||
|
|
4510e120ab | ||
|
|
da2af06ee6 | ||
|
|
9212c6d097 | ||
|
|
8660dea85a | ||
|
|
8c1342230b | ||
|
|
d0ddc1d57b | ||
|
|
fe1e953030 | ||
|
|
dab17af5a9 | ||
|
|
8dd2775092 | ||
|
|
7fb7b1e4af | ||
|
|
8966b73ac9 | ||
|
|
ddb2a91763 | ||
|
|
bc5bcbf11e | ||
|
|
287ee291cc | ||
|
|
2bceda01ae |
No files matched your search
@@ -25,6 +25,12 @@
|
||||
"commands": [
|
||||
"fake"
|
||||
]
|
||||
},
|
||||
"dotnet-t4": {
|
||||
"version": "3.0.0",
|
||||
"commands": [
|
||||
"t4"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
FROM ubuntu:22.04
|
||||
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
# Note installations that take a while (more than 10s)
|
||||
|
||||
RUN apt-get update
|
||||
RUN apt-get install -y ca-certificates
|
||||
RUN apt-get install -y ccache
|
||||
RUN apt-get install -y curl
|
||||
RUN apt-get install -y fish
|
||||
RUN apt-get install -y gdb
|
||||
# git-all: ~250s
|
||||
RUN apt-get install -y git-all
|
||||
RUN apt-get install -y gnupg
|
||||
# liblttng-ust-dev: ~30s
|
||||
RUN apt-get install -y liblttng-ust-dev
|
||||
RUN apt-get install -y libssh2-1-dev
|
||||
RUN apt-get install -y locales
|
||||
RUN apt-get install -y ninja-build
|
||||
# openssh-server: ~40s
|
||||
RUN apt-get install -y openssh-server
|
||||
RUN apt-get install -y pkg-config
|
||||
RUN apt-get install -y software-properties-common
|
||||
RUN apt-get install -y sudo
|
||||
RUN apt-get install -y tzdata
|
||||
RUN apt-get install -y vim
|
||||
RUN apt-get install -y zip
|
||||
|
||||
# Python: ~30s
|
||||
RUN apt-get install -y \
|
||||
python3-pip \
|
||||
python3-venv \
|
||||
&& python3 -m pip install --upgrade pip
|
||||
|
||||
# GCC
|
||||
ARG gcc_major=13
|
||||
RUN \
|
||||
add-apt-repository ppa:ubuntu-toolchain-r/test \
|
||||
&& apt-get update \
|
||||
&& apt-get install -y g++-$gcc_major
|
||||
|
||||
# Clang
|
||||
ARG clang_major=17
|
||||
RUN \
|
||||
curl -fsSL https://apt.llvm.org/llvm-snapshot.gpg.key 2> /dev/null \
|
||||
| gpg --dearmor - \
|
||||
| tee /usr/share/keyrings/llvm-snapshot.gpg > /dev/null \
|
||||
&& echo "deb [signed-by=/usr/share/keyrings/llvm-snapshot.gpg] http://apt.llvm.org/$(lsb_release -cs)/ llvm-toolchain-$(lsb_release -cs)-$clang_major main" \
|
||||
| tee -a "/etc/apt/sources.list.d/llvm.list" \
|
||||
&& apt-get update \
|
||||
&& apt-get install -y \
|
||||
clang-$clang_major \
|
||||
clang-format-$clang_major \
|
||||
clangd-$clang_major
|
||||
|
||||
# CMake
|
||||
RUN \
|
||||
curl -fsSL https://apt.kitware.com/keys/kitware-archive-latest.asc 2> /dev/null \
|
||||
| gpg --dearmor - \
|
||||
| tee /usr/share/keyrings/kitware-archive-keyring.gpg > /dev/null \
|
||||
&& echo "deb [signed-by=/usr/share/keyrings/kitware-archive-keyring.gpg] https://apt.kitware.com/ubuntu/ $(lsb_release -cs) main" \
|
||||
| tee /etc/apt/sources.list.d/kitware.list > /dev/null \
|
||||
&& apt-get update \
|
||||
&& apt-get install -y cmake
|
||||
|
||||
# Dotnet
|
||||
RUN apt-get update && apt-get install -y dotnet7
|
||||
|
||||
# Node
|
||||
ARG node_major=18
|
||||
RUN mkdir -p /etc/apt/keyrings \
|
||||
&& curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key \
|
||||
| gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg \
|
||||
&& echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$node_major.x nodistro main" \
|
||||
| tee /etc/apt/sources.list.d/nodesource.list \
|
||||
&& apt-get update \
|
||||
&& apt-get install -y nodejs
|
||||
|
||||
# Emumba (deps)
|
||||
RUN apt-get update && apt-get -y install rapidjson-dev
|
||||
# Emumba
|
||||
COPY emumba /emumba
|
||||
RUN dpkg -i /emumba/emumba-deribit-connector-3.3.1-Linux.LICENSE_DISABLED.deb \
|
||||
&& rm -r /emumba
|
||||
|
||||
# Pcap
|
||||
RUN apt-get update && apt-get install -y libpcap0.8-dev
|
||||
|
||||
# Databento (deps)
|
||||
RUN apt-get update && apt-get -y install libzstd-dev
|
||||
|
||||
# Docker in Docker
|
||||
RUN apt-get update && apt-get install -y \
|
||||
docker.io \
|
||||
docker-compose \
|
||||
docker-compose-v2
|
||||
|
||||
# Set up default executables (update-alternatives)
|
||||
RUN \
|
||||
update-alternatives --install /usr/bin/clang clang /usr/bin/clang-$clang_major 100; \
|
||||
update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-$clang_major 100; \
|
||||
update-alternatives --install /usr/bin/clang-format clang-format /usr/bin/clang-format-$clang_major 100; \
|
||||
update-alternatives --install /usr/bin/clangd clangd /usr/bin/clangd-$clang_major 100; \
|
||||
update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-$gcc_major 100; \
|
||||
update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-$gcc_major 100
|
||||
|
||||
# Add compiler symlinks for ccache
|
||||
RUN \
|
||||
ln -s /usr/bin/ccache /usr/local/bin/clang; \
|
||||
ln -s /usr/bin/ccache /usr/local/bin/clang++; \
|
||||
ln -s /usr/bin/ccache /usr/local/bin/clang-$clang_major; \
|
||||
ln -s /usr/bin/ccache /usr/local/bin/clang++-$clang_major; \
|
||||
ln -s /usr/bin/ccache /usr/local/bin/gcc; \
|
||||
ln -s /usr/bin/ccache /usr/local/bin/g++
|
||||
|
||||
RUN locale-gen en_US.UTF-8
|
||||
|
||||
ARG docker_user="bts"
|
||||
ARG docker_uid="1000"
|
||||
ARG docker_pass="bts"
|
||||
|
||||
RUN \
|
||||
groupadd -g "$docker_uid" "$docker_user" \
|
||||
&& useradd \
|
||||
-m \
|
||||
-u "$docker_uid" \
|
||||
-g "$docker_uid" \
|
||||
-G sudo \
|
||||
--password "$(openssl passwd -1 "$docker_pass")" \
|
||||
"$docker_user"
|
||||
|
||||
RUN usermod -aG docker "$docker_user"
|
||||
@@ -0,0 +1,43 @@
|
||||
{
|
||||
"dockerFile": "Dockerfile",
|
||||
// Creates local dir to mount to HOME in docker
|
||||
"initializeCommand": "mkdir -p ${localEnv:HOME}/.bts/devcontainer-mounts/${devcontainerId}",
|
||||
"hostRequirements": {
|
||||
"memory": "4gb",
|
||||
"storage": "6gb"
|
||||
},
|
||||
"postCreateCommand": "/home/bts/spark/docker/sparkd/dev/devcontainer_post_create.sh",
|
||||
"containerUser": "bts",
|
||||
"workspaceMount": "source=${localWorkspaceFolder},target=/home/bts/spark,type=bind",
|
||||
"workspaceFolder": "/home/bts/spark",
|
||||
"updateRemoteUserUID": true,
|
||||
"shutdownAction": "none",
|
||||
// Note: If running multiple containers on the same host, each must use a
|
||||
// unique set of ports. Usually we just add 1000 to each port as needed. For
|
||||
// example, if 8000-8003 is taken, go with 9000-9003, then 10000-10003, etc.
|
||||
"runArgs": [
|
||||
"--shm-size",
|
||||
"2gb",
|
||||
"--network",
|
||||
"host"
|
||||
],
|
||||
"mounts": [
|
||||
"source=${localEnv:HOME}/.bts/devcontainer-mounts/${devcontainerId},target=/home/bts,type=bind",
|
||||
"source=/var/run/docker.sock,target=/var/run/docker.sock,type=bind"
|
||||
],
|
||||
"customizations": {
|
||||
"vscode": {
|
||||
"settings": {
|
||||
"clangd.arguments": [
|
||||
"--compile-commands-dir=${workspaceFolder}/build/clang/debug"
|
||||
]
|
||||
},
|
||||
"extensions": [
|
||||
"eamodio.gitlens",
|
||||
"llvm-vs-code-extensions.vscode-clangd",
|
||||
"ms-vscode.cmake-tools",
|
||||
"ms-vscode.cpptools"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,4 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
this_dir="$(realpath "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")")"
|
||||
sudo dpkg -i "$this_dir/emumba-deribit-connector-3.3.1-Linux.LICENSE_DISABLED.deb"
|
||||
+30
-16
@@ -207,17 +207,23 @@ dotnet_naming_symbols.parameters.applicable_accessibilities = public,internal,pr
|
||||
dotnet_naming_symbols.private_symbols.applicable_kinds = property,method,field,event,delegate
|
||||
dotnet_naming_symbols.private_symbols.applicable_accessibilities = protected,private
|
||||
|
||||
# local symbols
|
||||
dotnet_naming_symbols.local_symbols.applicable_kinds = local
|
||||
|
||||
# parameter symbols
|
||||
dotnet_naming_symbols.parameter_symbols.applicable_kinds = parameter
|
||||
|
||||
# Naming styles
|
||||
|
||||
dotnet_naming_style.snake_case.required_prefix =
|
||||
dotnet_naming_style.snake_case.required_suffix =
|
||||
dotnet_naming_style.snake_case.word_separator = _
|
||||
dotnet_naming_style.snake_case.capitalization = all_lower
|
||||
dotnet_naming_style.pascal_case.required_prefix =
|
||||
dotnet_naming_style.pascal_case.required_suffix =
|
||||
dotnet_naming_style.pascal_case.word_separator =
|
||||
dotnet_naming_style.pascal_case.capitalization = pascal_case
|
||||
|
||||
dotnet_naming_style.private_snake_case.required_prefix = _
|
||||
dotnet_naming_style.private_snake_case.required_suffix =
|
||||
dotnet_naming_style.private_snake_case.word_separator = _
|
||||
dotnet_naming_style.private_snake_case.capitalization = all_lower
|
||||
dotnet_naming_style.camel_case.required_prefix =
|
||||
dotnet_naming_style.camel_case.required_suffix =
|
||||
dotnet_naming_style.camel_case.word_separator =
|
||||
dotnet_naming_style.camel_case.capitalization = camel_case
|
||||
|
||||
dotnet_naming_style.user_types.required_prefix =
|
||||
dotnet_naming_style.user_types.required_suffix =
|
||||
@@ -229,6 +235,10 @@ dotnet_naming_style.interface.required_suffix =
|
||||
dotnet_naming_style.interface.word_separator =
|
||||
dotnet_naming_style.interface.capitalization = pascal_case
|
||||
|
||||
dotnet_naming_style.local.capitalization = camel_case
|
||||
|
||||
dotnet_naming_style.parameter.capitalization = camel_case
|
||||
|
||||
# rules
|
||||
dotnet_naming_rule.user_types.symbols = user_types
|
||||
dotnet_naming_rule.user_types.style = user_types
|
||||
@@ -238,14 +248,18 @@ dotnet_naming_rule.interfaces.symbols = interface
|
||||
dotnet_naming_rule.interfaces.style = interface_style
|
||||
dotnet_naming_rule.interfaces.severity = suggestion
|
||||
|
||||
dotnet_naming_rule.public_members_snake_case.symbols = public_symbols
|
||||
dotnet_naming_rule.public_members_snake_case.style = snake_case
|
||||
dotnet_naming_rule.public_members_snake_case.severity = suggestion
|
||||
dotnet_naming_rule.public_members.symbols = public_symbols
|
||||
dotnet_naming_rule.public_members.style = pascal_case
|
||||
dotnet_naming_rule.public_members.severity = suggestion
|
||||
|
||||
dotnet_naming_rule.private_members_snake_case.symbols = private_symbols
|
||||
dotnet_naming_rule.private_members_snake_case.style = private_snake_case
|
||||
dotnet_naming_rule.private_members_snake_case.severity = suggestion
|
||||
dotnet_naming_rule.private_members.symbols = private_symbols
|
||||
dotnet_naming_rule.private_members.style = camel_case
|
||||
dotnet_naming_rule.private_members.severity = suggestion
|
||||
|
||||
dotnet_naming_rule.parameters.symbols = parameters
|
||||
dotnet_naming_rule.parameters.style = snake_case
|
||||
dotnet_naming_rule.variables_are_camel_case.severity = suggestion
|
||||
dotnet_naming_rule.variables_are_camel_case.symbols = local_symbols
|
||||
dotnet_naming_rule.variables_are_camel_case.style = local
|
||||
|
||||
dotnet_naming_rule.parameters.symbols = parameter_symbols
|
||||
dotnet_naming_rule.parameters.style = parameter
|
||||
dotnet_naming_rule.parameters.severity = suggestion
|
||||
@@ -0,0 +1,81 @@
|
||||
# This file defines the global default configuration for docker deployments.
|
||||
# It is tracked in source control. For temporary modifications, please create
|
||||
# a separate file called ".env.local" (it's in .gitignore, so won't be tracked).
|
||||
# If a variable is defined in both files, the value in .env.local will be used.
|
||||
#
|
||||
# About the deployment procedure:
|
||||
# We use Docker Compose to build images and launch containers for various services
|
||||
# that make up our software suite:
|
||||
# - sparkd
|
||||
# - pubsub
|
||||
# - md-publisher
|
||||
# - webapp (DSQA on the web)
|
||||
# - api-server (websocket based)
|
||||
# From inside a devcontainer, you can launch all services in separate containers
|
||||
# on your machine by running:
|
||||
#
|
||||
# tools/deploy.sh
|
||||
#
|
||||
# This script builds release versions for each service, packaged (generally) in
|
||||
# self-contained directories. Next, it runs a few "docker compose" commands to
|
||||
# build docker images loaded with the self-contained binaries from the previous
|
||||
# step, and start containers with those images to run each service. To view the
|
||||
# commands that deploy.sh runs internally (without actually running them), run:
|
||||
#
|
||||
# tools/deploy.sh --dry-run
|
||||
#
|
||||
# For additional information/help, run:
|
||||
#
|
||||
# tools/deploy.sh --help
|
||||
#
|
||||
|
||||
### Sparkd ###
|
||||
# The internal image for sparkd to use. For more info, view:
|
||||
# src/app_sparkd/Dockerfile
|
||||
SPARKD__IMAGE=sparkd
|
||||
# The 'spark.conf' for this service to use
|
||||
SPARKD__CONF_FILE=src/app_sparkd/spark.conf
|
||||
# To run replay md, put recorded md files in SPARKD__MD_RECORDING_DIR, and use:
|
||||
# SPARKD__IMAGE=sparkd_md_replay
|
||||
# SPARKD__CONF_FILE=src/app_sparkd/spark.local.conf
|
||||
# (configure which md to replay in the new SPARKD__CONF_FILE)
|
||||
SPARKD__MD_RECORDING_DIR=.md_recording
|
||||
SPARKD__SOURCE_DIR=install/sparkd-release-gcc
|
||||
SPARKD__CONFIG_PORT=8000
|
||||
SPARKD__QUICKBUS_PORT=8001
|
||||
SPARKD__SIM_FIX_PORT=8002
|
||||
|
||||
### Pubsub ###
|
||||
# The 'spark.conf' for this service to use
|
||||
PUBSUB__CONF_FILE=src/DataStreamSuite/PubSubServer/spark.conf
|
||||
PUBSUB__CS_SOURCE_DIR=build/Release/bin/net7.0/linux-x64/publish
|
||||
PUBSUB__CPP_SOURCE_DIR=install/data-stream-suite-linux
|
||||
# The appsettings to load at runtime. Expects a file named:
|
||||
# src/DataStreamSuite/PubSub/appsettings.${PUBSUB__DOTNET_ENVIRONMENT}.json
|
||||
PUBSUB__DOTNET_ENVIRONMENT=Staging
|
||||
|
||||
### Md Publisher ###
|
||||
# The 'spark.conf' for this service to use
|
||||
MD_PUBLISHER__CONF_FILE=src/DataStreamSuite/DataStreamPublisher/spark.conf
|
||||
MD_PUBLISHER__SOURCE_DIR=build/Release/bin/net7.0/linux-x64/publish
|
||||
# Determines which appsettings to load at runtime. Expects a file named:
|
||||
# src/DataStreamSuite/DataStreamPublisher/appsettings.${MD_PUBLISHER__DOTNET_ENVIRONMENT}.json
|
||||
MD_PUBLISHER__DOTNET_ENVIRONMENT=MarketData
|
||||
|
||||
### Webapp (DSQA on the web) ###
|
||||
# The 'spark.conf' for this service to use
|
||||
WEBAPP__CONF_FILE=src/client/spark_api_server/spark.conf
|
||||
WEBAPP__SOURCE_DIR=build/Release/bin/net7.0/linux-x64/publish
|
||||
WEBAPP__WEB_ROOT=build/Bts.DataStreamWebApp.Client/production/dist
|
||||
# Determines which appsettings to load at runtime. Expects a file named:
|
||||
# src/DataStreamSuite/Bts.DataStreamWebApp.Server/appsettings.${WEBAPP__ASPNETCORE_ENVIRONMENT}.json
|
||||
WEBAPP__ASPNETCORE_ENVIRONMENT=Staging
|
||||
|
||||
### Api Server ###
|
||||
# The 'spark.conf' for this service to use
|
||||
API_SERVER__CONF_FILE=src/client/spark_api_server/spark.conf
|
||||
API_SERVER__CS_SOURCE_DIR=build/Release/bin/net7.0/linux-x64/publish
|
||||
API_SERVER__CPP_SOURCE_DIR=install/spark-api-server-linux
|
||||
# Determines which appsettings to load at runtime. Expects a file named:
|
||||
# src/client/spark_api_server/appsettings.${API_SERVER__ASPNETCORE_ENVIRONMENT}.json
|
||||
API_SERVER__ASPNETCORE_ENVIRONMENT=Staging
|
||||
@@ -0,0 +1,4 @@
|
||||
*.cmd text=auto eol=crlf
|
||||
*.cs text=auto eol=crlf
|
||||
*.sh text=auto eol=lf
|
||||
*.py text=auto eol=lf
|
||||
+7
-2
@@ -8,7 +8,9 @@ cmake-build-debug/
|
||||
.idea/
|
||||
.dir-locals.el
|
||||
*.pyc
|
||||
**.vscode
|
||||
**.vscode/*
|
||||
!.vscode/launch.json
|
||||
!.vscode/tasks.json
|
||||
.vs
|
||||
obj/
|
||||
*.csproj.user
|
||||
@@ -54,6 +56,9 @@ trace_data/
|
||||
/src/Spark.Admin.WebApp/src/bin/
|
||||
**/CMakeDeps.cmake
|
||||
**/CMakeDeps_win.cmake
|
||||
**/.devcontainer
|
||||
.devcontainer/
|
||||
*.Generated.cs
|
||||
*.lst
|
||||
src/app_sparkd/spark.local.conf
|
||||
.env.local
|
||||
.md_recording
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
[submodule "externals"]
|
||||
path = externals
|
||||
url = git@bitbucket.org:bluetradesys/externals.git
|
||||
url = https://bitbucket.org/bluetradesys/externals.git
|
||||
[submodule "vcpkg"]
|
||||
path = vcpkg
|
||||
url = https://github.com/microsoft/vcpkg.git
|
||||
Vendored
+369
@@ -0,0 +1,369 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": ".NET Core Attach",
|
||||
"type": "coreclr",
|
||||
"request": "attach"
|
||||
},
|
||||
{
|
||||
"name": "Api Server",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"program": "",
|
||||
"windows": {
|
||||
"preLaunchTask": "Build Api Server (Debug)",
|
||||
"program": "spark_api_server.exe",
|
||||
"args": [
|
||||
"run",
|
||||
],
|
||||
"cwd": "build/Debug/bin/net7.0",
|
||||
},
|
||||
"linux": {
|
||||
"preLaunchTask": "Build Api Server (Debug)",
|
||||
"program": "spark_api_server",
|
||||
"args": [
|
||||
"run",
|
||||
],
|
||||
"cwd": "build/Debug/bin/net7.0",
|
||||
},
|
||||
"env": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development",
|
||||
},
|
||||
"stopAtEntry": false,
|
||||
"console": "integratedTerminal"
|
||||
},
|
||||
{
|
||||
"name": "Api Server (Skip Build)",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"program": "",
|
||||
"windows": {
|
||||
"program": "spark_api_server.exe",
|
||||
"args": [
|
||||
"run",
|
||||
],
|
||||
"cwd": "build/Debug/bin/net7.0",
|
||||
},
|
||||
"linux": {
|
||||
"program": "spark_api_server",
|
||||
"args": [
|
||||
"run",
|
||||
],
|
||||
"cwd": "build/Debug/bin/net7.0",
|
||||
},
|
||||
"env": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development",
|
||||
},
|
||||
"stopAtEntry": false,
|
||||
"console": "integratedTerminal"
|
||||
},
|
||||
{
|
||||
"name": "Bts.DataStreamWebApp.Server",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"preLaunchTask": "Build DataStream (Debug)",
|
||||
"program": "${workspaceFolder}/build/Debug/bin/net7.0/Bts.DataStreamWebApp.Server.dll",
|
||||
"cwd": "${workspaceFolder}/build/Debug/bin/net7.0",
|
||||
"env": {
|
||||
"ASPNETCORE_HTTP_PORT": "8080",
|
||||
"ASPNETCORE_HTTPS_PORT": "8443",
|
||||
"ASPNETCORE_ENVIRONMENT": "${input:dataStreamWebAppServerEnvironment}",
|
||||
"ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "Microsoft.AspNetCore.SpaProxy",
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Bts.DataStreamWebApp.Server (Skip Build)",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/build/Debug/bin/net7.0/Bts.DataStreamWebApp.Server.dll",
|
||||
"cwd": "${workspaceFolder}/build/Debug/bin/net7.0",
|
||||
"env": {
|
||||
"ASPNETCORE_HTTP_PORT": "8080",
|
||||
"ASPNETCORE_HTTPS_PORT": "8443",
|
||||
"ASPNETCORE_ENVIRONMENT": "${input:dataStreamWebAppServerEnvironment}",
|
||||
"ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "Microsoft.AspNetCore.SpaProxy",
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "DataStreamPublisher",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"preLaunchTask": "Build DataStream (Debug)",
|
||||
"program": "",
|
||||
"linux": {
|
||||
"program": "DataStreamPublisher",
|
||||
},
|
||||
"windows": {
|
||||
"program": "DataStreamPublisher.exe",
|
||||
},
|
||||
"env": {
|
||||
"DOTNET_ENVIRONMENT": "${input:dataStreamPublisherEnvironment}",
|
||||
},
|
||||
"cwd": "${workspaceFolder}/build/Debug/bin/net7.0",
|
||||
"stopAtEntry": false,
|
||||
"console": "integratedTerminal"
|
||||
},
|
||||
{
|
||||
"name": "DataStreamPublisher (Skip Build)",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"program": "",
|
||||
"linux": {
|
||||
"program": "DataStreamPublisher",
|
||||
},
|
||||
"windows": {
|
||||
"program": "DataStreamPublisher.exe",
|
||||
},
|
||||
"env": {
|
||||
"DOTNET_ENVIRONMENT": "${input:dataStreamPublisherEnvironment}",
|
||||
},
|
||||
"cwd": "${workspaceFolder}/build/Debug/bin/net7.0",
|
||||
"stopAtEntry": false,
|
||||
"console": "integratedTerminal"
|
||||
},
|
||||
{
|
||||
"name": "(gdb) Launch",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"program": "/home/bts/spark/build/sparkd-debug-clang/server/sparkd",
|
||||
"args": ["run"],
|
||||
"stopAtEntry": false,
|
||||
"cwd": "/home/bts/spark/build/sparkd-debug-clang/server",
|
||||
"environment": [],
|
||||
"externalConsole": false,
|
||||
"MIMode": "gdb",
|
||||
},
|
||||
{
|
||||
"name": "DataStreamQueryAnalyzer",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"preLaunchTask": "Build DataStreamQueryAnalyzer (Debug)",
|
||||
"program": "",
|
||||
"windows": {
|
||||
"program": "DataStreamQueryAnalyzer.exe",
|
||||
"args": [
|
||||
"--config",
|
||||
"${workspaceFolder}/src/DataStreamSuite/DataStreamQueryAnalyzer/Configurations/DataStreamQueryAnalyzer.json"
|
||||
],
|
||||
"cwd": "build/Debug/bin/net7.0-windows",
|
||||
"env": {
|
||||
"PYTHON_EXE": "${workspaceFolder}/.venv/Scripts/python.exe"
|
||||
},
|
||||
},
|
||||
"stopAtEntry": false,
|
||||
"console": "integratedTerminal",
|
||||
},
|
||||
{
|
||||
"name": "PubSubServer",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"preLaunchTask": "Build DataStream (Debug)",
|
||||
"program": "",
|
||||
"linux": {
|
||||
"program": "PubSubServer",
|
||||
},
|
||||
"windows": {
|
||||
"program": "PubSubServer.exe",
|
||||
},
|
||||
"cwd": "build/Debug/bin/net7.0",
|
||||
"env": {
|
||||
"DOTNET_ENVIRONMENT": "${input:pubSubServerEnvironment}",
|
||||
},
|
||||
"stopAtEntry": false,
|
||||
"console": "integratedTerminal"
|
||||
},
|
||||
{
|
||||
"name": "PubSubServer (Skip Build)",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"program": "",
|
||||
"linux": {
|
||||
"program": "PubSubServer",
|
||||
},
|
||||
"windows": {
|
||||
"program": "PubSubServer.exe",
|
||||
},
|
||||
"cwd": "build/Debug/bin/net7.0",
|
||||
"env": {
|
||||
"DOTNET_ENVIRONMENT": "${input:pubSubServerEnvironment}",
|
||||
},
|
||||
"stopAtEntry": false,
|
||||
"console": "integratedTerminal"
|
||||
},
|
||||
{
|
||||
"name": "Spark",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"program": "",
|
||||
"windows": {
|
||||
"preLaunchTask": "Build Spark (Debug)",
|
||||
"program": "Spark.exe",
|
||||
"args": [
|
||||
"--sparkd",
|
||||
"http://127.0.0.1:8000/config"
|
||||
],
|
||||
"cwd": "build/Debug/bin/net7.0-windows",
|
||||
},
|
||||
"stopAtEntry": false,
|
||||
"console": "integratedTerminal"
|
||||
},
|
||||
{
|
||||
"name": "Spark (Parameterized)",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"preLaunchTask": "Build Spark (Debug)",
|
||||
"program": "",
|
||||
"windows": {
|
||||
"program": "Spark.exe",
|
||||
"args": [
|
||||
"--sparkd",
|
||||
"${input:sparkConfigServer}"
|
||||
],
|
||||
"cwd": "build/Debug/bin/net7.0-windows",
|
||||
},
|
||||
"stopAtEntry": false,
|
||||
"console": "integratedTerminal"
|
||||
},
|
||||
{
|
||||
"name": "Sparkd",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"preLaunchTask": "Build Sparkd (Debug | Clang)",
|
||||
"program": "",
|
||||
"linux": {
|
||||
"program": "${workspaceFolder}/build/sparkd-debug-clang/src/app_sparkd/sparkd",
|
||||
},
|
||||
"args": [
|
||||
"run"
|
||||
],
|
||||
"cwd": "${workspaceFolder}/build/sparkd-debug-clang/src/app_sparkd",
|
||||
"stopAtEntry": false,
|
||||
"externalConsole": false,
|
||||
"MIMode": "gdb",
|
||||
"setupCommands": [
|
||||
{
|
||||
"description": "Enable pretty-printing for gdb",
|
||||
"text": "-enable-pretty-printing",
|
||||
"ignoreFailures": true
|
||||
},
|
||||
{
|
||||
"description": "Set Disassembly Flavor to Intel",
|
||||
"text": "-gdb-set disassembly-flavor intel",
|
||||
"ignoreFailures": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Sparkd (Skip Build)",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"program": "",
|
||||
"linux": {
|
||||
"program": "${workspaceFolder}/build/sparkd-debug-clang/src/app_sparkd/sparkd",
|
||||
},
|
||||
"args": [
|
||||
"run"
|
||||
],
|
||||
"cwd": "${workspaceFolder}/build/sparkd-debug-clang/src/app_sparkd",
|
||||
"stopAtEntry": false,
|
||||
"externalConsole": false,
|
||||
"MIMode": "gdb",
|
||||
"setupCommands": [
|
||||
{
|
||||
"description": "Enable pretty-printing for gdb",
|
||||
"text": "-enable-pretty-printing",
|
||||
"ignoreFailures": true
|
||||
},
|
||||
{
|
||||
"description": "Set Disassembly Flavor to Intel",
|
||||
"text": "-gdb-set disassembly-flavor intel",
|
||||
"ignoreFailures": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Sparkd Web (Skip Build)",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"program": "",
|
||||
"linux": {
|
||||
"program": "${workspaceFolder}/build/sparkd-debug-clang/src/app_sparkd/sparkd",
|
||||
},
|
||||
"args": [
|
||||
"web"
|
||||
],
|
||||
"cwd": "${workspaceFolder}/build/sparkd-debug-clang/src/app_sparkd",
|
||||
"stopAtEntry": false,
|
||||
"externalConsole": false,
|
||||
"MIMode": "gdb",
|
||||
"setupCommands": [
|
||||
{
|
||||
"description": "Enable pretty-printing for gdb",
|
||||
"text": "-enable-pretty-printing",
|
||||
"ignoreFailures": true
|
||||
},
|
||||
{
|
||||
"description": "Set Disassembly Flavor to Intel",
|
||||
"text": "-gdb-set disassembly-flavor intel",
|
||||
"ignoreFailures": true
|
||||
}
|
||||
]
|
||||
},
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"id": "dataStreamPublisherEnvironment",
|
||||
"type": "pickString",
|
||||
"description": "Publisher Configuration",
|
||||
"options": [
|
||||
"Development",
|
||||
"MarketData",
|
||||
"Production",
|
||||
"ProductionAws",
|
||||
"Staging",
|
||||
],
|
||||
"default": "MarketDataPublisher",
|
||||
},
|
||||
{
|
||||
"id": "pubSubServerEnvironment",
|
||||
"type": "pickString",
|
||||
"description": "PubSub Configuration",
|
||||
"options": [
|
||||
"Development",
|
||||
"EchoServer",
|
||||
"Production",
|
||||
"ProductionAws",
|
||||
"Staging",
|
||||
],
|
||||
"default": "Development",
|
||||
},
|
||||
{
|
||||
"id": "dataStreamWebAppServerEnvironment",
|
||||
"type": "pickString",
|
||||
"description": "DataStream WebApp Environment",
|
||||
"options": [
|
||||
"Development",
|
||||
"Production",
|
||||
"ProductionAws",
|
||||
"Staging",
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "sparkConfigServer",
|
||||
"type": "promptString",
|
||||
"description": "Config Server URL",
|
||||
"default": "http://localhost:8000/config",
|
||||
},
|
||||
{
|
||||
"id": "isSparkApiEnabled",
|
||||
"type": "pickString",
|
||||
"description": "Enable Spark Api (connect to sparkd)",
|
||||
"options": [
|
||||
"True",
|
||||
"False",
|
||||
],
|
||||
"default": "True",
|
||||
}
|
||||
]
|
||||
}
|
||||
Vendored
+1038
File diff suppressed because it is too large.
Load diff
+87
-126
@@ -14,12 +14,17 @@ set(
|
||||
CACHE
|
||||
STRING
|
||||
"External dependencies root folder (should contain folders: lib, bin, include")
|
||||
set(SPARK_BIN "${EXTERNALS_ROOT}/bin")
|
||||
set(SPARK_INCLUDE "${EXTERNALS_ROOT}/include")
|
||||
set(SPARK_LIB "${EXTERNALS_ROOT}/lib/$<CONFIG>")
|
||||
set(BUILD_API_SERVER OFF CACHE BOOL "Build the api server")
|
||||
|
||||
# SHARED_MEMORY_PREFIX serves as a kind of namespace so multiple applications
|
||||
# can run simultaneously without fighting over the same shm files (e.g., sparkd,
|
||||
# api server, etc.).
|
||||
set(SHARED_MEMORY_PREFIX "\${BTS_SHARED_MEMORY_PREFIX}" CACHE STRING "Prefix to use when creating shared memory files")
|
||||
set(EXTERNALS_BIN "${EXTERNALS_ROOT}/bin")
|
||||
set(EXTERNALS_INCLUDE "${EXTERNALS_ROOT}/include")
|
||||
set(EXTERNALS_LIB "${EXTERNALS_ROOT}/lib/$<CONFIG>")
|
||||
set(BUILD_DOCS OFF CACHE BOOL "Build documentation")
|
||||
set(BUILD_SDK OFF CACHE BOOL "Build the sdk")
|
||||
set(EXPORT_MD_CONSUMER OFF CACHE BOOL "Export (extern) C functions for MD consumer interop")
|
||||
if (WIN32)
|
||||
set(BUILD_SPARKD OFF CACHE BOOL "Build sparkd")
|
||||
set(BUILD_ADMIN_WEB_APP OFF CACHE BOOL "Build the Admin WebApp")
|
||||
@@ -28,129 +33,85 @@ else()
|
||||
set(BUILD_ADMIN_WEB_APP ON CACHE BOOL "Build the Admin WebApp")
|
||||
endif()
|
||||
|
||||
include_directories(BEFORE SYSTEM ${SPARK_INCLUDE} ${EXTERNALS_ROOT}/include/zlib)
|
||||
link_directories(${SPARK_LIB})
|
||||
add_compile_definitions(SHARED_MEMORY_PREFIX="${SHARED_MEMORY_PREFIX}")
|
||||
if(DEFINED APP_DATA_DIR)
|
||||
add_compile_definitions(APP_DATA_DIR="${APP_DATA_DIR}")
|
||||
endif()
|
||||
add_compile_definitions(EXPORT_MD_CONSUMER="${EXPORT_MD_CONSUMER}")
|
||||
|
||||
if(BUILD_API_SERVER)
|
||||
add_compile_definitions(SPARK_ENABLE_API_SERVER)
|
||||
if(BUILD_SPARKD)
|
||||
# Note: All macros that begin w/ 'CCAPI' are ccapi's macros (defined and/or
|
||||
# read by their code). We override some below.
|
||||
add_compile_definitions(SPARK_ENABLE_CCAPI)
|
||||
|
||||
# This allows us to override hardcoded exchange-urls with ones read from
|
||||
# config (i.e., resolved at runtime rather than compile-time)
|
||||
add_compile_definitions(CCAPI_EXPOSE_INTERNAL)
|
||||
|
||||
# Enable ccapi services
|
||||
add_compile_definitions(CCAPI_ENABLE_SERVICE_MARKET_DATA)
|
||||
add_compile_definitions(CCAPI_ENABLE_SERVICE_EXECUTION_MANAGEMENT)
|
||||
# Enable ccapi exchanges
|
||||
add_compile_definitions(CCAPI_ENABLE_EXCHANGE_BINANCE)
|
||||
add_compile_definitions(CCAPI_ENABLE_EXCHANGE_BINANCE_COIN_FUTURES)
|
||||
add_compile_definitions(CCAPI_ENABLE_EXCHANGE_BINANCE_US)
|
||||
add_compile_definitions(CCAPI_ENABLE_EXCHANGE_BINANCE_USDS_FUTURES)
|
||||
add_compile_definitions(CCAPI_ENABLE_EXCHANGE_COINBASE)
|
||||
add_compile_definitions(CCAPI_ENABLE_EXCHANGE_DERIBIT)
|
||||
add_compile_definitions(CCAPI_ENABLE_EXCHANGE_OKX)
|
||||
|
||||
set(CCAPI_LOG_LEVEL
|
||||
"Warn"
|
||||
CACHE STRING "<Fatal|Error|Warn|Info|Debug|Trace> Log level for ccapi")
|
||||
string(TOUPPER "${CCAPI_LOG_LEVEL}" _ccapi_log_level_upper)
|
||||
add_compile_definitions("CCAPI_ENABLE_LOG_${_ccapi_log_level_upper}")
|
||||
|
||||
# ** Binance **
|
||||
add_compile_definitions(CCAPI_BINANCE_URL_REST_BASE="https://api.binance.com")
|
||||
add_compile_definitions(BINANCE_INSTRUMENTS_PATH="/api/v3/exchangeInfo")
|
||||
add_compile_definitions(BINANCE_PRICE_STATS_PATH="/api/v3/ticker/24hr")
|
||||
|
||||
# ** Binance US **
|
||||
add_compile_definitions(BINANCE_US_INSTRUMENTS_PATH="/api/v3/exchangeInfo")
|
||||
add_compile_definitions(BINANCE_US_PRICE_STATS_PATH="/api/v3/ticker/24hr")
|
||||
|
||||
# ** Binance USDS Futures **
|
||||
add_compile_definitions(CCAPI_BINANCE_USDS_FUTURES_URL_REST_BASE="https://dapi.binance.com")
|
||||
add_compile_definitions(BINANCE_USDS_FUTURES_INSTRUMENTS_PATH="/dapi/v1/exchangeInfo")
|
||||
add_compile_definitions(BINANCE_USDS_FUTURES_PRICE_STATS_PATH="/dapi/v1/ticker/24hr")
|
||||
|
||||
# ** Deribit **
|
||||
add_compile_definitions(DERIBIT_INSTRUMENT_PATH="/api/v2/public/get_instrument")
|
||||
add_compile_definitions(DERIBIT_INSTRUMENTS_PATH="/api/v2/public/get_instruments")
|
||||
add_compile_definitions(DERIBIT_COMBOS_PATH="/api/v2/public/get_combos")
|
||||
add_compile_definitions(DERIBIT_TICKER_PATH="/api/v2/public/ticker")
|
||||
add_compile_definitions(DERIBIT_CURRENCIES_METHOD="public/get_currencies")
|
||||
add_compile_definitions(DERIBIT_INSTRUMENT_METHOD="public/get_instrument")
|
||||
add_compile_definitions(DERIBIT_INSTRUMENTS_METHOD="public/get_instruments")
|
||||
add_compile_definitions(DERIBIT_COMBO_DETAILS_METHOD="public/get_combo_details")
|
||||
add_compile_definitions(DERIBIT_COMBOS_METHOD="public/get_combos")
|
||||
|
||||
# ** Okx **
|
||||
add_compile_definitions(OKX_INSTRUMENTS_PATH="/api/v5/public/instruments")
|
||||
add_compile_definitions(OKX_UNDERLYING_PATH="/api/v5/public/underlying")
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
add_compile_definitions(SHARED_MEMORY_PREFIX="spark")
|
||||
add_compile_definitions(APP_DATA_DIR="\$\{APPDATA\}/bts/")
|
||||
# subdirs
|
||||
add_subdirectory(src/lib)
|
||||
else()
|
||||
# make sparkd look for libspark.so in its directory
|
||||
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
|
||||
set(CMAKE_INSTALL_RPATH ".")
|
||||
set(CMAKE_INSTALL_PREFIX "${CMAKE_SOURCE_DIR}/install")
|
||||
set(SPARK_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}/$<CONFIG>")
|
||||
|
||||
if(BUILD_API_SERVER)
|
||||
add_compile_definitions(APP_DATA_DIR="\$\{HOME\}/spark_api/")
|
||||
add_compile_definitions(SHARED_MEMORY_PREFIX="spark_api")
|
||||
elseif(BUILD_SPARKD)
|
||||
add_compile_definitions(SHARED_MEMORY_PREFIX="sparkd")
|
||||
add_compile_definitions(APP_DATA_DIR="\$\{HOME\}/sparkdata/")
|
||||
|
||||
# Note: All macros that begin w/ 'CCAPI' are ccapi's macros (defined and/or
|
||||
# read by their code). We override some below.
|
||||
add_compile_definitions(SPARK_ENABLE_CCAPI)
|
||||
|
||||
# This allows us to override hardcoded exchange-urls with ones read from
|
||||
# config (i.e., resolved at runtime rather than compile-time)
|
||||
add_compile_definitions(CCAPI_EXPOSE_INTERNAL)
|
||||
|
||||
# Enable ccapi services
|
||||
add_compile_definitions(CCAPI_ENABLE_SERVICE_MARKET_DATA)
|
||||
add_compile_definitions(CCAPI_ENABLE_SERVICE_EXECUTION_MANAGEMENT)
|
||||
# Enable ccapi exchanges
|
||||
add_compile_definitions(CCAPI_ENABLE_EXCHANGE_BINANCE)
|
||||
add_compile_definitions(CCAPI_ENABLE_EXCHANGE_BINANCE_COIN_FUTURES)
|
||||
add_compile_definitions(CCAPI_ENABLE_EXCHANGE_BINANCE_US)
|
||||
add_compile_definitions(CCAPI_ENABLE_EXCHANGE_BINANCE_USDS_FUTURES)
|
||||
add_compile_definitions(CCAPI_ENABLE_EXCHANGE_COINBASE)
|
||||
add_compile_definitions(CCAPI_ENABLE_EXCHANGE_DERIBIT)
|
||||
add_compile_definitions(CCAPI_ENABLE_EXCHANGE_OKX)
|
||||
|
||||
set(CCAPI_LOG_LEVEL
|
||||
"Warn"
|
||||
CACHE STRING "<Fatal|Error|Warn|Info|Debug|Trace> Log level for ccapi")
|
||||
string(TOUPPER "${CCAPI_LOG_LEVEL}" _ccapi_log_level_upper)
|
||||
add_compile_definitions("CCAPI_ENABLE_LOG_${_ccapi_log_level_upper}")
|
||||
|
||||
# ** Binance **
|
||||
add_compile_definitions(CCAPI_BINANCE_URL_REST_BASE="https://api.binance.com")
|
||||
add_compile_definitions(BINANCE_INSTRUMENTS_PATH="/api/v3/exchangeInfo")
|
||||
add_compile_definitions(BINANCE_PRICE_STATS_PATH="/api/v3/ticker/24hr")
|
||||
|
||||
# ** Binance US **
|
||||
add_compile_definitions(BINANCE_US_INSTRUMENTS_PATH="/api/v3/exchangeInfo")
|
||||
add_compile_definitions(BINANCE_US_PRICE_STATS_PATH="/api/v3/ticker/24hr")
|
||||
|
||||
# ** Binance USDS Futures **
|
||||
add_compile_definitions(CCAPI_BINANCE_USDS_FUTURES_URL_REST_BASE="https://dapi.binance.com")
|
||||
add_compile_definitions(BINANCE_USDS_FUTURES_INSTRUMENTS_PATH="/dapi/v1/exchangeInfo")
|
||||
add_compile_definitions(BINANCE_USDS_FUTURES_PRICE_STATS_PATH="/dapi/v1/ticker/24hr")
|
||||
|
||||
# ** Deribit **
|
||||
add_compile_definitions(DERIBIT_INSTRUMENT_PATH="/api/v2/public/get_instrument")
|
||||
add_compile_definitions(DERIBIT_INSTRUMENTS_PATH="/api/v2/public/get_instruments")
|
||||
add_compile_definitions(DERIBIT_COMBOS_PATH="/api/v2/public/get_combos")
|
||||
add_compile_definitions(DERIBIT_TICKER_PATH="/api/v2/public/ticker")
|
||||
add_compile_definitions(DERIBIT_CURRENCIES_METHOD="public/get_currencies")
|
||||
add_compile_definitions(DERIBIT_INSTRUMENT_METHOD="public/get_instrument")
|
||||
add_compile_definitions(DERIBIT_INSTRUMENTS_METHOD="public/get_instruments")
|
||||
add_compile_definitions(DERIBIT_COMBO_DETAILS_METHOD="public/get_combo_details")
|
||||
add_compile_definitions(DERIBIT_COMBOS_METHOD="public/get_combos")
|
||||
|
||||
# ** Okx **
|
||||
add_compile_definitions(OKX_INSTRUMENTS_PATH="/api/v5/public/instruments")
|
||||
add_compile_definitions(OKX_UNDERLYING_PATH="/api/v5/public/underlying")
|
||||
endif()
|
||||
|
||||
# subdirs
|
||||
if (BUILD_SPARKD)
|
||||
add_subdirectory(src/server/sparkd)
|
||||
add_subdirectory(src/data_files)
|
||||
endif()
|
||||
add_subdirectory(src/lib)
|
||||
if (BUILD_ADMIN_WEB_APP)
|
||||
add_subdirectory(src/Spark.Admin.WebApp)
|
||||
endif()
|
||||
if(BUILD_DOCS)
|
||||
add_subdirectory(doc/user)
|
||||
endif()
|
||||
if(BUILD_SDK)
|
||||
add_subdirectory(src/sdk)
|
||||
endif()
|
||||
|
||||
if(BUILD_SPARKD)
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_BINARY_DIR}/server
|
||||
COMMAND mkdir -p ${CMAKE_BINARY_DIR}/server
|
||||
COMMAND ln ARGS -sf ${CMAKE_BINARY_DIR}/src/server/sparkd/sparkd ${CMAKE_BINARY_DIR}/server
|
||||
COMMAND ln ARGS -sf ${CMAKE_BINARY_DIR}/data_files ${CMAKE_BINARY_DIR}/server
|
||||
COMMAND ln ARGS -sf ${CMAKE_BINARY_DIR}/src/lib/libspark.so ${CMAKE_BINARY_DIR}/server
|
||||
COMMAND
|
||||
ln ARGS -sf
|
||||
${EXTERNALS_ROOT}/lib/Release/libOnixS.IceImpactMulticastPriceFeedHandlerCpp.so.3.16.0.0
|
||||
${CMAKE_BINARY_DIR}/server
|
||||
COMMAND ln ARGS -sf ${EXTERNALS_ROOT}/lib/Release/libACE-5.7.5.so ${CMAKE_BINARY_DIR}/server
|
||||
COMMAND mkdir ARGS -p ${CMAKE_BINARY_DIR}/server/plugins
|
||||
COMMENT "Creating server runtime layout"
|
||||
DEPENDS sparkd data_files_dir)
|
||||
|
||||
add_custom_target(server_layout ALL DEPENDS ${CMAKE_BINARY_DIR}/server)
|
||||
|
||||
install(
|
||||
DIRECTORY "${CMAKE_BINARY_DIR}/server/plugins"
|
||||
DESTINATION "${SPARK_INSTALL_PREFIX}/bin")
|
||||
install(
|
||||
FILES
|
||||
"${SPARK_LIB}/libACE-5.7.5.so"
|
||||
"${SPARK_LIB}/libOnixS.IceImpactMulticastPriceFeedHandlerCpp.so.3.16.0.0"
|
||||
DESTINATION "${SPARK_INSTALL_PREFIX}/bin")
|
||||
endif()
|
||||
# subdirs
|
||||
add_subdirectory(src/lib_system)
|
||||
add_subdirectory(src/lib_domain)
|
||||
add_subdirectory(src/lib_http)
|
||||
if (BUILD_SPARKD)
|
||||
add_subdirectory(src/lib_python_md)
|
||||
add_subdirectory(src/app_sparkd)
|
||||
add_subdirectory(src/data_files)
|
||||
endif()
|
||||
add_subdirectory(src/lib_spark)
|
||||
if (BUILD_ADMIN_WEB_APP)
|
||||
add_subdirectory(src/Spark.Admin.WebApp)
|
||||
endif()
|
||||
if(BUILD_DOCS)
|
||||
add_subdirectory(doc/user)
|
||||
endif()
|
||||
if(BUILD_SDK)
|
||||
add_subdirectory(src/sdk)
|
||||
endif()
|
||||
+117
-85
@@ -15,7 +15,7 @@
|
||||
"rhs": "Windows"
|
||||
},
|
||||
"generator": "Visual Studio 17 2022",
|
||||
"binaryDir": "${sourceDir}/build",
|
||||
"binaryDir": "${sourceDir}/build/${presetName}",
|
||||
"environment": {
|
||||
"SPARK_CMAKE_CXX_FLAGS": "/MP /WX /wd4250 /wd4251 /wd4244 /wd4267 /wd4355 /wd4275 /wd4345 /bigobj /EHsc /DCURL_STATICLIB /D_WINSOCK_DEPRECATED_NO_WARNINGS /D__TBB_NO_IMPLICIT_LINKAGE /DBOOST_ALL_NO_LIB /std:c++20 /D_SCL_SECURE_NO_WARNINGS /D_CRT_SECURE_NO_WARNINGS /D_WIN32_WINNT=0x0600"
|
||||
},
|
||||
@@ -28,9 +28,12 @@
|
||||
"CMAKE_SHARED_LINKER_FLAGS_RELEASE": "/OPT:REF /OPT:ICF /LTCG",
|
||||
"CMAKE_TOOLCHAIN_FILE": "${sourceDir}/vcpkg/scripts/buildsystems/vcpkg.cmake",
|
||||
"EXTERNALS_ROOT": "${sourceDir}/externals/windows",
|
||||
"CONFIG_DEFAULTS_PATH": "config/profiles/default/*.conf",
|
||||
"DOTNET_BINARY_DIR": "${sourceDir}/build/$<CONFIG>/bin/net7.0",
|
||||
"DOTNET_WINDOWS_BINARY_DIR": "${sourceDir}/build/$<CONFIG>/bin/net7.0-windows"
|
||||
"CONFIG_DEFAULTS_PATH": "spark/config/profiles/default/*.conf",
|
||||
"DOTNET_BINARY_DIR": "${sourceDir}/build/$<CONFIG>/bin/net7.0;${sourceDir}/build/$<CONFIG>/bin/net7.0-windows",
|
||||
"EXPORT_MD_CONSUMER": {
|
||||
"type": "BOOL",
|
||||
"value": "ON"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -46,14 +49,11 @@
|
||||
"binaryDir": "${sourceDir}/build/${presetName}",
|
||||
"cacheVariables": {
|
||||
"platform": "",
|
||||
"CMAKE_BUILD_WITH_INSTALL_RPATH": {
|
||||
"type": "BOOL",
|
||||
"value": "ON"
|
||||
},
|
||||
"CMAKE_CXX_STANDARD": "20",
|
||||
"CMAKE_INSTALL_RPATH": ".",
|
||||
"CMAKE_INSTALL_PREFIX": "${sourceDir}/install/${presetName}/sparkd",
|
||||
"CMAKE_INSTALL_PREFIX": "${sourceDir}/install/${presetName}",
|
||||
"CMAKE_PREFIX_PATH": "${sourceDir}/cmake/;${sourceDir}/.venv/lib/python3.10/site-packages/pybind11/share/cmake/pybind11",
|
||||
"CMAKE_EXE_LINKER_FLAGS": "-Wno-undef",
|
||||
"CMAKE_TOOLCHAIN_FILE": "${sourceDir}/vcpkg/scripts/buildsystems/vcpkg.cmake",
|
||||
"EXTERNALS_ROOT": "${sourceDir}/externals/linux",
|
||||
"BUILD_SDK": {
|
||||
"type": "BOOL",
|
||||
@@ -77,7 +77,7 @@
|
||||
"value": "ON"
|
||||
},
|
||||
"CCAPI_LOG_LEVEL": "Info",
|
||||
"CONFIG_DEFAULTS_PATH": "config/profiles/md_dev/*.conf;config/profiles/default/*.conf"
|
||||
"CONFIG_DEFAULTS_PATH": "spark/config/profiles/md_dev/*.conf;spark/config/profiles/default/*.conf"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -88,105 +88,74 @@
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "Release",
|
||||
"CCAPI_LOG_LEVEL": "Warn",
|
||||
"CONFIG_DEFAULTS_PATH": "config/profiles/md_prod/*.conf;config/profiles/default/*.conf"
|
||||
"CONFIG_DEFAULTS_PATH": "spark/config/profiles/md_prod/*.conf;spark/config/profiles/default/*.conf"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"name": "sparkd-debug-clang",
|
||||
"inherits": "sparkd-debug",
|
||||
"displayName": "Debug (clang)",
|
||||
"displayName": "Sparkd (Debug | Clang)",
|
||||
"description": "Debug build compiled w/ clang",
|
||||
"binaryDir": "${sourceDir}/build/clang/debug",
|
||||
"cacheVariables": {
|
||||
"CMAKE_C_COMPILER": "clang",
|
||||
"CMAKE_CXX_COMPILER": "clang++",
|
||||
"CMAKE_CXX_FLAGS_DEBUG": "-g -fPIC -Wall -pedantic -Wextra -Werror -Wno-missing-braces -Wno-ignored-qualifiers --std=c++20 -fdiagnostics-color -DDEBUG",
|
||||
"CMAKE_INSTALL_PREFIX": "${sourceDir}/install/clang/debug/sparkd"
|
||||
"CMAKE_CXX_FLAGS_DEBUG": "-g -fPIC -Wall -pedantic -Wextra -Werror -Wno-missing-braces -Wno-ignored-qualifiers --std=c++20 -fdiagnostics-color -DDEBUG"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"name": "sparkd-debug-gcc",
|
||||
"inherits": "sparkd-debug",
|
||||
"displayName": "Debug (gcc)",
|
||||
"displayName": "Sparkd (Debug | Gcc)",
|
||||
"description": "Debug build compiled w/ gcc",
|
||||
"binaryDir": "${sourceDir}/build/gcc/debug",
|
||||
"cacheVariables": {
|
||||
"CMAKE_C_COMPILER": "gcc",
|
||||
"CMAKE_CXX_COMPILER": "g++",
|
||||
"CMAKE_CXX_FLAGS_DEBUG": "-g -fPIC -Wall -pedantic -Wextra -Werror -Wno-missing-braces -Wno-ignored-qualifiers --std=c++20 -fdiagnostics-color -Wno-stringop-overread -DDEBUG",
|
||||
"CMAKE_INSTALL_PREFIX": "${sourceDir}/install/gcc/debug/sparkd"
|
||||
"CMAKE_CXX_FLAGS_DEBUG": "-g -fPIC -Wall -pedantic -Wextra -Werror -Wno-missing-braces -Wno-ignored-qualifiers --std=c++20 -fdiagnostics-color -Wno-stringop-overread -DDEBUG"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"name": "sparkd-release-clang",
|
||||
"inherits": "sparkd-release",
|
||||
"displayName": "Release (clang)",
|
||||
"displayName": "Sparkd (Release | Clang)",
|
||||
"description": "Release build compiled w/ clang",
|
||||
"binaryDir": "${sourceDir}/build/clang/release",
|
||||
"cacheVariables": {
|
||||
"CMAKE_C_COMPILER": "clang",
|
||||
"CMAKE_CXX_COMPILER": "clang++",
|
||||
"CMAKE_CXX_FLAGS_RELEASE": "-fPIC -Wall -pedantic -Wextra -Werror -Wno-missing-braces -Wno-ignored-qualifiers --std=c++20 -fdiagnostics-color -fno-omit-frame-pointer -DNDEBUG -O3",
|
||||
"CMAKE_INSTALL_PREFIX": "${sourceDir}/install/clang/release/sparkd"
|
||||
"CMAKE_CXX_FLAGS_RELEASE": "-fPIC -Wall -pedantic -Wextra -Werror -Wno-missing-braces -Wno-ignored-qualifiers --std=c++20 -fdiagnostics-color -fno-omit-frame-pointer -DNDEBUG -O3"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"name": "sparkd-release-gcc",
|
||||
"inherits": "sparkd-release",
|
||||
"displayName": "Release (gcc)",
|
||||
"displayName": "Sparkd (Release | Gcc)",
|
||||
"description": "Release build compiled w/ gcc",
|
||||
"binaryDir": "${sourceDir}/build/gcc/release",
|
||||
"cacheVariables": {
|
||||
"CMAKE_C_COMPILER": "gcc",
|
||||
"CMAKE_CXX_COMPILER": "g++",
|
||||
"CMAKE_CXX_FLAGS_RELEASE": "-fPIC -Wall -pedantic -Wextra -Werror -Wno-missing-braces -Wno-ignored-qualifiers --std=c++20 -fdiagnostics-color -Wno-stringop-overread -Wno-maybe-uninitialized -fno-omit-frame-pointer -DNDEBUG -O3",
|
||||
"CMAKE_INSTALL_PREFIX": "${sourceDir}/install/gcc/release/sparkd"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"name": "spark-api-server-base",
|
||||
"hidden": true,
|
||||
"binaryDir": "${sourceDir}/build/${presetName}",
|
||||
"cacheVariables": {
|
||||
"BUILD_API_SERVER": {
|
||||
"type": "bool",
|
||||
"value": "ON"
|
||||
},
|
||||
"CONFIG_DEFAULTS_PATH": "config/profiles/md_dev/*.conf;config/profiles/default/*.conf"
|
||||
"CMAKE_CXX_FLAGS_RELEASE": "-fPIC -Wall -pedantic -Wextra -Werror -Wno-missing-braces -Wno-ignored-qualifiers -Wno-stringop-overflow --std=c++20 -fdiagnostics-color -Wno-stringop-overread -Wno-maybe-uninitialized -fno-omit-frame-pointer -DNDEBUG -O3"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"name": "spark-api-server-windows",
|
||||
"inherits": "spark",
|
||||
"displayName": "Spark Api Server",
|
||||
"cacheVariables": {
|
||||
"BUILD_API_SERVER": {
|
||||
"type": "bool",
|
||||
"value": "ON"
|
||||
}
|
||||
}
|
||||
"displayName": "Spark Api Server (Windows)"
|
||||
},
|
||||
|
||||
{
|
||||
"name": "spark-api-server-linux",
|
||||
"inherits": "sparkd",
|
||||
"displayName": "Spark Api Server",
|
||||
"displayName": "Spark Api Server (Linux)",
|
||||
"generator": "Ninja Multi-Config",
|
||||
"cacheVariables": {
|
||||
"BUILD_ADMIN_WEB_APP": {
|
||||
"type": "BOOL",
|
||||
"value": "OFF"
|
||||
},
|
||||
"BUILD_API_SERVER": {
|
||||
"type": "bool",
|
||||
"value": "ON"
|
||||
},
|
||||
"BUILD_SPARKD": {
|
||||
"type": "BOOL",
|
||||
"value": "OFF"
|
||||
@@ -195,9 +164,16 @@
|
||||
"CMAKE_CXX_COMPILER": "clang++",
|
||||
"CMAKE_CXX_FLAGS_DEBUG": "-g -fPIC -Wall -pedantic -Wextra -Werror -Wno-missing-braces -Wno-ignored-qualifiers --std=c++20 -fdiagnostics-color -DDEBUG",
|
||||
"CMAKE_CXX_FLAGS_RELEASE": "-fPIC -Wall -pedantic -Wextra -Werror -Wno-missing-braces -Wno-ignored-qualifiers --std=c++20 -fdiagnostics-color -fno-omit-frame-pointer -DNDEBUG -O3",
|
||||
"CMAKE_INSTALL_PREFIX": "${sourceDir}/install/${presetName}",
|
||||
"CONFIG_DEFAULTS_PATH": "config/profiles/default/*.conf",
|
||||
"DOTNET_BINARY_DIR": "${sourceDir}/build/$<CONFIG>/bin/net7.0"
|
||||
"CMAKE_EXPORT_COMPILE_COMMANDS": {
|
||||
"type": "BOOL",
|
||||
"value": "ON"
|
||||
},
|
||||
"CONFIG_DEFAULTS_PATH": "spark/config/profiles/default/*.conf",
|
||||
"DOTNET_BINARY_DIR": "${sourceDir}/build/$<CONFIG>/bin/net7.0",
|
||||
"EXPORT_MD_CONSUMER": {
|
||||
"type": "BOOL",
|
||||
"value": "ON"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -220,13 +196,56 @@
|
||||
},
|
||||
|
||||
{
|
||||
"name": "data-stream-suite",
|
||||
"name": "data-stream-suite-windows",
|
||||
"condition": {
|
||||
"type": "equals",
|
||||
"lhs": "${hostSystemName}",
|
||||
"rhs": "Windows"
|
||||
},
|
||||
"inherits": "spark",
|
||||
"displayName": "Data Stream Suite",
|
||||
"displayName": "Data Stream Suite (Windows)",
|
||||
"description": "Data Stream utils ported over from Edge",
|
||||
"binaryDir": "${sourceDir}/build/${presetName}",
|
||||
"cacheVariables": {
|
||||
"CONFIG_DEFAULTS_PATH": "config/profiles/default/*.conf;config/profiles/data_stream/*.conf"
|
||||
"CONFIG_DEFAULTS_PATH": "spark/config/profiles/default/*.conf;spark/config/profiles/data_stream/*.conf",
|
||||
"DOTNET_BINARY_DIR": "${sourceDir}/build/$<CONFIG>/bin/net7.0;${sourceDir}/build/$<CONFIG>/bin/net7.0-windows"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"name": "data-stream-suite-linux",
|
||||
"displayName": "Data Stream Suite (Linux)",
|
||||
"description": "Data Stream utils ported over from Edge",
|
||||
"condition": {
|
||||
"type": "equals",
|
||||
"lhs": "${hostSystemName}",
|
||||
"rhs": "Linux"
|
||||
},
|
||||
"inherits": "sparkd",
|
||||
"generator": "Ninja Multi-Config",
|
||||
"cacheVariables": {
|
||||
"BUILD_ADMIN_WEB_APP": {
|
||||
"type": "BOOL",
|
||||
"value": "OFF"
|
||||
},
|
||||
"BUILD_SDK": {
|
||||
"type": "BOOL",
|
||||
"value": "OFF"
|
||||
},
|
||||
"BUILD_SPARKD": {
|
||||
"type": "BOOL",
|
||||
"value": "OFF"
|
||||
},
|
||||
"CMAKE_C_COMPILER": "clang",
|
||||
"CMAKE_CXX_COMPILER": "clang++",
|
||||
"CMAKE_CXX_FLAGS_DEBUG": "-g -fPIC -Wall -pedantic -Wextra -Werror -Wno-missing-braces -Wno-ignored-qualifiers --std=c++20 -fdiagnostics-color -DDEBUG",
|
||||
"CMAKE_CXX_FLAGS_RELEASE": "-fPIC -Wall -pedantic -Wextra -Werror -Wno-missing-braces -Wno-ignored-qualifiers --std=c++20 -fdiagnostics-color -fno-omit-frame-pointer -DNDEBUG -O3",
|
||||
"CONFIG_DEFAULTS_PATH": "spark/config/profiles/default/*.conf;spark/config/profiles/data_stream/*.conf",
|
||||
"DOTNET_BINARY_DIR": "${sourceDir}/build/$<CONFIG>/bin/net7.0;${sourceDir}/build/$<CONFIG>/bin/net8.0",
|
||||
"EXPORT_MD_CONSUMER": {
|
||||
"type": "BOOL",
|
||||
"value": "ON"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -244,7 +263,7 @@
|
||||
|
||||
{
|
||||
"name": "spark-debug",
|
||||
"displayName": "Debug",
|
||||
"displayName": "Spark (Debug)",
|
||||
"inherits": "spark",
|
||||
"configurePreset": "spark",
|
||||
"configuration": "Debug"
|
||||
@@ -252,7 +271,7 @@
|
||||
|
||||
{
|
||||
"name": "spark-release",
|
||||
"displayName": "Release",
|
||||
"displayName": "Spark (Release)",
|
||||
"inherits": "spark",
|
||||
"configurePreset": "spark",
|
||||
"configuration": "Release"
|
||||
@@ -265,43 +284,42 @@
|
||||
"lhs": "${hostSystemName}",
|
||||
"rhs": "Linux"
|
||||
},
|
||||
"hidden": true,
|
||||
"targets": [
|
||||
"data_files_dir",
|
||||
"admin_web_app_bundle",
|
||||
"install",
|
||||
"libspark",
|
||||
"rapidjson_project",
|
||||
"server_layout",
|
||||
"sparkd"
|
||||
]
|
||||
"hidden": true
|
||||
},
|
||||
|
||||
{
|
||||
"name": "sparkd-debug-clang",
|
||||
"configurePreset": "sparkd-debug-clang",
|
||||
"displayName": "Debug (clang)",
|
||||
"displayName": "Sparkd (Debug | Clang)",
|
||||
"inherits": "sparkd"
|
||||
},
|
||||
|
||||
{
|
||||
"name": "sparkd-debug-clang-j6",
|
||||
"configurePreset": "sparkd-debug-clang",
|
||||
"displayName": "Sparkd (Debug | Clang | jobs=6)",
|
||||
"inherits": "sparkd",
|
||||
"jobs": 6
|
||||
},
|
||||
|
||||
{
|
||||
"name": "sparkd-debug-gcc",
|
||||
"configurePreset": "sparkd-debug-gcc",
|
||||
"displayName": "Debug (gcc)",
|
||||
"displayName": "Sparkd (Debug | Gcc)",
|
||||
"inherits": "sparkd"
|
||||
},
|
||||
|
||||
{
|
||||
"name": "sparkd-release-clang",
|
||||
"configurePreset": "sparkd-release-clang",
|
||||
"displayName": "Release (clang)",
|
||||
"displayName": "Sparkd (Release | Clang)",
|
||||
"inherits": "sparkd"
|
||||
},
|
||||
|
||||
{
|
||||
"name": "sparkd-release-gcc",
|
||||
"configurePreset": "sparkd-release-gcc",
|
||||
"displayName": "Release (gcc)",
|
||||
"displayName": "Sparkd (Release | Gcc)",
|
||||
"inherits": "sparkd"
|
||||
},
|
||||
|
||||
@@ -318,14 +336,14 @@
|
||||
|
||||
{
|
||||
"name": "spark-api-server-windows-debug",
|
||||
"displayName": "Spark Api Server (Debug)",
|
||||
"displayName": "Spark Api Server (Windows | Debug)",
|
||||
"inherits": "spark-api-server-windows",
|
||||
"configuration": "Debug"
|
||||
},
|
||||
|
||||
{
|
||||
"name": "spark-api-server-windows-release",
|
||||
"displayName": "Spark Api Server (Debug)",
|
||||
"displayName": "Spark Api Server (Windows | Release)",
|
||||
"inherits": "spark-api-server-windows",
|
||||
"configuration": "Release"
|
||||
},
|
||||
@@ -344,14 +362,14 @@
|
||||
{
|
||||
"name": "spark-api-server-linux-debug",
|
||||
"inherits": "spark-api-server-linux",
|
||||
"displayName": "Spark Api Server (Debug)",
|
||||
"displayName": "Spark Api Server (Linux | Debug)",
|
||||
"configuration": "Debug"
|
||||
},
|
||||
|
||||
{
|
||||
"name": "spark-api-server-linux-release",
|
||||
"inherits": "spark-api-server-linux",
|
||||
"displayName": "Spark Api Server (Release)",
|
||||
"displayName": "Spark Api Server (Linux | Release)",
|
||||
"configuration": "Release"
|
||||
},
|
||||
|
||||
@@ -371,16 +389,30 @@
|
||||
},
|
||||
|
||||
{
|
||||
"name": "data-stream-suite-debug",
|
||||
"displayName": "DataStreamSuite (Debug)",
|
||||
"configurePreset": "data-stream-suite",
|
||||
"name": "data-stream-suite-windows-debug",
|
||||
"displayName": "Data Stream Suite (Windows | Debug)",
|
||||
"configurePreset": "data-stream-suite-windows",
|
||||
"configuration": "Debug"
|
||||
},
|
||||
|
||||
{
|
||||
"name": "data-stream-suite-release",
|
||||
"displayName": "DataStreamSuite (Release)",
|
||||
"configurePreset": "data-stream-suite",
|
||||
"name": "data-stream-suite-windows-release",
|
||||
"displayName": "Data Stream Suite (Windows | Release)",
|
||||
"configurePreset": "data-stream-suite-windows",
|
||||
"configuration": "Release"
|
||||
},
|
||||
|
||||
{
|
||||
"name": "data-stream-suite-linux-debug",
|
||||
"displayName": "Data Stream Suite (Linux | Debug)",
|
||||
"configurePreset": "data-stream-suite-linux",
|
||||
"configuration": "Debug"
|
||||
},
|
||||
|
||||
{
|
||||
"name": "data-stream-suite-linux-release",
|
||||
"displayName": "Data Stream Suite (Linux | Release)",
|
||||
"configurePreset": "data-stream-suite-linux",
|
||||
"configuration": "Release"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -14,6 +14,16 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "spark_test", "src\client\sp
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Spark.Console", "src\client\Spark.Console\Spark.Console.csproj", "{89D666E6-B500-498F-B026-4D167F68ADFC}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bts.Net", "src\DataStreamSuite\Bts.Net\Bts.Net.csproj", "{CCDCB00A-CABF-4D82-8A5F-33EEC8ACE51D}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DataStreamCore", "src\DataStreamSuite\DataStreamCore\DataStreamCore.csproj", "{CB62D5D2-3495-4488-BFBC-7C7A3725A1EE}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DataStream", "src\DataStreamSuite\DataStream\DataStream.csproj", "{05995ED5-650A-4955-9DFC-3242B737E77A}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharedStreams", "src\DataStreamSuite\SharedStreams\SharedStreams.csproj", "{A8B861DE-E098-4291-98EE-76AA0F5F5A7B}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PubSub", "src\DataStreamSuite\PubSub\PubSub.csproj", "{EFA9F78D-083E-457A-BABB-9386C88C32C0}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
@@ -70,6 +80,46 @@ Global
|
||||
{89D666E6-B500-498F-B026-4D167F68ADFC}.Release|x64.Build.0 = Release|x64
|
||||
{89D666E6-B500-498F-B026-4D167F68ADFC}.RelWithDebInfo|x64.ActiveCfg = Debug|x64
|
||||
{89D666E6-B500-498F-B026-4D167F68ADFC}.RelWithDebInfo|x64.Build.0 = Debug|x64
|
||||
{CCDCB00A-CABF-4D82-8A5F-33EEC8ACE51D}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{CCDCB00A-CABF-4D82-8A5F-33EEC8ACE51D}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{CCDCB00A-CABF-4D82-8A5F-33EEC8ACE51D}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU
|
||||
{CCDCB00A-CABF-4D82-8A5F-33EEC8ACE51D}.MinSizeRel|x64.Build.0 = Debug|Any CPU
|
||||
{CCDCB00A-CABF-4D82-8A5F-33EEC8ACE51D}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{CCDCB00A-CABF-4D82-8A5F-33EEC8ACE51D}.Release|x64.Build.0 = Release|Any CPU
|
||||
{CCDCB00A-CABF-4D82-8A5F-33EEC8ACE51D}.RelWithDebInfo|x64.ActiveCfg = Debug|Any CPU
|
||||
{CCDCB00A-CABF-4D82-8A5F-33EEC8ACE51D}.RelWithDebInfo|x64.Build.0 = Debug|Any CPU
|
||||
{CB62D5D2-3495-4488-BFBC-7C7A3725A1EE}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{CB62D5D2-3495-4488-BFBC-7C7A3725A1EE}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{CB62D5D2-3495-4488-BFBC-7C7A3725A1EE}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU
|
||||
{CB62D5D2-3495-4488-BFBC-7C7A3725A1EE}.MinSizeRel|x64.Build.0 = Debug|Any CPU
|
||||
{CB62D5D2-3495-4488-BFBC-7C7A3725A1EE}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{CB62D5D2-3495-4488-BFBC-7C7A3725A1EE}.Release|x64.Build.0 = Release|Any CPU
|
||||
{CB62D5D2-3495-4488-BFBC-7C7A3725A1EE}.RelWithDebInfo|x64.ActiveCfg = Debug|Any CPU
|
||||
{CB62D5D2-3495-4488-BFBC-7C7A3725A1EE}.RelWithDebInfo|x64.Build.0 = Debug|Any CPU
|
||||
{05995ED5-650A-4955-9DFC-3242B737E77A}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{05995ED5-650A-4955-9DFC-3242B737E77A}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{05995ED5-650A-4955-9DFC-3242B737E77A}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU
|
||||
{05995ED5-650A-4955-9DFC-3242B737E77A}.MinSizeRel|x64.Build.0 = Debug|Any CPU
|
||||
{05995ED5-650A-4955-9DFC-3242B737E77A}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{05995ED5-650A-4955-9DFC-3242B737E77A}.Release|x64.Build.0 = Release|Any CPU
|
||||
{05995ED5-650A-4955-9DFC-3242B737E77A}.RelWithDebInfo|x64.ActiveCfg = Debug|Any CPU
|
||||
{05995ED5-650A-4955-9DFC-3242B737E77A}.RelWithDebInfo|x64.Build.0 = Debug|Any CPU
|
||||
{A8B861DE-E098-4291-98EE-76AA0F5F5A7B}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{A8B861DE-E098-4291-98EE-76AA0F5F5A7B}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{A8B861DE-E098-4291-98EE-76AA0F5F5A7B}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU
|
||||
{A8B861DE-E098-4291-98EE-76AA0F5F5A7B}.MinSizeRel|x64.Build.0 = Debug|Any CPU
|
||||
{A8B861DE-E098-4291-98EE-76AA0F5F5A7B}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{A8B861DE-E098-4291-98EE-76AA0F5F5A7B}.Release|x64.Build.0 = Release|Any CPU
|
||||
{A8B861DE-E098-4291-98EE-76AA0F5F5A7B}.RelWithDebInfo|x64.ActiveCfg = Debug|Any CPU
|
||||
{A8B861DE-E098-4291-98EE-76AA0F5F5A7B}.RelWithDebInfo|x64.Build.0 = Debug|Any CPU
|
||||
{EFA9F78D-083E-457A-BABB-9386C88C32C0}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{EFA9F78D-083E-457A-BABB-9386C88C32C0}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{EFA9F78D-083E-457A-BABB-9386C88C32C0}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU
|
||||
{EFA9F78D-083E-457A-BABB-9386C88C32C0}.MinSizeRel|x64.Build.0 = Debug|Any CPU
|
||||
{EFA9F78D-083E-457A-BABB-9386C88C32C0}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{EFA9F78D-083E-457A-BABB-9386C88C32C0}.Release|x64.Build.0 = Release|Any CPU
|
||||
{EFA9F78D-083E-457A-BABB-9386C88C32C0}.RelWithDebInfo|x64.ActiveCfg = Debug|Any CPU
|
||||
{EFA9F78D-083E-457A-BABB-9386C88C32C0}.RelWithDebInfo|x64.Build.0 = Debug|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
include_guard(GLOBAL)
|
||||
|
||||
macro(export_to_parent)
|
||||
foreach(var IN ITEMS ${ARGN})
|
||||
set(${var} ${${var}} PARENT_SCOPE)
|
||||
endforeach()
|
||||
endmacro()
|
||||
@@ -0,0 +1,142 @@
|
||||
include_guard(DIRECTORY)
|
||||
include(${CMAKE_SOURCE_DIR}/cmake/ExportToParent.cmake)
|
||||
include(${CMAKE_SOURCE_DIR}/cmake/InstallBasic.cmake)
|
||||
include(${CMAKE_SOURCE_DIR}/cmake/ProtobufGenerateCpp.cmake)
|
||||
include(${CMAKE_SOURCE_DIR}/cmake/SetFirstDefined.cmake)
|
||||
include(${CMAKE_SOURCE_DIR}/cmake/safe_dep_glob.cmake)
|
||||
|
||||
function(init_library)
|
||||
set(_options SHARED STATIC)
|
||||
set(_one_value_args
|
||||
NAME
|
||||
SOURCE_DIR
|
||||
INCLUDE_DIR
|
||||
)
|
||||
set(_multi_value_args)
|
||||
cmake_parse_arguments(_ARGS "${_options}" "${_one_value_args}" "${_multi_value_args}" ${ARGN})
|
||||
if (_ARGS_SHARED AND _ARGS_STATIC)
|
||||
message(FATAL_ERROR "Invalid args passed to init_library: cannot specify STATIC and SHARED")
|
||||
endif()
|
||||
set_first_defined(_name _ARGS_NAME PROJECT_NAME)
|
||||
set_first_defined(_source_dir _ARGS_SOURCE_DIR _name)
|
||||
set_first_defined(_include_dir _ARGS_INCLUDE_DIR _source_dir)
|
||||
|
||||
# Cpp sources
|
||||
file(
|
||||
GLOB_RECURSE ${_name}_SOURCES
|
||||
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${_source_dir}/*.cpp
|
||||
)
|
||||
# Note: cpp files inside 'tests' dir(s) are considered tests.
|
||||
# Remove tests from main sources, and add them to test sources
|
||||
foreach(item ${${_name}_SOURCES})
|
||||
if(${item} MATCHES "tests/.*\.cpp$")
|
||||
list(APPEND ${_name}_TEST_SOURCES ${item})
|
||||
endif()
|
||||
endforeach()
|
||||
foreach(item ${${_name}_TEST_SOURCES})
|
||||
list(REMOVE_ITEM ${_name}_SOURCES ${item})
|
||||
endforeach()
|
||||
|
||||
# Proto sources
|
||||
file(
|
||||
GLOB_RECURSE ${_name}_PROTO_SOURCES
|
||||
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${_source_dir}/protobufs/*.proto
|
||||
)
|
||||
update_deps_file("${${_name}_PROTO_SOURCES};")
|
||||
protobuf_generate_cpp(
|
||||
CXX_SOURCES ${_name}_CXX_PROTO_SOURCES
|
||||
CXX_HEADERS ${_name}_CXX_PROTO_HEADERS
|
||||
CXX_OUT_DIR ${CMAKE_CURRENT_BINARY_DIR}
|
||||
PROTO_INCLUDE_DIRS
|
||||
${EXTERNALS_INCLUDE}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
PROTO_SOURCES
|
||||
${${_name}_PROTO_SOURCES}
|
||||
)
|
||||
|
||||
export_to_parent(
|
||||
${_name}_SOURCES
|
||||
${_name}_TEST_SOURCES
|
||||
${_name}_PROTO_SOURCES
|
||||
${_name}_CXX_PROTO_SOURCES
|
||||
${_name}_CXX_PROTO_HEADERS
|
||||
)
|
||||
|
||||
# Add main lib
|
||||
if (_ARGS_STATIC)
|
||||
add_library(${_name} STATIC ${${_name}_SOURCES} ${${_name}_CXX_PROTO_SOURCES})
|
||||
elseif(_ARGS_SHARED)
|
||||
add_library(${_name} SHARED ${${_name}_SOURCES} ${${_name}_CXX_PROTO_SOURCES})
|
||||
else()
|
||||
add_library(${_name} ${${_name}_SOURCES} ${${_name}_CXX_PROTO_SOURCES})
|
||||
endif()
|
||||
target_include_directories(
|
||||
${_name}
|
||||
SYSTEM
|
||||
BEFORE
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${EXTERNALS_ROOT}/include>
|
||||
$<BUILD_INTERFACE:${EXTERNALS_ROOT}/include/zlib>
|
||||
)
|
||||
target_include_directories(
|
||||
${_name}
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
)
|
||||
# Include protos (if any)
|
||||
if (${_name}_PROTO_SOURCES)
|
||||
target_include_directories(
|
||||
${_name}
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>
|
||||
)
|
||||
endif()
|
||||
target_link_directories(
|
||||
${_name}
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>
|
||||
$<BUILD_INTERFACE:${EXTERNALS_ROOT}/lib/$<CONFIG>>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_LIBDIR}>
|
||||
)
|
||||
# Install main lib
|
||||
foreach(_hdr ${${_name}_CXX_PROTO_HEADERS})
|
||||
file(RELATIVE_PATH _relative_path ${CMAKE_CURRENT_BINARY_DIR} ${_hdr})
|
||||
install(FILES ${_hdr} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${_relative_path})
|
||||
endforeach()
|
||||
install_basic(
|
||||
NAME ${_name}
|
||||
INCLUDE_DIR ${_include_dir}
|
||||
)
|
||||
|
||||
# Add tests executable (if there are any)
|
||||
if (${_name}_TEST_SOURCES AND NOT WIN32)
|
||||
add_executable(${_name}-tests ${${_name}_TEST_SOURCES})
|
||||
|
||||
get_target_property(_lib_type ${_name} TYPE)
|
||||
if (_lib_type STREQUAL "SHARED_LIBRARY")
|
||||
# Set RPATH so the tests exe knows where to find the shared lib.
|
||||
set_target_properties(
|
||||
${_name}-tests
|
||||
PROPERTIES
|
||||
BUILD_RPATH "$ORIGIN"
|
||||
INSTALL_RPATH "$ORIGIN/../${CMAKE_INSTALL_LIBDIR}"
|
||||
)
|
||||
endif()
|
||||
|
||||
# Link main lib
|
||||
target_link_directories(
|
||||
${_name}-tests
|
||||
PRIVATE
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_LIBDIR}>
|
||||
)
|
||||
target_link_libraries(${_name}-tests PRIVATE ${_name})
|
||||
|
||||
# Catch2
|
||||
find_package(Catch2 CONFIG REQUIRED COMPONENTS Catch2WithMain)
|
||||
target_link_libraries(${_name}-tests PRIVATE Catch2::Catch2WithMain)
|
||||
endif()
|
||||
endfunction()
|
||||
@@ -0,0 +1,39 @@
|
||||
include_guard(DIRECTORY)
|
||||
include(GNUInstallDirs)
|
||||
include(${CMAKE_SOURCE_DIR}/cmake/PackBasic.cmake)
|
||||
include(${CMAKE_SOURCE_DIR}/cmake/SetFirstDefined.cmake)
|
||||
|
||||
function(install_basic)
|
||||
set(_options)
|
||||
set(_one_value_args NAME INCLUDE_DIR)
|
||||
set(_multi_value_args)
|
||||
cmake_parse_arguments(_ARGS "${_options}" "${_one_value_args}" "${_multi_value_args}" ${ARGN})
|
||||
set_first_defined(_name _ARGS_NAME PROJECT_NAME)
|
||||
set_first_defined(_include_dir _ARGS_INCLUDE_DIR _name)
|
||||
|
||||
file(
|
||||
GLOB_RECURSE ${_name}_HEADERS
|
||||
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${_include_dir}/*.h)
|
||||
|
||||
target_sources(${_name}
|
||||
PUBLIC
|
||||
FILE_SET HEADERS FILES ${${_name}_HEADERS})
|
||||
|
||||
install(
|
||||
TARGETS ${_name}
|
||||
EXPORT ${_name}Targets
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
FILE_SET HEADERS DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||
)
|
||||
|
||||
install(
|
||||
EXPORT ${_name}Targets
|
||||
FILE ${_name}Targets.cmake
|
||||
NAMESPACE ${_name}::
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${_name})
|
||||
|
||||
pack_basic()
|
||||
endfunction()
|
||||
@@ -0,0 +1,44 @@
|
||||
include_guard(DIRECTORY)
|
||||
include(CMakePackageConfigHelpers)
|
||||
include(${CMAKE_SOURCE_DIR}/cmake/SetFirstDefined.cmake)
|
||||
|
||||
function(pack_basic)
|
||||
set(_options)
|
||||
set(_one_value_args NAME)
|
||||
set(_multi_value_args)
|
||||
cmake_parse_arguments(_ARGS "${_options}" "${_one_value_args}" "${_multi_value_args}" ${ARGN})
|
||||
set_first_defined(_name _ARGS_NAME PROJECT_NAME)
|
||||
|
||||
find_package(Git QUIET)
|
||||
|
||||
if(GIT_FOUND)
|
||||
execute_process(
|
||||
COMMAND ${GIT_EXECUTABLE} describe --tags --always --dirty
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE PROJECT_VERSION
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
endif()
|
||||
|
||||
if(NOT GIT_FOUND OR PROJECT_VERSION STREQUAL "")
|
||||
set(PROJECT_VERSION "0.0.0")
|
||||
endif()
|
||||
|
||||
write_basic_package_version_file(
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/${_name}ConfigVersion.cmake"
|
||||
VERSION ${PROJECT_VERSION}
|
||||
COMPATIBILITY AnyNewerVersion
|
||||
)
|
||||
|
||||
configure_package_config_file(
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/Config.cmake.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/${_name}Config.cmake"
|
||||
INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${_name}
|
||||
)
|
||||
|
||||
install(
|
||||
FILES
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/${_name}Config.cmake"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/${_name}ConfigVersion.cmake"
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${_name})
|
||||
endfunction()
|
||||
@@ -1,145 +0,0 @@
|
||||
set(Protobuf_PROTOC_EXECUTABLE "${SPARK_BIN}/protoc")
|
||||
set(PROTOBUF_INCLUDE_DIRS "${SPARK_INCLUDE}")
|
||||
set(PROTOBUF_STATIC_LIB "libprotobuf")
|
||||
|
||||
function(Protobuf_Generate_Cpp SRCS HDRS)
|
||||
set(${SRCS})
|
||||
set(${HDRS})
|
||||
|
||||
foreach(FIL ${ARGN})
|
||||
get_filename_component(ABS_FIL ${FIL} ABSOLUTE)
|
||||
get_filename_component(FIL_WE ${FIL} NAME_WE)
|
||||
get_filename_component(FIL_DIR ${FIL} DIRECTORY)
|
||||
if(FIL_DIR)
|
||||
set(FIL_WE "${FIL_DIR}/${FIL_WE}")
|
||||
endif()
|
||||
|
||||
list(APPEND ${SRCS} "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.cc")
|
||||
list(APPEND ${HDRS} "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.h")
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.cc"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.h"
|
||||
COMMAND
|
||||
${Protobuf_PROTOC_EXECUTABLE} ARGS --cpp_out=${CMAKE_BINARY_DIR}/src -I
|
||||
${PROTOBUF_INCLUDE_DIRS} -I ${CMAKE_SOURCE_DIR}/src ${ABS_FIL}
|
||||
DEPENDS ${ABS_FIL}
|
||||
COMMENT "Running C++ protocol buffer compiler on ${FIL}"
|
||||
VERBATIM)
|
||||
endforeach()
|
||||
|
||||
set_source_files_properties(${${SRCS}} ${${HDRS}} PROPERTIES GENERATED TRUE)
|
||||
|
||||
# remove some warnings from protobuf generated files
|
||||
if(WIN32)
|
||||
set_source_files_properties(${${SRCS}} PROPERTIES COMPILE_FLAGS
|
||||
"/wd4309 /wd4838")
|
||||
else()
|
||||
set_source_files_properties(
|
||||
${${SRCS}}
|
||||
PROPERTIES
|
||||
COMPILE_FLAGS
|
||||
"-Wno-unused-parameter -Wno-effc++ -Wno-pedantic -Wno-sign-compare -Wno-uninitialized"
|
||||
)
|
||||
endif()
|
||||
|
||||
set(${SRCS}
|
||||
${${SRCS}}
|
||||
PARENT_SCOPE)
|
||||
set(${HDRS}
|
||||
${${HDRS}}
|
||||
PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(Service_Compiler_Generate_Cpp SRCS HDRS)
|
||||
set(${SRCS})
|
||||
set(${HDRS})
|
||||
|
||||
foreach(FIL ${ARGN})
|
||||
get_filename_component(ABS_FIL ${FIL} ABSOLUTE)
|
||||
get_filename_component(FIL_WE ${FIL} NAME_WE)
|
||||
get_filename_component(FIL_DIR ${FIL} DIRECTORY)
|
||||
if(FIL_DIR)
|
||||
set(FIL_WE "${FIL_DIR}/${FIL_WE}")
|
||||
endif()
|
||||
|
||||
list(APPEND ${SRCS} "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.cc")
|
||||
list(APPEND ${HDRS} "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.h")
|
||||
|
||||
list(APPEND ${SRCS} "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.client.pb.cc")
|
||||
list(APPEND ${HDRS} "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.client.pb.h")
|
||||
|
||||
list(APPEND ${SRCS} "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.server.pb.cc")
|
||||
list(APPEND ${HDRS} "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.server.pb.h")
|
||||
|
||||
set(TEMPLATES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/api/service_compiler/templates/cpp/client.pb.cc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/api/service_compiler/templates/cpp/client.pb.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/api/service_compiler/templates/cpp/server.pb.cc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/api/service_compiler/templates/cpp/server.pb.h
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
add_custom_command(
|
||||
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.cc"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.h"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.client.pb.cc"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.client.pb.h"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.server.pb.cc"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.server.pb.h"
|
||||
COMMAND SET PYTHONPATH=${SPARK_PYTHON}
|
||||
COMMAND ${CMAKE_SOURCE_DIR}/.venv/Scripts/activate.bat
|
||||
COMMAND
|
||||
${Protobuf_PROTOC_EXECUTABLE} ARGS --cpp_out=${CMAKE_BINARY_DIR}/src
|
||||
--plugin=protoc-gen-service=${CMAKE_SOURCE_DIR}/src/lib/api/service_compiler/plugin.cmd
|
||||
--service_out=lang=cpp:${CMAKE_BINARY_DIR}/src -I
|
||||
${PROTOBUF_INCLUDE_DIRS} -I ${CMAKE_SOURCE_DIR}/src ${ABS_FIL}
|
||||
DEPENDS ${ABS_FIL} ${TEMPLATES}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/api/service_compiler/plugin.py
|
||||
COMMENT "Running C++ service compiler on ${FIL}"
|
||||
VERBATIM)
|
||||
else()
|
||||
add_custom_command(
|
||||
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.cc"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.h"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.client.pb.cc"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.client.pb.h"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.server.pb.cc"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.server.pb.h"
|
||||
COMMAND ${CMAKE_SOURCE_DIR}/tools/venv_exec.sh
|
||||
ARGS
|
||||
${Protobuf_PROTOC_EXECUTABLE}
|
||||
--cpp_out=${CMAKE_BINARY_DIR}/src
|
||||
--plugin=protoc-gen-service=${CMAKE_SOURCE_DIR}/src/lib/api/service_compiler/plugin.py
|
||||
--service_out=lang=cpp,make_file_name=${ABS_FIL}:${CMAKE_BINARY_DIR}/src
|
||||
-I ${PROTOBUF_INCLUDE_DIRS} -I ${CMAKE_SOURCE_DIR}/src ${ABS_FIL}
|
||||
DEPENDS ${ABS_FIL} ${TEMPLATES}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/api/service_compiler/plugin.py
|
||||
COMMENT "Running C++ service compiler on ${FIL}"
|
||||
VERBATIM)
|
||||
endif()
|
||||
|
||||
endforeach()
|
||||
|
||||
# remove some warnings from protobuf generated files
|
||||
if(WIN32)
|
||||
set_source_files_properties(${${SRCS}} PROPERTIES COMPILE_FLAGS
|
||||
"/wd4309 /wd4838")
|
||||
else()
|
||||
set_source_files_properties(
|
||||
${${SRCS}}
|
||||
PROPERTIES
|
||||
COMPILE_FLAGS
|
||||
"-Wno-unused-parameter -Wno-effc++ -Wno-pedantic -Wno-sign-compare -Wno-uninitialized"
|
||||
)
|
||||
endif()
|
||||
|
||||
set(${SRCS}
|
||||
${${SRCS}}
|
||||
PARENT_SCOPE)
|
||||
set(${HDRS}
|
||||
${${HDRS}}
|
||||
PARENT_SCOPE)
|
||||
|
||||
endfunction()
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
include_guard(GLOBAL)
|
||||
|
||||
function(protobuf_generate_cpp)
|
||||
set(_options)
|
||||
set(_one_value_args
|
||||
CXX_SOURCES
|
||||
CXX_HEADERS
|
||||
CXX_OUT_DIR
|
||||
PROTOC
|
||||
)
|
||||
set(_multi_value_args
|
||||
PROTO_INCLUDE_DIRS
|
||||
PROTO_SOURCES
|
||||
)
|
||||
cmake_parse_arguments(_ARGS "${_options}" "${_one_value_args}" "${_multi_value_args}" ${ARGN})
|
||||
|
||||
if (NOT DEFINED _ARGS_PROTOC)
|
||||
if (WIN32)
|
||||
set(_ARGS_PROTOC "${EXTERNALS_BIN}/protoc.exe")
|
||||
else()
|
||||
set(_ARGS_PROTOC "${EXTERNALS_BIN}/protoc")
|
||||
endif()
|
||||
endif()
|
||||
set(${_ARGS_CXX_SOURCES})
|
||||
set(${_ARGS_CXX_HEADERS})
|
||||
|
||||
set(_proto_include_cli_args)
|
||||
foreach(_dir ${_ARGS_PROTO_INCLUDE_DIRS})
|
||||
list(APPEND _proto_include_cli_args -I ${_dir})
|
||||
endforeach()
|
||||
|
||||
foreach(_fil ${_ARGS_PROTO_SOURCES})
|
||||
get_filename_component(_abs_fil ${_fil} ABSOLUTE)
|
||||
get_filename_component(_fil_we ${_fil} NAME_WE)
|
||||
get_filename_component(_fil_dir ${_fil} DIRECTORY)
|
||||
if(_fil_dir)
|
||||
set(_fil_we "${_fil_dir}/${_fil_we}")
|
||||
endif()
|
||||
list(APPEND ${_ARGS_CXX_SOURCES} "${_ARGS_CXX_OUT_DIR}/${_fil_we}.pb.cc")
|
||||
list(APPEND ${_ARGS_CXX_HEADERS} "${_ARGS_CXX_OUT_DIR}/${_fil_we}.pb.h")
|
||||
message(STATUS "add_custom_command for ${_fil} -> ${_ARGS_CXX_OUT_DIR}/${_fil_we}.pb.h")
|
||||
add_custom_command(
|
||||
OUTPUT
|
||||
"${_ARGS_CXX_OUT_DIR}/${_fil_we}.pb.cc"
|
||||
"${_ARGS_CXX_OUT_DIR}/${_fil_we}.pb.h"
|
||||
COMMAND
|
||||
${_ARGS_PROTOC}
|
||||
ARGS
|
||||
--cpp_out=${_ARGS_CXX_OUT_DIR} ${_proto_include_cli_args} ${_fil}
|
||||
DEPENDS ${_abs_fil}
|
||||
COMMENT "Running C++ protocol buffer compiler on ${_fil}"
|
||||
VERBATIM
|
||||
)
|
||||
endforeach()
|
||||
|
||||
set_source_files_properties(
|
||||
${${_ARGS_CXX_SOURCES}}
|
||||
${${_ARGS_CXX_HEADERS}}
|
||||
PROPERTIES
|
||||
GENERATED TRUE
|
||||
)
|
||||
|
||||
# remove some warnings from protobuf generated files
|
||||
if(WIN32)
|
||||
set_source_files_properties(
|
||||
${${_ARGS_CXX_SOURCES}}
|
||||
PROPERTIES
|
||||
COMPILE_FLAGS "/wd4309 /wd4838"
|
||||
)
|
||||
else()
|
||||
set_source_files_properties(
|
||||
${${_ARGS_CXX_SOURCES}}
|
||||
PROPERTIES
|
||||
COMPILE_FLAGS "-Wno-unused-parameter -Wno-effc++ -Wno-pedantic -Wno-sign-compare -Wno-uninitialized"
|
||||
)
|
||||
endif()
|
||||
|
||||
set(${_ARGS_CXX_SOURCES} ${${_ARGS_CXX_SOURCES}} PARENT_SCOPE)
|
||||
set(${_ARGS_CXX_HEADERS} ${${_ARGS_CXX_HEADERS}} PARENT_SCOPE)
|
||||
endfunction()
|
||||
@@ -0,0 +1,58 @@
|
||||
function(protobuf_generate_cpp_config)
|
||||
set(_options)
|
||||
set(_one_value_args
|
||||
PROTO_SOURCES_HEADER
|
||||
PROTO_DEFAULTS_HEADER
|
||||
)
|
||||
set(_multi_value_args
|
||||
PROTO_SOURCES
|
||||
PROTO_DEFAULTS
|
||||
)
|
||||
cmake_parse_arguments(_ARGS "${_options}" "${_one_value_args}" "${_multi_value_args}" ${ARGN})
|
||||
|
||||
# Configure the 'config_proto_files' header. It provides an array of strings populated with the
|
||||
# files in PROTO_SOURCES. At runtime, we use this array to generate a special 'config' proto
|
||||
# message with fields for each message defined in said files. A global instance of this 'config'
|
||||
# proto is then constructed, and populated with [compile-time] defaults, and [runtime] overrides
|
||||
# (i.e., in spark.conf). Calls to `bts::config::get<T>()` retrieve the value from the field
|
||||
# associated with type `T` in this global instance.
|
||||
message(STATUS "PROTO_SOURCES: ${_ARGS_PROTO_SOURCES}")
|
||||
message(STATUS "PROTO_SOURCES_HEADER: ${_ARGS_PROTO_SOURCES_HEADER}")
|
||||
message(STATUS "PROTO_DEFAULTS_HEADER: ${_ARGS_PROTO_DEFAULTS_HEADER}")
|
||||
if (_ARGS_PROTO_SOURCES_HEADER)
|
||||
set(PROTO_SOURCES)
|
||||
set(PROTO_SOURCES_CXX_ARRAY_ITEMS "")
|
||||
foreach(_proto_path ${_ARGS_PROTO_SOURCES})
|
||||
list(APPEND PROTO_SOURCES ${_proto_path})
|
||||
string(APPEND PROTO_SOURCES_CXX_ARRAY_ITEMS "\"${_proto_path}\",\n")
|
||||
endforeach()
|
||||
list(LENGTH PROTO_SOURCES PROTO_SOURCES_LENGTH)
|
||||
message(STATUS "CONFIGURING PROTO_SOURCES_HEADER): ${_ARGS_PROTO_SOURCES_HEADER}")
|
||||
configure_file(${CMAKE_SOURCE_DIR}/cmake/config_proto_files.h.in ${_ARGS_PROTO_SOURCES_HEADER})
|
||||
endif()
|
||||
|
||||
# Generate static defaults. Ideally, this would be a single string, but we use an array because
|
||||
# the compiler complains if the string is longer than 65k.
|
||||
set(_cfg_defaults_str "inline const char * config_static_defaults[] = { ")
|
||||
|
||||
foreach(_cfg_file_path ${_ARGS_PROTO_DEFAULTS})
|
||||
file(READ ${_cfg_file_path} _cfg_file_content)
|
||||
string(REPLACE "\"" "\\\"" _cfg_file_content_escaped ${_cfg_file_content})
|
||||
string(REPLACE "\n" ";" _cfg_lines ${_cfg_file_content_escaped})
|
||||
|
||||
foreach(_line ${_cfg_lines})
|
||||
string(APPEND _cfg_defaults_str "\n \"${_line}\",")
|
||||
endforeach(_line)
|
||||
endforeach(_cfg_file_path)
|
||||
|
||||
string(APPEND _cfg_defaults_str "};")
|
||||
set(_old_cfg_defaults_str "")
|
||||
|
||||
if(EXISTS ${_ARGS_PROTO_DEFAULTS_HEADER})
|
||||
file(READ ${_ARGS_PROTO_DEFAULTS_HEADER} _old_cfg_defaults_str)
|
||||
endif()
|
||||
|
||||
if(NOT _cfg_defaults_str STREQUAL _old_cfg_defaults_str)
|
||||
file(WRITE "${_ARGS_PROTO_DEFAULTS_HEADER}" "${_cfg_defaults_str}")
|
||||
endif()
|
||||
endfunction()
|
||||
@@ -0,0 +1,49 @@
|
||||
include_guard(DIRECTORY)
|
||||
|
||||
function(protobuf_generate_fs)
|
||||
set(_options)
|
||||
set(_one_value_args TARGET_NAME OUT_DIR PROTOC)
|
||||
set(_multi_value_args PROTO_INCLUDE_DIRS PROTO_SOURCES)
|
||||
cmake_parse_arguments(_ARGS "${_options}" "${_one_value_args}" "${_multi_value_args}" ${ARGN})
|
||||
|
||||
if (NOT DEFINED _ARGS_TARGET_NAME)
|
||||
set(_ARGS_TARGET_NAME "${PROJECT_NAME}_generate_fs_protos")
|
||||
endif()
|
||||
if (NOT DEFINED _ARGS_PROTOC)
|
||||
set(_ARGS_PROTOC "${EXTERNALS_BIN}/protoc")
|
||||
endif()
|
||||
|
||||
set(_proto_include_cli_args)
|
||||
foreach(_dir ${_ARGS_PROTO_INCLUDE_DIRS})
|
||||
list(APPEND _proto_include_cli_args -I ${_dir})
|
||||
endforeach()
|
||||
|
||||
set(_outputs)
|
||||
foreach(_proto_source ${_ARGS_PROTO_SOURCES})
|
||||
# get_filename_component(_abs_proto_source ${_proto_source} ABSOLUTE)
|
||||
get_filename_component(_proto_source_we ${_proto_source} NAME_WE)
|
||||
# get_filename_component(_proto_source_dir ${_proto_source} DIRECTORY)
|
||||
list(APPEND _outputs ${_ARGS_OUT_DIR}/${_proto_source_we}.fable.fs)
|
||||
endforeach()
|
||||
|
||||
set(_venv_exec ${CMAKE_SOURCE_DIR}/tools/venv_exec.sh)
|
||||
set(_plugin_py ${CMAKE_SOURCE_DIR}/src/lib_spark/spark/api/service_compiler/plugin.py)
|
||||
set(_template_fs ${CMAKE_SOURCE_DIR}/src/lib_spark/spark/api/service_compiler/templates/fs/fable.fs)
|
||||
add_custom_command(
|
||||
OUTPUT ${_outputs}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
COMMAND ${_venv_exec}
|
||||
${_ARGS_PROTOC}
|
||||
--plugin=protoc-gen-service=${_plugin_py}
|
||||
--service_out=lang=fs,strip_out_path=1:${_ARGS_OUT_DIR}
|
||||
${_proto_include_cli_args}
|
||||
${_ARGS_PROTO_SOURCES}
|
||||
DEPENDS
|
||||
${_venv_exec}
|
||||
${_plugin_py}
|
||||
${_template_fs}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/package-lock.json
|
||||
${_ARGS_PROTO_SOURCES}
|
||||
)
|
||||
add_custom_target(${_ARGS_TARGET_NAME} ALL DEPENDS "${_outputs}")
|
||||
endfunction()
|
||||
@@ -0,0 +1,33 @@
|
||||
include_guard(DIRECTORY)
|
||||
|
||||
function(protobuf_generate_js)
|
||||
set(_options)
|
||||
set(_one_value_args TARGET_NAME OUTPUT)
|
||||
set(_multi_value_args PROTO_INCLUDE_DIRS PROTO_SOURCES)
|
||||
cmake_parse_arguments(_ARGS "${_options}" "${_one_value_args}" "${_multi_value_args}" ${ARGN})
|
||||
|
||||
if (NOT DEFINED _ARGS_TARGET_NAME)
|
||||
set(_ARGS_TARGET_NAME "${PROJECT_NAME}_generate_js_protos")
|
||||
endif()
|
||||
|
||||
set(_proto_include_cli_args)
|
||||
foreach(_dir ${_ARGS_PROTO_INCLUDE_DIRS})
|
||||
list(APPEND _proto_include_cli_args -p ${_dir})
|
||||
endforeach()
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${_ARGS_OUTPUT}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
COMMAND npx
|
||||
--no-install pbjs
|
||||
-t json-module
|
||||
-w commonjs
|
||||
-o ${_ARGS_OUTPUT}
|
||||
${_proto_include_cli_args}
|
||||
${_ARGS_PROTO_SOURCES}
|
||||
DEPENDS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/package-lock.json
|
||||
${_ARGS_PROTO_SOURCES}
|
||||
)
|
||||
add_custom_target(${_ARGS_TARGET_NAME} ALL DEPENDS ${_ARGS_OUTPUT})
|
||||
endfunction()
|
||||
@@ -0,0 +1,10 @@
|
||||
include_guard(GLOBAL)
|
||||
|
||||
macro(set_first_defined RESULT)
|
||||
foreach(_arg ${ARGN})
|
||||
if (DEFINED ${_arg})
|
||||
set(${RESULT} ${${_arg}})
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
endmacro()
|
||||
@@ -0,0 +1,49 @@
|
||||
include_guard(DIRECTORY)
|
||||
include(${CMAKE_SOURCE_DIR}/cmake/TernaryOperator.cmake)
|
||||
|
||||
function(sym_link_dir)
|
||||
set(_options)
|
||||
set(_one_value_args TARGET_NAME SOURCE DEST COMMENT)
|
||||
set(_multi_value_args)
|
||||
cmake_parse_arguments(_ARGS "${_options}" "${_one_value_args}" "${_multi_value_args}" ${ARGN})
|
||||
add_custom_command(
|
||||
OUTPUT ${_ARGS_DEST}
|
||||
COMMAND ln ARGS -sf ${_ARGS_SOURCE} ${_ARGS_DEST}
|
||||
)
|
||||
set_ternary(_comment _ARGS_COMMENT "${_ARGS_COMMENT}" "linking dir ${_ARGS_SOURCE} -> ${_ARGS_DEST}")
|
||||
add_custom_target(
|
||||
${_ARGS_TARGET_NAME} ALL
|
||||
DEPENDS ${_ARGS_DEST}
|
||||
COMMENT "${_comment}"
|
||||
)
|
||||
endfunction()
|
||||
|
||||
function(sym_link_file)
|
||||
set(_options)
|
||||
set(_one_value_args SOURCE DEST INSTALL_DEST)
|
||||
set(_multi_value_args)
|
||||
cmake_parse_arguments(_ARGS "${_options}" "${_one_value_args}" "${_multi_value_args}" ${ARGN})
|
||||
file(
|
||||
CREATE_LINK
|
||||
${_ARGS_SOURCE}
|
||||
${_ARGS_DEST}
|
||||
SYMBOLIC
|
||||
)
|
||||
if (DEFINED _ARGS_INSTALL_DEST)
|
||||
install(
|
||||
FILES
|
||||
${_ARGS_SOURCE}
|
||||
DESTINATION ${_ARGS_INSTALL_DEST}
|
||||
)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(sym_link_local_lib LIB_NAME)
|
||||
set(_lib_file_name "${CMAKE_SHARED_LIBRARY_PREFIX}${LIB_NAME}.so")
|
||||
file(
|
||||
CREATE_LINK
|
||||
"${CMAKE_BINARY_DIR}/src/lib_${LIB_NAME}/${_lib_file_name}"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/${_lib_file_name}"
|
||||
SYMBOLIC
|
||||
)
|
||||
endfunction()
|
||||
@@ -0,0 +1,9 @@
|
||||
include_guard(GLOBAL)
|
||||
|
||||
macro(set_ternary RESULT CONDITION TRUE_VALUE FALSE_VALUE)
|
||||
if(${CONDITION})
|
||||
set(${RESULT} ${TRUE_VALUE})
|
||||
else()
|
||||
set(${RESULT} ${FALSE_VALUE})
|
||||
endif()
|
||||
endmacro()
|
||||
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
|
||||
namespace bts::@PROJECT_NAME@::protobufs {
|
||||
|
||||
inline std::array<const char *, @PROTO_SOURCES_LENGTH@> config_proto_files = {
|
||||
@PROTO_SOURCES_CXX_ARRAY_ITEMS@
|
||||
};
|
||||
|
||||
} // namespace bts::@PROJECT_NAME@::protobufs
|
||||
@@ -5,7 +5,7 @@ cmake_minimum_required(VERSION 3.5)
|
||||
cmake_policy(SET CMP0076 NEW)
|
||||
|
||||
# add protos to the library to facilitate source_group
|
||||
target_sources(libspark PUBLIC ${Config_Protos} ${NonConfig_Protos} ${Service_Protos})
|
||||
target_sources(spark PUBLIC ${Config_Protos} ${NonConfig_Protos} ${Service_Protos})
|
||||
|
||||
function(assign_source_group)
|
||||
foreach(_source IN ITEMS ${ARGN})
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
services:
|
||||
sparkd:
|
||||
build:
|
||||
dockerfile: Dockerfile
|
||||
context: ./sparkd
|
||||
command: [ "./sparkd", "run" ]
|
||||
ports: [ "8000:8000", "8001:8001", "8002:8002" ]
|
||||
|
||||
pubsub:
|
||||
build:
|
||||
dockerfile: pubsub.Dockerfile
|
||||
context: ./DataStream
|
||||
command: [ "./PubSubServer" ]
|
||||
environment:
|
||||
- DOTNET_ENVIRONMENT=Production
|
||||
ports:
|
||||
- 22019:22019
|
||||
|
||||
md-publisher:
|
||||
build:
|
||||
dockerfile: md-publisher.Dockerfile
|
||||
context: ./DataStream
|
||||
depends_on:
|
||||
- pubsub
|
||||
- sparkd
|
||||
command:
|
||||
[
|
||||
"dockerize",
|
||||
"-wait",
|
||||
"tcp://pubsub:22019",
|
||||
"-wait",
|
||||
"tcp://sparkd:8000",
|
||||
"-timeout",
|
||||
"10s",
|
||||
"./DataStreamPublisher"
|
||||
]
|
||||
environment:
|
||||
- DOTNET_ENVIRONMENT=MarketData
|
||||
|
||||
webapp:
|
||||
ports:
|
||||
- 8080:8080
|
||||
- 8443:8443
|
||||
build:
|
||||
dockerfile: webapp.Dockerfile
|
||||
context: ./DataStream
|
||||
command: [ "./Bts.DataStreamWebApp.Server" ]
|
||||
environment:
|
||||
- ASPNETCORE_HTTP_PORT=8080
|
||||
- ASPNETCORE_HTTPS_PORT=8443
|
||||
- ASPNETCORE_ENVIRONMENT=Staging
|
||||
@@ -0,0 +1,79 @@
|
||||
services:
|
||||
sparkd:
|
||||
build:
|
||||
dockerfile: src/app_sparkd/Dockerfile
|
||||
args:
|
||||
- IMAGE=${SPARKD__IMAGE}
|
||||
- SOURCE_DIR=${SPARKD__SOURCE_DIR}
|
||||
- CONF_FILE=${SPARKD__CONF_FILE}
|
||||
- MD_RECORDING_DIR=${SPARKD__MD_RECORDING_DIR}
|
||||
command: [ "./sparkd", "run" ]
|
||||
ports:
|
||||
- "8000:8000"
|
||||
- "8001:8001"
|
||||
- "8002:8002"
|
||||
|
||||
pubsub:
|
||||
environment:
|
||||
- DOTNET_ENVIRONMENT=${PUBSUB__DOTNET_ENVIRONMENT}
|
||||
build:
|
||||
dockerfile: src/DataStreamSuite/PubSubServer/Dockerfile
|
||||
args:
|
||||
- CS_SOURCE_DIR=${PUBSUB__CS_SOURCE_DIR}
|
||||
- CPP_SOURCE_DIR=${PUBSUB__CPP_SOURCE_DIR}
|
||||
- CONF_FILE=${PUBSUB__CONF_FILE}
|
||||
ports:
|
||||
- "22019:22019"
|
||||
command: [ "./PubSubServer" ]
|
||||
|
||||
md-publisher:
|
||||
build:
|
||||
dockerfile: src/DataStreamSuite/DataStreamPublisher/Dockerfile
|
||||
args:
|
||||
- SOURCE_DIR=${MD_PUBLISHER__SOURCE_DIR}
|
||||
- CONF_FILE=${MD_PUBLISHER__CONF_FILE}
|
||||
depends_on:
|
||||
- pubsub
|
||||
- sparkd
|
||||
command: [ "dockerize", "-wait", "tcp://pubsub:22019", "-wait", "tcp://sparkd:8000", "-timeout", "10s", "./DataStreamPublisher" ]
|
||||
environment:
|
||||
- DOTNET_ENVIRONMENT=${MD_PUBLISHER__DOTNET_ENVIRONMENT}
|
||||
|
||||
webapp:
|
||||
ports:
|
||||
- "8080:8080"
|
||||
- "8443:8443"
|
||||
build:
|
||||
dockerfile: src/DataStreamSuite/Bts.DataStreamWebApp.Server/Dockerfile
|
||||
args:
|
||||
- SOURCE_DIR=${WEBAPP__SOURCE_DIR}
|
||||
- WEB_ROOT=${WEBAPP__WEB_ROOT}
|
||||
- CONF_FILE=${WEBAPP__CONF_FILE}
|
||||
command: [ "./Bts.DataStreamWebApp.Server" ]
|
||||
environment:
|
||||
- ASPNETCORE_ENVIRONMENT=${WEBAPP__ASPNETCORE_ENVIRONMENT}
|
||||
|
||||
api-server:
|
||||
depends_on:
|
||||
- sparkd
|
||||
ports:
|
||||
- 8008:8008
|
||||
- 9443:9443
|
||||
build:
|
||||
dockerfile: src/client/spark_api_server/Dockerfile
|
||||
command: [ "dockerize", "-wait", "tcp://sparkd:8000", "-timeout", "10s", "./spark_api_server", "run" ]
|
||||
environment:
|
||||
- ASPNETCORE_ENVIRONMENT=${API_SERVER__ASPNETCORE_ENVIRONMENT}
|
||||
|
||||
sparkd-ping-test:
|
||||
depends_on:
|
||||
- sparkd
|
||||
profiles:
|
||||
- ping-test
|
||||
build:
|
||||
context: .
|
||||
dockerfile_inline: |
|
||||
FROM bluetradingsystems/linux_dotnet7
|
||||
USER "root"
|
||||
RUN apt-get update && apt-get -y install iputils-ping
|
||||
command: [ "ping", "sparkd" ]
|
||||
@@ -53,7 +53,7 @@ The status callback is called when the market for this security opens, closes, o
|
||||
// Subscribe to security trading status
|
||||
void IAlgoServices::subscribe_status(SecurityKey);
|
||||
// You implement
|
||||
virtual void on_status(SecurityKey, co2::TradingStatus) override;
|
||||
virtual void on_status(SecurityKey, domain::protobufs::TradingStatus) override;
|
||||
```
|
||||
|
||||
# Child Orders
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
FROM ubuntu:22.04
|
||||
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y pkg-config \
|
||||
&& apt-get install -y locales \
|
||||
&& apt-get install -y ca-certificates \
|
||||
&& apt-get install -y libssh2-1-dev \
|
||||
&& apt-get install -y software-properties-common \
|
||||
&& apt-get install -y sudo
|
||||
|
||||
# GCC
|
||||
ARG gcc_major=13
|
||||
RUN add-apt-repository ppa:ubuntu-toolchain-r/test \
|
||||
&& apt-get update \
|
||||
&& apt-get install -y g++-$gcc_major
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y dotnet7
|
||||
|
||||
RUN locale-gen en_US.UTF-8
|
||||
|
||||
ARG docker_user="bts"
|
||||
ARG docker_uid="1000"
|
||||
ARG docker_pass="bts"
|
||||
|
||||
RUN \
|
||||
groupadd -g "$docker_uid" "$docker_user" \
|
||||
&& useradd \
|
||||
-m \
|
||||
-u "$docker_uid" \
|
||||
-g "$docker_uid" \
|
||||
-G sudo \
|
||||
--password "$(openssl passwd -1 "$docker_pass")" \
|
||||
"$docker_user"
|
||||
|
||||
USER bts
|
||||
WORKDIR /home/bts
|
||||
+1
-1
Submodule externals updated: cae5fd20da...4f5e385556.
@@ -1,45 +0,0 @@
|
||||
/* global use, db */
|
||||
// MongoDB Playground
|
||||
// To disable this template go to Settings | MongoDB | Use Default Template For Playground.
|
||||
// Make sure you are connected to enable completions and to be able to run a playground.
|
||||
// Use Ctrl+Space inside a snippet or a string literal to trigger completions.
|
||||
// The result of the last command run in a playground is shown on the results panel.
|
||||
// By default the first 20 documents will be returned with a cursor.
|
||||
// Use 'console.log()' to print to the debug output.
|
||||
// For more documentation on playgrounds please refer to
|
||||
// https://www.mongodb.com/docs/mongodb-vscode/playgrounds/
|
||||
|
||||
// Select the database to use.
|
||||
use('mongodbVSCodePlaygroundDB');
|
||||
|
||||
// Insert a few documents into the sales collection.
|
||||
db.getCollection('sales').insertMany([
|
||||
{ 'item': 'abc', 'price': 10, 'quantity': 2, 'date': new Date('2014-03-01T08:00:00Z') },
|
||||
{ 'item': 'jkl', 'price': 20, 'quantity': 1, 'date': new Date('2014-03-01T09:00:00Z') },
|
||||
{ 'item': 'xyz', 'price': 5, 'quantity': 10, 'date': new Date('2014-03-15T09:00:00Z') },
|
||||
{ 'item': 'xyz', 'price': 5, 'quantity': 20, 'date': new Date('2014-04-04T11:21:39.736Z') },
|
||||
{ 'item': 'abc', 'price': 10, 'quantity': 10, 'date': new Date('2014-04-04T21:23:13.331Z') },
|
||||
{ 'item': 'def', 'price': 7.5, 'quantity': 5, 'date': new Date('2015-06-04T05:08:13Z') },
|
||||
{ 'item': 'def', 'price': 7.5, 'quantity': 10, 'date': new Date('2015-09-10T08:43:00Z') },
|
||||
{ 'item': 'abc', 'price': 10, 'quantity': 5, 'date': new Date('2016-02-06T20:20:13Z') },
|
||||
]);
|
||||
|
||||
// Run a find command to view items sold on April 4th, 2014.
|
||||
const salesOnApril4th = db.getCollection('sales').find({
|
||||
date: { $gte: new Date('2014-04-04'), $lt: new Date('2014-04-05') }
|
||||
}).count();
|
||||
|
||||
// Print a message to the output window.
|
||||
console.log(`${salesOnApril4th} sales occurred in 2014.`);
|
||||
|
||||
// Here we run an aggregation and open a cursor to the results.
|
||||
// Use '.toArray()' to exhaust the cursor to return the whole result set.
|
||||
// You can use '.hasNext()/.next()' to iterate through the cursor page by page.
|
||||
db.getCollection('sales').aggregate([
|
||||
// Find all of the sales that occurred in 2014.
|
||||
{ $match: { date: { $gte: new Date('2014-01-01'), $lt: new Date('2015-01-01') } } },
|
||||
// Group the total sales for each product.
|
||||
{ $group: { _id: '$item', totalSaleAmount: { $sum: { $multiply: ['$price', '$quantity'] } } } }
|
||||
]);
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
public int Integer;
|
||||
public double Real;
|
||||
public string Identifier;
|
||||
public DateTime DateTime;
|
||||
public ImmutableList<IArithmeticExpression> Arguments;
|
||||
public ImmutableList<Assignment> Assignments;
|
||||
public IArithmeticExpression Argument;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Google.Protobuf" Version="3.24.3" />
|
||||
<PackageReference Include="YaccLexTools" Version="1.2.0" />
|
||||
<PackageReference Include="YaccLexTools" Version="1.2.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -1,41 +1,22 @@
|
||||
using mbts.spark;
|
||||
using System.Diagnostics;
|
||||
|
||||
using System;
|
||||
using System.Runtime;
|
||||
namespace BCG.Utilities.General;
|
||||
|
||||
namespace BCG.Utilities.General
|
||||
{
|
||||
/// <summary>
|
||||
/// Summary description for Crono.
|
||||
/// </summary>
|
||||
public class Crono
|
||||
{
|
||||
public Crono()
|
||||
{
|
||||
myTimer = new HighPerformanceTimer();
|
||||
}
|
||||
/// <summary>
|
||||
/// Summary description for Crono.
|
||||
/// </summary>
|
||||
public class Crono {
|
||||
readonly Stopwatch myTimer = new();
|
||||
|
||||
public void start()
|
||||
{myTimer.start();}
|
||||
public void start() =>
|
||||
myTimer.Start();
|
||||
|
||||
public void stop()
|
||||
{myTimer.stop();}
|
||||
public void stop() =>
|
||||
myTimer.Stop();
|
||||
|
||||
public TimeSpan time
|
||||
{
|
||||
get
|
||||
{
|
||||
return new TimeSpan((long) (myTimer.totalMilliseconds * TimeSpan.TicksPerMillisecond));
|
||||
}
|
||||
}
|
||||
|
||||
public double miliseconds
|
||||
{
|
||||
get
|
||||
{return myTimer.totalMilliseconds;}
|
||||
}
|
||||
|
||||
private HighPerformanceTimer myTimer;
|
||||
}
|
||||
public TimeSpan time =>
|
||||
myTimer.Elapsed;
|
||||
|
||||
public double miliseconds =>
|
||||
myTimer.Elapsed.TotalMilliseconds;
|
||||
}
|
||||
@@ -1,192 +1,192 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Reflection;
|
||||
using Microsoft.Win32;
|
||||
|
||||
namespace BCG
|
||||
{
|
||||
public enum RegistryRoot { HKCU, HKLM }
|
||||
|
||||
[Serializable]
|
||||
public class BlueRegistry
|
||||
{
|
||||
public const string BlueSubKey = @"Software\Blue Capital Group\";
|
||||
public static readonly string ApplicationPrefix;
|
||||
protected string myFullPath;
|
||||
|
||||
public BlueRegistry(string subPath)
|
||||
{
|
||||
myFullPath = string.Concat(BlueRegistry.ApplicationPrefix, @"\", subPath);
|
||||
}
|
||||
|
||||
public BlueRegistry(BlueRegistry parent, string subPath)
|
||||
{
|
||||
myFullPath = string.Concat(parent.myFullPath, @"\", subPath);
|
||||
}
|
||||
|
||||
static BlueRegistry()
|
||||
{
|
||||
string app = "Applications";
|
||||
|
||||
Assembly ass = Assembly.GetEntryAssembly();
|
||||
if (ass != null)
|
||||
{
|
||||
app = ass.GetName().Name;
|
||||
|
||||
object[] attrs = ass.GetCustomAttributes(
|
||||
Type.GetType("System.Reflection.AssemblyTitleAttribute"), true);
|
||||
|
||||
if (attrs.Length > 0 && ((AssemblyTitleAttribute)attrs[0]).Title != string.Empty)
|
||||
{
|
||||
app = ((AssemblyTitleAttribute)attrs[0]).Title;
|
||||
}
|
||||
}
|
||||
|
||||
ApplicationPrefix = string.Concat(BlueRegistry.BlueSubKey, app);
|
||||
}
|
||||
|
||||
public object getValue(string name)
|
||||
{
|
||||
return getValue(RegistryRoot.HKCU, name);
|
||||
}
|
||||
|
||||
public object getValue(string name, object defaultValue)
|
||||
{
|
||||
return getValue(RegistryRoot.HKCU, name, defaultValue);
|
||||
}
|
||||
|
||||
public void setValue(string name, object value)
|
||||
{
|
||||
setValue(RegistryRoot.HKCU, name, value);
|
||||
}
|
||||
|
||||
public void deleteValue(string name)
|
||||
{
|
||||
deleteValue(RegistryRoot.HKCU, name);
|
||||
}
|
||||
|
||||
private RegistryKey myGetRegistryKey(RegistryRoot root)
|
||||
{
|
||||
if (root == RegistryRoot.HKCU)
|
||||
return Registry.CurrentUser.CreateSubKey(myFullPath);
|
||||
else
|
||||
return Registry.LocalMachine.CreateSubKey(myFullPath);
|
||||
}
|
||||
|
||||
#region Generic Methods
|
||||
internal virtual void setValue(RegistryRoot root, string name, object value)
|
||||
{
|
||||
using (RegistryKey rk = myGetRegistryKey(root))
|
||||
{
|
||||
rk.SetValue(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
internal virtual object getValue(RegistryRoot root, string name)
|
||||
{
|
||||
using (RegistryKey rk = myGetRegistryKey(root))
|
||||
{
|
||||
return rk.GetValue(name);
|
||||
}
|
||||
}
|
||||
|
||||
internal virtual void deleteValue(RegistryRoot root, string name)
|
||||
{
|
||||
using (RegistryKey rk = myGetRegistryKey(root))
|
||||
{
|
||||
rk.DeleteValue(name);
|
||||
}
|
||||
}
|
||||
|
||||
internal virtual object getValue(RegistryRoot root, string name, object defaultValue)
|
||||
{
|
||||
using (RegistryKey rk = myGetRegistryKey(root))
|
||||
{
|
||||
return rk.GetValue(name, defaultValue);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Double
|
||||
internal virtual void setDouble(RegistryRoot root, string name, double value)
|
||||
{
|
||||
using (RegistryKey rk = myGetRegistryKey(root))
|
||||
{
|
||||
DoubleRegistryHandler.setValue(rk, name, value);
|
||||
}
|
||||
}
|
||||
|
||||
internal virtual double getDouble(RegistryRoot root, string name)
|
||||
{
|
||||
using (RegistryKey rk = myGetRegistryKey(root))
|
||||
{
|
||||
return DoubleRegistryHandler.getValue(rk, name);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Enum
|
||||
internal virtual void setEnum(RegistryRoot root, string name, Enum value)
|
||||
{
|
||||
using (RegistryKey rk = myGetRegistryKey(root))
|
||||
{
|
||||
EnumRegistryHandler.setValue(rk, name, value);
|
||||
}
|
||||
}
|
||||
|
||||
internal virtual Enum getEnum(RegistryRoot root, string name, Type enumType)
|
||||
{
|
||||
using (RegistryKey rk = myGetRegistryKey(root))
|
||||
{
|
||||
return EnumRegistryHandler.getValue(rk, name, enumType);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Array
|
||||
internal virtual void setArray(RegistryRoot root, string name, Array array)
|
||||
{
|
||||
using (RegistryKey rk = myGetRegistryKey(root))
|
||||
{
|
||||
ArrayRegistryHandler.setValue(rk, name, array);
|
||||
}
|
||||
}
|
||||
|
||||
internal virtual Array getArray(RegistryRoot root, string name, Type elementType)
|
||||
{
|
||||
using (RegistryKey rk = myGetRegistryKey(root))
|
||||
{
|
||||
return ArrayRegistryHandler.getValue(rk, name, elementType);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region SortedList
|
||||
internal virtual void setSortedList(RegistryRoot root, string name, SortedList slist)
|
||||
{
|
||||
using (RegistryKey rk = myGetRegistryKey(root))
|
||||
{
|
||||
SortedListRegistryHandler.setValue(rk, name, slist);
|
||||
}
|
||||
}
|
||||
|
||||
internal virtual SortedList getSortedList(RegistryRoot root, string name)
|
||||
{
|
||||
using (RegistryKey rk = myGetRegistryKey(root))
|
||||
{
|
||||
return SortedListRegistryHandler.getValue(rk, name);
|
||||
}
|
||||
}
|
||||
|
||||
internal virtual void deleteSortedList(RegistryRoot root, string name)
|
||||
{
|
||||
using (RegistryKey rk = myGetRegistryKey(root))
|
||||
{
|
||||
SortedListRegistryHandler.deleteValue(rk, name);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Reflection;
|
||||
using Microsoft.Win32;
|
||||
|
||||
namespace BCG
|
||||
{
|
||||
public enum RegistryRoot { HKCU, HKLM }
|
||||
|
||||
[Serializable]
|
||||
public class BlueRegistry
|
||||
{
|
||||
public const string BlueSubKey = @"Software\Blue Capital Group\";
|
||||
public static readonly string ApplicationPrefix;
|
||||
protected string myFullPath;
|
||||
|
||||
public BlueRegistry(string subPath)
|
||||
{
|
||||
myFullPath = string.Concat(BlueRegistry.ApplicationPrefix, @"\", subPath);
|
||||
}
|
||||
|
||||
public BlueRegistry(BlueRegistry parent, string subPath)
|
||||
{
|
||||
myFullPath = string.Concat(parent.myFullPath, @"\", subPath);
|
||||
}
|
||||
|
||||
static BlueRegistry()
|
||||
{
|
||||
string app = "Applications";
|
||||
|
||||
Assembly ass = Assembly.GetEntryAssembly();
|
||||
if (ass != null)
|
||||
{
|
||||
app = ass.GetName().Name;
|
||||
|
||||
object[] attrs = ass.GetCustomAttributes(
|
||||
Type.GetType("System.Reflection.AssemblyTitleAttribute"), true);
|
||||
|
||||
if (attrs.Length > 0 && ((AssemblyTitleAttribute)attrs[0]).Title != string.Empty)
|
||||
{
|
||||
app = ((AssemblyTitleAttribute)attrs[0]).Title;
|
||||
}
|
||||
}
|
||||
|
||||
ApplicationPrefix = string.Concat(BlueRegistry.BlueSubKey, app);
|
||||
}
|
||||
|
||||
public object getValue(string name)
|
||||
{
|
||||
return getValue(RegistryRoot.HKCU, name);
|
||||
}
|
||||
|
||||
public object getValue(string name, object defaultValue)
|
||||
{
|
||||
return getValue(RegistryRoot.HKCU, name, defaultValue);
|
||||
}
|
||||
|
||||
public void setValue(string name, object value)
|
||||
{
|
||||
setValue(RegistryRoot.HKCU, name, value);
|
||||
}
|
||||
|
||||
public void deleteValue(string name)
|
||||
{
|
||||
deleteValue(RegistryRoot.HKCU, name);
|
||||
}
|
||||
|
||||
private RegistryKey myGetRegistryKey(RegistryRoot root)
|
||||
{
|
||||
if (root == RegistryRoot.HKCU)
|
||||
return Registry.CurrentUser.CreateSubKey(myFullPath);
|
||||
else
|
||||
return Registry.LocalMachine.CreateSubKey(myFullPath);
|
||||
}
|
||||
|
||||
#region Generic Methods
|
||||
public virtual void setValue(RegistryRoot root, string name, object value)
|
||||
{
|
||||
using (RegistryKey rk = myGetRegistryKey(root))
|
||||
{
|
||||
rk.SetValue(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
internal virtual object getValue(RegistryRoot root, string name)
|
||||
{
|
||||
using (RegistryKey rk = myGetRegistryKey(root))
|
||||
{
|
||||
return rk.GetValue(name);
|
||||
}
|
||||
}
|
||||
|
||||
internal virtual void deleteValue(RegistryRoot root, string name)
|
||||
{
|
||||
using (RegistryKey rk = myGetRegistryKey(root))
|
||||
{
|
||||
rk.DeleteValue(name);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual object getValue(RegistryRoot root, string name, object defaultValue)
|
||||
{
|
||||
using (RegistryKey rk = myGetRegistryKey(root))
|
||||
{
|
||||
return rk.GetValue(name, defaultValue);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Double
|
||||
internal virtual void setDouble(RegistryRoot root, string name, double value)
|
||||
{
|
||||
using (RegistryKey rk = myGetRegistryKey(root))
|
||||
{
|
||||
DoubleRegistryHandler.setValue(rk, name, value);
|
||||
}
|
||||
}
|
||||
|
||||
internal virtual double getDouble(RegistryRoot root, string name)
|
||||
{
|
||||
using (RegistryKey rk = myGetRegistryKey(root))
|
||||
{
|
||||
return DoubleRegistryHandler.getValue(rk, name);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Enum
|
||||
internal virtual void setEnum(RegistryRoot root, string name, Enum value)
|
||||
{
|
||||
using (RegistryKey rk = myGetRegistryKey(root))
|
||||
{
|
||||
EnumRegistryHandler.setValue(rk, name, value);
|
||||
}
|
||||
}
|
||||
|
||||
internal virtual Enum getEnum(RegistryRoot root, string name, Type enumType)
|
||||
{
|
||||
using (RegistryKey rk = myGetRegistryKey(root))
|
||||
{
|
||||
return EnumRegistryHandler.getValue(rk, name, enumType);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Array
|
||||
internal virtual void setArray(RegistryRoot root, string name, Array array)
|
||||
{
|
||||
using (RegistryKey rk = myGetRegistryKey(root))
|
||||
{
|
||||
ArrayRegistryHandler.setValue(rk, name, array);
|
||||
}
|
||||
}
|
||||
|
||||
internal virtual Array getArray(RegistryRoot root, string name, Type elementType)
|
||||
{
|
||||
using (RegistryKey rk = myGetRegistryKey(root))
|
||||
{
|
||||
return ArrayRegistryHandler.getValue(rk, name, elementType);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region SortedList
|
||||
internal virtual void setSortedList(RegistryRoot root, string name, SortedList slist)
|
||||
{
|
||||
using (RegistryKey rk = myGetRegistryKey(root))
|
||||
{
|
||||
SortedListRegistryHandler.setValue(rk, name, slist);
|
||||
}
|
||||
}
|
||||
|
||||
internal virtual SortedList getSortedList(RegistryRoot root, string name)
|
||||
{
|
||||
using (RegistryKey rk = myGetRegistryKey(root))
|
||||
{
|
||||
return SortedListRegistryHandler.getValue(rk, name);
|
||||
}
|
||||
}
|
||||
|
||||
internal virtual void deleteSortedList(RegistryRoot root, string name)
|
||||
{
|
||||
using (RegistryKey rk = myGetRegistryKey(root))
|
||||
{
|
||||
SortedListRegistryHandler.deleteValue(rk, name);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,9 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0-windows</TargetFramework>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<UseWindowsForms>true</UseWindowsForms>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,4 +1,6 @@
|
||||
using System;
|
||||
using System.Runtime.Versioning;
|
||||
|
||||
using Microsoft.Win32;
|
||||
|
||||
namespace BCG
|
||||
@@ -10,6 +12,7 @@ namespace BCG
|
||||
rk.SetValue (name, value.ToString ());
|
||||
}
|
||||
|
||||
[SupportedOSPlatform("windows")]
|
||||
public static double getValue (RegistryKey rk, string name)
|
||||
{
|
||||
object v = rk.GetValue (name);
|
||||
|
||||
@@ -1,19 +1,11 @@
|
||||
namespace Bts.BooleanExpressions;
|
||||
|
||||
using bts;
|
||||
|
||||
class BooleanExpression : IBooleanExpression {
|
||||
readonly Func<IDictionary<string, object?>, bool> evaluate;
|
||||
|
||||
public BooleanExpression(Func<IDictionary<string, object?>, bool> evaluate) =>
|
||||
this.evaluate = evaluate;
|
||||
|
||||
public bool Evaluate(IDictionary<string, object?> env) {
|
||||
try {
|
||||
return evaluate(env);
|
||||
} catch (Exception ex) {
|
||||
Log.assert(false, $"BooleanExpression.Evaluate failed: {ex}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
public bool Evaluate(IDictionary<string, object?> env) =>
|
||||
evaluate(env);
|
||||
}
|
||||
@@ -47,11 +47,6 @@ IsOfType '/'
|
||||
|
||||
%%
|
||||
|
||||
{StringConstant} {
|
||||
yylval.String = yytext.Substring(1, yytext.Length - 2).Replace(@"\'", "'");
|
||||
return (int)Token.STRING_CONSTANT;
|
||||
}
|
||||
|
||||
{BooleanConstant} {
|
||||
yylval.Boolean = yytext.ToLower() switch {
|
||||
"true" => true,
|
||||
@@ -62,6 +57,11 @@ IsOfType '/'
|
||||
return (int)Token.BOOLEAN_CONSTANT;
|
||||
}
|
||||
|
||||
{StringConstant} {
|
||||
yylval.String = yytext.Substring(1, yytext.Length - 2).Replace(@"\'", "'");
|
||||
return (int)Token.STRING_CONSTANT;
|
||||
}
|
||||
|
||||
{NullConstant} {
|
||||
yylval.Null = DBNull.Value;
|
||||
return (int)Token.NULL_CONSTANT;
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="YaccLexTools" Version="1.2.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\DataStreamCore\DataStreamCore.csproj" />
|
||||
<ProjectReference Include="..\ExpressionCore\ExpressionCore.csproj" />
|
||||
<ProjectReference Include="..\..\client\spark_core\spark_core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Label="ColumnExpression">
|
||||
<Scanner Include="ColumnExpressionTokens.lex" />
|
||||
<Parser Include="ColumnExpressionGrammar.y" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
File renamed without changes.
@@ -0,0 +1,62 @@
|
||||
namespace Bts.ColumnExpressions;
|
||||
|
||||
public class ColumnExpression {
|
||||
public ColumnExpression(string name, Type? type = null, object? value = null) {
|
||||
Name = name;
|
||||
Type = type
|
||||
?? value?.GetType()
|
||||
?? throw new ArgumentException(
|
||||
"Type must be specified explicitly when value is null", nameof(type));
|
||||
Value = value
|
||||
?? DBNull.Value;
|
||||
}
|
||||
|
||||
public string Name { get; }
|
||||
|
||||
public Type Type { get; }
|
||||
|
||||
public object Value { get; }
|
||||
|
||||
public static ColumnExpression Create<T>(string name, T value, Type? type = null) {
|
||||
// Try to convert value to 'type' to verify they are compatible
|
||||
// Note: Can't use `System.Type.IsAssignableFrom` because it doesn't
|
||||
// account for implicit conversions (e.g., int -> long), just inheritance.
|
||||
if (type is not null && !ConvertUtils.try_convert(type, value, out _)) {
|
||||
throw new ArgumentException(
|
||||
$"Type '{type}' is not assignable from value type '{value?.GetType()}'");
|
||||
}
|
||||
return new(name, type ?? typeof(T), value);
|
||||
}
|
||||
|
||||
internal static Type ParseType(string typeId) {
|
||||
return Candidates().ExceptNull().FirstOrDefault() ??
|
||||
throw new ArgumentException($"Failed to parse Type from '{typeId}'", nameof(typeId));
|
||||
|
||||
IEnumerable<Type?> Candidates() {
|
||||
if (typeId.Length == 0) {
|
||||
yield break;
|
||||
}
|
||||
yield return Type.GetType(typeId);
|
||||
yield return Type.GetType($"System.{typeId}");
|
||||
if (typeId.Length > 1) {
|
||||
yield return Type.GetType($"System.{char.ToUpper(typeId[0]) + typeId[1..]}");
|
||||
}
|
||||
yield return typeId.ToLower() switch {
|
||||
"float64" or "double" or "real64" or "number" => typeof(double),
|
||||
"float32" or "single" or "real32" or "real" or "float" => typeof(float),
|
||||
"int16" or "short" or "integer16" or "signed16" => typeof(short),
|
||||
"int32" or "int" or "integer" or "integer32" or "signed" => typeof(int),
|
||||
"int64" or "long" or "integer64" or "signed64" => typeof(long),
|
||||
"uint16" or "ushort" or "unsigned16" => typeof(ushort),
|
||||
"uint32" or "uint" or "unsigned" => typeof(uint),
|
||||
"uint64" or "ulong" or "unsigned64" => typeof(ulong),
|
||||
"char" => typeof(char),
|
||||
"byte" or "uint8" => typeof(byte),
|
||||
"bool" or "boolean" => typeof(bool),
|
||||
"string" or "text" => typeof(string),
|
||||
"date" or "datetime" => typeof(DateTime),
|
||||
_ => null
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
%namespace Bts.ColumnExpressions
|
||||
%partial
|
||||
%visibility internal
|
||||
%tokentype ColumnExpressionToken
|
||||
%parsertype ColumnExpressionParser
|
||||
|
||||
%union {
|
||||
public int Integer;
|
||||
public double Real;
|
||||
public bool Boolean;
|
||||
public string String;
|
||||
public string Identifier;
|
||||
public string TypeId;
|
||||
public DateTime DateTime;
|
||||
public Tuple<string, Type> ColumnDefinition;
|
||||
public ColumnExpression ColumnExpression;
|
||||
public ImmutableList<ColumnExpression> ColumnExpressions;
|
||||
}
|
||||
|
||||
%token BOOLEAN_CONSTANT, INTEGER_CONSTANT, REAL_CONSTANT, DATE_TIME_CONSTANT, STRING_CONSTANT
|
||||
%token IDENTIFIER, EQUALS, TYPE_ID, OF_TYPE
|
||||
|
||||
%nonassoc EQUALS
|
||||
|
||||
%type <ColumnDefinition> ColumnDefinition
|
||||
%type <ColumnExpression> ColumnExpression
|
||||
%type <ColumnExpressions> ColumnExpressions
|
||||
|
||||
%%
|
||||
|
||||
ColumnExpressions :
|
||||
ColumnExpression { $$ = ImmutableList.CreateRange(new[] { $1 }); }
|
||||
| ColumnExpressions ColumnExpression { $$ = $1.Add($2); }
|
||||
;
|
||||
|
||||
ColumnExpression :
|
||||
ColumnDefinition EQUALS INTEGER_CONSTANT { $$ = ColumnExpression.Create($1.Item1, $3.Integer, $1.Item2); }
|
||||
| ColumnDefinition EQUALS REAL_CONSTANT { $$ = ColumnExpression.Create($1.Item1, $3.Real, $1.Item2); }
|
||||
| ColumnDefinition EQUALS DATE_TIME_CONSTANT { $$ = ColumnExpression.Create($1.Item1, $3.DateTime, $1.Item2); }
|
||||
| ColumnDefinition EQUALS BOOLEAN_CONSTANT { $$ = ColumnExpression.Create($1.Item1, $3.Boolean, $1.Item2); }
|
||||
| ColumnDefinition EQUALS STRING_CONSTANT { $$ = ColumnExpression.Create($1.Item1, $3.String, $1.Item2); }
|
||||
| ColumnDefinition { $$ = new($1.Item1, $1.Item2); }
|
||||
;
|
||||
|
||||
ColumnDefinition :
|
||||
IDENTIFIER { $$ = new($1.Identifier, null); }
|
||||
| IDENTIFIER OF_TYPE IDENTIFIER { $$ = new($1.Identifier, ColumnExpression.ParseType($3.Identifier)); }
|
||||
| IDENTIFIER OF_TYPE TYPE_ID { $$ = new($1.Identifier, ColumnExpression.ParseType($3.TypeId)); }
|
||||
;
|
||||
@@ -0,0 +1,18 @@
|
||||
namespace Bts.ColumnExpressions;
|
||||
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
public class ColumnExpressionInterpreter {
|
||||
public static IList<ColumnExpression> Evaluate(Stream stream) {
|
||||
var parser = new ColumnExpressionParser();
|
||||
var res = parser.Parse(stream);
|
||||
return res?.ColumnExpressions ?? ImmutableList<ColumnExpression>.Empty.Add(
|
||||
res?.ColumnExpression ?? throw new Exception("Failed to parse column(s) expression"));
|
||||
}
|
||||
|
||||
public static IList<ColumnExpression> Evaluate(string str) {
|
||||
using var ms = new MemoryStream(Encoding.Default.GetBytes(str));
|
||||
return Evaluate(ms);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
namespace Bts.ColumnExpressions;
|
||||
|
||||
using System.Text;
|
||||
|
||||
partial class ColumnExpressionParser {
|
||||
public ColumnExpressionParser() : base(null) { }
|
||||
|
||||
public ValueType? Parse(string s) {
|
||||
using var ms = new MemoryStream(Encoding.Default.GetBytes(s));
|
||||
return Parse(ms);
|
||||
}
|
||||
|
||||
public ValueType? Parse(Stream stream) {
|
||||
Scanner = new ColumnExpressionScanner(stream);
|
||||
Parse();
|
||||
return CurrentSemanticValue;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace Bts.ColumnExpressions;
|
||||
|
||||
partial class ColumnExpressionScanner {
|
||||
public override void yyerror(string format, params object[] args) {
|
||||
base.yyerror(format, args);
|
||||
Console.WriteLine(format, args);
|
||||
Console.WriteLine();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
%namespace Bts.ColumnExpressions
|
||||
%scannertype ColumnExpressionScanner
|
||||
%visibility internal
|
||||
%tokentype ColumnExpressionToken
|
||||
|
||||
%option stack, minimize, parser, verbose, persistbuffer, noembedbuffers
|
||||
|
||||
/* Literal Constants */
|
||||
Letter [a-zA-Z]
|
||||
BooleanConstant true|false
|
||||
StringConstant '([^\'\\]*|\\.)*'
|
||||
DateTimeConstant ([1-9]|'10'|'11'|'12')\/([1-9]|([1-2][0-9])|'30'|'31')\/[0-9][0-9][0-9]*
|
||||
IntegerConstant -?[0-9]+
|
||||
NullConstant 'null'
|
||||
RealConstant -?[0-9]+\.[0-9]+
|
||||
|
||||
/* Relational Operators */
|
||||
Equals =
|
||||
OfType /
|
||||
|
||||
Identifier {Letter}({Letter}*[0-9]*_*)*
|
||||
NamespacePrefix {Identifier}\.
|
||||
TypeId {NamespacePrefix}*{Identifier}
|
||||
|
||||
/* Utility Tokens */
|
||||
OpenParenthesis \(
|
||||
CloseParenthesis \)
|
||||
Comma ,
|
||||
QuoteOpen \[
|
||||
QuoteClose \]
|
||||
|
||||
/* Comments */
|
||||
LineComment \/\/[^\n\r]*(\n|\r|\r\n)
|
||||
|
||||
%%
|
||||
|
||||
{Equals} {
|
||||
return (int)ColumnExpressionToken.EQUALS;
|
||||
}
|
||||
|
||||
{OfType} {
|
||||
return (int)ColumnExpressionToken.OF_TYPE;
|
||||
}
|
||||
|
||||
{StringConstant} {
|
||||
yylval.String = yytext.Substring(1, yytext.Length - 2).Replace(@"\'","'");
|
||||
return (int)ColumnExpressionToken.STRING_CONSTANT;
|
||||
}
|
||||
|
||||
{BooleanConstant} {
|
||||
yylval.Boolean = yytext.ToLower() switch {
|
||||
"true" => true,
|
||||
"false" => false,
|
||||
_ => throw new Exception(
|
||||
string.Format("Expected yytext to be 'true' or 'false' (actually '{0}')", yytext))
|
||||
};
|
||||
return (int)ColumnExpressionToken.BOOLEAN_CONSTANT;
|
||||
}
|
||||
|
||||
{DateTimeConstant} {
|
||||
yylval.DateTime = DateTime.Parse(yytext);
|
||||
return (int)ColumnExpressionToken.DATE_TIME_CONSTANT;
|
||||
}
|
||||
|
||||
{IntegerConstant} {
|
||||
yylval.Integer = int.Parse(yytext);
|
||||
return (int)ColumnExpressionToken.INTEGER_CONSTANT;
|
||||
}
|
||||
|
||||
{RealConstant} {
|
||||
yylval.Real = double.Parse(yytext);
|
||||
return (int)ColumnExpressionToken.REAL_CONSTANT;
|
||||
}
|
||||
|
||||
{Identifier} {
|
||||
yylval.Identifier = yytext;
|
||||
return (int)ColumnExpressionToken.IDENTIFIER;
|
||||
}
|
||||
|
||||
{TypeId} {
|
||||
yylval.TypeId = yytext;
|
||||
return (int)ColumnExpressionToken.TYPE_ID;
|
||||
}
|
||||
|
||||
%%
|
||||
@@ -0,0 +1,720 @@
|
||||
// ==============================================================
|
||||
// <auto-generated>
|
||||
// This code automatically produced from an embedded resource.
|
||||
// Do not edit this file, or it will become incompatible with
|
||||
// the specification from which it was generated.
|
||||
// </auto-generated>
|
||||
// ==============================================================
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Globalization;
|
||||
|
||||
namespace QUT.GplexBuffers
|
||||
{
|
||||
// Code copied from GPLEX embedded resource
|
||||
[Serializable]
|
||||
internal class BufferException : Exception
|
||||
{
|
||||
public BufferException() { }
|
||||
public BufferException(string message) : base(message) { }
|
||||
public BufferException(string message, Exception innerException)
|
||||
: base(message, innerException) { }
|
||||
protected BufferException(SerializationInfo info, StreamingContext context)
|
||||
: base(info, context) { }
|
||||
}
|
||||
|
||||
internal abstract class ScanBuff
|
||||
{
|
||||
private string fileNm;
|
||||
|
||||
public const int EndOfFile = -1;
|
||||
public const int UnicodeReplacementChar = 0xFFFD;
|
||||
|
||||
public bool IsFile { get { return (fileNm != null); } }
|
||||
public string FileName { get { return fileNm; } set { fileNm = value; } }
|
||||
|
||||
public abstract int Pos { get; set; }
|
||||
public abstract int Read();
|
||||
public virtual void Mark() { }
|
||||
|
||||
public abstract string GetString(int begin, int limit);
|
||||
|
||||
public static ScanBuff GetBuffer(string source)
|
||||
{
|
||||
return new StringBuffer(source);
|
||||
}
|
||||
|
||||
public static ScanBuff GetBuffer(IList<string> source)
|
||||
{
|
||||
return new LineBuffer(source);
|
||||
}
|
||||
|
||||
#if (!NOFILES)
|
||||
public static ScanBuff GetBuffer(Stream source)
|
||||
{
|
||||
return new BuildBuffer(source);
|
||||
}
|
||||
|
||||
#if (!BYTEMODE)
|
||||
public static ScanBuff GetBuffer(Stream source, int fallbackCodePage)
|
||||
{
|
||||
return new BuildBuffer(source, fallbackCodePage);
|
||||
}
|
||||
#endif // !BYTEMODE
|
||||
#endif // !NOFILES
|
||||
}
|
||||
|
||||
#region Buffer classes
|
||||
|
||||
// ==============================================================
|
||||
// ===== Definitions for various ScanBuff derived classes ====
|
||||
// ==============================================================
|
||||
// =============== String input ================
|
||||
// ==============================================================
|
||||
|
||||
/// <summary>
|
||||
/// This class reads characters from a single string as
|
||||
/// required, for example, by Visual Studio language services
|
||||
/// </summary>
|
||||
sealed class StringBuffer : ScanBuff
|
||||
{
|
||||
string str; // input buffer
|
||||
int bPos; // current position in buffer
|
||||
int sLen;
|
||||
|
||||
public StringBuffer(string source)
|
||||
{
|
||||
this.str = source;
|
||||
this.sLen = source.Length;
|
||||
this.FileName = null;
|
||||
}
|
||||
|
||||
public override int Read()
|
||||
{
|
||||
if (bPos < sLen) return str[bPos++];
|
||||
else if (bPos == sLen) { bPos++; return '\n'; } // one strike, see new line
|
||||
else { bPos++; return EndOfFile; } // two strikes and you're out!
|
||||
}
|
||||
|
||||
public override string GetString(int begin, int limit)
|
||||
{
|
||||
// "limit" can be greater than sLen with the BABEL
|
||||
// option set. Read returns a "virtual" EOL if
|
||||
// an attempt is made to read past the end of the
|
||||
// string buffer. Without the guard any attempt
|
||||
// to fetch yytext for a token that includes the
|
||||
// EOL will throw an index exception.
|
||||
if (limit > sLen) limit = sLen;
|
||||
if (limit <= begin) return "";
|
||||
else return str.Substring(begin, limit - begin);
|
||||
}
|
||||
|
||||
public override int Pos
|
||||
{
|
||||
get { return bPos; }
|
||||
set { bPos = value; }
|
||||
}
|
||||
|
||||
public override string ToString() { return "StringBuffer"; }
|
||||
}
|
||||
|
||||
// ==============================================================
|
||||
// The LineBuff class contributed by Nigel Horspool,
|
||||
// nigelh@cs.uvic.cs
|
||||
// ==============================================================
|
||||
|
||||
sealed class LineBuffer : ScanBuff
|
||||
{
|
||||
IList<string> line; // list of source lines from a file
|
||||
int numLines; // number of strings in line list
|
||||
string curLine; // current line in that list
|
||||
int cLine; // index of current line in the list
|
||||
int curLen; // length of current line
|
||||
int curLineStart; // position of line start in whole file
|
||||
int curLineEnd; // position of line end in whole file
|
||||
int maxPos; // max position ever visited in whole file
|
||||
int cPos; // ordinal number of code in source
|
||||
|
||||
// Constructed from a list of strings, one per source line.
|
||||
// The lines have had trailing '\n' characters removed.
|
||||
public LineBuffer(IList<string> lineList)
|
||||
{
|
||||
line = lineList;
|
||||
numLines = line.Count;
|
||||
cPos = curLineStart = 0;
|
||||
curLine = (numLines > 0 ? line[0] : "");
|
||||
maxPos = curLineEnd = curLen = curLine.Length;
|
||||
cLine = 1;
|
||||
FileName = null;
|
||||
}
|
||||
|
||||
public override int Read()
|
||||
{
|
||||
if (cPos < curLineEnd)
|
||||
return curLine[cPos++ - curLineStart];
|
||||
if (cPos++ == curLineEnd)
|
||||
return '\n';
|
||||
if (cLine >= numLines)
|
||||
return EndOfFile;
|
||||
curLine = line[cLine];
|
||||
curLen = curLine.Length;
|
||||
curLineStart = curLineEnd + 1;
|
||||
curLineEnd = curLineStart + curLen;
|
||||
if (curLineEnd > maxPos)
|
||||
maxPos = curLineEnd;
|
||||
cLine++;
|
||||
return curLen > 0 ? curLine[0] : '\n';
|
||||
}
|
||||
|
||||
// To speed up searches for the line containing a position
|
||||
private int cachedPosition;
|
||||
private int cachedIxdex;
|
||||
private int cachedLineStart;
|
||||
|
||||
// Given a position pos within the entire source, the results are
|
||||
// ix -- the index of the containing line
|
||||
// lstart -- the position of the first character on that line
|
||||
private void findIndex(int pos, out int ix, out int lstart)
|
||||
{
|
||||
if (pos >= cachedPosition)
|
||||
{
|
||||
ix = cachedIxdex; lstart = cachedLineStart;
|
||||
}
|
||||
else
|
||||
{
|
||||
ix = lstart = 0;
|
||||
}
|
||||
while (ix < numLines)
|
||||
{
|
||||
int len = line[ix].Length + 1;
|
||||
if (pos < lstart + len) break;
|
||||
lstart += len;
|
||||
ix++;
|
||||
}
|
||||
cachedPosition = pos;
|
||||
cachedIxdex = ix;
|
||||
cachedLineStart = lstart;
|
||||
}
|
||||
|
||||
public override string GetString(int begin, int limit)
|
||||
{
|
||||
if (begin >= maxPos || limit <= begin) return "";
|
||||
int endIx, begIx, endLineStart, begLineStart;
|
||||
findIndex(begin, out begIx, out begLineStart);
|
||||
int begCol = begin - begLineStart;
|
||||
findIndex(limit, out endIx, out endLineStart);
|
||||
int endCol = limit - endLineStart;
|
||||
string s = line[begIx];
|
||||
if (begIx == endIx)
|
||||
{
|
||||
// the usual case, substring all on one line
|
||||
return (endCol <= s.Length) ?
|
||||
s.Substring(begCol, endCol - begCol)
|
||||
: s.Substring(begCol) + "\n";
|
||||
}
|
||||
// the string spans multiple lines, yuk!
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (begCol < s.Length)
|
||||
sb.Append(s.Substring(begCol));
|
||||
for (; ; )
|
||||
{
|
||||
sb.Append("\n");
|
||||
s = line[++begIx];
|
||||
if (begIx >= endIx) break;
|
||||
sb.Append(s);
|
||||
}
|
||||
if (endCol <= s.Length)
|
||||
{
|
||||
sb.Append(s.Substring(0, endCol));
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.Append(s);
|
||||
sb.Append("\n");
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public override int Pos
|
||||
{
|
||||
get { return cPos; }
|
||||
set
|
||||
{
|
||||
cPos = value;
|
||||
findIndex(cPos, out cLine, out curLineStart);
|
||||
// cLine should be the *next* line after curLine.
|
||||
curLine = (cLine < numLines ? line[cLine++] : "");
|
||||
curLineEnd = curLineStart + curLine.Length;
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString() { return "LineBuffer"; }
|
||||
}
|
||||
|
||||
#if (!NOFILES)
|
||||
// ==============================================================
|
||||
// ===== class BuildBuff : for unicode text files ========
|
||||
// ==============================================================
|
||||
|
||||
class BuildBuffer : ScanBuff
|
||||
{
|
||||
// Double buffer for char stream.
|
||||
class BufferElement
|
||||
{
|
||||
StringBuilder bldr = new StringBuilder();
|
||||
StringBuilder next = new StringBuilder();
|
||||
int minIx;
|
||||
int maxIx;
|
||||
int brkIx;
|
||||
bool appendToNext;
|
||||
|
||||
internal BufferElement() { }
|
||||
|
||||
internal int MaxIndex { get { return maxIx; } }
|
||||
// internal int MinIndex { get { return minIx; } }
|
||||
|
||||
internal char this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (index < minIx || index >= maxIx)
|
||||
throw new BufferException("Index was outside data buffer");
|
||||
else if (index < brkIx)
|
||||
return bldr[index - minIx];
|
||||
else
|
||||
return next[index - brkIx];
|
||||
}
|
||||
}
|
||||
|
||||
internal void Append(char[] block, int count)
|
||||
{
|
||||
maxIx += count;
|
||||
if (appendToNext)
|
||||
this.next.Append(block, 0, count);
|
||||
else
|
||||
{
|
||||
this.bldr.Append(block, 0, count);
|
||||
brkIx = maxIx;
|
||||
appendToNext = true;
|
||||
}
|
||||
}
|
||||
|
||||
internal string GetString(int start, int limit)
|
||||
{
|
||||
if (limit <= start)
|
||||
return "";
|
||||
if (start >= minIx && limit <= maxIx)
|
||||
if (limit < brkIx) // String entirely in bldr builder
|
||||
return bldr.ToString(start - minIx, limit - start);
|
||||
else if (start >= brkIx) // String entirely in next builder
|
||||
return next.ToString(start - brkIx, limit - start);
|
||||
else // Must do a string-concatenation
|
||||
return
|
||||
bldr.ToString(start - minIx, brkIx - start) +
|
||||
next.ToString(0, limit - brkIx);
|
||||
else
|
||||
throw new BufferException("String was outside data buffer");
|
||||
}
|
||||
|
||||
internal void Mark(int limit)
|
||||
{
|
||||
if (limit > brkIx + 16) // Rotate blocks
|
||||
{
|
||||
StringBuilder temp = bldr;
|
||||
bldr = next;
|
||||
next = temp;
|
||||
next.Length = 0;
|
||||
minIx = brkIx;
|
||||
brkIx = maxIx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BufferElement data = new BufferElement();
|
||||
|
||||
int bPos; // Postion index in the StringBuilder
|
||||
BlockReader NextBlk; // Delegate that serves char-arrays;
|
||||
|
||||
private string EncodingName
|
||||
{
|
||||
get
|
||||
{
|
||||
StreamReader rdr = NextBlk.Target as StreamReader;
|
||||
return (rdr == null ? "raw-bytes" : rdr.CurrentEncoding.BodyName);
|
||||
}
|
||||
}
|
||||
|
||||
public BuildBuffer(Stream stream)
|
||||
{
|
||||
FileStream fStrm = (stream as FileStream);
|
||||
if (fStrm != null) FileName = fStrm.Name;
|
||||
NextBlk = BlockReaderFactory.Raw(stream);
|
||||
}
|
||||
|
||||
#if (!BYTEMODE)
|
||||
public BuildBuffer(Stream stream, int fallbackCodePage)
|
||||
{
|
||||
FileStream fStrm = (stream as FileStream);
|
||||
if (fStrm != null) FileName = fStrm.Name;
|
||||
NextBlk = BlockReaderFactory.Get(stream, fallbackCodePage);
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Marks a conservative lower bound for the buffer,
|
||||
/// allowing space to be reclaimed. If an application
|
||||
/// needs to call GetString at arbitrary past locations
|
||||
/// in the input stream, Mark() is not called.
|
||||
/// </summary>
|
||||
public override void Mark() { data.Mark(bPos - 2); }
|
||||
|
||||
public override int Pos
|
||||
{
|
||||
get { return bPos; }
|
||||
set { bPos = value; }
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Read returns the ordinal number of the next char, or
|
||||
/// EOF (-1) for an end of stream. Note that the next
|
||||
/// code point may require *two* calls of Read().
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override int Read()
|
||||
{
|
||||
//
|
||||
// Characters at positions
|
||||
// [data.offset, data.offset + data.bldr.Length)
|
||||
// are available in data.bldr.
|
||||
//
|
||||
if (bPos < data.MaxIndex)
|
||||
{
|
||||
// ch0 cannot be EOF
|
||||
return (int)data[bPos++];
|
||||
}
|
||||
else // Read from underlying stream
|
||||
{
|
||||
// Experimental code, blocks of page size
|
||||
char[] chrs = new char[4096];
|
||||
int count = NextBlk(chrs, 0, 4096);
|
||||
if (count == 0)
|
||||
return EndOfFile;
|
||||
else
|
||||
{
|
||||
data.Append(chrs, count);
|
||||
return (int)data[bPos++];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override string GetString(int begin, int limit)
|
||||
{
|
||||
return data.GetString(begin, limit);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "StringBuilder buffer, encoding: " + this.EncodingName;
|
||||
}
|
||||
}
|
||||
|
||||
// =============== End ScanBuff-derived classes ==================
|
||||
|
||||
internal delegate int BlockReader(char[] block, int index, int number);
|
||||
|
||||
// A delegate factory, serving up a delegate that
|
||||
// reads a block of characters from the underlying
|
||||
// encoded stream, via a StreamReader object.
|
||||
//
|
||||
internal static class BlockReaderFactory
|
||||
{
|
||||
public static BlockReader Raw(Stream stream)
|
||||
{
|
||||
return delegate(char[] block, int index, int number)
|
||||
{
|
||||
byte[] b = new byte[number];
|
||||
int count = stream.Read(b, 0, number);
|
||||
int i = 0;
|
||||
int j = index;
|
||||
for (; i < count; i++, j++)
|
||||
block[j] = (char)b[i];
|
||||
return count;
|
||||
};
|
||||
}
|
||||
|
||||
#if (!BYTEMODE)
|
||||
public static BlockReader Get(Stream stream, int fallbackCodePage)
|
||||
{
|
||||
Encoding encoding;
|
||||
int preamble = Preamble(stream);
|
||||
|
||||
if (preamble != 0) // There is a valid BOM here!
|
||||
encoding = Encoding.GetEncoding(preamble);
|
||||
else if (fallbackCodePage == -1) // Fallback is "raw" bytes
|
||||
return Raw(stream);
|
||||
else if (fallbackCodePage != -2) // Anything but "guess"
|
||||
encoding = Encoding.GetEncoding(fallbackCodePage);
|
||||
else // This is the "guess" option
|
||||
{
|
||||
int guess = new Guesser(stream).GuessCodePage();
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
if (guess == -1) // ==> this is a 7-bit file
|
||||
encoding = Encoding.ASCII;
|
||||
else if (guess == 65001)
|
||||
encoding = Encoding.UTF8;
|
||||
else // ==> use the machine default
|
||||
encoding = Encoding.Default;
|
||||
}
|
||||
StreamReader reader = new StreamReader(stream, encoding);
|
||||
return reader.Read;
|
||||
}
|
||||
|
||||
static int Preamble(Stream stream)
|
||||
{
|
||||
int b0 = stream.ReadByte();
|
||||
int b1 = stream.ReadByte();
|
||||
|
||||
if (b0 == 0xfe && b1 == 0xff)
|
||||
return 1201; // UTF16BE
|
||||
if (b0 == 0xff && b1 == 0xfe)
|
||||
return 1200; // UTF16LE
|
||||
|
||||
int b2 = stream.ReadByte();
|
||||
if (b0 == 0xef && b1 == 0xbb && b2 == 0xbf)
|
||||
return 65001; // UTF8
|
||||
//
|
||||
// There is no unicode preamble, so we
|
||||
// return denoter for the machine default.
|
||||
//
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
return 0;
|
||||
}
|
||||
#endif // !BYTEMODE
|
||||
}
|
||||
#endif // !NOFILES
|
||||
#endregion Buffer classes
|
||||
|
||||
// ==============================================================
|
||||
// ============ class CodePageHandling =============
|
||||
// ==============================================================
|
||||
#if (!NOFILES)
|
||||
public static class CodePageHandling
|
||||
{
|
||||
public static int GetCodePage(string option)
|
||||
{
|
||||
string command = option.ToUpperInvariant();
|
||||
if (command.StartsWith("CodePage:", StringComparison.OrdinalIgnoreCase))
|
||||
command = command.Substring(9);
|
||||
try
|
||||
{
|
||||
if (command.Equals("RAW"))
|
||||
return -1;
|
||||
else if (command.Equals("GUESS"))
|
||||
return -2;
|
||||
else if (command.Equals("DEFAULT"))
|
||||
return 0;
|
||||
else if (char.IsDigit(command[0]))
|
||||
return int.Parse(command, CultureInfo.InvariantCulture);
|
||||
else
|
||||
{
|
||||
Encoding enc = Encoding.GetEncoding(command);
|
||||
return enc.CodePage;
|
||||
}
|
||||
}
|
||||
catch (FormatException)
|
||||
{
|
||||
Console.Error.WriteLine(
|
||||
"Invalid format \"{0}\", using machine default", option);
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
Console.Error.WriteLine(
|
||||
"Unknown code page \"{0}\", using machine default", option);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#region guesser
|
||||
#if (!BYTEMODE)
|
||||
// ==============================================================
|
||||
// ============ Encoding Guesser =============
|
||||
// ==============================================================
|
||||
|
||||
/// <summary>
|
||||
/// This class provides a simple finite state automaton that
|
||||
/// scans the file looking for (1) valid UTF-8 byte patterns,
|
||||
/// (2) bytes >= 0x80 which are not part of a UTF-8 sequence.
|
||||
/// The method then guesses whether it is UTF-8 or maybe some
|
||||
/// local machine default encoding. This works well for the
|
||||
/// various Latin encodings.
|
||||
/// </summary>
|
||||
internal class Guesser
|
||||
{
|
||||
ScanBuff buffer;
|
||||
|
||||
public int GuessCodePage() { return Scan(); }
|
||||
|
||||
const int maxAccept = 10;
|
||||
const int initial = 0;
|
||||
const int eofNum = 0;
|
||||
const int goStart = -1;
|
||||
const int INITIAL = 0;
|
||||
const int EndToken = 0;
|
||||
|
||||
#region user code
|
||||
/*
|
||||
* Reads the bytes of a file to determine if it is
|
||||
* UTF-8 or a single-byte code page file.
|
||||
*/
|
||||
public long utfX;
|
||||
public long uppr;
|
||||
#endregion user code
|
||||
|
||||
int state;
|
||||
int currentStart = startState[0];
|
||||
int code;
|
||||
|
||||
#region ScannerTables
|
||||
static int[] startState = new int[] { 11, 0 };
|
||||
|
||||
#region CharacterMap
|
||||
static sbyte[] map = new sbyte[256] {
|
||||
/* '\0' */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/* '\x10' */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/* '\x20' */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/* '0' */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/* '@' */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/* 'P' */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/* '`' */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/* 'p' */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/* '\x80' */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
/* '\x90' */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
/* '\xA0' */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
/* '\xB0' */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
/* '\xC0' */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
/* '\xD0' */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
/* '\xE0' */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
/* '\xF0' */ 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5 };
|
||||
#endregion
|
||||
|
||||
static sbyte[][] nextState = new sbyte[][] {
|
||||
new sbyte[] {0, 0, 0, 0, 0, 0},
|
||||
new sbyte[] {-1, -1, 10, -1, -1, -1},
|
||||
new sbyte[] {-1, -1, -1, -1, -1, -1},
|
||||
new sbyte[] {-1, -1, 8, -1, -1, -1},
|
||||
new sbyte[] {-1, -1, 5, -1, -1, -1},
|
||||
new sbyte[] {-1, -1, 6, -1, -1, -1},
|
||||
new sbyte[] {-1, -1, 7, -1, -1, -1},
|
||||
null,
|
||||
new sbyte[] {-1, -1, 9, -1, -1, -1},
|
||||
null,
|
||||
null,
|
||||
new sbyte[] {-1, 1, 2, 3, 4, 2}
|
||||
};
|
||||
|
||||
|
||||
[SuppressMessage("Microsoft.Performance", "CA1810:InitializeReferenceTypeStaticFieldsInline")]
|
||||
// Reason for suppression: cannot have self-reference in array initializer.
|
||||
static Guesser()
|
||||
{
|
||||
nextState[7] = nextState[2];
|
||||
nextState[9] = nextState[2];
|
||||
nextState[10] = nextState[2];
|
||||
}
|
||||
|
||||
int NextState()
|
||||
{
|
||||
if (code == ScanBuff.EndOfFile)
|
||||
return eofNum;
|
||||
else
|
||||
return nextState[state][map[code]];
|
||||
}
|
||||
#endregion
|
||||
|
||||
public Guesser(System.IO.Stream file) { SetSource(file); }
|
||||
|
||||
public void SetSource(System.IO.Stream source)
|
||||
{
|
||||
this.buffer = new BuildBuffer(source);
|
||||
code = buffer.Read();
|
||||
}
|
||||
|
||||
int Scan()
|
||||
{
|
||||
for (; ; )
|
||||
{
|
||||
int next;
|
||||
state = currentStart;
|
||||
while ((next = NextState()) == goStart)
|
||||
code = buffer.Read();
|
||||
|
||||
state = next;
|
||||
code = buffer.Read();
|
||||
|
||||
while ((next = NextState()) > eofNum)
|
||||
{
|
||||
state = next;
|
||||
code = buffer.Read();
|
||||
}
|
||||
if (state <= maxAccept)
|
||||
{
|
||||
#region ActionSwitch
|
||||
#pragma warning disable 162
|
||||
switch (state)
|
||||
{
|
||||
case eofNum:
|
||||
switch (currentStart)
|
||||
{
|
||||
case 11:
|
||||
if (utfX == 0 && uppr == 0) return -1; /* raw ascii */
|
||||
else if (uppr * 10 > utfX) return 0; /* default code page */
|
||||
else return 65001; /* UTF-8 encoding */
|
||||
break;
|
||||
}
|
||||
return EndToken;
|
||||
case 1: // Recognized '{Upper128}', Shortest string "\xC0"
|
||||
case 2: // Recognized '{Upper128}', Shortest string "\x80"
|
||||
case 3: // Recognized '{Upper128}', Shortest string "\xE0"
|
||||
case 4: // Recognized '{Upper128}', Shortest string "\xF0"
|
||||
uppr++;
|
||||
break;
|
||||
case 5: // Recognized '{Utf8pfx4}{Utf8cont}', Shortest string "\xF0\x80"
|
||||
uppr += 2;
|
||||
break;
|
||||
case 6: // Recognized '{Utf8pfx4}{Utf8cont}{2}', Shortest string "\xF0\x80\x80"
|
||||
uppr += 3;
|
||||
break;
|
||||
case 7: // Recognized '{Utf8pfx4}{Utf8cont}{3}', Shortest string "\xF0\x80\x80\x80"
|
||||
utfX += 3;
|
||||
break;
|
||||
case 8: // Recognized '{Utf8pfx3}{Utf8cont}', Shortest string "\xE0\x80"
|
||||
uppr += 2;
|
||||
break;
|
||||
case 9: // Recognized '{Utf8pfx3}{Utf8cont}{2}', Shortest string "\xE0\x80\x80"
|
||||
utfX += 2;
|
||||
break;
|
||||
case 10: // Recognized '{Utf8pfx2}{Utf8cont}', Shortest string "\xC0\x80"
|
||||
utfX++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#pragma warning restore 162
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
} // end class Guesser
|
||||
|
||||
#endif // !BYTEMODE
|
||||
#endregion
|
||||
#endif // !NOFILES
|
||||
|
||||
// End of code copied from embedded resource
|
||||
}
|
||||
@@ -0,0 +1,884 @@
|
||||
// ==============================================================
|
||||
// <auto-generated>
|
||||
// This code automatically produced from an embedded resource.
|
||||
// Do not edit this file, or it will become incompatible with
|
||||
// the specification from which it was generated.
|
||||
// </auto-generated>
|
||||
// ==============================================================
|
||||
|
||||
// Gardens Point Parser Generator
|
||||
// Copyright (c) Wayne Kelly, QUT 2005-2010
|
||||
// (see accompanying GPPGcopyright.rtf)
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Globalization;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace QUT.Gppg {
|
||||
/// <summary>
|
||||
/// Abstract class for GPPG shift-reduce parsers.
|
||||
/// Parsers generated by GPPG derive from this base
|
||||
/// class, overriding the abstract Initialize() and
|
||||
/// DoAction() methods.
|
||||
/// </summary>
|
||||
/// <typeparam name="TValue">Semantic value type</typeparam>
|
||||
/// <typeparam name="TSpan">Location type</typeparam>
|
||||
#if EXPORT_GPPG
|
||||
public abstract class ShiftReduceParser<TValue, TSpan>
|
||||
#else
|
||||
internal abstract class ShiftReduceParser<TValue, TSpan>
|
||||
#endif
|
||||
where TSpan : IMerge<TSpan>, new() {
|
||||
private AbstractScanner<TValue, TSpan> scanner;
|
||||
/// <summary>
|
||||
/// The abstract scanner for this parser.
|
||||
/// </summary>
|
||||
protected AbstractScanner<TValue, TSpan> Scanner {
|
||||
get { return scanner; }
|
||||
set { scanner = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for base class
|
||||
/// </summary>
|
||||
/// <param name="scanner">Scanner instance for this parser</param>
|
||||
protected ShiftReduceParser( AbstractScanner<TValue, TSpan> scanner ) {
|
||||
this.scanner = scanner;
|
||||
}
|
||||
|
||||
// ==============================================================
|
||||
// TECHNICAL EXPLANATION.
|
||||
// Why the next two fields are not exposed via properties.
|
||||
// ==============================================================
|
||||
// These fields are of the generic parameter types, and are
|
||||
// frequently instantiated as struct types in derived classes.
|
||||
// Semantic actions are defined in the derived classes and refer
|
||||
// to instance fields of these structs. In such cases the code
|
||||
// "get_CurrentSemanticValue().myField = blah;" will fail since
|
||||
// the getter pushes the value of the field, not the reference.
|
||||
// So, in the presence of properties, gppg would need to encode
|
||||
// such field accesses as ...
|
||||
// "tmp = get_CurrentSemanticValue(); // Fetch value
|
||||
// tmp.myField = blah; // update
|
||||
// set_CurrentSemanticValue(tmp); " // Write update back.
|
||||
// There is no issue if TValue is restricted to be a ref type.
|
||||
// The same explanation applies to scanner.yylval.
|
||||
// ==============================================================
|
||||
/// <summary>
|
||||
/// The current value of the "$$" symbolic variable in the parser
|
||||
/// </summary>
|
||||
[SuppressMessage( "Microsoft.Design", "CA1051:DoNotDeclareVisibleInstanceFields" )]
|
||||
protected TValue CurrentSemanticValue;
|
||||
|
||||
/// <summary>
|
||||
/// The current value of the "@$" symbolic variable in the parser
|
||||
/// </summary>
|
||||
[SuppressMessage( "Microsoft.Design", "CA1051:DoNotDeclareVisibleInstanceFields" )]
|
||||
protected TSpan CurrentLocationSpan;
|
||||
protected int NextToken;
|
||||
|
||||
private TSpan LastSpan;
|
||||
private State FsaState;
|
||||
private bool recovering;
|
||||
private int tokensSinceLastError;
|
||||
|
||||
private PushdownPrefixState<State> StateStack = new PushdownPrefixState<State>();
|
||||
private PushdownPrefixState<TValue> valueStack = new PushdownPrefixState<TValue>();
|
||||
private PushdownPrefixState<TSpan> locationStack = new PushdownPrefixState<TSpan>();
|
||||
|
||||
/// <summary>
|
||||
/// The stack of semantic value (YYSTYPE) values.
|
||||
/// </summary>
|
||||
protected PushdownPrefixState<TValue> ValueStack { get { return valueStack; } }
|
||||
|
||||
/// <summary>
|
||||
/// The stack of location value (YYLTYPE) varlues.
|
||||
/// </summary>
|
||||
protected PushdownPrefixState<TSpan> LocationStack { get { return locationStack; } }
|
||||
|
||||
private int errorToken;
|
||||
private int endOfFileToken;
|
||||
private string[] nonTerminals;
|
||||
private State[] states;
|
||||
private Rule[] rules;
|
||||
|
||||
/// <summary>
|
||||
/// Initialization method to allow derived classes
|
||||
/// to insert the rule list into this base class.
|
||||
/// </summary>
|
||||
/// <param name="rules">The array of Rule objects</param>
|
||||
protected void InitRules( Rule[] rules ) { this.rules = rules; }
|
||||
|
||||
/// <summary>
|
||||
/// Initialization method to allow derived classes to
|
||||
/// insert the states table into this base class.
|
||||
/// </summary>
|
||||
/// <param name="states">The pre-initialized states table</param>
|
||||
protected void InitStates( State[] states ) { this.states = states; }
|
||||
|
||||
/// <summary>
|
||||
/// OBSOLETE FOR VERSION 1.4.0
|
||||
/// </summary>
|
||||
/// <param name="size"></param>
|
||||
protected void InitStateTable( int size ) { states = new State[size]; }
|
||||
|
||||
/// <summary>
|
||||
/// Initialization method to allow derived classes
|
||||
/// to insert the special value for the error and EOF tokens.
|
||||
/// </summary>
|
||||
/// <param name="err">The error state ordinal</param>
|
||||
/// <param name="end">The EOF stat ordinal</param>
|
||||
protected void InitSpecialTokens( int err, int end ) {
|
||||
errorToken = err;
|
||||
endOfFileToken = end;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialization method to allow derived classes to
|
||||
/// insert the non-terminal symbol names into this base class.
|
||||
/// </summary>
|
||||
/// <param name="names">Non-terminal symbol names</param>
|
||||
protected void InitNonTerminals( string[] names ) { nonTerminals = names; }
|
||||
|
||||
#region YYAbort, YYAccept etcetera.
|
||||
[Serializable]
|
||||
[SuppressMessage( "Microsoft.Design", "CA1064:ExceptionsShouldBePublic" )]
|
||||
// Reason for FxCop message suppression -
|
||||
// This exception cannot escape from the local context
|
||||
private class AcceptException : Exception {
|
||||
internal AcceptException() { }
|
||||
protected AcceptException( SerializationInfo i, StreamingContext c ) : base( i, c ) { }
|
||||
}
|
||||
[Serializable]
|
||||
[SuppressMessage( "Microsoft.Design", "CA1064:ExceptionsShouldBePublic" )]
|
||||
// Reason for FxCop message suppression -
|
||||
// This exception cannot escape from the local context
|
||||
private class AbortException : Exception {
|
||||
internal AbortException() { }
|
||||
protected AbortException( SerializationInfo i, StreamingContext c ) : base( i, c ) { }
|
||||
}
|
||||
[Serializable]
|
||||
[SuppressMessage( "Microsoft.Design", "CA1064:ExceptionsShouldBePublic" )]
|
||||
// Reason for FxCop message suppression -
|
||||
// This exception cannot escape from the local context
|
||||
private class ErrorException : Exception {
|
||||
internal ErrorException() { }
|
||||
protected ErrorException( SerializationInfo i, StreamingContext c ) : base( i, c ) { }
|
||||
}
|
||||
|
||||
// The following methods are only called from within
|
||||
// a semantic action. The thrown exceptions can never
|
||||
// propagate outside the ShiftReduceParser class in
|
||||
// which they are nested.
|
||||
|
||||
/// <summary>
|
||||
/// Force parser to terminate, returning "true"
|
||||
/// </summary>
|
||||
protected static void YYAccept() { throw new AcceptException(); }
|
||||
|
||||
/// <summary>
|
||||
/// Force parser to terminate, returning "false"
|
||||
/// </summary>
|
||||
protected static void YYAbort() { throw new AbortException(); }
|
||||
|
||||
/// <summary>
|
||||
/// Force parser to terminate, returning
|
||||
/// "false" if error recovery fails.
|
||||
/// </summary>
|
||||
protected static void YYError() { throw new ErrorException(); }
|
||||
|
||||
/// <summary>
|
||||
/// Check if parser in error recovery state.
|
||||
/// </summary>
|
||||
protected bool YYRecovering { get { return recovering; } }
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Abstract base method. ShiftReduceParser calls this
|
||||
/// to initialize the base class data structures. Concrete
|
||||
/// parser classes must override this method.
|
||||
/// </summary>
|
||||
protected abstract void Initialize();
|
||||
|
||||
/// <summary>
|
||||
/// Main entry point of the Shift-Reduce Parser.
|
||||
/// </summary>
|
||||
/// <returns>True if parse succeeds, else false for
|
||||
/// unrecoverable errors</returns>
|
||||
public bool Parse() {
|
||||
Initialize(); // allow derived classes to instantiate rules, states and nonTerminals
|
||||
|
||||
NextToken = 0;
|
||||
FsaState = states[0];
|
||||
|
||||
StateStack.Push( FsaState );
|
||||
valueStack.Push( CurrentSemanticValue );
|
||||
LocationStack.Push( CurrentLocationSpan );
|
||||
|
||||
while (true) {
|
||||
#if TRACE_ACTIONS
|
||||
Console.Error.WriteLine("Entering state {0} ", FsaState.number);
|
||||
DisplayStack();
|
||||
#endif
|
||||
int action = FsaState.defaultAction;
|
||||
|
||||
if (FsaState.ParserTable != null) {
|
||||
if (NextToken == 0) {
|
||||
// We save the last token span, so that the location span
|
||||
// of production right hand sides that begin or end with a
|
||||
// nullable production will be correct.
|
||||
LastSpan = scanner.yylloc;
|
||||
NextToken = scanner.yylex();
|
||||
#if TRACE_ACTIONS
|
||||
Console.Error.WriteLine( "Reading: Next token is {0}", TerminalToString( NextToken ) );
|
||||
#endif
|
||||
}
|
||||
#if TRACE_ACTIONS
|
||||
else
|
||||
Console.Error.WriteLine( "Next token is still {0}", TerminalToString( NextToken ) );
|
||||
#endif
|
||||
if (FsaState.ParserTable.ContainsKey( NextToken ))
|
||||
action = FsaState.ParserTable[NextToken];
|
||||
}
|
||||
|
||||
if (action > 0) // shift
|
||||
{
|
||||
Shift( action );
|
||||
}
|
||||
else if (action < 0) // reduce
|
||||
{
|
||||
try {
|
||||
Reduce( -action );
|
||||
if (action == -1) // accept
|
||||
return true;
|
||||
}
|
||||
catch (AbortException) {
|
||||
return false;
|
||||
}
|
||||
catch (AcceptException) {
|
||||
return true;
|
||||
}
|
||||
catch (ErrorException) {
|
||||
if (!ErrorRecovery())
|
||||
return false;
|
||||
else
|
||||
throw; // Rethrow x, preserving information.
|
||||
}
|
||||
}
|
||||
else if (action == 0 && !ErrorRecovery()) // error
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void Shift( int stateIndex ) {
|
||||
#if TRACE_ACTIONS
|
||||
Console.Error.Write("Shifting token {0}, ", TerminalToString(NextToken));
|
||||
#endif
|
||||
FsaState = states[stateIndex];
|
||||
|
||||
valueStack.Push( scanner.yylval );
|
||||
StateStack.Push( FsaState );
|
||||
LocationStack.Push( scanner.yylloc );
|
||||
|
||||
if (recovering) {
|
||||
if (NextToken != errorToken)
|
||||
tokensSinceLastError++;
|
||||
|
||||
if (tokensSinceLastError > 5)
|
||||
recovering = false;
|
||||
}
|
||||
|
||||
if (NextToken != endOfFileToken)
|
||||
NextToken = 0;
|
||||
}
|
||||
|
||||
private void Reduce( int ruleNumber ) {
|
||||
#if TRACE_ACTIONS
|
||||
DisplayRule(ruleNumber);
|
||||
#endif
|
||||
Rule rule = rules[ruleNumber];
|
||||
int rhLen = rule.RightHandSide.Length;
|
||||
//
|
||||
// Default actions for unit productions.
|
||||
//
|
||||
if (rhLen == 1) {
|
||||
CurrentSemanticValue = valueStack.TopElement(); // Default action: $$ = $1;
|
||||
CurrentLocationSpan = LocationStack.TopElement(); // Default action "@$ = @1;
|
||||
}
|
||||
else if (rhLen == 0) {
|
||||
// Create a new blank value.
|
||||
// Explicit semantic action may mutate this value
|
||||
CurrentSemanticValue = default( TValue );
|
||||
// The location span for an empty production will start with the
|
||||
// beginning of the next lexeme, and end with the finish of the
|
||||
// previous lexeme. This gives the correct behaviour when this
|
||||
// nonsense value is used in later Merge operations.
|
||||
CurrentLocationSpan = (scanner.yylloc != null && LastSpan != null ?
|
||||
scanner.yylloc.Merge( LastSpan ) :
|
||||
default( TSpan ));
|
||||
}
|
||||
else {
|
||||
// Default action: $$ = $1;
|
||||
CurrentSemanticValue = valueStack[LocationStack.Depth - rhLen];
|
||||
// Default action "@$ = @1.Merge(@N)" for location info.
|
||||
TSpan at1 = LocationStack[LocationStack.Depth - rhLen];
|
||||
TSpan atN = LocationStack[LocationStack.Depth - 1];
|
||||
CurrentLocationSpan =
|
||||
((at1 != null && atN != null) ? at1.Merge( atN ) : default( TSpan ));
|
||||
}
|
||||
|
||||
DoAction( ruleNumber );
|
||||
|
||||
for (int i = 0; i < rule.RightHandSide.Length; i++) {
|
||||
StateStack.Pop();
|
||||
valueStack.Pop();
|
||||
LocationStack.Pop();
|
||||
}
|
||||
FsaState = StateStack.TopElement();
|
||||
|
||||
if (FsaState.Goto.ContainsKey( rule.LeftHandSide ))
|
||||
FsaState = states[FsaState.Goto[rule.LeftHandSide]];
|
||||
|
||||
StateStack.Push( FsaState );
|
||||
valueStack.Push( CurrentSemanticValue );
|
||||
LocationStack.Push( CurrentLocationSpan );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Execute the selected action from array.
|
||||
/// Must be overriden in derived classes.
|
||||
/// </summary>
|
||||
/// <param name="actionNumber">Index of the action to perform</param>
|
||||
protected abstract void DoAction( int actionNumber );
|
||||
|
||||
private bool ErrorRecovery() {
|
||||
bool discard;
|
||||
|
||||
if (!recovering) // if not recovering from previous error
|
||||
ReportError();
|
||||
|
||||
if (!FindErrorRecoveryState())
|
||||
return false;
|
||||
//
|
||||
// The interim fix for the "looping in error recovery"
|
||||
// artifact involved moving the setting of the recovering
|
||||
// bool until after invalid tokens have been discarded.
|
||||
//
|
||||
ShiftErrorToken();
|
||||
discard = DiscardInvalidTokens();
|
||||
recovering = true;
|
||||
tokensSinceLastError = 0;
|
||||
return discard;
|
||||
}
|
||||
|
||||
private void ReportError() {
|
||||
StringBuilder errorMsg = new StringBuilder();
|
||||
errorMsg.AppendFormat( "Syntax error, unexpected {0}", TerminalToString( NextToken ) );
|
||||
|
||||
if (FsaState.ParserTable.Count < 7) {
|
||||
bool first = true;
|
||||
foreach (int terminal in FsaState.ParserTable.Keys) {
|
||||
if (first)
|
||||
errorMsg.Append( ", expecting " );
|
||||
else
|
||||
errorMsg.Append( ", or " );
|
||||
|
||||
errorMsg.Append( TerminalToString( terminal ) );
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
scanner.yyerror( errorMsg.ToString() );
|
||||
}
|
||||
|
||||
private void ShiftErrorToken() {
|
||||
int old_next = NextToken;
|
||||
NextToken = errorToken;
|
||||
|
||||
Shift( FsaState.ParserTable[NextToken] );
|
||||
|
||||
#if TRACE_ACTIONS
|
||||
Console.Error.WriteLine("Entering state {0} ", FsaState.number);
|
||||
#endif
|
||||
NextToken = old_next;
|
||||
}
|
||||
|
||||
private bool FindErrorRecoveryState() {
|
||||
while (true) // pop states until one found that accepts error token
|
||||
{
|
||||
if (FsaState.ParserTable != null &&
|
||||
FsaState.ParserTable.ContainsKey( errorToken ) &&
|
||||
FsaState.ParserTable[errorToken] > 0) // shift
|
||||
return true;
|
||||
|
||||
#if TRACE_ACTIONS
|
||||
Console.Error.WriteLine("Error: popping state {0}", StateStack.TopElement().number);
|
||||
#endif
|
||||
StateStack.Pop();
|
||||
valueStack.Pop();
|
||||
LocationStack.Pop();
|
||||
|
||||
#if TRACE_ACTIONS
|
||||
DisplayStack();
|
||||
#endif
|
||||
if (StateStack.IsEmpty()) {
|
||||
#if TRACE_ACTIONS
|
||||
Console.Error.WriteLine("Aborting: didn't find a state that accepts error token");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
else
|
||||
FsaState = StateStack.TopElement();
|
||||
}
|
||||
}
|
||||
|
||||
private bool DiscardInvalidTokens() {
|
||||
|
||||
int action = FsaState.defaultAction;
|
||||
|
||||
if (FsaState.ParserTable != null) {
|
||||
// Discard tokens until find one that works ...
|
||||
while (true) {
|
||||
if (NextToken == 0) {
|
||||
#if TRACE_ACTIONS
|
||||
Console.Error.Write("Reading a token: ");
|
||||
#endif
|
||||
NextToken = scanner.yylex();
|
||||
}
|
||||
#if TRACE_ACTIONS
|
||||
Console.Error.WriteLine("Next token is {0}", TerminalToString(NextToken));
|
||||
#endif
|
||||
if (NextToken == endOfFileToken)
|
||||
return false;
|
||||
|
||||
if (FsaState.ParserTable.ContainsKey( NextToken ))
|
||||
action = FsaState.ParserTable[NextToken];
|
||||
|
||||
if (action != 0)
|
||||
return true;
|
||||
else {
|
||||
#if TRACE_ACTIONS
|
||||
Console.Error.WriteLine("Error: Discarding {0}", TerminalToString(NextToken));
|
||||
#endif
|
||||
NextToken = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (recovering && tokensSinceLastError == 0) {
|
||||
//
|
||||
// Boolean recovering is not set until after the first
|
||||
// error token has been shifted. Thus if we get back
|
||||
// here with recovering set and no tokens read we are
|
||||
// looping on the same error recovery action. This
|
||||
// happens if current_state.ParserTable is null because
|
||||
// the state has an LR(0) reduction, but not all
|
||||
// lookahead tokens are valid. This only occurs for
|
||||
// error productions that *end* on "error".
|
||||
//
|
||||
// This action discards tokens one at a time until
|
||||
// the looping stops. Another attack would be to always
|
||||
// use the LALR(1) table if a production ends on "error"
|
||||
//
|
||||
#if TRACE_ACTIONS
|
||||
Console.Error.WriteLine("Error: panic discard of {0}", TerminalToString(NextToken));
|
||||
#endif
|
||||
if (NextToken == endOfFileToken)
|
||||
return false;
|
||||
NextToken = 0;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Traditional YACC method. Discards the next input token.
|
||||
/// </summary>
|
||||
[SuppressMessage( "Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "yyclearin" )]
|
||||
[SuppressMessage( "Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "yyclearin" )]
|
||||
// Reason for FxCop message suppression -
|
||||
// This is a traditional name for YACC-like functionality
|
||||
protected void yyclearin() { NextToken = 0; }
|
||||
|
||||
/// <summary>
|
||||
/// Tradional YACC method. Clear the "recovering" flag.
|
||||
/// </summary>
|
||||
[SuppressMessage( "Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "yyerrok" )]
|
||||
[SuppressMessage( "Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "yyerrok" )]
|
||||
// Reason for FxCop message suppression -
|
||||
// This is a traditional name for YACC-like functionality
|
||||
protected void yyerrok() { recovering = false; }
|
||||
|
||||
/// <summary>
|
||||
/// OBSOLETE FOR VERSION 1.4.0
|
||||
/// Method used by derived types to insert new
|
||||
/// state instances in the "states" array.
|
||||
/// </summary>
|
||||
/// <param name="stateNumber">index of the state</param>
|
||||
/// <param name="state">data for the state</param>
|
||||
protected void AddState( int stateNumber, State state ) {
|
||||
states[stateNumber] = state;
|
||||
state.number = stateNumber;
|
||||
}
|
||||
|
||||
private void DisplayStack() {
|
||||
Console.Error.Write( "State stack is now:" );
|
||||
for (int i = 0; i < StateStack.Depth; i++)
|
||||
Console.Error.Write( " {0}", StateStack[i].number );
|
||||
Console.Error.WriteLine();
|
||||
}
|
||||
|
||||
private void DisplayRule( int ruleNumber ) {
|
||||
Console.Error.Write( "Reducing stack by rule {0}, ", ruleNumber );
|
||||
DisplayProduction( rules[ruleNumber] );
|
||||
}
|
||||
|
||||
private void DisplayProduction( Rule rule ) {
|
||||
if (rule.RightHandSide.Length == 0)
|
||||
Console.Error.Write( "/* empty */ " );
|
||||
else
|
||||
foreach (int symbol in rule.RightHandSide)
|
||||
Console.Error.Write( "{0} ", SymbolToString( symbol ) );
|
||||
|
||||
Console.Error.WriteLine( "-> {0}", SymbolToString( rule.LeftHandSide ) );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Abstract state class naming terminal symbols.
|
||||
/// This is overridden by derived classes with the
|
||||
/// name (or alias) to be used in error messages.
|
||||
/// </summary>
|
||||
/// <param name="terminal">The terminal ordinal</param>
|
||||
/// <returns></returns>
|
||||
protected abstract string TerminalToString( int terminal );
|
||||
|
||||
private string SymbolToString( int symbol ) {
|
||||
if (symbol < 0)
|
||||
return nonTerminals[-symbol - 1];
|
||||
else
|
||||
return TerminalToString( symbol );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return text representation of argument character
|
||||
/// </summary>
|
||||
/// <param name="input">The character to convert</param>
|
||||
/// <returns>String representation of the character</returns>
|
||||
protected static string CharToString( char input ) {
|
||||
switch (input) {
|
||||
case '\a': return @"'\a'";
|
||||
case '\b': return @"'\b'";
|
||||
case '\f': return @"'\f'";
|
||||
case '\n': return @"'\n'";
|
||||
case '\r': return @"'\r'";
|
||||
case '\t': return @"'\t'";
|
||||
case '\v': return @"'\v'";
|
||||
case '\0': return @"'\0'";
|
||||
default: return string.Format( CultureInfo.InvariantCulture, "'{0}'", input );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Classes implementing this interface must supply a
|
||||
/// method that merges two location objects to return
|
||||
/// a new object of the same type.
|
||||
/// GPPG-generated parsers have the default location
|
||||
/// action equivalent to "@$ = @1.Merge(@N);" where N
|
||||
/// is the right-hand-side length of the production.
|
||||
/// </summary>
|
||||
/// <typeparam name="TSpan">The Location type</typeparam>
|
||||
#if EXPORT_GPPG
|
||||
public interface IMerge<TSpan>
|
||||
#else
|
||||
internal interface IMerge<TSpan>
|
||||
#endif
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface method that creates a location object from
|
||||
/// the current and last object. Typically used to create
|
||||
/// a location object extending from the start of the @1
|
||||
/// object to the end of the @N object.
|
||||
/// </summary>
|
||||
/// <param name="last">The lexically last object to merge</param>
|
||||
/// <returns>The merged location object</returns>
|
||||
TSpan Merge( TSpan last );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is the default class that carries location
|
||||
/// information from the scanner to the parser.
|
||||
/// If you don't declare "%YYLTYPE Foo" the parser
|
||||
/// will expect to deal with this type.
|
||||
/// </summary>
|
||||
#if EXPORT_GPPG
|
||||
public class LexLocation : IMerge<LexLocation>
|
||||
#else
|
||||
[SuppressMessage( "Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses" )]
|
||||
internal class LexLocation : IMerge<LexLocation>
|
||||
#endif
|
||||
{
|
||||
private int startLine; // start line
|
||||
private int startColumn; // start column
|
||||
private int endLine; // end line
|
||||
private int endColumn; // end column
|
||||
|
||||
/// <summary>
|
||||
/// The line at which the text span starts.
|
||||
/// </summary>
|
||||
public int StartLine { get { return startLine; } }
|
||||
|
||||
/// <summary>
|
||||
/// The column at which the text span starts.
|
||||
/// </summary>
|
||||
public int StartColumn { get { return startColumn; } }
|
||||
|
||||
/// <summary>
|
||||
/// The line on which the text span ends.
|
||||
/// </summary>
|
||||
public int EndLine { get { return endLine; } }
|
||||
|
||||
/// <summary>
|
||||
/// The column of the first character
|
||||
/// beyond the end of the text span.
|
||||
/// </summary>
|
||||
public int EndColumn { get { return endColumn; } }
|
||||
|
||||
/// <summary>
|
||||
/// Default no-arg constructor.
|
||||
/// </summary>
|
||||
public LexLocation() { }
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for text-span with given start and end.
|
||||
/// </summary>
|
||||
/// <param name="sl">start line</param>
|
||||
/// <param name="sc">start column</param>
|
||||
/// <param name="el">end line </param>
|
||||
/// <param name="ec">end column</param>
|
||||
public LexLocation( int sl, int sc, int el, int ec ) { startLine = sl; startColumn = sc; endLine = el; endColumn = ec; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a text location which spans from the
|
||||
/// start of "this" to the end of the argument "last"
|
||||
/// </summary>
|
||||
/// <param name="last">The last location in the result span</param>
|
||||
/// <returns>The merged span</returns>
|
||||
public LexLocation Merge( LexLocation last ) { return new LexLocation( this.startLine, this.startColumn, last.endLine, last.endColumn ); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Abstract scanner class that GPPG expects its scanners to
|
||||
/// extend.
|
||||
/// </summary>
|
||||
/// <typeparam name="TValue">Semantic value type YYSTYPE</typeparam>
|
||||
/// <typeparam name="TSpan">Source location type YYLTYPE</typeparam>
|
||||
#if EXPORT_GPPG
|
||||
public abstract class AbstractScanner<TValue, TSpan>
|
||||
#else
|
||||
internal abstract class AbstractScanner<TValue, TSpan>
|
||||
#endif
|
||||
where TSpan : IMerge<TSpan> {
|
||||
/// <summary>
|
||||
/// Lexical value optionally set by the scanner. The value
|
||||
/// is of the %YYSTYPE type declared in the parser spec.
|
||||
/// </summary>
|
||||
[SuppressMessage( "Microsoft.Design", "CA1051:DoNotDeclareVisibleInstanceFields" )]
|
||||
[SuppressMessage( "Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "yylval" )]
|
||||
[SuppressMessage( "Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "yylval" )]
|
||||
// Reason for FxCop message suppression -
|
||||
// This is a traditional name for YACC-like functionality
|
||||
// A field must be declared for this value of parametric type,
|
||||
// since it may be instantiated by a value struct. If it were
|
||||
// implemented as a property, machine generated code in derived
|
||||
// types would not be able to select on the returned value.
|
||||
#pragma warning disable 649
|
||||
public TValue yylval; // Lexical value: set by scanner
|
||||
#pragma warning restore 649
|
||||
|
||||
/// <summary>
|
||||
/// Current scanner location property. The value is of the
|
||||
/// type declared by %YYLTYPE in the parser specification.
|
||||
/// </summary>
|
||||
[SuppressMessage( "Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "yylloc" )]
|
||||
[SuppressMessage( "Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "yylloc" )]
|
||||
// Reason for FxCop message suppression -
|
||||
// This is a traditional name for YACC-like functionality
|
||||
public virtual TSpan yylloc {
|
||||
get { return default( TSpan ); } // Empty implementation allowing
|
||||
set { /* skip */ } // yylloc to be ignored entirely.
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Main call point for LEX-like scanners. Returns an int
|
||||
/// corresponding to the token recognized by the scanner.
|
||||
/// </summary>
|
||||
/// <returns>An int corresponding to the token</returns>
|
||||
[SuppressMessage( "Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "yylex" )]
|
||||
[SuppressMessage( "Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "yylex" )]
|
||||
// Reason for FxCop message suppression -
|
||||
// This is a traditional name for YACC-like functionality
|
||||
public abstract int yylex();
|
||||
|
||||
/// <summary>
|
||||
/// Traditional error reporting provided by LEX-like scanners
|
||||
/// to their YACC-like clients.
|
||||
/// </summary>
|
||||
/// <param name="format">Message format string</param>
|
||||
/// <param name="args">Optional array of args</param>
|
||||
[SuppressMessage( "Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "yyerror" )]
|
||||
[SuppressMessage( "Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "yyerror" )]
|
||||
// Reason for FxCop message suppression -
|
||||
// This is a traditional name for YACC-like functionality
|
||||
public virtual void yyerror( string format, params object[] args ) { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Encapsulated state for the parser.
|
||||
/// Opaque to users, visible to the tool-generated code.
|
||||
/// </summary>
|
||||
#if EXPORT_GPPG
|
||||
public class State
|
||||
{
|
||||
/// <summary>
|
||||
/// The number of states in the automaton.
|
||||
/// </summary>
|
||||
public int number;
|
||||
#else
|
||||
internal class State {
|
||||
/// <summary>
|
||||
/// The index of this state in the states array.
|
||||
/// </summary>
|
||||
internal int number;
|
||||
#endif
|
||||
internal Dictionary<int, int> ParserTable; // Terminal -> ParseAction
|
||||
internal Dictionary<int, int> Goto; // NonTerminal -> State;
|
||||
internal int defaultAction; // = 0; // ParseAction
|
||||
|
||||
/// <summary>
|
||||
/// State transition data for this state. Pairs of elements of the
|
||||
/// goto array associate symbol ordinals with next state indices.
|
||||
/// The actions array is passed to another constructor.
|
||||
/// </summary>
|
||||
/// <param name="actions">The action list</param>c
|
||||
/// <param name="goToList">Next state data</param>
|
||||
public State( int[] actions, int[] goToList )
|
||||
: this( actions ) {
|
||||
Goto = new Dictionary<int, int>();
|
||||
for (int i = 0; i < goToList.Length; i += 2)
|
||||
Goto.Add( goToList[i], goToList[i + 1] );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Action data for this state. Pairs of elements of the
|
||||
/// action array associate action ordinals with each of
|
||||
/// those symbols that have actions in the current state.
|
||||
/// </summary>
|
||||
/// <param name="actions">The action array</param>
|
||||
public State( int[] actions ) {
|
||||
ParserTable = new Dictionary<int, int>();
|
||||
for (int i = 0; i < actions.Length; i += 2)
|
||||
ParserTable.Add( actions[i], actions[i + 1] );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the default action for this state.
|
||||
/// </summary>
|
||||
/// <param name="defaultAction">Ordinal of the default action</param>
|
||||
public State( int defaultAction ) {
|
||||
this.defaultAction = defaultAction;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the default action and the state transition table.
|
||||
/// </summary>
|
||||
/// <param name="defaultAction">The default action</param>
|
||||
/// <param name="goToList">Transitions from this state</param>
|
||||
public State( int defaultAction, int[] goToList )
|
||||
: this( defaultAction ) {
|
||||
Goto = new Dictionary<int, int>();
|
||||
for (int i = 0; i < goToList.Length; i += 2)
|
||||
Goto.Add( goToList[i], goToList[i + 1] );
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rule representation at runtime.
|
||||
/// </summary>
|
||||
#if EXPORT_GPPG
|
||||
public class Rule
|
||||
#else
|
||||
internal class Rule
|
||||
#endif
|
||||
{
|
||||
internal int LeftHandSide; // symbol
|
||||
internal int[] RightHandSide; // symbols
|
||||
|
||||
/// <summary>
|
||||
/// Rule constructor. This holds the ordinal of
|
||||
/// the left hand side symbol, and the list of
|
||||
/// right hand side symbols, in lexical order.
|
||||
/// </summary>
|
||||
/// <param name="left">The LHS non-terminal</param>
|
||||
/// <param name="right">The RHS symbols, in lexical order</param>
|
||||
public Rule( int left, int[] right ) {
|
||||
this.LeftHandSide = left;
|
||||
this.RightHandSide = right;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stack utility for the shift-reduce parser.
|
||||
/// GPPG parsers have three instances:
|
||||
/// (1) The parser state stack, T = QUT.Gppg.State,
|
||||
/// (2) The semantic value stack, T = TValue,
|
||||
/// (3) The location stack, T = TSpan.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
#if EXPORT_GPPG
|
||||
public class PushdownPrefixState<T>
|
||||
#else
|
||||
internal class PushdownPrefixState<T>
|
||||
#endif
|
||||
{
|
||||
// Note that we cannot use the BCL Stack<T> class
|
||||
// here as derived types need to index into stacks.
|
||||
//
|
||||
private T[] array = new T[8];
|
||||
private int tos = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Indexer for values of the stack below the top.
|
||||
/// </summary>
|
||||
/// <param name="index">index of the element, starting from the bottom</param>
|
||||
/// <returns>the selected element</returns>
|
||||
public T this[int index] { get { return array[index]; } }
|
||||
|
||||
/// <summary>
|
||||
/// The current depth of the stack.
|
||||
/// </summary>
|
||||
public int Depth { get { return tos; } }
|
||||
|
||||
internal void Push( T value ) {
|
||||
if (tos >= array.Length) {
|
||||
T[] newarray = new T[array.Length * 2];
|
||||
System.Array.Copy( array, newarray, tos );
|
||||
array = newarray;
|
||||
}
|
||||
array[tos++] = value;
|
||||
}
|
||||
|
||||
internal T Pop() {
|
||||
T rslt = array[--tos];
|
||||
array[tos] = default( T );
|
||||
return rslt;
|
||||
}
|
||||
|
||||
internal T TopElement() { return array[tos - 1]; }
|
||||
|
||||
internal bool IsEmpty() { return tos == 0; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
global using System;
|
||||
global using System.Linq;
|
||||
global using System.Collections.Generic;
|
||||
global using System.Collections.Immutable;
|
||||
@@ -0,0 +1,24 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="YaccLexTools" Version="1.2.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\DataStreamCore\DataStreamCore.csproj" />
|
||||
<ProjectReference Include="..\ExpressionCore\ExpressionCore.csproj" />
|
||||
<ProjectReference Include="..\..\client\spark_core\spark_core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Label="ColumnSortExpression">
|
||||
<Scanner Include="ColumnSortExpressionTokens.lex" />
|
||||
<Parser Include="ColumnSortExpressionGrammar.y" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,11 @@
|
||||
namespace Bts.ColumnSortExpressions;
|
||||
|
||||
public class ColumnSortExpression {
|
||||
public ColumnSortExpression(string name, bool isAscending = true) {
|
||||
Name = name;
|
||||
IsAscending = isAscending;
|
||||
}
|
||||
|
||||
public string Name { get; }
|
||||
public bool IsAscending { get; }
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
%namespace Bts.ColumnSortExpressions
|
||||
%partial
|
||||
%visibility internal
|
||||
%tokentype ColumnSortExpressionToken
|
||||
%parsertype ColumnSortExpressionParser
|
||||
|
||||
%union {
|
||||
public string Identifier;
|
||||
public ColumnSortExpression Column;
|
||||
public ImmutableList<ColumnSortExpression> Columns;
|
||||
}
|
||||
|
||||
%token ASCENDING, DESCENDING, IDENTIFIER
|
||||
|
||||
%type <Column> Column
|
||||
%type <Columns> Columns
|
||||
|
||||
%%
|
||||
|
||||
Columns :
|
||||
Column { $$ = ImmutableList.CreateRange(new[] { $1 }); }
|
||||
| Columns Column { $$ = $1.Add($2); }
|
||||
;
|
||||
|
||||
Column :
|
||||
IDENTIFIER { $$ = new($1.Identifier, true); }
|
||||
| ASCENDING IDENTIFIER { $$ = new($2.Identifier, true); }
|
||||
| DESCENDING IDENTIFIER { $$ = new($2.Identifier, false); }
|
||||
;
|
||||
@@ -0,0 +1,18 @@
|
||||
namespace Bts.ColumnSortExpressions;
|
||||
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
public class ColumnSortExpressionInterpreter {
|
||||
public static IList<ColumnSortExpression> Evaluate(Stream stream) {
|
||||
var parser = new ColumnSortExpressionParser();
|
||||
var res = parser.Parse(stream);
|
||||
return res?.Columns ?? ImmutableList<ColumnSortExpression>.Empty.Add(
|
||||
res?.Column ?? throw new Exception("Failed to parse column(s) expression"));
|
||||
}
|
||||
|
||||
public static IList<ColumnSortExpression> Evaluate(string str) {
|
||||
using var ms = new MemoryStream(Encoding.Default.GetBytes(str));
|
||||
return Evaluate(ms);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
namespace Bts.ColumnSortExpressions;
|
||||
|
||||
using System.Text;
|
||||
|
||||
partial class ColumnSortExpressionParser {
|
||||
public ColumnSortExpressionParser() : base(null) { }
|
||||
|
||||
public ValueType? Parse(string s) {
|
||||
using var ms = new MemoryStream(Encoding.Default.GetBytes(s));
|
||||
return Parse(ms);
|
||||
}
|
||||
|
||||
public ValueType? Parse(Stream stream) {
|
||||
Scanner = new ColumnSortExpressionScanner(stream);
|
||||
Parse();
|
||||
return CurrentSemanticValue;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace Bts.ColumnSortExpressions;
|
||||
|
||||
partial class ColumnSortExpressionScanner {
|
||||
public override void yyerror(string format, params object[] args) {
|
||||
base.yyerror(format, args);
|
||||
Console.WriteLine(format, args);
|
||||
Console.WriteLine();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
%namespace Bts.ColumnSortExpressions
|
||||
%scannertype ColumnSortExpressionScanner
|
||||
%visibility internal
|
||||
%tokentype ColumnSortExpressionToken
|
||||
|
||||
%option stack, minimize, parser, verbose, persistbuffer, noembedbuffers
|
||||
|
||||
/* Literal Constants */
|
||||
Letter [a-zA-Z]
|
||||
|
||||
Identifier {Letter}({Letter}*[0-9]*_*)*
|
||||
Ascending +
|
||||
Descending -
|
||||
|
||||
%%
|
||||
|
||||
{Ascending} {
|
||||
return (int)ColumnSortExpressionToken.ASCENDING;
|
||||
}
|
||||
|
||||
{Descending} {
|
||||
return (int)ColumnSortExpressionToken.DESCENDING;
|
||||
}
|
||||
|
||||
{Identifier} {
|
||||
yylval.Identifier = yytext;
|
||||
return (int)ColumnSortExpressionToken.IDENTIFIER;
|
||||
}
|
||||
|
||||
%%
|
||||
@@ -0,0 +1,720 @@
|
||||
// ==============================================================
|
||||
// <auto-generated>
|
||||
// This code automatically produced from an embedded resource.
|
||||
// Do not edit this file, or it will become incompatible with
|
||||
// the specification from which it was generated.
|
||||
// </auto-generated>
|
||||
// ==============================================================
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Globalization;
|
||||
|
||||
namespace QUT.GplexBuffers
|
||||
{
|
||||
// Code copied from GPLEX embedded resource
|
||||
[Serializable]
|
||||
internal class BufferException : Exception
|
||||
{
|
||||
public BufferException() { }
|
||||
public BufferException(string message) : base(message) { }
|
||||
public BufferException(string message, Exception innerException)
|
||||
: base(message, innerException) { }
|
||||
protected BufferException(SerializationInfo info, StreamingContext context)
|
||||
: base(info, context) { }
|
||||
}
|
||||
|
||||
internal abstract class ScanBuff
|
||||
{
|
||||
private string fileNm;
|
||||
|
||||
public const int EndOfFile = -1;
|
||||
public const int UnicodeReplacementChar = 0xFFFD;
|
||||
|
||||
public bool IsFile { get { return (fileNm != null); } }
|
||||
public string FileName { get { return fileNm; } set { fileNm = value; } }
|
||||
|
||||
public abstract int Pos { get; set; }
|
||||
public abstract int Read();
|
||||
public virtual void Mark() { }
|
||||
|
||||
public abstract string GetString(int begin, int limit);
|
||||
|
||||
public static ScanBuff GetBuffer(string source)
|
||||
{
|
||||
return new StringBuffer(source);
|
||||
}
|
||||
|
||||
public static ScanBuff GetBuffer(IList<string> source)
|
||||
{
|
||||
return new LineBuffer(source);
|
||||
}
|
||||
|
||||
#if (!NOFILES)
|
||||
public static ScanBuff GetBuffer(Stream source)
|
||||
{
|
||||
return new BuildBuffer(source);
|
||||
}
|
||||
|
||||
#if (!BYTEMODE)
|
||||
public static ScanBuff GetBuffer(Stream source, int fallbackCodePage)
|
||||
{
|
||||
return new BuildBuffer(source, fallbackCodePage);
|
||||
}
|
||||
#endif // !BYTEMODE
|
||||
#endif // !NOFILES
|
||||
}
|
||||
|
||||
#region Buffer classes
|
||||
|
||||
// ==============================================================
|
||||
// ===== Definitions for various ScanBuff derived classes ====
|
||||
// ==============================================================
|
||||
// =============== String input ================
|
||||
// ==============================================================
|
||||
|
||||
/// <summary>
|
||||
/// This class reads characters from a single string as
|
||||
/// required, for example, by Visual Studio language services
|
||||
/// </summary>
|
||||
sealed class StringBuffer : ScanBuff
|
||||
{
|
||||
string str; // input buffer
|
||||
int bPos; // current position in buffer
|
||||
int sLen;
|
||||
|
||||
public StringBuffer(string source)
|
||||
{
|
||||
this.str = source;
|
||||
this.sLen = source.Length;
|
||||
this.FileName = null;
|
||||
}
|
||||
|
||||
public override int Read()
|
||||
{
|
||||
if (bPos < sLen) return str[bPos++];
|
||||
else if (bPos == sLen) { bPos++; return '\n'; } // one strike, see new line
|
||||
else { bPos++; return EndOfFile; } // two strikes and you're out!
|
||||
}
|
||||
|
||||
public override string GetString(int begin, int limit)
|
||||
{
|
||||
// "limit" can be greater than sLen with the BABEL
|
||||
// option set. Read returns a "virtual" EOL if
|
||||
// an attempt is made to read past the end of the
|
||||
// string buffer. Without the guard any attempt
|
||||
// to fetch yytext for a token that includes the
|
||||
// EOL will throw an index exception.
|
||||
if (limit > sLen) limit = sLen;
|
||||
if (limit <= begin) return "";
|
||||
else return str.Substring(begin, limit - begin);
|
||||
}
|
||||
|
||||
public override int Pos
|
||||
{
|
||||
get { return bPos; }
|
||||
set { bPos = value; }
|
||||
}
|
||||
|
||||
public override string ToString() { return "StringBuffer"; }
|
||||
}
|
||||
|
||||
// ==============================================================
|
||||
// The LineBuff class contributed by Nigel Horspool,
|
||||
// nigelh@cs.uvic.cs
|
||||
// ==============================================================
|
||||
|
||||
sealed class LineBuffer : ScanBuff
|
||||
{
|
||||
IList<string> line; // list of source lines from a file
|
||||
int numLines; // number of strings in line list
|
||||
string curLine; // current line in that list
|
||||
int cLine; // index of current line in the list
|
||||
int curLen; // length of current line
|
||||
int curLineStart; // position of line start in whole file
|
||||
int curLineEnd; // position of line end in whole file
|
||||
int maxPos; // max position ever visited in whole file
|
||||
int cPos; // ordinal number of code in source
|
||||
|
||||
// Constructed from a list of strings, one per source line.
|
||||
// The lines have had trailing '\n' characters removed.
|
||||
public LineBuffer(IList<string> lineList)
|
||||
{
|
||||
line = lineList;
|
||||
numLines = line.Count;
|
||||
cPos = curLineStart = 0;
|
||||
curLine = (numLines > 0 ? line[0] : "");
|
||||
maxPos = curLineEnd = curLen = curLine.Length;
|
||||
cLine = 1;
|
||||
FileName = null;
|
||||
}
|
||||
|
||||
public override int Read()
|
||||
{
|
||||
if (cPos < curLineEnd)
|
||||
return curLine[cPos++ - curLineStart];
|
||||
if (cPos++ == curLineEnd)
|
||||
return '\n';
|
||||
if (cLine >= numLines)
|
||||
return EndOfFile;
|
||||
curLine = line[cLine];
|
||||
curLen = curLine.Length;
|
||||
curLineStart = curLineEnd + 1;
|
||||
curLineEnd = curLineStart + curLen;
|
||||
if (curLineEnd > maxPos)
|
||||
maxPos = curLineEnd;
|
||||
cLine++;
|
||||
return curLen > 0 ? curLine[0] : '\n';
|
||||
}
|
||||
|
||||
// To speed up searches for the line containing a position
|
||||
private int cachedPosition;
|
||||
private int cachedIxdex;
|
||||
private int cachedLineStart;
|
||||
|
||||
// Given a position pos within the entire source, the results are
|
||||
// ix -- the index of the containing line
|
||||
// lstart -- the position of the first character on that line
|
||||
private void findIndex(int pos, out int ix, out int lstart)
|
||||
{
|
||||
if (pos >= cachedPosition)
|
||||
{
|
||||
ix = cachedIxdex; lstart = cachedLineStart;
|
||||
}
|
||||
else
|
||||
{
|
||||
ix = lstart = 0;
|
||||
}
|
||||
while (ix < numLines)
|
||||
{
|
||||
int len = line[ix].Length + 1;
|
||||
if (pos < lstart + len) break;
|
||||
lstart += len;
|
||||
ix++;
|
||||
}
|
||||
cachedPosition = pos;
|
||||
cachedIxdex = ix;
|
||||
cachedLineStart = lstart;
|
||||
}
|
||||
|
||||
public override string GetString(int begin, int limit)
|
||||
{
|
||||
if (begin >= maxPos || limit <= begin) return "";
|
||||
int endIx, begIx, endLineStart, begLineStart;
|
||||
findIndex(begin, out begIx, out begLineStart);
|
||||
int begCol = begin - begLineStart;
|
||||
findIndex(limit, out endIx, out endLineStart);
|
||||
int endCol = limit - endLineStart;
|
||||
string s = line[begIx];
|
||||
if (begIx == endIx)
|
||||
{
|
||||
// the usual case, substring all on one line
|
||||
return (endCol <= s.Length) ?
|
||||
s.Substring(begCol, endCol - begCol)
|
||||
: s.Substring(begCol) + "\n";
|
||||
}
|
||||
// the string spans multiple lines, yuk!
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (begCol < s.Length)
|
||||
sb.Append(s.Substring(begCol));
|
||||
for (; ; )
|
||||
{
|
||||
sb.Append("\n");
|
||||
s = line[++begIx];
|
||||
if (begIx >= endIx) break;
|
||||
sb.Append(s);
|
||||
}
|
||||
if (endCol <= s.Length)
|
||||
{
|
||||
sb.Append(s.Substring(0, endCol));
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.Append(s);
|
||||
sb.Append("\n");
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public override int Pos
|
||||
{
|
||||
get { return cPos; }
|
||||
set
|
||||
{
|
||||
cPos = value;
|
||||
findIndex(cPos, out cLine, out curLineStart);
|
||||
// cLine should be the *next* line after curLine.
|
||||
curLine = (cLine < numLines ? line[cLine++] : "");
|
||||
curLineEnd = curLineStart + curLine.Length;
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString() { return "LineBuffer"; }
|
||||
}
|
||||
|
||||
#if (!NOFILES)
|
||||
// ==============================================================
|
||||
// ===== class BuildBuff : for unicode text files ========
|
||||
// ==============================================================
|
||||
|
||||
class BuildBuffer : ScanBuff
|
||||
{
|
||||
// Double buffer for char stream.
|
||||
class BufferElement
|
||||
{
|
||||
StringBuilder bldr = new StringBuilder();
|
||||
StringBuilder next = new StringBuilder();
|
||||
int minIx;
|
||||
int maxIx;
|
||||
int brkIx;
|
||||
bool appendToNext;
|
||||
|
||||
internal BufferElement() { }
|
||||
|
||||
internal int MaxIndex { get { return maxIx; } }
|
||||
// internal int MinIndex { get { return minIx; } }
|
||||
|
||||
internal char this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (index < minIx || index >= maxIx)
|
||||
throw new BufferException("Index was outside data buffer");
|
||||
else if (index < brkIx)
|
||||
return bldr[index - minIx];
|
||||
else
|
||||
return next[index - brkIx];
|
||||
}
|
||||
}
|
||||
|
||||
internal void Append(char[] block, int count)
|
||||
{
|
||||
maxIx += count;
|
||||
if (appendToNext)
|
||||
this.next.Append(block, 0, count);
|
||||
else
|
||||
{
|
||||
this.bldr.Append(block, 0, count);
|
||||
brkIx = maxIx;
|
||||
appendToNext = true;
|
||||
}
|
||||
}
|
||||
|
||||
internal string GetString(int start, int limit)
|
||||
{
|
||||
if (limit <= start)
|
||||
return "";
|
||||
if (start >= minIx && limit <= maxIx)
|
||||
if (limit < brkIx) // String entirely in bldr builder
|
||||
return bldr.ToString(start - minIx, limit - start);
|
||||
else if (start >= brkIx) // String entirely in next builder
|
||||
return next.ToString(start - brkIx, limit - start);
|
||||
else // Must do a string-concatenation
|
||||
return
|
||||
bldr.ToString(start - minIx, brkIx - start) +
|
||||
next.ToString(0, limit - brkIx);
|
||||
else
|
||||
throw new BufferException("String was outside data buffer");
|
||||
}
|
||||
|
||||
internal void Mark(int limit)
|
||||
{
|
||||
if (limit > brkIx + 16) // Rotate blocks
|
||||
{
|
||||
StringBuilder temp = bldr;
|
||||
bldr = next;
|
||||
next = temp;
|
||||
next.Length = 0;
|
||||
minIx = brkIx;
|
||||
brkIx = maxIx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BufferElement data = new BufferElement();
|
||||
|
||||
int bPos; // Postion index in the StringBuilder
|
||||
BlockReader NextBlk; // Delegate that serves char-arrays;
|
||||
|
||||
private string EncodingName
|
||||
{
|
||||
get
|
||||
{
|
||||
StreamReader rdr = NextBlk.Target as StreamReader;
|
||||
return (rdr == null ? "raw-bytes" : rdr.CurrentEncoding.BodyName);
|
||||
}
|
||||
}
|
||||
|
||||
public BuildBuffer(Stream stream)
|
||||
{
|
||||
FileStream fStrm = (stream as FileStream);
|
||||
if (fStrm != null) FileName = fStrm.Name;
|
||||
NextBlk = BlockReaderFactory.Raw(stream);
|
||||
}
|
||||
|
||||
#if (!BYTEMODE)
|
||||
public BuildBuffer(Stream stream, int fallbackCodePage)
|
||||
{
|
||||
FileStream fStrm = (stream as FileStream);
|
||||
if (fStrm != null) FileName = fStrm.Name;
|
||||
NextBlk = BlockReaderFactory.Get(stream, fallbackCodePage);
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Marks a conservative lower bound for the buffer,
|
||||
/// allowing space to be reclaimed. If an application
|
||||
/// needs to call GetString at arbitrary past locations
|
||||
/// in the input stream, Mark() is not called.
|
||||
/// </summary>
|
||||
public override void Mark() { data.Mark(bPos - 2); }
|
||||
|
||||
public override int Pos
|
||||
{
|
||||
get { return bPos; }
|
||||
set { bPos = value; }
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Read returns the ordinal number of the next char, or
|
||||
/// EOF (-1) for an end of stream. Note that the next
|
||||
/// code point may require *two* calls of Read().
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override int Read()
|
||||
{
|
||||
//
|
||||
// Characters at positions
|
||||
// [data.offset, data.offset + data.bldr.Length)
|
||||
// are available in data.bldr.
|
||||
//
|
||||
if (bPos < data.MaxIndex)
|
||||
{
|
||||
// ch0 cannot be EOF
|
||||
return (int)data[bPos++];
|
||||
}
|
||||
else // Read from underlying stream
|
||||
{
|
||||
// Experimental code, blocks of page size
|
||||
char[] chrs = new char[4096];
|
||||
int count = NextBlk(chrs, 0, 4096);
|
||||
if (count == 0)
|
||||
return EndOfFile;
|
||||
else
|
||||
{
|
||||
data.Append(chrs, count);
|
||||
return (int)data[bPos++];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override string GetString(int begin, int limit)
|
||||
{
|
||||
return data.GetString(begin, limit);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "StringBuilder buffer, encoding: " + this.EncodingName;
|
||||
}
|
||||
}
|
||||
|
||||
// =============== End ScanBuff-derived classes ==================
|
||||
|
||||
internal delegate int BlockReader(char[] block, int index, int number);
|
||||
|
||||
// A delegate factory, serving up a delegate that
|
||||
// reads a block of characters from the underlying
|
||||
// encoded stream, via a StreamReader object.
|
||||
//
|
||||
internal static class BlockReaderFactory
|
||||
{
|
||||
public static BlockReader Raw(Stream stream)
|
||||
{
|
||||
return delegate(char[] block, int index, int number)
|
||||
{
|
||||
byte[] b = new byte[number];
|
||||
int count = stream.Read(b, 0, number);
|
||||
int i = 0;
|
||||
int j = index;
|
||||
for (; i < count; i++, j++)
|
||||
block[j] = (char)b[i];
|
||||
return count;
|
||||
};
|
||||
}
|
||||
|
||||
#if (!BYTEMODE)
|
||||
public static BlockReader Get(Stream stream, int fallbackCodePage)
|
||||
{
|
||||
Encoding encoding;
|
||||
int preamble = Preamble(stream);
|
||||
|
||||
if (preamble != 0) // There is a valid BOM here!
|
||||
encoding = Encoding.GetEncoding(preamble);
|
||||
else if (fallbackCodePage == -1) // Fallback is "raw" bytes
|
||||
return Raw(stream);
|
||||
else if (fallbackCodePage != -2) // Anything but "guess"
|
||||
encoding = Encoding.GetEncoding(fallbackCodePage);
|
||||
else // This is the "guess" option
|
||||
{
|
||||
int guess = new Guesser(stream).GuessCodePage();
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
if (guess == -1) // ==> this is a 7-bit file
|
||||
encoding = Encoding.ASCII;
|
||||
else if (guess == 65001)
|
||||
encoding = Encoding.UTF8;
|
||||
else // ==> use the machine default
|
||||
encoding = Encoding.Default;
|
||||
}
|
||||
StreamReader reader = new StreamReader(stream, encoding);
|
||||
return reader.Read;
|
||||
}
|
||||
|
||||
static int Preamble(Stream stream)
|
||||
{
|
||||
int b0 = stream.ReadByte();
|
||||
int b1 = stream.ReadByte();
|
||||
|
||||
if (b0 == 0xfe && b1 == 0xff)
|
||||
return 1201; // UTF16BE
|
||||
if (b0 == 0xff && b1 == 0xfe)
|
||||
return 1200; // UTF16LE
|
||||
|
||||
int b2 = stream.ReadByte();
|
||||
if (b0 == 0xef && b1 == 0xbb && b2 == 0xbf)
|
||||
return 65001; // UTF8
|
||||
//
|
||||
// There is no unicode preamble, so we
|
||||
// return denoter for the machine default.
|
||||
//
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
return 0;
|
||||
}
|
||||
#endif // !BYTEMODE
|
||||
}
|
||||
#endif // !NOFILES
|
||||
#endregion Buffer classes
|
||||
|
||||
// ==============================================================
|
||||
// ============ class CodePageHandling =============
|
||||
// ==============================================================
|
||||
#if (!NOFILES)
|
||||
public static class CodePageHandling
|
||||
{
|
||||
public static int GetCodePage(string option)
|
||||
{
|
||||
string command = option.ToUpperInvariant();
|
||||
if (command.StartsWith("CodePage:", StringComparison.OrdinalIgnoreCase))
|
||||
command = command.Substring(9);
|
||||
try
|
||||
{
|
||||
if (command.Equals("RAW"))
|
||||
return -1;
|
||||
else if (command.Equals("GUESS"))
|
||||
return -2;
|
||||
else if (command.Equals("DEFAULT"))
|
||||
return 0;
|
||||
else if (char.IsDigit(command[0]))
|
||||
return int.Parse(command, CultureInfo.InvariantCulture);
|
||||
else
|
||||
{
|
||||
Encoding enc = Encoding.GetEncoding(command);
|
||||
return enc.CodePage;
|
||||
}
|
||||
}
|
||||
catch (FormatException)
|
||||
{
|
||||
Console.Error.WriteLine(
|
||||
"Invalid format \"{0}\", using machine default", option);
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
Console.Error.WriteLine(
|
||||
"Unknown code page \"{0}\", using machine default", option);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#region guesser
|
||||
#if (!BYTEMODE)
|
||||
// ==============================================================
|
||||
// ============ Encoding Guesser =============
|
||||
// ==============================================================
|
||||
|
||||
/// <summary>
|
||||
/// This class provides a simple finite state automaton that
|
||||
/// scans the file looking for (1) valid UTF-8 byte patterns,
|
||||
/// (2) bytes >= 0x80 which are not part of a UTF-8 sequence.
|
||||
/// The method then guesses whether it is UTF-8 or maybe some
|
||||
/// local machine default encoding. This works well for the
|
||||
/// various Latin encodings.
|
||||
/// </summary>
|
||||
internal class Guesser
|
||||
{
|
||||
ScanBuff buffer;
|
||||
|
||||
public int GuessCodePage() { return Scan(); }
|
||||
|
||||
const int maxAccept = 10;
|
||||
const int initial = 0;
|
||||
const int eofNum = 0;
|
||||
const int goStart = -1;
|
||||
const int INITIAL = 0;
|
||||
const int EndToken = 0;
|
||||
|
||||
#region user code
|
||||
/*
|
||||
* Reads the bytes of a file to determine if it is
|
||||
* UTF-8 or a single-byte code page file.
|
||||
*/
|
||||
public long utfX;
|
||||
public long uppr;
|
||||
#endregion user code
|
||||
|
||||
int state;
|
||||
int currentStart = startState[0];
|
||||
int code;
|
||||
|
||||
#region ScannerTables
|
||||
static int[] startState = new int[] { 11, 0 };
|
||||
|
||||
#region CharacterMap
|
||||
static sbyte[] map = new sbyte[256] {
|
||||
/* '\0' */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/* '\x10' */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/* '\x20' */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/* '0' */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/* '@' */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/* 'P' */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/* '`' */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/* 'p' */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/* '\x80' */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
/* '\x90' */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
/* '\xA0' */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
/* '\xB0' */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
/* '\xC0' */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
/* '\xD0' */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
/* '\xE0' */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
/* '\xF0' */ 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5 };
|
||||
#endregion
|
||||
|
||||
static sbyte[][] nextState = new sbyte[][] {
|
||||
new sbyte[] {0, 0, 0, 0, 0, 0},
|
||||
new sbyte[] {-1, -1, 10, -1, -1, -1},
|
||||
new sbyte[] {-1, -1, -1, -1, -1, -1},
|
||||
new sbyte[] {-1, -1, 8, -1, -1, -1},
|
||||
new sbyte[] {-1, -1, 5, -1, -1, -1},
|
||||
new sbyte[] {-1, -1, 6, -1, -1, -1},
|
||||
new sbyte[] {-1, -1, 7, -1, -1, -1},
|
||||
null,
|
||||
new sbyte[] {-1, -1, 9, -1, -1, -1},
|
||||
null,
|
||||
null,
|
||||
new sbyte[] {-1, 1, 2, 3, 4, 2}
|
||||
};
|
||||
|
||||
|
||||
[SuppressMessage("Microsoft.Performance", "CA1810:InitializeReferenceTypeStaticFieldsInline")]
|
||||
// Reason for suppression: cannot have self-reference in array initializer.
|
||||
static Guesser()
|
||||
{
|
||||
nextState[7] = nextState[2];
|
||||
nextState[9] = nextState[2];
|
||||
nextState[10] = nextState[2];
|
||||
}
|
||||
|
||||
int NextState()
|
||||
{
|
||||
if (code == ScanBuff.EndOfFile)
|
||||
return eofNum;
|
||||
else
|
||||
return nextState[state][map[code]];
|
||||
}
|
||||
#endregion
|
||||
|
||||
public Guesser(System.IO.Stream file) { SetSource(file); }
|
||||
|
||||
public void SetSource(System.IO.Stream source)
|
||||
{
|
||||
this.buffer = new BuildBuffer(source);
|
||||
code = buffer.Read();
|
||||
}
|
||||
|
||||
int Scan()
|
||||
{
|
||||
for (; ; )
|
||||
{
|
||||
int next;
|
||||
state = currentStart;
|
||||
while ((next = NextState()) == goStart)
|
||||
code = buffer.Read();
|
||||
|
||||
state = next;
|
||||
code = buffer.Read();
|
||||
|
||||
while ((next = NextState()) > eofNum)
|
||||
{
|
||||
state = next;
|
||||
code = buffer.Read();
|
||||
}
|
||||
if (state <= maxAccept)
|
||||
{
|
||||
#region ActionSwitch
|
||||
#pragma warning disable 162
|
||||
switch (state)
|
||||
{
|
||||
case eofNum:
|
||||
switch (currentStart)
|
||||
{
|
||||
case 11:
|
||||
if (utfX == 0 && uppr == 0) return -1; /* raw ascii */
|
||||
else if (uppr * 10 > utfX) return 0; /* default code page */
|
||||
else return 65001; /* UTF-8 encoding */
|
||||
break;
|
||||
}
|
||||
return EndToken;
|
||||
case 1: // Recognized '{Upper128}', Shortest string "\xC0"
|
||||
case 2: // Recognized '{Upper128}', Shortest string "\x80"
|
||||
case 3: // Recognized '{Upper128}', Shortest string "\xE0"
|
||||
case 4: // Recognized '{Upper128}', Shortest string "\xF0"
|
||||
uppr++;
|
||||
break;
|
||||
case 5: // Recognized '{Utf8pfx4}{Utf8cont}', Shortest string "\xF0\x80"
|
||||
uppr += 2;
|
||||
break;
|
||||
case 6: // Recognized '{Utf8pfx4}{Utf8cont}{2}', Shortest string "\xF0\x80\x80"
|
||||
uppr += 3;
|
||||
break;
|
||||
case 7: // Recognized '{Utf8pfx4}{Utf8cont}{3}', Shortest string "\xF0\x80\x80\x80"
|
||||
utfX += 3;
|
||||
break;
|
||||
case 8: // Recognized '{Utf8pfx3}{Utf8cont}', Shortest string "\xE0\x80"
|
||||
uppr += 2;
|
||||
break;
|
||||
case 9: // Recognized '{Utf8pfx3}{Utf8cont}{2}', Shortest string "\xE0\x80\x80"
|
||||
utfX += 2;
|
||||
break;
|
||||
case 10: // Recognized '{Utf8pfx2}{Utf8cont}', Shortest string "\xC0\x80"
|
||||
utfX++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#pragma warning restore 162
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
} // end class Guesser
|
||||
|
||||
#endif // !BYTEMODE
|
||||
#endregion
|
||||
#endif // !NOFILES
|
||||
|
||||
// End of code copied from embedded resource
|
||||
}
|
||||
@@ -0,0 +1,884 @@
|
||||
// ==============================================================
|
||||
// <auto-generated>
|
||||
// This code automatically produced from an embedded resource.
|
||||
// Do not edit this file, or it will become incompatible with
|
||||
// the specification from which it was generated.
|
||||
// </auto-generated>
|
||||
// ==============================================================
|
||||
|
||||
// Gardens Point Parser Generator
|
||||
// Copyright (c) Wayne Kelly, QUT 2005-2010
|
||||
// (see accompanying GPPGcopyright.rtf)
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Globalization;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace QUT.Gppg {
|
||||
/// <summary>
|
||||
/// Abstract class for GPPG shift-reduce parsers.
|
||||
/// Parsers generated by GPPG derive from this base
|
||||
/// class, overriding the abstract Initialize() and
|
||||
/// DoAction() methods.
|
||||
/// </summary>
|
||||
/// <typeparam name="TValue">Semantic value type</typeparam>
|
||||
/// <typeparam name="TSpan">Location type</typeparam>
|
||||
#if EXPORT_GPPG
|
||||
public abstract class ShiftReduceParser<TValue, TSpan>
|
||||
#else
|
||||
internal abstract class ShiftReduceParser<TValue, TSpan>
|
||||
#endif
|
||||
where TSpan : IMerge<TSpan>, new() {
|
||||
private AbstractScanner<TValue, TSpan> scanner;
|
||||
/// <summary>
|
||||
/// The abstract scanner for this parser.
|
||||
/// </summary>
|
||||
protected AbstractScanner<TValue, TSpan> Scanner {
|
||||
get { return scanner; }
|
||||
set { scanner = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for base class
|
||||
/// </summary>
|
||||
/// <param name="scanner">Scanner instance for this parser</param>
|
||||
protected ShiftReduceParser( AbstractScanner<TValue, TSpan> scanner ) {
|
||||
this.scanner = scanner;
|
||||
}
|
||||
|
||||
// ==============================================================
|
||||
// TECHNICAL EXPLANATION.
|
||||
// Why the next two fields are not exposed via properties.
|
||||
// ==============================================================
|
||||
// These fields are of the generic parameter types, and are
|
||||
// frequently instantiated as struct types in derived classes.
|
||||
// Semantic actions are defined in the derived classes and refer
|
||||
// to instance fields of these structs. In such cases the code
|
||||
// "get_CurrentSemanticValue().myField = blah;" will fail since
|
||||
// the getter pushes the value of the field, not the reference.
|
||||
// So, in the presence of properties, gppg would need to encode
|
||||
// such field accesses as ...
|
||||
// "tmp = get_CurrentSemanticValue(); // Fetch value
|
||||
// tmp.myField = blah; // update
|
||||
// set_CurrentSemanticValue(tmp); " // Write update back.
|
||||
// There is no issue if TValue is restricted to be a ref type.
|
||||
// The same explanation applies to scanner.yylval.
|
||||
// ==============================================================
|
||||
/// <summary>
|
||||
/// The current value of the "$$" symbolic variable in the parser
|
||||
/// </summary>
|
||||
[SuppressMessage( "Microsoft.Design", "CA1051:DoNotDeclareVisibleInstanceFields" )]
|
||||
protected TValue CurrentSemanticValue;
|
||||
|
||||
/// <summary>
|
||||
/// The current value of the "@$" symbolic variable in the parser
|
||||
/// </summary>
|
||||
[SuppressMessage( "Microsoft.Design", "CA1051:DoNotDeclareVisibleInstanceFields" )]
|
||||
protected TSpan CurrentLocationSpan;
|
||||
protected int NextToken;
|
||||
|
||||
private TSpan LastSpan;
|
||||
private State FsaState;
|
||||
private bool recovering;
|
||||
private int tokensSinceLastError;
|
||||
|
||||
private PushdownPrefixState<State> StateStack = new PushdownPrefixState<State>();
|
||||
private PushdownPrefixState<TValue> valueStack = new PushdownPrefixState<TValue>();
|
||||
private PushdownPrefixState<TSpan> locationStack = new PushdownPrefixState<TSpan>();
|
||||
|
||||
/// <summary>
|
||||
/// The stack of semantic value (YYSTYPE) values.
|
||||
/// </summary>
|
||||
protected PushdownPrefixState<TValue> ValueStack { get { return valueStack; } }
|
||||
|
||||
/// <summary>
|
||||
/// The stack of location value (YYLTYPE) varlues.
|
||||
/// </summary>
|
||||
protected PushdownPrefixState<TSpan> LocationStack { get { return locationStack; } }
|
||||
|
||||
private int errorToken;
|
||||
private int endOfFileToken;
|
||||
private string[] nonTerminals;
|
||||
private State[] states;
|
||||
private Rule[] rules;
|
||||
|
||||
/// <summary>
|
||||
/// Initialization method to allow derived classes
|
||||
/// to insert the rule list into this base class.
|
||||
/// </summary>
|
||||
/// <param name="rules">The array of Rule objects</param>
|
||||
protected void InitRules( Rule[] rules ) { this.rules = rules; }
|
||||
|
||||
/// <summary>
|
||||
/// Initialization method to allow derived classes to
|
||||
/// insert the states table into this base class.
|
||||
/// </summary>
|
||||
/// <param name="states">The pre-initialized states table</param>
|
||||
protected void InitStates( State[] states ) { this.states = states; }
|
||||
|
||||
/// <summary>
|
||||
/// OBSOLETE FOR VERSION 1.4.0
|
||||
/// </summary>
|
||||
/// <param name="size"></param>
|
||||
protected void InitStateTable( int size ) { states = new State[size]; }
|
||||
|
||||
/// <summary>
|
||||
/// Initialization method to allow derived classes
|
||||
/// to insert the special value for the error and EOF tokens.
|
||||
/// </summary>
|
||||
/// <param name="err">The error state ordinal</param>
|
||||
/// <param name="end">The EOF stat ordinal</param>
|
||||
protected void InitSpecialTokens( int err, int end ) {
|
||||
errorToken = err;
|
||||
endOfFileToken = end;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialization method to allow derived classes to
|
||||
/// insert the non-terminal symbol names into this base class.
|
||||
/// </summary>
|
||||
/// <param name="names">Non-terminal symbol names</param>
|
||||
protected void InitNonTerminals( string[] names ) { nonTerminals = names; }
|
||||
|
||||
#region YYAbort, YYAccept etcetera.
|
||||
[Serializable]
|
||||
[SuppressMessage( "Microsoft.Design", "CA1064:ExceptionsShouldBePublic" )]
|
||||
// Reason for FxCop message suppression -
|
||||
// This exception cannot escape from the local context
|
||||
private class AcceptException : Exception {
|
||||
internal AcceptException() { }
|
||||
protected AcceptException( SerializationInfo i, StreamingContext c ) : base( i, c ) { }
|
||||
}
|
||||
[Serializable]
|
||||
[SuppressMessage( "Microsoft.Design", "CA1064:ExceptionsShouldBePublic" )]
|
||||
// Reason for FxCop message suppression -
|
||||
// This exception cannot escape from the local context
|
||||
private class AbortException : Exception {
|
||||
internal AbortException() { }
|
||||
protected AbortException( SerializationInfo i, StreamingContext c ) : base( i, c ) { }
|
||||
}
|
||||
[Serializable]
|
||||
[SuppressMessage( "Microsoft.Design", "CA1064:ExceptionsShouldBePublic" )]
|
||||
// Reason for FxCop message suppression -
|
||||
// This exception cannot escape from the local context
|
||||
private class ErrorException : Exception {
|
||||
internal ErrorException() { }
|
||||
protected ErrorException( SerializationInfo i, StreamingContext c ) : base( i, c ) { }
|
||||
}
|
||||
|
||||
// The following methods are only called from within
|
||||
// a semantic action. The thrown exceptions can never
|
||||
// propagate outside the ShiftReduceParser class in
|
||||
// which they are nested.
|
||||
|
||||
/// <summary>
|
||||
/// Force parser to terminate, returning "true"
|
||||
/// </summary>
|
||||
protected static void YYAccept() { throw new AcceptException(); }
|
||||
|
||||
/// <summary>
|
||||
/// Force parser to terminate, returning "false"
|
||||
/// </summary>
|
||||
protected static void YYAbort() { throw new AbortException(); }
|
||||
|
||||
/// <summary>
|
||||
/// Force parser to terminate, returning
|
||||
/// "false" if error recovery fails.
|
||||
/// </summary>
|
||||
protected static void YYError() { throw new ErrorException(); }
|
||||
|
||||
/// <summary>
|
||||
/// Check if parser in error recovery state.
|
||||
/// </summary>
|
||||
protected bool YYRecovering { get { return recovering; } }
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Abstract base method. ShiftReduceParser calls this
|
||||
/// to initialize the base class data structures. Concrete
|
||||
/// parser classes must override this method.
|
||||
/// </summary>
|
||||
protected abstract void Initialize();
|
||||
|
||||
/// <summary>
|
||||
/// Main entry point of the Shift-Reduce Parser.
|
||||
/// </summary>
|
||||
/// <returns>True if parse succeeds, else false for
|
||||
/// unrecoverable errors</returns>
|
||||
public bool Parse() {
|
||||
Initialize(); // allow derived classes to instantiate rules, states and nonTerminals
|
||||
|
||||
NextToken = 0;
|
||||
FsaState = states[0];
|
||||
|
||||
StateStack.Push( FsaState );
|
||||
valueStack.Push( CurrentSemanticValue );
|
||||
LocationStack.Push( CurrentLocationSpan );
|
||||
|
||||
while (true) {
|
||||
#if TRACE_ACTIONS
|
||||
Console.Error.WriteLine("Entering state {0} ", FsaState.number);
|
||||
DisplayStack();
|
||||
#endif
|
||||
int action = FsaState.defaultAction;
|
||||
|
||||
if (FsaState.ParserTable != null) {
|
||||
if (NextToken == 0) {
|
||||
// We save the last token span, so that the location span
|
||||
// of production right hand sides that begin or end with a
|
||||
// nullable production will be correct.
|
||||
LastSpan = scanner.yylloc;
|
||||
NextToken = scanner.yylex();
|
||||
#if TRACE_ACTIONS
|
||||
Console.Error.WriteLine( "Reading: Next token is {0}", TerminalToString( NextToken ) );
|
||||
#endif
|
||||
}
|
||||
#if TRACE_ACTIONS
|
||||
else
|
||||
Console.Error.WriteLine( "Next token is still {0}", TerminalToString( NextToken ) );
|
||||
#endif
|
||||
if (FsaState.ParserTable.ContainsKey( NextToken ))
|
||||
action = FsaState.ParserTable[NextToken];
|
||||
}
|
||||
|
||||
if (action > 0) // shift
|
||||
{
|
||||
Shift( action );
|
||||
}
|
||||
else if (action < 0) // reduce
|
||||
{
|
||||
try {
|
||||
Reduce( -action );
|
||||
if (action == -1) // accept
|
||||
return true;
|
||||
}
|
||||
catch (AbortException) {
|
||||
return false;
|
||||
}
|
||||
catch (AcceptException) {
|
||||
return true;
|
||||
}
|
||||
catch (ErrorException) {
|
||||
if (!ErrorRecovery())
|
||||
return false;
|
||||
else
|
||||
throw; // Rethrow x, preserving information.
|
||||
}
|
||||
}
|
||||
else if (action == 0 && !ErrorRecovery()) // error
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void Shift( int stateIndex ) {
|
||||
#if TRACE_ACTIONS
|
||||
Console.Error.Write("Shifting token {0}, ", TerminalToString(NextToken));
|
||||
#endif
|
||||
FsaState = states[stateIndex];
|
||||
|
||||
valueStack.Push( scanner.yylval );
|
||||
StateStack.Push( FsaState );
|
||||
LocationStack.Push( scanner.yylloc );
|
||||
|
||||
if (recovering) {
|
||||
if (NextToken != errorToken)
|
||||
tokensSinceLastError++;
|
||||
|
||||
if (tokensSinceLastError > 5)
|
||||
recovering = false;
|
||||
}
|
||||
|
||||
if (NextToken != endOfFileToken)
|
||||
NextToken = 0;
|
||||
}
|
||||
|
||||
private void Reduce( int ruleNumber ) {
|
||||
#if TRACE_ACTIONS
|
||||
DisplayRule(ruleNumber);
|
||||
#endif
|
||||
Rule rule = rules[ruleNumber];
|
||||
int rhLen = rule.RightHandSide.Length;
|
||||
//
|
||||
// Default actions for unit productions.
|
||||
//
|
||||
if (rhLen == 1) {
|
||||
CurrentSemanticValue = valueStack.TopElement(); // Default action: $$ = $1;
|
||||
CurrentLocationSpan = LocationStack.TopElement(); // Default action "@$ = @1;
|
||||
}
|
||||
else if (rhLen == 0) {
|
||||
// Create a new blank value.
|
||||
// Explicit semantic action may mutate this value
|
||||
CurrentSemanticValue = default( TValue );
|
||||
// The location span for an empty production will start with the
|
||||
// beginning of the next lexeme, and end with the finish of the
|
||||
// previous lexeme. This gives the correct behaviour when this
|
||||
// nonsense value is used in later Merge operations.
|
||||
CurrentLocationSpan = (scanner.yylloc != null && LastSpan != null ?
|
||||
scanner.yylloc.Merge( LastSpan ) :
|
||||
default( TSpan ));
|
||||
}
|
||||
else {
|
||||
// Default action: $$ = $1;
|
||||
CurrentSemanticValue = valueStack[LocationStack.Depth - rhLen];
|
||||
// Default action "@$ = @1.Merge(@N)" for location info.
|
||||
TSpan at1 = LocationStack[LocationStack.Depth - rhLen];
|
||||
TSpan atN = LocationStack[LocationStack.Depth - 1];
|
||||
CurrentLocationSpan =
|
||||
((at1 != null && atN != null) ? at1.Merge( atN ) : default( TSpan ));
|
||||
}
|
||||
|
||||
DoAction( ruleNumber );
|
||||
|
||||
for (int i = 0; i < rule.RightHandSide.Length; i++) {
|
||||
StateStack.Pop();
|
||||
valueStack.Pop();
|
||||
LocationStack.Pop();
|
||||
}
|
||||
FsaState = StateStack.TopElement();
|
||||
|
||||
if (FsaState.Goto.ContainsKey( rule.LeftHandSide ))
|
||||
FsaState = states[FsaState.Goto[rule.LeftHandSide]];
|
||||
|
||||
StateStack.Push( FsaState );
|
||||
valueStack.Push( CurrentSemanticValue );
|
||||
LocationStack.Push( CurrentLocationSpan );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Execute the selected action from array.
|
||||
/// Must be overriden in derived classes.
|
||||
/// </summary>
|
||||
/// <param name="actionNumber">Index of the action to perform</param>
|
||||
protected abstract void DoAction( int actionNumber );
|
||||
|
||||
private bool ErrorRecovery() {
|
||||
bool discard;
|
||||
|
||||
if (!recovering) // if not recovering from previous error
|
||||
ReportError();
|
||||
|
||||
if (!FindErrorRecoveryState())
|
||||
return false;
|
||||
//
|
||||
// The interim fix for the "looping in error recovery"
|
||||
// artifact involved moving the setting of the recovering
|
||||
// bool until after invalid tokens have been discarded.
|
||||
//
|
||||
ShiftErrorToken();
|
||||
discard = DiscardInvalidTokens();
|
||||
recovering = true;
|
||||
tokensSinceLastError = 0;
|
||||
return discard;
|
||||
}
|
||||
|
||||
private void ReportError() {
|
||||
StringBuilder errorMsg = new StringBuilder();
|
||||
errorMsg.AppendFormat( "Syntax error, unexpected {0}", TerminalToString( NextToken ) );
|
||||
|
||||
if (FsaState.ParserTable.Count < 7) {
|
||||
bool first = true;
|
||||
foreach (int terminal in FsaState.ParserTable.Keys) {
|
||||
if (first)
|
||||
errorMsg.Append( ", expecting " );
|
||||
else
|
||||
errorMsg.Append( ", or " );
|
||||
|
||||
errorMsg.Append( TerminalToString( terminal ) );
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
scanner.yyerror( errorMsg.ToString() );
|
||||
}
|
||||
|
||||
private void ShiftErrorToken() {
|
||||
int old_next = NextToken;
|
||||
NextToken = errorToken;
|
||||
|
||||
Shift( FsaState.ParserTable[NextToken] );
|
||||
|
||||
#if TRACE_ACTIONS
|
||||
Console.Error.WriteLine("Entering state {0} ", FsaState.number);
|
||||
#endif
|
||||
NextToken = old_next;
|
||||
}
|
||||
|
||||
private bool FindErrorRecoveryState() {
|
||||
while (true) // pop states until one found that accepts error token
|
||||
{
|
||||
if (FsaState.ParserTable != null &&
|
||||
FsaState.ParserTable.ContainsKey( errorToken ) &&
|
||||
FsaState.ParserTable[errorToken] > 0) // shift
|
||||
return true;
|
||||
|
||||
#if TRACE_ACTIONS
|
||||
Console.Error.WriteLine("Error: popping state {0}", StateStack.TopElement().number);
|
||||
#endif
|
||||
StateStack.Pop();
|
||||
valueStack.Pop();
|
||||
LocationStack.Pop();
|
||||
|
||||
#if TRACE_ACTIONS
|
||||
DisplayStack();
|
||||
#endif
|
||||
if (StateStack.IsEmpty()) {
|
||||
#if TRACE_ACTIONS
|
||||
Console.Error.WriteLine("Aborting: didn't find a state that accepts error token");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
else
|
||||
FsaState = StateStack.TopElement();
|
||||
}
|
||||
}
|
||||
|
||||
private bool DiscardInvalidTokens() {
|
||||
|
||||
int action = FsaState.defaultAction;
|
||||
|
||||
if (FsaState.ParserTable != null) {
|
||||
// Discard tokens until find one that works ...
|
||||
while (true) {
|
||||
if (NextToken == 0) {
|
||||
#if TRACE_ACTIONS
|
||||
Console.Error.Write("Reading a token: ");
|
||||
#endif
|
||||
NextToken = scanner.yylex();
|
||||
}
|
||||
#if TRACE_ACTIONS
|
||||
Console.Error.WriteLine("Next token is {0}", TerminalToString(NextToken));
|
||||
#endif
|
||||
if (NextToken == endOfFileToken)
|
||||
return false;
|
||||
|
||||
if (FsaState.ParserTable.ContainsKey( NextToken ))
|
||||
action = FsaState.ParserTable[NextToken];
|
||||
|
||||
if (action != 0)
|
||||
return true;
|
||||
else {
|
||||
#if TRACE_ACTIONS
|
||||
Console.Error.WriteLine("Error: Discarding {0}", TerminalToString(NextToken));
|
||||
#endif
|
||||
NextToken = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (recovering && tokensSinceLastError == 0) {
|
||||
//
|
||||
// Boolean recovering is not set until after the first
|
||||
// error token has been shifted. Thus if we get back
|
||||
// here with recovering set and no tokens read we are
|
||||
// looping on the same error recovery action. This
|
||||
// happens if current_state.ParserTable is null because
|
||||
// the state has an LR(0) reduction, but not all
|
||||
// lookahead tokens are valid. This only occurs for
|
||||
// error productions that *end* on "error".
|
||||
//
|
||||
// This action discards tokens one at a time until
|
||||
// the looping stops. Another attack would be to always
|
||||
// use the LALR(1) table if a production ends on "error"
|
||||
//
|
||||
#if TRACE_ACTIONS
|
||||
Console.Error.WriteLine("Error: panic discard of {0}", TerminalToString(NextToken));
|
||||
#endif
|
||||
if (NextToken == endOfFileToken)
|
||||
return false;
|
||||
NextToken = 0;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Traditional YACC method. Discards the next input token.
|
||||
/// </summary>
|
||||
[SuppressMessage( "Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "yyclearin" )]
|
||||
[SuppressMessage( "Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "yyclearin" )]
|
||||
// Reason for FxCop message suppression -
|
||||
// This is a traditional name for YACC-like functionality
|
||||
protected void yyclearin() { NextToken = 0; }
|
||||
|
||||
/// <summary>
|
||||
/// Tradional YACC method. Clear the "recovering" flag.
|
||||
/// </summary>
|
||||
[SuppressMessage( "Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "yyerrok" )]
|
||||
[SuppressMessage( "Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "yyerrok" )]
|
||||
// Reason for FxCop message suppression -
|
||||
// This is a traditional name for YACC-like functionality
|
||||
protected void yyerrok() { recovering = false; }
|
||||
|
||||
/// <summary>
|
||||
/// OBSOLETE FOR VERSION 1.4.0
|
||||
/// Method used by derived types to insert new
|
||||
/// state instances in the "states" array.
|
||||
/// </summary>
|
||||
/// <param name="stateNumber">index of the state</param>
|
||||
/// <param name="state">data for the state</param>
|
||||
protected void AddState( int stateNumber, State state ) {
|
||||
states[stateNumber] = state;
|
||||
state.number = stateNumber;
|
||||
}
|
||||
|
||||
private void DisplayStack() {
|
||||
Console.Error.Write( "State stack is now:" );
|
||||
for (int i = 0; i < StateStack.Depth; i++)
|
||||
Console.Error.Write( " {0}", StateStack[i].number );
|
||||
Console.Error.WriteLine();
|
||||
}
|
||||
|
||||
private void DisplayRule( int ruleNumber ) {
|
||||
Console.Error.Write( "Reducing stack by rule {0}, ", ruleNumber );
|
||||
DisplayProduction( rules[ruleNumber] );
|
||||
}
|
||||
|
||||
private void DisplayProduction( Rule rule ) {
|
||||
if (rule.RightHandSide.Length == 0)
|
||||
Console.Error.Write( "/* empty */ " );
|
||||
else
|
||||
foreach (int symbol in rule.RightHandSide)
|
||||
Console.Error.Write( "{0} ", SymbolToString( symbol ) );
|
||||
|
||||
Console.Error.WriteLine( "-> {0}", SymbolToString( rule.LeftHandSide ) );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Abstract state class naming terminal symbols.
|
||||
/// This is overridden by derived classes with the
|
||||
/// name (or alias) to be used in error messages.
|
||||
/// </summary>
|
||||
/// <param name="terminal">The terminal ordinal</param>
|
||||
/// <returns></returns>
|
||||
protected abstract string TerminalToString( int terminal );
|
||||
|
||||
private string SymbolToString( int symbol ) {
|
||||
if (symbol < 0)
|
||||
return nonTerminals[-symbol - 1];
|
||||
else
|
||||
return TerminalToString( symbol );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return text representation of argument character
|
||||
/// </summary>
|
||||
/// <param name="input">The character to convert</param>
|
||||
/// <returns>String representation of the character</returns>
|
||||
protected static string CharToString( char input ) {
|
||||
switch (input) {
|
||||
case '\a': return @"'\a'";
|
||||
case '\b': return @"'\b'";
|
||||
case '\f': return @"'\f'";
|
||||
case '\n': return @"'\n'";
|
||||
case '\r': return @"'\r'";
|
||||
case '\t': return @"'\t'";
|
||||
case '\v': return @"'\v'";
|
||||
case '\0': return @"'\0'";
|
||||
default: return string.Format( CultureInfo.InvariantCulture, "'{0}'", input );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Classes implementing this interface must supply a
|
||||
/// method that merges two location objects to return
|
||||
/// a new object of the same type.
|
||||
/// GPPG-generated parsers have the default location
|
||||
/// action equivalent to "@$ = @1.Merge(@N);" where N
|
||||
/// is the right-hand-side length of the production.
|
||||
/// </summary>
|
||||
/// <typeparam name="TSpan">The Location type</typeparam>
|
||||
#if EXPORT_GPPG
|
||||
public interface IMerge<TSpan>
|
||||
#else
|
||||
internal interface IMerge<TSpan>
|
||||
#endif
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface method that creates a location object from
|
||||
/// the current and last object. Typically used to create
|
||||
/// a location object extending from the start of the @1
|
||||
/// object to the end of the @N object.
|
||||
/// </summary>
|
||||
/// <param name="last">The lexically last object to merge</param>
|
||||
/// <returns>The merged location object</returns>
|
||||
TSpan Merge( TSpan last );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is the default class that carries location
|
||||
/// information from the scanner to the parser.
|
||||
/// If you don't declare "%YYLTYPE Foo" the parser
|
||||
/// will expect to deal with this type.
|
||||
/// </summary>
|
||||
#if EXPORT_GPPG
|
||||
public class LexLocation : IMerge<LexLocation>
|
||||
#else
|
||||
[SuppressMessage( "Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses" )]
|
||||
internal class LexLocation : IMerge<LexLocation>
|
||||
#endif
|
||||
{
|
||||
private int startLine; // start line
|
||||
private int startColumn; // start column
|
||||
private int endLine; // end line
|
||||
private int endColumn; // end column
|
||||
|
||||
/// <summary>
|
||||
/// The line at which the text span starts.
|
||||
/// </summary>
|
||||
public int StartLine { get { return startLine; } }
|
||||
|
||||
/// <summary>
|
||||
/// The column at which the text span starts.
|
||||
/// </summary>
|
||||
public int StartColumn { get { return startColumn; } }
|
||||
|
||||
/// <summary>
|
||||
/// The line on which the text span ends.
|
||||
/// </summary>
|
||||
public int EndLine { get { return endLine; } }
|
||||
|
||||
/// <summary>
|
||||
/// The column of the first character
|
||||
/// beyond the end of the text span.
|
||||
/// </summary>
|
||||
public int EndColumn { get { return endColumn; } }
|
||||
|
||||
/// <summary>
|
||||
/// Default no-arg constructor.
|
||||
/// </summary>
|
||||
public LexLocation() { }
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for text-span with given start and end.
|
||||
/// </summary>
|
||||
/// <param name="sl">start line</param>
|
||||
/// <param name="sc">start column</param>
|
||||
/// <param name="el">end line </param>
|
||||
/// <param name="ec">end column</param>
|
||||
public LexLocation( int sl, int sc, int el, int ec ) { startLine = sl; startColumn = sc; endLine = el; endColumn = ec; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a text location which spans from the
|
||||
/// start of "this" to the end of the argument "last"
|
||||
/// </summary>
|
||||
/// <param name="last">The last location in the result span</param>
|
||||
/// <returns>The merged span</returns>
|
||||
public LexLocation Merge( LexLocation last ) { return new LexLocation( this.startLine, this.startColumn, last.endLine, last.endColumn ); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Abstract scanner class that GPPG expects its scanners to
|
||||
/// extend.
|
||||
/// </summary>
|
||||
/// <typeparam name="TValue">Semantic value type YYSTYPE</typeparam>
|
||||
/// <typeparam name="TSpan">Source location type YYLTYPE</typeparam>
|
||||
#if EXPORT_GPPG
|
||||
public abstract class AbstractScanner<TValue, TSpan>
|
||||
#else
|
||||
internal abstract class AbstractScanner<TValue, TSpan>
|
||||
#endif
|
||||
where TSpan : IMerge<TSpan> {
|
||||
/// <summary>
|
||||
/// Lexical value optionally set by the scanner. The value
|
||||
/// is of the %YYSTYPE type declared in the parser spec.
|
||||
/// </summary>
|
||||
[SuppressMessage( "Microsoft.Design", "CA1051:DoNotDeclareVisibleInstanceFields" )]
|
||||
[SuppressMessage( "Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "yylval" )]
|
||||
[SuppressMessage( "Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "yylval" )]
|
||||
// Reason for FxCop message suppression -
|
||||
// This is a traditional name for YACC-like functionality
|
||||
// A field must be declared for this value of parametric type,
|
||||
// since it may be instantiated by a value struct. If it were
|
||||
// implemented as a property, machine generated code in derived
|
||||
// types would not be able to select on the returned value.
|
||||
#pragma warning disable 649
|
||||
public TValue yylval; // Lexical value: set by scanner
|
||||
#pragma warning restore 649
|
||||
|
||||
/// <summary>
|
||||
/// Current scanner location property. The value is of the
|
||||
/// type declared by %YYLTYPE in the parser specification.
|
||||
/// </summary>
|
||||
[SuppressMessage( "Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "yylloc" )]
|
||||
[SuppressMessage( "Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "yylloc" )]
|
||||
// Reason for FxCop message suppression -
|
||||
// This is a traditional name for YACC-like functionality
|
||||
public virtual TSpan yylloc {
|
||||
get { return default( TSpan ); } // Empty implementation allowing
|
||||
set { /* skip */ } // yylloc to be ignored entirely.
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Main call point for LEX-like scanners. Returns an int
|
||||
/// corresponding to the token recognized by the scanner.
|
||||
/// </summary>
|
||||
/// <returns>An int corresponding to the token</returns>
|
||||
[SuppressMessage( "Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "yylex" )]
|
||||
[SuppressMessage( "Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "yylex" )]
|
||||
// Reason for FxCop message suppression -
|
||||
// This is a traditional name for YACC-like functionality
|
||||
public abstract int yylex();
|
||||
|
||||
/// <summary>
|
||||
/// Traditional error reporting provided by LEX-like scanners
|
||||
/// to their YACC-like clients.
|
||||
/// </summary>
|
||||
/// <param name="format">Message format string</param>
|
||||
/// <param name="args">Optional array of args</param>
|
||||
[SuppressMessage( "Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "yyerror" )]
|
||||
[SuppressMessage( "Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "yyerror" )]
|
||||
// Reason for FxCop message suppression -
|
||||
// This is a traditional name for YACC-like functionality
|
||||
public virtual void yyerror( string format, params object[] args ) { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Encapsulated state for the parser.
|
||||
/// Opaque to users, visible to the tool-generated code.
|
||||
/// </summary>
|
||||
#if EXPORT_GPPG
|
||||
public class State
|
||||
{
|
||||
/// <summary>
|
||||
/// The number of states in the automaton.
|
||||
/// </summary>
|
||||
public int number;
|
||||
#else
|
||||
internal class State {
|
||||
/// <summary>
|
||||
/// The index of this state in the states array.
|
||||
/// </summary>
|
||||
internal int number;
|
||||
#endif
|
||||
internal Dictionary<int, int> ParserTable; // Terminal -> ParseAction
|
||||
internal Dictionary<int, int> Goto; // NonTerminal -> State;
|
||||
internal int defaultAction; // = 0; // ParseAction
|
||||
|
||||
/// <summary>
|
||||
/// State transition data for this state. Pairs of elements of the
|
||||
/// goto array associate symbol ordinals with next state indices.
|
||||
/// The actions array is passed to another constructor.
|
||||
/// </summary>
|
||||
/// <param name="actions">The action list</param>c
|
||||
/// <param name="goToList">Next state data</param>
|
||||
public State( int[] actions, int[] goToList )
|
||||
: this( actions ) {
|
||||
Goto = new Dictionary<int, int>();
|
||||
for (int i = 0; i < goToList.Length; i += 2)
|
||||
Goto.Add( goToList[i], goToList[i + 1] );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Action data for this state. Pairs of elements of the
|
||||
/// action array associate action ordinals with each of
|
||||
/// those symbols that have actions in the current state.
|
||||
/// </summary>
|
||||
/// <param name="actions">The action array</param>
|
||||
public State( int[] actions ) {
|
||||
ParserTable = new Dictionary<int, int>();
|
||||
for (int i = 0; i < actions.Length; i += 2)
|
||||
ParserTable.Add( actions[i], actions[i + 1] );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the default action for this state.
|
||||
/// </summary>
|
||||
/// <param name="defaultAction">Ordinal of the default action</param>
|
||||
public State( int defaultAction ) {
|
||||
this.defaultAction = defaultAction;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the default action and the state transition table.
|
||||
/// </summary>
|
||||
/// <param name="defaultAction">The default action</param>
|
||||
/// <param name="goToList">Transitions from this state</param>
|
||||
public State( int defaultAction, int[] goToList )
|
||||
: this( defaultAction ) {
|
||||
Goto = new Dictionary<int, int>();
|
||||
for (int i = 0; i < goToList.Length; i += 2)
|
||||
Goto.Add( goToList[i], goToList[i + 1] );
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rule representation at runtime.
|
||||
/// </summary>
|
||||
#if EXPORT_GPPG
|
||||
public class Rule
|
||||
#else
|
||||
internal class Rule
|
||||
#endif
|
||||
{
|
||||
internal int LeftHandSide; // symbol
|
||||
internal int[] RightHandSide; // symbols
|
||||
|
||||
/// <summary>
|
||||
/// Rule constructor. This holds the ordinal of
|
||||
/// the left hand side symbol, and the list of
|
||||
/// right hand side symbols, in lexical order.
|
||||
/// </summary>
|
||||
/// <param name="left">The LHS non-terminal</param>
|
||||
/// <param name="right">The RHS symbols, in lexical order</param>
|
||||
public Rule( int left, int[] right ) {
|
||||
this.LeftHandSide = left;
|
||||
this.RightHandSide = right;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stack utility for the shift-reduce parser.
|
||||
/// GPPG parsers have three instances:
|
||||
/// (1) The parser state stack, T = QUT.Gppg.State,
|
||||
/// (2) The semantic value stack, T = TValue,
|
||||
/// (3) The location stack, T = TSpan.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
#if EXPORT_GPPG
|
||||
public class PushdownPrefixState<T>
|
||||
#else
|
||||
internal class PushdownPrefixState<T>
|
||||
#endif
|
||||
{
|
||||
// Note that we cannot use the BCL Stack<T> class
|
||||
// here as derived types need to index into stacks.
|
||||
//
|
||||
private T[] array = new T[8];
|
||||
private int tos = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Indexer for values of the stack below the top.
|
||||
/// </summary>
|
||||
/// <param name="index">index of the element, starting from the bottom</param>
|
||||
/// <returns>the selected element</returns>
|
||||
public T this[int index] { get { return array[index]; } }
|
||||
|
||||
/// <summary>
|
||||
/// The current depth of the stack.
|
||||
/// </summary>
|
||||
public int Depth { get { return tos; } }
|
||||
|
||||
internal void Push( T value ) {
|
||||
if (tos >= array.Length) {
|
||||
T[] newarray = new T[array.Length * 2];
|
||||
System.Array.Copy( array, newarray, tos );
|
||||
array = newarray;
|
||||
}
|
||||
array[tos++] = value;
|
||||
}
|
||||
|
||||
internal T Pop() {
|
||||
T rslt = array[--tos];
|
||||
array[tos] = default( T );
|
||||
return rslt;
|
||||
}
|
||||
|
||||
internal T TopElement() { return array[tos - 1]; }
|
||||
|
||||
internal bool IsEmpty() { return tos == 0; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
global using System;
|
||||
global using System.Linq;
|
||||
global using System.Collections.Generic;
|
||||
global using System.Collections.Immutable;
|
||||
@@ -0,0 +1 @@
|
||||
VITE_DATASTREAM_WEBSOCKET_URL=wss://localhost:8443/ws
|
||||
@@ -0,0 +1 @@
|
||||
VITE_DATASTREAM_WEBSOCKET_URL=wss://localhost:8443/ws
|
||||
@@ -0,0 +1,24 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
.DS_Store
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
@@ -0,0 +1,11 @@
|
||||
<Project Sdk="Microsoft.VisualStudio.JavaScript.Sdk/0.5.128-alpha">
|
||||
<PropertyGroup>
|
||||
<StartupCommand>npm run dev</StartupCommand>
|
||||
<JavaScriptTestRoot>src\</JavaScriptTestRoot>
|
||||
<JavaScriptTestFramework>Jest</JavaScriptTestFramework>
|
||||
<!-- Allows the build (or compile) script located on package.json to run on Build -->
|
||||
<ShouldRunBuildScript>true</ShouldRunBuildScript>
|
||||
<!-- Folder where production build objects will be placed -->
|
||||
<PublishAssetsDirectory>$(MSBuildProjectDirectory)\distill</PublishAssetsDirectory>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,8 @@
|
||||
# React + Vite
|
||||
|
||||
This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
|
||||
|
||||
Currently, two official plugins are available:
|
||||
|
||||
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
|
||||
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
|
||||
@@ -0,0 +1,36 @@
|
||||
import importPlugin from "eslint-plugin-import";
|
||||
import reactPkg from "eslint-plugin-react";
|
||||
const { configs: reactConfigs } = reactPkg;
|
||||
import js from "@eslint/js";
|
||||
import defineConfig from "./vite.config.js";
|
||||
|
||||
export default [
|
||||
js.configs.recommended,
|
||||
importPlugin.flatConfigs.recommended,
|
||||
reactConfigs.flat.recommended,
|
||||
reactConfigs.flat["jsx-runtime"],
|
||||
{
|
||||
files: ["**/*.{js,jsx}"],
|
||||
languageOptions: {
|
||||
ecmaVersion: "latest",
|
||||
sourceType: "module",
|
||||
globals: {
|
||||
console: "readonly"
|
||||
}
|
||||
},
|
||||
settings: {
|
||||
"import/resolver": {
|
||||
vite: {
|
||||
viteConfig: defineConfig({ mode: "development" })
|
||||
}
|
||||
}
|
||||
},
|
||||
rules: {
|
||||
semi: "error",
|
||||
"prefer-const": "error",
|
||||
"no-unused-vars": "warn",
|
||||
"import/no-dynamic-require": "warn",
|
||||
"import/no-nodejs-modules": "warn",
|
||||
}
|
||||
}
|
||||
];
|
||||
@@ -0,0 +1,13 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/ico" href="/logo.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>BTS Cloud Streams</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/src/main.jsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<clear />
|
||||
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
|
||||
</packageSources>
|
||||
<disabledPackageSources>
|
||||
<clear />
|
||||
</disabledPackageSources>
|
||||
</configuration>
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"name": "bts.datastreamwebapp.client",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@angular/material": "^18.2.8",
|
||||
"@emotion/react": "^11.13.3",
|
||||
"@emotion/styled": "^11.13.0",
|
||||
"@fontsource/noto-sans": "^5.1.0",
|
||||
"@material/data-table": "^15.0.0-canary.423edc3dc.0",
|
||||
"@mui/icons-material": "^6.1.4",
|
||||
"@mui/material": "^6.1.4",
|
||||
"@mui/x-data-grid": "^7.20.0",
|
||||
"bulma": "^1.0.2",
|
||||
"classnames": "^2.5.1",
|
||||
"react": "^18.3.1",
|
||||
"react-data-grid": "^7.0.0-beta.47",
|
||||
"react-data-table-component": "^7.6.2",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-json-view-lite": "^1.5.0",
|
||||
"react-pro-sidebar": "^1.1.0",
|
||||
"react-use-websocket": "^4.9.0",
|
||||
"rpc-websockets": "^9.0.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^18.3.11",
|
||||
"@types/react-dom": "^18.3.1",
|
||||
"@vitejs/plugin-react": "^4.3.2",
|
||||
"eslint": "^9.12.0",
|
||||
"@eslint/js": "^9.12.0",
|
||||
"eslint-plugin-import": "^2.31.0",
|
||||
"eslint-plugin-react": "^7.37.1",
|
||||
"eslint-plugin-react-hooks": "^5.0.0",
|
||||
"eslint-plugin-react-refresh": "^0.4.12",
|
||||
"eslint-import-resolver-vite": "^2.0.1",
|
||||
"react-mui-sidebar": "^1.3.8",
|
||||
"vite": "^5.4.9"
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 8.2 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 107 KiB |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
@@ -0,0 +1,40 @@
|
||||
import { Sidebar, Menu, MenuItem, Submenu, Logo } from "react-mui-sidebar";
|
||||
import './App.css';
|
||||
|
||||
const AnimatedSideBar = () => {
|
||||
return (
|
||||
<Sidebar className={"sidebar-container"} width={"270px"}>
|
||||
<Logo img="https://adminmart.com/wp-content/uploads/2024/03/logo-admin-mart-news.png">
|
||||
AdminMart
|
||||
</Logo>
|
||||
<Menu subHeading="HOME">
|
||||
<MenuItem link="/" badge="true">
|
||||
Modern
|
||||
</MenuItem>
|
||||
<MenuItem>eCommerce</MenuItem>
|
||||
<MenuItem>Analytical</MenuItem>
|
||||
</Menu>
|
||||
<Menu subHeading="APPS">
|
||||
<MenuItem>Chat</MenuItem>
|
||||
<MenuItem>Calendar</MenuItem>
|
||||
</Menu>
|
||||
<Menu subHeading="OTHERS">
|
||||
<Submenu title="Menu Level">
|
||||
<MenuItem>Post</MenuItem>
|
||||
<MenuItem>Details</MenuItem>
|
||||
<Submenu title="Level 2">
|
||||
<MenuItem>new</MenuItem>
|
||||
<MenuItem>Hello</MenuItem>
|
||||
</Submenu>
|
||||
</Submenu>
|
||||
|
||||
<MenuItem>Chip</MenuItem>
|
||||
<MenuItem target="_blank" link="google.com">
|
||||
External Link
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
</Sidebar>
|
||||
);
|
||||
};
|
||||
|
||||
export default AnimatedSideBar;
|
||||
@@ -0,0 +1,101 @@
|
||||
@use "@material/checkbox";
|
||||
@use "@material/icon-button";
|
||||
@use "@material/data-table/data-table";
|
||||
|
||||
.root-div {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.main-content-div {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.title-div {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.container {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.container-column {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.container-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
box.query-input-form {
|
||||
/* p: 2, display: "flex", flexFlow: "column", alignItems: "stretch" */
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
/* li.ps-menuitem-root:hover {
|
||||
background-color: #ff9922;
|
||||
} */
|
||||
|
||||
.container-row-centered {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
h1#main-header {
|
||||
padding: 4px 8px 4px 8px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
td:hover {
|
||||
background-color: cadetblue;
|
||||
}
|
||||
|
||||
td#cell-decimal {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
td#cell-integer {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
td#cell-string {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
td#cell-date-time {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* Sidebar.css */
|
||||
/* .sidebar-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
position: relative;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 100vh;
|
||||
background-color: #333;
|
||||
color: white;
|
||||
overflow: hidden;
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.sidebar.closed {
|
||||
width: 0;
|
||||
}
|
||||
|
||||
.sidebar.open {
|
||||
width: 250px;
|
||||
} */
|
||||
@@ -0,0 +1,173 @@
|
||||
import { ThemeProvider, CssBaseline, GlobalStyles } from '@mui/material';
|
||||
import QueryStatusView from './QueryStatusView';
|
||||
import useMediaQuery from '@mui/material/useMediaQuery';
|
||||
import QueryControl from './QueryControl';
|
||||
import DataTable from './DataTable';
|
||||
import { useState, useEffect, useMemo } from 'react';
|
||||
import useWebSocket, { ReadyState } from 'react-use-websocket';
|
||||
import Sidebar from './SideBar';
|
||||
import getTheme from './Theme';
|
||||
|
||||
import '@fontsource/noto-sans';
|
||||
import './App.css';
|
||||
import './SideBar.css';
|
||||
|
||||
const webSocketUrl = import.meta.env.VITE_DATASTREAM_WEBSOCKET_URL;
|
||||
// Always use the same subscription id (1), because we only show 1 table at a time.
|
||||
// The server will automatically dispose the previous subscription and start a new one
|
||||
// if we're currently subscribed to another query.
|
||||
const subscriptionId = "1";
|
||||
|
||||
var rpcReqIdCounter = 1;
|
||||
|
||||
function subscribeReq(query) {
|
||||
return {
|
||||
jsonrpc: "2.0",
|
||||
id: rpcReqIdCounter++,
|
||||
method: "subscribe",
|
||||
params: {
|
||||
subscription_id: subscriptionId,
|
||||
query: query
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function unsubscribeReq() {
|
||||
return {
|
||||
jsonrpc: "2.0",
|
||||
id: rpcReqIdCounter++,
|
||||
method: "unsubscribe",
|
||||
params: {
|
||||
subscription_id: subscriptionId,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const App = () => {
|
||||
const prefersDarkMode = useMediaQuery('(prefers-color-scheme: dark)');
|
||||
const theme = getTheme({ mode: prefersDarkMode ? 'dark' : 'light' });
|
||||
const globalStyles = {
|
||||
':root': {
|
||||
'--primary-color': theme.palette.primary.main,
|
||||
'--primary-dark-color': theme.palette.primary.dark,
|
||||
'--secondary-color': theme.palette.secondary.main,
|
||||
'--secondary-dark-color': theme.palette.secondary.dark,
|
||||
'--background-color': theme.palette.background.default,
|
||||
},
|
||||
};
|
||||
const [blueTable, setBlueTable] = useState({ columns: null, rows: null });
|
||||
const [queryError, setQueryError] = useState(null);
|
||||
const [queryState, setQueryState] = useState("Unsubscribed");
|
||||
const queryStateDetails = useMemo(() => {
|
||||
if (queryState == "Unsubscribed") {
|
||||
return "Enter query above, then click the play button to subscribe";
|
||||
}
|
||||
if (queryState == "Subscribed") {
|
||||
return null;
|
||||
}
|
||||
}, [queryState]);
|
||||
const [sidebarIsOpen, setSidebarIsOpen] = useState(false);
|
||||
const [cannedQuery, setCannedQuery] = useState(null);
|
||||
|
||||
const onCannedQueryClicked = (cannedQuery) => {
|
||||
console.info(`Executing canned query: ${JSON.stringify(cannedQuery)}`);
|
||||
const queryText = cannedQuery.query.join("\n");
|
||||
setCannedQuery({ queryText: queryText, clickTime: Date.now() });
|
||||
subscribe(queryText);
|
||||
};
|
||||
|
||||
const { sendJsonMessage, getWebSocket, readyState } = useWebSocket(
|
||||
webSocketUrl,
|
||||
{
|
||||
onOpen: (e) => console.info(`WebSocket open. ${JSON.stringify(e)}`),
|
||||
onClose: (e) => console.info(`WebSocket closed. ${JSON.stringify(e)}`),
|
||||
onError: (e) => console.error(`WebSocket error: ${JSON.stringify(e)}`),
|
||||
shouldReconnect: () => true,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
console.info(`WebSocket readyState: ${readyState}`)
|
||||
if (readyState != ReadyState.OPEN) {
|
||||
return;
|
||||
}
|
||||
const ws = getWebSocket();
|
||||
ws.onmessage = e => {
|
||||
console.info(`Received message: ${e.data}`);
|
||||
const msg = JSON.parse(e.data);
|
||||
setQueryError(msg.error);
|
||||
if (msg.error != null) {
|
||||
setQueryState("Error");
|
||||
} else if (msg.id != null) {
|
||||
setQueryState(msg.result.status);
|
||||
} else {
|
||||
console.assert(msg.params.subscription_id == subscriptionId);
|
||||
console.info(`Received rows: ${msg.params.table.all}`);
|
||||
setBlueTable({ columns: msg.params.table.columns, rows: msg.params.table.all });
|
||||
}
|
||||
};
|
||||
}, [getWebSocket, readyState]);
|
||||
|
||||
const subscribe = (query) => {
|
||||
const req = subscribeReq(query);
|
||||
console.info(`Subscribing: ${JSON.stringify(subscribeReq(query))}`);
|
||||
sendJsonMessage(req);
|
||||
};
|
||||
|
||||
const unsubscribe = () => {
|
||||
const req = unsubscribeReq();
|
||||
console.info(`Unsubscribing: ${JSON.stringify(req)}`);
|
||||
sendJsonMessage(req);
|
||||
};
|
||||
|
||||
const onOpened = () => {
|
||||
setSidebarIsOpen(true);
|
||||
};
|
||||
|
||||
const onClosed = () => {
|
||||
setSidebarIsOpen(false);
|
||||
};
|
||||
|
||||
const sidebarWidth = sidebarIsOpen ? '250px' : '65px';
|
||||
return (
|
||||
<ThemeProvider theme={theme}>
|
||||
<CssBaseline />
|
||||
<GlobalStyles styles={globalStyles} />
|
||||
<div className='root-div'>
|
||||
<div style={{
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'flex-start',
|
||||
flexWrap: 'nowrap',
|
||||
width: sidebarWidth,
|
||||
transition: 'width 0.3s ease',
|
||||
}}>
|
||||
<Sidebar onSelection={onCannedQueryClicked} onOpened={onOpened} onClosed={onClosed} />
|
||||
</div>
|
||||
<div style={{
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
left: sidebarWidth,
|
||||
width: '100%',
|
||||
transition: 'width 0.3s ease',
|
||||
}}>
|
||||
<div style={{ width: '100%', display: 'flex', flexDirection: 'column', alignItems: 'flex-start', margin: theme.spacing(2, 0, 0, 0) }}>
|
||||
<div style={{ width: '90%', rightMargin: '100px' }}>
|
||||
<QueryControl
|
||||
queryState={queryState}
|
||||
queryText={cannedQuery?.queryText}
|
||||
queryTextResetTime={cannedQuery?.clickTime}
|
||||
subscribe={subscribe}
|
||||
unsubscribe={unsubscribe} />
|
||||
</div>
|
||||
<div style={{ width: '90%', rightMargin: '100px' }}>
|
||||
<QueryStatusView queryState={queryState} details={queryStateDetails} error={queryError} />
|
||||
<DataTable columns={blueTable?.columns ?? []} rows={blueTable?.rows ?? []} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ThemeProvider>
|
||||
);
|
||||
};
|
||||
|
||||
export default App;
|
||||
@@ -0,0 +1,53 @@
|
||||
@use "@material/checkbox";
|
||||
@use "@material/icon-button";
|
||||
@use "@material/data-table/data-table";
|
||||
|
||||
.data-grid-container {
|
||||
overflow: auto;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
|
||||
.data-grid {
|
||||
max-height: 1000px;
|
||||
}
|
||||
|
||||
div[role=columnheader] {
|
||||
border-top: 0px;
|
||||
border-bottom: 0px;
|
||||
background-color: var(--primary-dark-color);
|
||||
}
|
||||
|
||||
/* div[role=columnheader] {
|
||||
border-top: 0px;
|
||||
border-bottom: 0px;
|
||||
background-color: var(--primary-dark-color);
|
||||
}
|
||||
|
||||
.rdg-row {
|
||||
border: 0px;
|
||||
border-top: 0px;
|
||||
border-bottom: 0px;
|
||||
background-color: rgba(var(--primary-dark-color), 0.8);
|
||||
color: var(--primary-color);
|
||||
}
|
||||
|
||||
.rdg-row-odd {
|
||||
border: 0px;
|
||||
border-top: 0px;
|
||||
border-bottom: 0px;
|
||||
background-color: var(--primary-dark-color);
|
||||
color: var(--primary-color);
|
||||
}
|
||||
|
||||
.rdg-cell {
|
||||
border-bottom: 0px;
|
||||
}
|
||||
|
||||
.rdg-cell.even {
|
||||
border-bottom: 5px;
|
||||
}
|
||||
|
||||
.rdg-cell.odd {
|
||||
border-bottom: 5px;
|
||||
} */
|
||||
@@ -0,0 +1,32 @@
|
||||
@use "@material/checkbox";
|
||||
@use "@material/icon-button";
|
||||
@use "@material/data-table/data-table";
|
||||
|
||||
th {
|
||||
font-size: large;
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
td {
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
td:hover {
|
||||
background-color: cadetblue;
|
||||
}
|
||||
|
||||
td#cell-decimal {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
td#cell-integer {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
td#cell-string {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
td#cell-date-time {
|
||||
text-align: center;
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import { useTheme } from '@mui/material/styles';
|
||||
import { DataGrid } from '@mui/x-data-grid';
|
||||
import './DataGrid.css';
|
||||
import { useMemo, useState } from 'react';
|
||||
|
||||
export default function DataTable({ columns, rows }) {
|
||||
const theme = useTheme();
|
||||
const [columnWidths, setColumnWidths] = useState({});
|
||||
|
||||
const handleColumnResize = (params) => {
|
||||
const newWidth = params.width;
|
||||
setColumnWidths((prevWidths) => ({
|
||||
...prevWidths,
|
||||
[params.colDef.field]: params.width,
|
||||
}));
|
||||
};
|
||||
|
||||
const getGridColDef = useMemo(() => {
|
||||
return col => {
|
||||
return {
|
||||
field: col.name,
|
||||
headerName: col.name,
|
||||
width: columnWidths[col.name],
|
||||
};
|
||||
};
|
||||
}, [columnWidths]);
|
||||
|
||||
return (
|
||||
<DataGrid
|
||||
className='data-grid-container'
|
||||
autosizeOnMount={false}
|
||||
columns={columns?.map(getGridColDef) ?? []}
|
||||
onColumnResize={handleColumnResize}
|
||||
rows={rows ?? []}
|
||||
sx={{
|
||||
margin: theme.spacing(2, 0, 0, 0),
|
||||
borderColor: 'primary.main',
|
||||
backgroundColor: 'primary.dark',
|
||||
color: 'text.primary',
|
||||
'& .MuiDataGrid-columnHeader': {
|
||||
color: 'primary.main',
|
||||
fontWeight: 700,
|
||||
backgroundColor: 'primary.dark'
|
||||
},
|
||||
'& .MuiDataGrid-filler': {
|
||||
color: 'primary.main',
|
||||
fontWeight: 700,
|
||||
backgroundColor: 'primary.dark'
|
||||
},
|
||||
'& .MuiDataGrid-cell': {
|
||||
color: 'text.primary',
|
||||
},
|
||||
'& .MuiDataGrid-cell:hover': {
|
||||
color: 'primary.main',
|
||||
},
|
||||
'& .MuiDataGrid-row': {
|
||||
'--DataGrid-rowBorderColor': 'secondary.dark'
|
||||
}
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
DataTable.propTypes = {
|
||||
columns: PropTypes.arrayOf(
|
||||
PropTypes.shape({
|
||||
name: PropTypes.string.isRequired,
|
||||
type: PropTypes.string.isRequired,
|
||||
})
|
||||
).isRequired,
|
||||
rows: PropTypes.arrayOf(PropTypes.array).isRequired,
|
||||
apiRef: PropTypes.object,
|
||||
};
|
||||
@@ -0,0 +1,119 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import DataTable from './DataTable';
|
||||
import { useRef, useState, useEffect } from 'react';
|
||||
import { useGridApiRef } from '@mui/x-data-grid';
|
||||
import Box from '@mui/material/Box';
|
||||
import Button from '@mui/material/Button';
|
||||
import Grid from '@mui/material/Grid';
|
||||
import Paper from '@mui/material/Paper';
|
||||
import PlayArrowIcon from '@mui/icons-material/PlayArrow';
|
||||
import StopIcon from '@mui/icons-material/Stop';
|
||||
import TextField from '@mui/material/TextField';
|
||||
import Tooltip from '@mui/material/Tooltip';
|
||||
|
||||
const QueryControl = (props) => {
|
||||
const { queryState, queryText, queryTextResetTime, subscribe, unsubscribe } = props;
|
||||
// const theme = useTheme();
|
||||
let textInput = useRef();
|
||||
const [queryTextChangeTime, setQueryTextChangeTime] = useState(null);
|
||||
useEffect(() => {
|
||||
if (queryText == null || textInput.current == null) {
|
||||
return;
|
||||
}
|
||||
// Init text field (unless a non-empty string is already present, or the user has modified
|
||||
// the query - we don't want to overwrite their changes).
|
||||
if (queryTextChangeTime == null || queryTextResetTime > queryTextChangeTime) {
|
||||
console.info(`Initializing query text: ${queryText}`)
|
||||
textInput.current.value = queryText;
|
||||
}
|
||||
}, [queryText, queryTextChangeTime, queryTextResetTime]);
|
||||
const onClearClick = () => {
|
||||
textInput.current.value = '';
|
||||
};
|
||||
|
||||
const onRunClick = () => {
|
||||
subscribe(textInput.current.value);
|
||||
};
|
||||
|
||||
const onStopClick = () => {
|
||||
unsubscribe();
|
||||
};
|
||||
|
||||
const onKeyDown = (e) => {
|
||||
// Detect keyboard shortcuts.
|
||||
// Ctrl+Enter : Run
|
||||
if (e.ctrlKey && e.key === 'Enter') {
|
||||
onRunClick();
|
||||
}
|
||||
};
|
||||
|
||||
const onChange = (e) => {
|
||||
// So we know not to overwrite the changes with the canned query on re-render
|
||||
setQueryTextChangeTime(Date.now());
|
||||
};
|
||||
|
||||
return (
|
||||
<Box sx={{ display: "flex", flexFlow: "column" }}>
|
||||
<Paper elevation={3} sx={{ color: 'primary.main' }}>
|
||||
<Box sx={{ p: 2 }}>
|
||||
<TextField
|
||||
fullWidth
|
||||
multiline
|
||||
rows={10}
|
||||
variant="outlined"
|
||||
onChange={onChange}
|
||||
onKeyDown={onKeyDown}
|
||||
inputRef={textInput}
|
||||
placeholder="Enter Query..."
|
||||
/>
|
||||
</Box>
|
||||
<Box sx={{ p: 2, borderTop: 1 }}>
|
||||
<Grid container spacing={2} justifyContent="flex-start">
|
||||
<Grid item xs>
|
||||
<Tooltip title="Clear Query Text">
|
||||
<Button onClick={onClearClick} sx={{ padding: '11px', color: 'text.dark' }}>
|
||||
Clear
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<Tooltip title="Run (Ctrl+Enter)">
|
||||
<Button onClick={onRunClick} sx={{
|
||||
color: `queryStartButton.${queryState}.color`,
|
||||
bgcolor: `queryStartButton.${queryState}.backgroundColor`,
|
||||
padding: '11px'
|
||||
}}>
|
||||
<PlayArrowIcon />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<Tooltip title="Stop">
|
||||
<Button onClick={onStopClick} sx={{
|
||||
color: `queryStopButton.${queryState}.color`,
|
||||
bgcolor: `queryStopButton.${queryState}.backgroundColor`,
|
||||
padding: '11px'
|
||||
}}>
|
||||
<StopIcon />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Box>
|
||||
</Paper>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
QueryControl.propTypes = {
|
||||
columns: PropTypes.array,
|
||||
rows: PropTypes.array,
|
||||
isRunning: PropTypes.bool,
|
||||
queryText: PropTypes.string,
|
||||
queryTextResetTime: PropTypes.number,
|
||||
queryState: PropTypes.string,
|
||||
subscribe: PropTypes.func,
|
||||
unsubscribe: PropTypes.func,
|
||||
};
|
||||
|
||||
export default QueryControl;
|
||||
@@ -0,0 +1,73 @@
|
||||
import { useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Box, Typography, Collapse } from '@mui/material';
|
||||
import Alert from '@mui/material/Alert';
|
||||
import AlertTitle from '@mui/material/AlertTitle';
|
||||
import { useTheme } from '@mui/material/styles';
|
||||
import { alpha } from '@mui/system';
|
||||
|
||||
const QueryStatusView = ({ queryState, details, error }) => {
|
||||
const theme = useTheme();
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
let header = queryState;
|
||||
let headerContent = null;
|
||||
const detailElements = [];
|
||||
let severity = queryState == "Subscribed" ? "success" : "info";
|
||||
let cursor = details == null ? "default" : "pointer";
|
||||
if (error != null) {
|
||||
severity = "error";
|
||||
cursor = "pointer";
|
||||
header = `Error Code: ${error.code}`;
|
||||
headerContent = error.message;
|
||||
detailElements.push(<Typography key="error-msg" variant="body1">{error.data.error_message}</Typography>);
|
||||
detailElements.push(<Typography key="error-details" variant="subtitle1">Stack Trace:</Typography>);
|
||||
(error.data.stack_trace ?? []).forEach((line, idx) => detailElements.push(
|
||||
<Typography key={`stacktrace-${idx}`} variant="body2" component="pre" sx={{ whiteSpace: 'pre-wrap' }}>
|
||||
{line}
|
||||
</Typography>));
|
||||
} else if (details != null) {
|
||||
detailElements.push(<Typography key="status-msg" variant="body1">{details}</Typography>);
|
||||
}
|
||||
return (
|
||||
<Box sx={{ margin: theme.spacing(2, 0, 0, 0) }}>
|
||||
<Alert
|
||||
severity={severity}
|
||||
onClick={() => setOpen(!open)}
|
||||
sx={{
|
||||
margin: theme.spacing(2, 0, 0, 0),
|
||||
cursor: cursor,
|
||||
}}>
|
||||
<AlertTitle>{header}</AlertTitle>
|
||||
{headerContent}
|
||||
</Alert>
|
||||
{detailElements.length == 0
|
||||
? null
|
||||
: <Collapse in={open}>
|
||||
<Box
|
||||
sx={{
|
||||
backgroundColor: alpha(theme.palette[severity].light, 0.75),
|
||||
color: theme.palette[severity].contrastText,
|
||||
padding: theme.spacing(2),
|
||||
marginTop: theme.spacing(0),
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
}}
|
||||
>
|
||||
{detailElements}
|
||||
</Box>
|
||||
</Collapse>}
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
QueryStatusView.propTypes = {
|
||||
queryState: PropTypes.string,
|
||||
details: PropTypes.string,
|
||||
error: PropTypes.shape({
|
||||
code: PropTypes.number,
|
||||
message: PropTypes.string,
|
||||
data: PropTypes.object,
|
||||
})
|
||||
};
|
||||
|
||||
export default QueryStatusView;
|
||||
@@ -0,0 +1,27 @@
|
||||
import 'react-data-grid/lib/styles.css';
|
||||
import PropTypes from 'prop-types';
|
||||
import DataGrid from 'react-data-grid';
|
||||
import './DataGrid.css';
|
||||
|
||||
function getGridColDef(col) {
|
||||
return {
|
||||
key: col.name,
|
||||
name: col.name,
|
||||
};
|
||||
}
|
||||
|
||||
export default function ReactDataGrid({columns, rows}) {
|
||||
return (
|
||||
<DataGrid className={"data-grid"} rows={rows} columns={columns.map(getGridColDef)} />
|
||||
);
|
||||
}
|
||||
|
||||
ReactDataGrid.propTypes = {
|
||||
columns: PropTypes.arrayOf(
|
||||
PropTypes.shape({
|
||||
name: PropTypes.string.isRequired,
|
||||
type: PropTypes.string.isRequired,
|
||||
})
|
||||
).isRequired,
|
||||
rows: PropTypes.arrayOf(PropTypes.array).isRequired,
|
||||
};
|
||||
@@ -0,0 +1,98 @@
|
||||
/* Sidebar.css */
|
||||
.app-container {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
flex-direction: row;
|
||||
justify-content: flex-start;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-start;
|
||||
align-items: flex-start;
|
||||
background-color: transparent;
|
||||
color: white;
|
||||
overflow: hidden;
|
||||
transition: width 0.3s ease;
|
||||
}
|
||||
|
||||
.sidebar.open {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.sidebar.closed {
|
||||
width: 0%;
|
||||
}
|
||||
|
||||
.sidebar-toggle-button {
|
||||
border: 0px;
|
||||
border-radius: 50%;
|
||||
box-shadow: rgba(9, 30, 66, 0.08) 0px 0px 0px 1px, rgba(9, 30, 66, 0.08) 0px 2px 4px 1px;
|
||||
color: var(--primary-color);
|
||||
cursor: pointer;
|
||||
height: 24px;
|
||||
opacity: 1;
|
||||
outline: 0px;
|
||||
padding: 0px;
|
||||
background-color: transparent;
|
||||
transition: background-color 100ms linear 0s, color 100ms linear 0s, opacity 300ms cubic-bezier(0.2, 0, 0, 1) 0s, transform 300ms cubic-bezier(0.2, 0, 0, 1) 0s;
|
||||
width: 20%;
|
||||
}
|
||||
|
||||
.sidebar-toggle-button:hover {
|
||||
transition: background-color 100ms linear 0s, color 100ms linear 0s, opacity 300ms cubic-bezier(0.2, 0, 0, 1) 0s, transform 300ms cubic-bezier(0.2, 0, 0, 1) 0s;
|
||||
}
|
||||
|
||||
.main-content.open {
|
||||
width: 165px;
|
||||
transition: width 0.3s ease;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.main-content.closed {
|
||||
width: 0%;
|
||||
/* min-width: 25px; */
|
||||
transition: width 0.3s ease;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.sidebar-menu-item {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.sidebar-menu-item.open {
|
||||
width: 100%;
|
||||
/* justify-content: flex-start; */
|
||||
transition: width 0.3s ease;
|
||||
}
|
||||
|
||||
.sidebar-menu-item.closed {
|
||||
width: 0%;
|
||||
min-width: 0px;
|
||||
/* justify-content: flex-start; */
|
||||
transition: width 0.3s ease;
|
||||
}
|
||||
|
||||
.sidebar-menu-item-content.open {
|
||||
width: 100%;
|
||||
/* justify-content: flex-start; */
|
||||
transition: width 0.3s ease;
|
||||
}
|
||||
|
||||
.sidebar-menu-item-content.closed {
|
||||
width: 0px;
|
||||
/* justify-content: flex-start; */
|
||||
transition: width 0.3s ease;
|
||||
}
|
||||
|
||||
/* Ensure span can shrink */
|
||||
.button-text {
|
||||
display: block; /* Make span a block element */
|
||||
width: 100%; /* Ensure it takes the full width of its parent */
|
||||
overflow: hidden; /* Hide any overflow content */
|
||||
white-space: nowrap; /* Prevent text wrapping */
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import Button from '@mui/material/Button';
|
||||
import { useTheme } from '@mui/material/styles';
|
||||
import PropTypes from 'prop-types';
|
||||
import Tooltip from '@mui/material/Tooltip';
|
||||
import ChevronLeftRounded from "@mui/icons-material/ChevronLeftRounded";
|
||||
import ChevronRightRounded from '@mui/icons-material/ChevronRightRounded';
|
||||
import FileCopyIcon from '@mui/icons-material/FileCopy';
|
||||
import './SideBar.css';
|
||||
|
||||
const Sidebar = ({ onSelection, onOpened, onClosed }) => {
|
||||
const theme = useTheme();
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [cannedQueries, setCannedQueries] = useState([]);
|
||||
const Icon = isOpen ? ChevronLeftRounded : ChevronRightRounded;
|
||||
|
||||
const toggleIsOpen = () => {
|
||||
if (isOpen) {
|
||||
setIsOpen(false);
|
||||
if (onClosed != null) {
|
||||
onClosed();
|
||||
}
|
||||
} else {
|
||||
setIsOpen(true);
|
||||
if (onOpened != null) {
|
||||
onOpened();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const onMenuItemClick = (event, cannedQuery) => {
|
||||
console.info(`menu item clicked: ${cannedQuery.name}`);
|
||||
onSelection(cannedQuery);
|
||||
};
|
||||
|
||||
// const onMenuItemClick = async (event, cannedQuery) => {
|
||||
// try {
|
||||
// await navigator.clipboard.writeText(cannedQuery.query.join("\n"));
|
||||
// alert(`Copied ${cannedQuery.name} to clipboard`);
|
||||
// } catch (err) {
|
||||
// console.error('Failed to copy query text: ', err);
|
||||
// }
|
||||
// };
|
||||
|
||||
useEffect(() => {
|
||||
const fetchCannedQueries = async () => {
|
||||
try {
|
||||
const response = await fetch('api/cannedqueries');
|
||||
const data = await response.json();
|
||||
setCannedQueries(data);
|
||||
} catch (error) {
|
||||
console.error('Error fetching WebSocket config:', error);
|
||||
}
|
||||
};
|
||||
fetchCannedQueries();
|
||||
}, []);
|
||||
|
||||
const mainContentClass = `main-content ${isOpen ? 'open' : 'closed'}`;
|
||||
const menuItemClass = `sidebar-menu-item ${isOpen ? 'open' : 'closed'}`;
|
||||
const menuItemContentClass = `sidebar-menu-item-content ${isOpen ? 'open' : 'closed'}`;
|
||||
const toggleButtonTitle = `${isOpen ? 'Hide' : 'Show'} Common Queries`;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={"sidebar"}
|
||||
style={{
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'flexStart',
|
||||
alignItems: 'flexStart',
|
||||
margin: theme.spacing(2, 0, 0, 0)
|
||||
}}
|
||||
>
|
||||
<div className={mainContentClass}>
|
||||
{cannedQueries.map(cq =>
|
||||
<Button key={cq.name} className={menuItemClass} onClick={(event) => onMenuItemClick(event, cq)}>
|
||||
<div className={menuItemContentClass}>
|
||||
<span className='button-text'>{cq.name}</span>
|
||||
</div>
|
||||
</Button>)
|
||||
}
|
||||
{/* {cannedQueries.map(cq =>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
startIcon={<FileCopyIcon />}
|
||||
onClick={onMenuItemClick}
|
||||
>
|
||||
<div className={menuItemContentClass}>
|
||||
<span className='button-text'>{cq.name}</span>
|
||||
</div>
|
||||
</Button>)} */}
|
||||
</div>
|
||||
<Tooltip title={toggleButtonTitle}>
|
||||
<Button onClick={toggleIsOpen}>
|
||||
<Icon className="w-5 h-5" />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Sidebar;
|
||||
|
||||
Sidebar.propTypes = {
|
||||
onSelection: PropTypes.func,
|
||||
onOpened: PropTypes.func,
|
||||
onClosed: PropTypes.func,
|
||||
};
|
||||
@@ -0,0 +1,112 @@
|
||||
import { createTheme } from '@mui/material/styles';
|
||||
import PropTypes from 'prop-types';
|
||||
import '@fontsource/noto-sans';
|
||||
import './App.css';
|
||||
|
||||
const getLightPalette = () => {
|
||||
return {
|
||||
mode: 'light',
|
||||
primary: {
|
||||
light: '#6573c3',
|
||||
main: '#3f51b5',
|
||||
dark: '#2c387e',
|
||||
contrastText: '#ffffff',
|
||||
},
|
||||
secondary: {
|
||||
light: '#f73378',
|
||||
main: '#f50057',
|
||||
dark: '#ab003c',
|
||||
contrastText: '#ffffff',
|
||||
},
|
||||
text: {
|
||||
primary: '#000000c4',
|
||||
secondary: '#00000086',
|
||||
disabled: '#0000005b',
|
||||
hint: '#0000005b',
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
const getDarkPalette = () => {
|
||||
return {
|
||||
mode: 'dark',
|
||||
primary: {
|
||||
light: '#bcc5ff',
|
||||
main: '#33baf9',
|
||||
dark: '#202334',
|
||||
contrastText: '#78a2ac',
|
||||
},
|
||||
secondary: {
|
||||
light: '#9fd0b8',
|
||||
main: '#5eb289',
|
||||
dark: '#ffffff12',
|
||||
contrastText: '#c8d4f7',
|
||||
},
|
||||
action: {
|
||||
hoverOpacity: 0.08
|
||||
},
|
||||
text: {
|
||||
primary: '#eaf8f8',
|
||||
dark: '#eaf8f8a0'
|
||||
},
|
||||
queryStartButton: {
|
||||
Subscribed: {
|
||||
color: '#33baf9',
|
||||
backgroundColor: '#ffffff40',
|
||||
},
|
||||
Unsubscribed: {
|
||||
color: '#ffffff40',
|
||||
backgroundColor: '#ffffff00',
|
||||
}
|
||||
},
|
||||
queryStopButton: {
|
||||
Subscribed: {
|
||||
color: '#ff4444a0',
|
||||
backgroundColor: '#ffffff40',
|
||||
},
|
||||
Unsubscribed: {
|
||||
color: '#ff444450',
|
||||
backgroundColor: '#ffffff00',
|
||||
}
|
||||
},
|
||||
error: {
|
||||
light: '#e57373',
|
||||
main: '#f44336',
|
||||
dark: '#d32f2f',
|
||||
contrastText: '#fff',
|
||||
},
|
||||
warning: {
|
||||
light: '#ffb74d',
|
||||
main: '#ff9800',
|
||||
dark: '#f57c00',
|
||||
contrastText: '#000',
|
||||
},
|
||||
info: {
|
||||
light: '#64b5f6',
|
||||
main: '#2196f3',
|
||||
dark: '#303030',
|
||||
contrastText: '#fff',
|
||||
},
|
||||
success: {
|
||||
light: '#81c784',
|
||||
main: '#4caf50',
|
||||
dark: '#388e3c',
|
||||
contrastText: '#000',
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
const getTheme = ({ mode }) => {
|
||||
return createTheme({
|
||||
typography: {
|
||||
fontFamily: '"Helvetica"'
|
||||
},
|
||||
palette: mode == 'dark' ? getDarkPalette() : getLightPalette()
|
||||
});
|
||||
};
|
||||
|
||||
export default getTheme;
|
||||
|
||||
getTheme.propTypes = {
|
||||
mode: PropTypes.string.isRequired,
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="35.93" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 228"><path fill="#00D8FF" d="M210.483 73.824a171.49 171.49 0 0 0-8.24-2.597c.465-1.9.893-3.777 1.273-5.621c6.238-30.281 2.16-54.676-11.769-62.708c-13.355-7.7-35.196.329-57.254 19.526a171.23 171.23 0 0 0-6.375 5.848a155.866 155.866 0 0 0-4.241-3.917C100.759 3.829 77.587-4.822 63.673 3.233C50.33 10.957 46.379 33.89 51.995 62.588a170.974 170.974 0 0 0 1.892 8.48c-3.28.932-6.445 1.924-9.474 2.98C17.309 83.498 0 98.307 0 113.668c0 15.865 18.582 31.778 46.812 41.427a145.52 145.52 0 0 0 6.921 2.165a167.467 167.467 0 0 0-2.01 9.138c-5.354 28.2-1.173 50.591 12.134 58.266c13.744 7.926 36.812-.22 59.273-19.855a145.567 145.567 0 0 0 5.342-4.923a168.064 168.064 0 0 0 6.92 6.314c21.758 18.722 43.246 26.282 56.54 18.586c13.731-7.949 18.194-32.003 12.4-61.268a145.016 145.016 0 0 0-1.535-6.842c1.62-.48 3.21-.974 4.76-1.488c29.348-9.723 48.443-25.443 48.443-41.52c0-15.417-17.868-30.326-45.517-39.844Zm-6.365 70.984c-1.4.463-2.836.91-4.3 1.345c-3.24-10.257-7.612-21.163-12.963-32.432c5.106-11 9.31-21.767 12.459-31.957c2.619.758 5.16 1.557 7.61 2.4c23.69 8.156 38.14 20.213 38.14 29.504c0 9.896-15.606 22.743-40.946 31.14Zm-10.514 20.834c2.562 12.94 2.927 24.64 1.23 33.787c-1.524 8.219-4.59 13.698-8.382 15.893c-8.067 4.67-25.32-1.4-43.927-17.412a156.726 156.726 0 0 1-6.437-5.87c7.214-7.889 14.423-17.06 21.459-27.246c12.376-1.098 24.068-2.894 34.671-5.345a134.17 134.17 0 0 1 1.386 6.193ZM87.276 214.515c-7.882 2.783-14.16 2.863-17.955.675c-8.075-4.657-11.432-22.636-6.853-46.752a156.923 156.923 0 0 1 1.869-8.499c10.486 2.32 22.093 3.988 34.498 4.994c7.084 9.967 14.501 19.128 21.976 27.15a134.668 134.668 0 0 1-4.877 4.492c-9.933 8.682-19.886 14.842-28.658 17.94ZM50.35 144.747c-12.483-4.267-22.792-9.812-29.858-15.863c-6.35-5.437-9.555-10.836-9.555-15.216c0-9.322 13.897-21.212 37.076-29.293c2.813-.98 5.757-1.905 8.812-2.773c3.204 10.42 7.406 21.315 12.477 32.332c-5.137 11.18-9.399 22.249-12.634 32.792a134.718 134.718 0 0 1-6.318-1.979Zm12.378-84.26c-4.811-24.587-1.616-43.134 6.425-47.789c8.564-4.958 27.502 2.111 47.463 19.835a144.318 144.318 0 0 1 3.841 3.545c-7.438 7.987-14.787 17.08-21.808 26.988c-12.04 1.116-23.565 2.908-34.161 5.309a160.342 160.342 0 0 1-1.76-7.887Zm110.427 27.268a347.8 347.8 0 0 0-7.785-12.803c8.168 1.033 15.994 2.404 23.343 4.08c-2.206 7.072-4.956 14.465-8.193 22.045a381.151 381.151 0 0 0-7.365-13.322Zm-45.032-43.861c5.044 5.465 10.096 11.566 15.065 18.186a322.04 322.04 0 0 0-30.257-.006c4.974-6.559 10.069-12.652 15.192-18.18ZM82.802 87.83a323.167 323.167 0 0 0-7.227 13.238c-3.184-7.553-5.909-14.98-8.134-22.152c7.304-1.634 15.093-2.97 23.209-3.984a321.524 321.524 0 0 0-7.848 12.897Zm8.081 65.352c-8.385-.936-16.291-2.203-23.593-3.793c2.26-7.3 5.045-14.885 8.298-22.6a321.187 321.187 0 0 0 7.257 13.246c2.594 4.48 5.28 8.868 8.038 13.147Zm37.542 31.03c-5.184-5.592-10.354-11.779-15.403-18.433c4.902.192 9.899.29 14.978.29c5.218 0 10.376-.117 15.453-.343c-4.985 6.774-10.018 12.97-15.028 18.486Zm52.198-57.817c3.422 7.8 6.306 15.345 8.596 22.52c-7.422 1.694-15.436 3.058-23.88 4.071a382.417 382.417 0 0 0 7.859-13.026a347.403 347.403 0 0 0 7.425-13.565Zm-16.898 8.101a358.557 358.557 0 0 1-12.281 19.815a329.4 329.4 0 0 1-23.444.823c-7.967 0-15.716-.248-23.178-.732a310.202 310.202 0 0 1-12.513-19.846h.001a307.41 307.41 0 0 1-10.923-20.627a310.278 310.278 0 0 1 10.89-20.637l-.001.001a307.318 307.318 0 0 1 12.413-19.761c7.613-.576 15.42-.876 23.31-.876H128c7.926 0 15.743.303 23.354.883a329.357 329.357 0 0 1 12.335 19.695a358.489 358.489 0 0 1 11.036 20.54a329.472 329.472 0 0 1-11 20.722Zm22.56-122.124c8.572 4.944 11.906 24.881 6.52 51.026c-.344 1.668-.73 3.367-1.15 5.09c-10.622-2.452-22.155-4.275-34.23-5.408c-7.034-10.017-14.323-19.124-21.64-27.008a160.789 160.789 0 0 1 5.888-5.4c18.9-16.447 36.564-22.941 44.612-18.3ZM128 90.808c12.625 0 22.86 10.235 22.86 22.86s-10.235 22.86-22.86 22.86s-22.86-10.235-22.86-22.86s10.235-22.86 22.86-22.86Z"></path></svg>
|
||||
|
After Width: | Height: | Size: 4.0 KiB |
@@ -0,0 +1,51 @@
|
||||
.dark-high-contrast {
|
||||
--md-sys-color-primary: rgb(251 250 255);
|
||||
--md-sys-color-surface-tint: rgb(165 200 255);
|
||||
--md-sys-color-on-primary: rgb(0 0 0);
|
||||
--md-sys-color-primary-container: rgb(173 204 255);
|
||||
--md-sys-color-on-primary-container: rgb(0 0 0);
|
||||
--md-sys-color-secondary: rgb(250 250 255);
|
||||
--md-sys-color-on-secondary: rgb(0 0 0);
|
||||
--md-sys-color-secondary-container: rgb(159 208 255);
|
||||
--md-sys-color-on-secondary-container: rgb(0 0 0);
|
||||
--md-sys-color-tertiary: rgb(255 249 251);
|
||||
--md-sys-color-on-tertiary: rgb(0 0 0);
|
||||
--md-sys-color-tertiary-container: rgb(222 193 231);
|
||||
--md-sys-color-on-tertiary-container: rgb(0 0 0);
|
||||
--md-sys-color-error: rgb(255 249 249);
|
||||
--md-sys-color-on-error: rgb(0 0 0);
|
||||
--md-sys-color-error-container: rgb(255 186 177);
|
||||
--md-sys-color-on-error-container: rgb(0 0 0);
|
||||
--md-sys-color-background: rgb(17 19 24);
|
||||
--md-sys-color-on-background: rgb(225 226 233);
|
||||
--md-sys-color-surface: rgb(17 19 24);
|
||||
--md-sys-color-on-surface: rgb(255 255 255);
|
||||
--md-sys-color-surface-variant: rgb(67 71 78);
|
||||
--md-sys-color-on-surface-variant: rgb(251 250 255);
|
||||
--md-sys-color-outline: rgb(200 202 212);
|
||||
--md-sys-color-outline-variant: rgb(200 202 212);
|
||||
--md-sys-color-shadow: rgb(0 0 0);
|
||||
--md-sys-color-scrim: rgb(0 0 0);
|
||||
--md-sys-color-inverse-surface: rgb(225 226 233);
|
||||
--md-sys-color-inverse-on-surface: rgb(0 0 0);
|
||||
--md-sys-color-inverse-primary: rgb(0 42 83);
|
||||
--md-sys-color-primary-fixed: rgb(219 231 255);
|
||||
--md-sys-color-on-primary-fixed: rgb(0 0 0);
|
||||
--md-sys-color-primary-fixed-dim: rgb(173 204 255);
|
||||
--md-sys-color-on-primary-fixed-variant: rgb(0 22 49);
|
||||
--md-sys-color-secondary-fixed: rgb(214 233 255);
|
||||
--md-sys-color-on-secondary-fixed: rgb(0 0 0);
|
||||
--md-sys-color-secondary-fixed-dim: rgb(159 208 255);
|
||||
--md-sys-color-on-secondary-fixed-variant: rgb(0 24 42);
|
||||
--md-sys-color-tertiary-fixed: rgb(249 222 255);
|
||||
--md-sys-color-on-tertiary-fixed: rgb(0 0 0);
|
||||
--md-sys-color-tertiary-fixed-dim: rgb(222 193 231);
|
||||
--md-sys-color-on-tertiary-fixed-variant: rgb(33 14 42);
|
||||
--md-sys-color-surface-dim: rgb(17 19 24);
|
||||
--md-sys-color-surface-bright: rgb(55 57 62);
|
||||
--md-sys-color-surface-container-lowest: rgb(12 14 19);
|
||||
--md-sys-color-surface-container-low: rgb(25 28 32);
|
||||
--md-sys-color-surface-container: rgb(29 32 36);
|
||||
--md-sys-color-surface-container-high: rgb(40 42 47);
|
||||
--md-sys-color-surface-container-highest: rgb(50 53 58);
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
.dark-medium-contrast {
|
||||
--md-sys-color-primary: rgb(173 204 255);
|
||||
--md-sys-color-surface-tint: rgb(165 200 255);
|
||||
--md-sys-color-on-primary: rgb(0 22 49);
|
||||
--md-sys-color-primary-container: rgb(112 146 198);
|
||||
--md-sys-color-on-primary-container: rgb(0 0 0);
|
||||
--md-sys-color-secondary: rgb(159 208 255);
|
||||
--md-sys-color-on-secondary: rgb(0 24 42);
|
||||
--md-sys-color-secondary-container: rgb(100 149 193);
|
||||
--md-sys-color-on-secondary-container: rgb(0 0 0);
|
||||
--md-sys-color-tertiary: rgb(222 193 231);
|
||||
--md-sys-color-on-tertiary: rgb(33 14 42);
|
||||
--md-sys-color-tertiary-container: rgb(162 136 171);
|
||||
--md-sys-color-on-tertiary-container: rgb(0 0 0);
|
||||
--md-sys-color-error: rgb(255 186 177);
|
||||
--md-sys-color-on-error: rgb(55 0 1);
|
||||
--md-sys-color-error-container: rgb(255 84 73);
|
||||
--md-sys-color-on-error-container: rgb(0 0 0);
|
||||
--md-sys-color-background: rgb(17 19 24);
|
||||
--md-sys-color-on-background: rgb(225 226 233);
|
||||
--md-sys-color-surface: rgb(17 19 24);
|
||||
--md-sys-color-on-surface: rgb(251 250 255);
|
||||
--md-sys-color-surface-variant: rgb(67 71 78);
|
||||
--md-sys-color-on-surface-variant: rgb(200 202 212);
|
||||
--md-sys-color-outline: rgb(160 163 171);
|
||||
--md-sys-color-outline-variant: rgb(128 131 139);
|
||||
--md-sys-color-shadow: rgb(0 0 0);
|
||||
--md-sys-color-scrim: rgb(0 0 0);
|
||||
--md-sys-color-inverse-surface: rgb(225 226 233);
|
||||
--md-sys-color-inverse-on-surface: rgb(40 42 47);
|
||||
--md-sys-color-inverse-primary: rgb(35 73 120);
|
||||
--md-sys-color-primary-fixed: rgb(212 227 255);
|
||||
--md-sys-color-on-primary-fixed: rgb(0 17 40);
|
||||
--md-sys-color-primary-fixed-dim: rgb(165 200 255);
|
||||
--md-sys-color-on-primary-fixed-variant: rgb(10 55 100);
|
||||
--md-sys-color-secondary-fixed: rgb(206 229 255);
|
||||
--md-sys-color-on-secondary-fixed: rgb(0 18 34);
|
||||
--md-sys-color-secondary-fixed-dim: rgb(154 203 250);
|
||||
--md-sys-color-on-secondary-fixed-variant: rgb(0 57 91);
|
||||
--md-sys-color-tertiary-fixed: rgb(247 216 255);
|
||||
--md-sys-color-on-tertiary-fixed: rgb(28 9 37);
|
||||
--md-sys-color-tertiary-fixed-dim: rgb(218 189 226);
|
||||
--md-sys-color-on-tertiary-fixed-variant: rgb(67 46 76);
|
||||
--md-sys-color-surface-dim: rgb(17 19 24);
|
||||
--md-sys-color-surface-bright: rgb(55 57 62);
|
||||
--md-sys-color-surface-container-lowest: rgb(12 14 19);
|
||||
--md-sys-color-surface-container-low: rgb(25 28 32);
|
||||
--md-sys-color-surface-container: rgb(29 32 36);
|
||||
--md-sys-color-surface-container-high: rgb(40 42 47);
|
||||
--md-sys-color-surface-container-highest: rgb(50 53 58);
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
.dark {
|
||||
--md-sys-color-primary: rgb(165 200 255);
|
||||
--md-sys-color-surface-tint: rgb(165 200 255);
|
||||
--md-sys-color-on-primary: rgb(0 49 94);
|
||||
--md-sys-color-primary-container: rgb(34 72 118);
|
||||
--md-sys-color-on-primary-container: rgb(212 227 255);
|
||||
--md-sys-color-secondary: rgb(154 203 250);
|
||||
--md-sys-color-on-secondary: rgb(0 51 83);
|
||||
--md-sys-color-secondary-container: rgb(12 74 114);
|
||||
--md-sys-color-on-secondary-container: rgb(206 229 255);
|
||||
--md-sys-color-tertiary: rgb(218 189 226);
|
||||
--md-sys-color-on-tertiary: rgb(61 41 70);
|
||||
--md-sys-color-tertiary-container: rgb(85 63 93);
|
||||
--md-sys-color-on-tertiary-container: rgb(247 216 255);
|
||||
--md-sys-color-error: rgb(255 180 171);
|
||||
--md-sys-color-on-error: rgb(105 0 5);
|
||||
--md-sys-color-error-container: rgb(147 0 10);
|
||||
--md-sys-color-on-error-container: rgb(255 218 214);
|
||||
--md-sys-color-background: rgb(17 19 24);
|
||||
--md-sys-color-on-background: rgb(225 226 233);
|
||||
--md-sys-color-surface: rgb(17 19 24);
|
||||
--md-sys-color-on-surface: rgb(225 226 233);
|
||||
--md-sys-color-surface-variant: rgb(67 71 78);
|
||||
--md-sys-color-on-surface-variant: rgb(195 198 207);
|
||||
--md-sys-color-outline: rgb(141 145 153);
|
||||
--md-sys-color-outline-variant: rgb(67 71 78);
|
||||
--md-sys-color-shadow: rgb(0 0 0);
|
||||
--md-sys-color-scrim: rgb(0 0 0);
|
||||
--md-sys-color-inverse-surface: rgb(225 226 233);
|
||||
--md-sys-color-inverse-on-surface: rgb(46 48 53);
|
||||
--md-sys-color-inverse-primary: rgb(60 96 144);
|
||||
--md-sys-color-primary-fixed: rgb(212 227 255);
|
||||
--md-sys-color-on-primary-fixed: rgb(0 28 58);
|
||||
--md-sys-color-primary-fixed-dim: rgb(165 200 255);
|
||||
--md-sys-color-on-primary-fixed-variant: rgb(34 72 118);
|
||||
--md-sys-color-secondary-fixed: rgb(206 229 255);
|
||||
--md-sys-color-on-secondary-fixed: rgb(0 29 50);
|
||||
--md-sys-color-secondary-fixed-dim: rgb(154 203 250);
|
||||
--md-sys-color-on-secondary-fixed-variant: rgb(12 74 114);
|
||||
--md-sys-color-tertiary-fixed: rgb(247 216 255);
|
||||
--md-sys-color-on-tertiary-fixed: rgb(39 20 48);
|
||||
--md-sys-color-tertiary-fixed-dim: rgb(218 189 226);
|
||||
--md-sys-color-on-tertiary-fixed-variant: rgb(85 63 93);
|
||||
--md-sys-color-surface-dim: rgb(17 19 24);
|
||||
--md-sys-color-surface-bright: rgb(55 57 62);
|
||||
--md-sys-color-surface-container-lowest: rgb(12 14 19);
|
||||
--md-sys-color-surface-container-low: rgb(25 28 32);
|
||||
--md-sys-color-surface-container: rgb(29 32 36);
|
||||
--md-sys-color-surface-container-high: rgb(40 42 47);
|
||||
--md-sys-color-surface-container-highest: rgb(50 53 58);
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
.light-high-contrast {
|
||||
--md-sys-color-primary: rgb(0 34 70);
|
||||
--md-sys-color-surface-tint: rgb(60 96 144);
|
||||
--md-sys-color-on-primary: rgb(255 255 255);
|
||||
--md-sys-color-primary-container: rgb(29 68 114);
|
||||
--md-sys-color-on-primary-container: rgb(255 255 255);
|
||||
--md-sys-color-secondary: rgb(0 36 61);
|
||||
--md-sys-color-on-secondary: rgb(255 255 255);
|
||||
--md-sys-color-secondary-container: rgb(3 70 110);
|
||||
--md-sys-color-on-secondary-container: rgb(255 255 255);
|
||||
--md-sys-color-tertiary: rgb(46 26 55);
|
||||
--md-sys-color-on-tertiary: rgb(255 255 255);
|
||||
--md-sys-color-tertiary-container: rgb(81 59 89);
|
||||
--md-sys-color-on-tertiary-container: rgb(255 255 255);
|
||||
--md-sys-color-error: rgb(78 0 2);
|
||||
--md-sys-color-on-error: rgb(255 255 255);
|
||||
--md-sys-color-error-container: rgb(140 0 9);
|
||||
--md-sys-color-on-error-container: rgb(255 255 255);
|
||||
--md-sys-color-background: rgb(249 249 255);
|
||||
--md-sys-color-on-background: rgb(25 28 32);
|
||||
--md-sys-color-surface: rgb(249 249 255);
|
||||
--md-sys-color-on-surface: rgb(0 0 0);
|
||||
--md-sys-color-surface-variant: rgb(224 226 236);
|
||||
--md-sys-color-on-surface-variant: rgb(32 36 43);
|
||||
--md-sys-color-outline: rgb(63 67 74);
|
||||
--md-sys-color-outline-variant: rgb(63 67 74);
|
||||
--md-sys-color-shadow: rgb(0 0 0);
|
||||
--md-sys-color-scrim: rgb(0 0 0);
|
||||
--md-sys-color-inverse-surface: rgb(46 48 53);
|
||||
--md-sys-color-inverse-on-surface: rgb(255 255 255);
|
||||
--md-sys-color-inverse-primary: rgb(228 236 255);
|
||||
--md-sys-color-primary-fixed: rgb(29 68 114);
|
||||
--md-sys-color-on-primary-fixed: rgb(255 255 255);
|
||||
--md-sys-color-primary-fixed-dim: rgb(0 45 88);
|
||||
--md-sys-color-on-primary-fixed-variant: rgb(255 255 255);
|
||||
--md-sys-color-secondary-fixed: rgb(3 70 110);
|
||||
--md-sys-color-on-secondary-fixed: rgb(255 255 255);
|
||||
--md-sys-color-secondary-fixed-dim: rgb(0 47 77);
|
||||
--md-sys-color-on-secondary-fixed-variant: rgb(255 255 255);
|
||||
--md-sys-color-tertiary-fixed: rgb(81 59 89);
|
||||
--md-sys-color-on-tertiary-fixed: rgb(255 255 255);
|
||||
--md-sys-color-tertiary-fixed-dim: rgb(57 37 66);
|
||||
--md-sys-color-on-tertiary-fixed-variant: rgb(255 255 255);
|
||||
--md-sys-color-surface-dim: rgb(217 218 224);
|
||||
--md-sys-color-surface-bright: rgb(249 249 255);
|
||||
--md-sys-color-surface-container-lowest: rgb(255 255 255);
|
||||
--md-sys-color-surface-container-low: rgb(243 243 250);
|
||||
--md-sys-color-surface-container: rgb(237 237 244);
|
||||
--md-sys-color-surface-container-high: rgb(231 232 238);
|
||||
--md-sys-color-surface-container-highest: rgb(225 226 233);
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
.light-medium-contrast {
|
||||
--md-sys-color-primary: rgb(29 68 114);
|
||||
--md-sys-color-surface-tint: rgb(60 96 144);
|
||||
--md-sys-color-on-primary: rgb(255 255 255);
|
||||
--md-sys-color-primary-container: rgb(83 118 167);
|
||||
--md-sys-color-on-primary-container: rgb(255 255 255);
|
||||
--md-sys-color-secondary: rgb(3 70 110);
|
||||
--md-sys-color-on-secondary: rgb(255 255 255);
|
||||
--md-sys-color-secondary-container: rgb(71 121 163);
|
||||
--md-sys-color-on-secondary-container: rgb(255 255 255);
|
||||
--md-sys-color-tertiary: rgb(81 59 89);
|
||||
--md-sys-color-on-tertiary: rgb(255 255 255);
|
||||
--md-sys-color-tertiary-container: rgb(133 108 141);
|
||||
--md-sys-color-on-tertiary-container: rgb(255 255 255);
|
||||
--md-sys-color-error: rgb(140 0 9);
|
||||
--md-sys-color-on-error: rgb(255 255 255);
|
||||
--md-sys-color-error-container: rgb(218 52 46);
|
||||
--md-sys-color-on-error-container: rgb(255 255 255);
|
||||
--md-sys-color-background: rgb(249 249 255);
|
||||
--md-sys-color-on-background: rgb(25 28 32);
|
||||
--md-sys-color-surface: rgb(249 249 255);
|
||||
--md-sys-color-on-surface: rgb(25 28 32);
|
||||
--md-sys-color-surface-variant: rgb(224 226 236);
|
||||
--md-sys-color-on-surface-variant: rgb(63 67 74);
|
||||
--md-sys-color-outline: rgb(91 95 103);
|
||||
--md-sys-color-outline-variant: rgb(119 123 131);
|
||||
--md-sys-color-shadow: rgb(0 0 0);
|
||||
--md-sys-color-scrim: rgb(0 0 0);
|
||||
--md-sys-color-inverse-surface: rgb(46 48 53);
|
||||
--md-sys-color-inverse-on-surface: rgb(240 240 247);
|
||||
--md-sys-color-inverse-primary: rgb(165 200 255);
|
||||
--md-sys-color-primary-fixed: rgb(83 118 167);
|
||||
--md-sys-color-on-primary-fixed: rgb(255 255 255);
|
||||
--md-sys-color-primary-fixed-dim: rgb(58 93 141);
|
||||
--md-sys-color-on-primary-fixed-variant: rgb(255 255 255);
|
||||
--md-sys-color-secondary-fixed: rgb(71 121 163);
|
||||
--md-sys-color-on-secondary-fixed: rgb(255 255 255);
|
||||
--md-sys-color-secondary-fixed-dim: rgb(43 96 137);
|
||||
--md-sys-color-on-secondary-fixed-variant: rgb(255 255 255);
|
||||
--md-sys-color-tertiary-fixed: rgb(133 108 141);
|
||||
--md-sys-color-on-tertiary-fixed: rgb(255 255 255);
|
||||
--md-sys-color-tertiary-fixed-dim: rgb(107 84 116);
|
||||
--md-sys-color-on-tertiary-fixed-variant: rgb(255 255 255);
|
||||
--md-sys-color-surface-dim: rgb(217 218 224);
|
||||
--md-sys-color-surface-bright: rgb(249 249 255);
|
||||
--md-sys-color-surface-container-lowest: rgb(255 255 255);
|
||||
--md-sys-color-surface-container-low: rgb(243 243 250);
|
||||
--md-sys-color-surface-container: rgb(237 237 244);
|
||||
--md-sys-color-surface-container-high: rgb(231 232 238);
|
||||
--md-sys-color-surface-container-highest: rgb(225 226 233);
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
.light {
|
||||
--md-sys-color-primary: rgb(60 96 144);
|
||||
--md-sys-color-surface-tint: rgb(60 96 144);
|
||||
--md-sys-color-on-primary: rgb(255 255 255);
|
||||
--md-sys-color-primary-container: rgb(212 227 255);
|
||||
--md-sys-color-on-primary-container: rgb(0 28 58);
|
||||
--md-sys-color-secondary: rgb(46 98 140);
|
||||
--md-sys-color-on-secondary: rgb(255 255 255);
|
||||
--md-sys-color-secondary-container: rgb(206 229 255);
|
||||
--md-sys-color-on-secondary-container: rgb(0 29 50);
|
||||
--md-sys-color-tertiary: rgb(110 86 118);
|
||||
--md-sys-color-on-tertiary: rgb(255 255 255);
|
||||
--md-sys-color-tertiary-container: rgb(247 216 255);
|
||||
--md-sys-color-on-tertiary-container: rgb(39 20 48);
|
||||
--md-sys-color-error: rgb(186 26 26);
|
||||
--md-sys-color-on-error: rgb(255 255 255);
|
||||
--md-sys-color-error-container: rgb(255 218 214);
|
||||
--md-sys-color-on-error-container: rgb(65 0 2);
|
||||
--md-sys-color-background: rgb(249 249 255);
|
||||
--md-sys-color-on-background: rgb(25 28 32);
|
||||
--md-sys-color-surface: rgb(249 249 255);
|
||||
--md-sys-color-on-surface: rgb(25 28 32);
|
||||
--md-sys-color-surface-variant: rgb(224 226 236);
|
||||
--md-sys-color-on-surface-variant: rgb(67 71 78);
|
||||
--md-sys-color-outline: rgb(116 119 127);
|
||||
--md-sys-color-outline-variant: rgb(195 198 207);
|
||||
--md-sys-color-shadow: rgb(0 0 0);
|
||||
--md-sys-color-scrim: rgb(0 0 0);
|
||||
--md-sys-color-inverse-surface: rgb(46 48 53);
|
||||
--md-sys-color-inverse-on-surface: rgb(240 240 247);
|
||||
--md-sys-color-inverse-primary: rgb(165 200 255);
|
||||
--md-sys-color-primary-fixed: rgb(212 227 255);
|
||||
--md-sys-color-on-primary-fixed: rgb(0 28 58);
|
||||
--md-sys-color-primary-fixed-dim: rgb(165 200 255);
|
||||
--md-sys-color-on-primary-fixed-variant: rgb(34 72 118);
|
||||
--md-sys-color-secondary-fixed: rgb(206 229 255);
|
||||
--md-sys-color-on-secondary-fixed: rgb(0 29 50);
|
||||
--md-sys-color-secondary-fixed-dim: rgb(154 203 250);
|
||||
--md-sys-color-on-secondary-fixed-variant: rgb(12 74 114);
|
||||
--md-sys-color-tertiary-fixed: rgb(247 216 255);
|
||||
--md-sys-color-on-tertiary-fixed: rgb(39 20 48);
|
||||
--md-sys-color-tertiary-fixed-dim: rgb(218 189 226);
|
||||
--md-sys-color-on-tertiary-fixed-variant: rgb(85 63 93);
|
||||
--md-sys-color-surface-dim: rgb(217 218 224);
|
||||
--md-sys-color-surface-bright: rgb(249 249 255);
|
||||
--md-sys-color-surface-container-lowest: rgb(255 255 255);
|
||||
--md-sys-color-surface-container-low: rgb(243 243 250);
|
||||
--md-sys-color-surface-container: rgb(237 237 244);
|
||||
--md-sys-color-surface-container-high: rgb(231 232 238);
|
||||
--md-sys-color-surface-container-highest: rgb(225 226 233);
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
:root {
|
||||
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
|
||||
line-height: 1.5;
|
||||
font-weight: 400;
|
||||
|
||||
color-scheme: light dark;
|
||||
color: rgba(255, 255, 255, 0.87);
|
||||
background-color: #242424;
|
||||
|
||||
font-synthesis: none;
|
||||
text-rendering: optimizeLegibility;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
a {
|
||||
font-weight: 500;
|
||||
color: #646cff;
|
||||
text-decoration: inherit;
|
||||
}
|
||||
a:hover {
|
||||
color: #535bf2;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
display: flex;
|
||||
place-items: center;
|
||||
min-width: 320px;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
button {
|
||||
border-radius: 8px;
|
||||
border: 1px solid transparent;
|
||||
padding: 0.6em 1.2em;
|
||||
font-size: 1em;
|
||||
font-weight: 500;
|
||||
font-family: inherit;
|
||||
background-color: #1a1a1a;
|
||||
cursor: pointer;
|
||||
transition: border-color 0.25s;
|
||||
}
|
||||
button:hover {
|
||||
border-color: #646cff;
|
||||
}
|
||||
button:focus,
|
||||
button:focus-visible {
|
||||
outline: 4px auto -webkit-focus-ring-color;
|
||||
}
|
||||
|
||||
button#query-button {
|
||||
height: 5em;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
button#play-button {
|
||||
padding: '10px 20px';
|
||||
font-size: '16px';
|
||||
cursor: 'pointer';
|
||||
background-color: '#28a745';
|
||||
color: '#fff';
|
||||
border: 'none';
|
||||
border-radius: '5px';
|
||||
};
|
||||
|
||||
button#pause-button {
|
||||
background-color: #ffc107;
|
||||
}
|
||||
|
||||
button#stop-button {
|
||||
background-color: #dc3545;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 3.2em;
|
||||
line-height: 1.1;
|
||||
}
|
||||
|
||||
p#footer {
|
||||
float: none;
|
||||
clear: both;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
|
||||
table#query-output {
|
||||
float: none;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
textarea#query-input {
|
||||
height: 5em;
|
||||
width: 50em;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: light) {
|
||||
:root {
|
||||
color: #213547;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
a:hover {
|
||||
color: #747bff;
|
||||
}
|
||||
button {
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom/client';
|
||||
import App from './App';
|
||||
|
||||
ReactDOM.createRoot(document.getElementById('root')).render(
|
||||
<App />
|
||||
)
|
||||
@@ -0,0 +1,83 @@
|
||||
import { fileURLToPath, URL } from 'node:url';
|
||||
import { defineConfig } from 'vite';
|
||||
import plugin from '@vitejs/plugin-react';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import child_process from 'child_process';
|
||||
import process, { env } from 'process';
|
||||
|
||||
const baseFolder =
|
||||
process.env.APPDATA !== undefined && process.env.APPDATA !== ''
|
||||
? `${process.env.APPDATA}/ASP.NET/https`
|
||||
: `${process.env.HOME}/.aspnet/https`;
|
||||
|
||||
const certificateName = "bts.datastreamwebapp.client";
|
||||
const certFilePath = path.join(baseFolder, `${certificateName}.pem`);
|
||||
const keyFilePath = path.join(baseFolder, `${certificateName}.key`);
|
||||
|
||||
if (!fs.existsSync(certFilePath) || !fs.existsSync(keyFilePath)) {
|
||||
if (0 !== child_process.spawnSync('dotnet', [
|
||||
'dev-certs',
|
||||
'https',
|
||||
'--export-path',
|
||||
certFilePath,
|
||||
'--format',
|
||||
'Pem',
|
||||
'--no-password',
|
||||
], { stdio: 'inherit', }).status) {
|
||||
throw new Error("Could not create certificate.");
|
||||
}
|
||||
}
|
||||
|
||||
export default defineConfig(({ $$command, mode, $$isSsrBuild, $$isPreview }) => {
|
||||
const target = env.ASPNETCORE_HTTPS_PORT
|
||||
? `https://localhost:${env.ASPNETCORE_HTTPS_PORT}`
|
||||
: env.ASPNETCORE_URLS
|
||||
? env.ASPNETCORE_URLS.split(';')[0]
|
||||
: 'https://localhost:8443';
|
||||
return {
|
||||
plugins: [plugin()],
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': fileURLToPath(new URL('./src', import.meta.url))
|
||||
}
|
||||
},
|
||||
build: {
|
||||
minify: false,
|
||||
sourcemap: true,
|
||||
outDir: `../../../build/Bts.DataStreamWebApp.Client/${mode}/dist`
|
||||
},
|
||||
server: {
|
||||
proxy: {
|
||||
'^/api': {
|
||||
target,
|
||||
secure: false,
|
||||
configure: (proxy) => {
|
||||
proxy.on('error', (err) => {
|
||||
console.log('proxy error', err);
|
||||
});
|
||||
proxy.on('proxyReq', (proxyReq, req) => {
|
||||
console.log(`Forwarding ${proxyReq.method} ${proxyReq.protocol}//${proxyReq.host}${proxyReq.path} to ${req.socket.remoteAddress}${req.url}`);
|
||||
});
|
||||
proxy.on('proxyRes', (proxyRes, req, res) => {
|
||||
console.log(`Forwarding response ${req.socket.localAddress} to ${res.socket.remoteAddress}. Status=${proxyRes.statusCode}`);
|
||||
});
|
||||
},
|
||||
},
|
||||
'^/ws': {
|
||||
target,
|
||||
secure: false
|
||||
},
|
||||
'^/browse': {
|
||||
target,
|
||||
secure: false
|
||||
}
|
||||
},
|
||||
port: 5173,
|
||||
https: {
|
||||
key: fs.readFileSync(keyFilePath),
|
||||
cert: fs.readFileSync(certFilePath),
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,40 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<InvariantGlobalization>true</InvariantGlobalization>
|
||||
<SpaRoot>..\Bts.DataStreamWebApp.Client</SpaRoot>
|
||||
<SpaProxyLaunchCommand>npm run dev</SpaProxyLaunchCommand>
|
||||
<SpaProxyServerUrl>https://localhost:5173</SpaProxyServerUrl>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="CommandLineParser" Version="2.9.1" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.SpaProxy" Version="7.0.20" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.SpaServices.Extensions" Version="7.0.20" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Bts.DataStreamWebApp.Client\Bts.DataStreamWebApp.Client.esproj">
|
||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\DataStream\DataStream.csproj" />
|
||||
<ProjectReference Include="..\SharedStreams\SharedStreams.csproj" />
|
||||
<ProjectReference Include="..\..\client\spark_api\spark_api.csproj" />
|
||||
<ProjectReference Include="..\..\client\spark_core\spark_core.csproj" />
|
||||
<ProjectReference Include="..\..\client\spark_websocket\spark_websocket.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ConfigurationProfile Include="appsettings.Development.json" />
|
||||
<ConfigurationProfile Include="appsettings.Production.json" />
|
||||
<ConfigurationProfile Include="appsettings.ProductionAws.json" />
|
||||
<ConfigurationProfile Include="appsettings.Staging.json" />
|
||||
<ConfigurationProfile Include="appsettings.json" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
Loaded 100 of 2931 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user