Compare commits
919 Commits
1.0.1-BETA
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f66492ce4b | ||
|
|
e069c699e9 | ||
|
|
8963b2dba1 | ||
|
|
9ec9a526f5 | ||
|
|
b4114589ff | ||
| 6689c9ce1f | |||
|
|
0c1773f25d | ||
|
|
d0ff9a9592 | ||
|
|
bf36070860 | ||
|
|
5552773e5e | ||
|
|
b3a1077270 | ||
|
|
1c5f75bcd6 | ||
|
|
2455039594 | ||
|
|
f47676c225 | ||
|
|
0881e0ed86 | ||
|
|
e457b60b30 | ||
|
|
a6746f8161 | ||
|
|
144f0228cc | ||
|
|
7300e6b0bd | ||
|
|
0ef8a36172 | ||
|
|
c0be043aaf | ||
|
|
dd74289eaf | ||
|
|
3da69257a0 | ||
|
|
13e4e577bb | ||
|
|
5387face45 | ||
|
|
eac2a8e70f | ||
|
|
04fcb7e38f | ||
|
|
45018a2163 | ||
|
|
b7ad4478a4 | ||
|
|
c16f19c80e | ||
|
|
87018882d1 | ||
| 2547514abb | |||
|
|
9447eacbd2 | ||
|
|
0b424a71ec | ||
|
|
45671faaea | ||
|
|
016d1154fc | ||
|
|
f3911d5831 | ||
|
|
93e90c5a04 | ||
|
|
8039c75b3e | ||
|
|
a647c8b174 | ||
|
|
d3b4976ea2 | ||
|
|
b1c8303870 | ||
|
|
a3ef984f4f | ||
|
|
ca86a63180 | ||
|
|
07b79693af | ||
|
|
4ef9e18ac6 | ||
|
|
320cc3c60b | ||
|
|
45d0d76a7f | ||
|
|
b2b42d5f8c | ||
|
|
90b1f2f6da | ||
|
|
2e775ef2fb | ||
|
|
f17d2bbca1 | ||
|
|
79b02254c4 | ||
|
|
19245ce805 | ||
|
|
0fa927afa7 | ||
|
|
d9b3f98e35 | ||
|
|
81e7968230 | ||
|
|
06f3b96992 | ||
| 1038182a16 | |||
| 60091bfe56 | |||
| f4de6dd9b1 | |||
|
|
3d93a80cce | ||
|
|
94eff54fa9 | ||
|
|
e9dde4d2f8 | ||
|
|
0a5e22e5b0 | ||
|
|
3a5cfba4e1 | ||
|
|
07b75e4543 | ||
|
|
e4f150b34f | ||
|
|
ca2ae0d0e7 | ||
|
|
828506720c | ||
|
|
ad712b63f9 | ||
|
|
4c3d5a788d | ||
|
|
df89135455 | ||
|
|
95d452870c | ||
|
|
8a82ff9fe4 | ||
|
|
dd24b2ad75 | ||
|
|
17fa7a7724 | ||
|
|
d01ba94ed7 | ||
|
|
c7c7585950 | ||
|
|
f869936cfd | ||
|
|
0ad253c6f0 | ||
|
|
52d04d5044 | ||
|
|
bff2dc9cd2 | ||
|
|
b903df5d0d | ||
|
|
416d910577 | ||
|
|
37b7a0708f | ||
|
|
6ceaa6adb0 | ||
|
|
0447826e7c | ||
|
|
3ef60a61a2 | ||
|
|
31802a8bde | ||
|
|
c2bc77a649 | ||
|
|
4dd7a18301 | ||
|
|
a29894ee2b | ||
|
|
2f8ac7f673 | ||
|
|
b050fbbcbe | ||
|
|
caa11605fc | ||
|
|
cfcdd1a3f9 | ||
|
|
95ff606ba1 | ||
|
|
4cc9b650c5 | ||
|
|
cd2436342d | ||
|
|
3ae2d09fe3 | ||
|
|
35b3403de6 | ||
|
|
f780ebdf76 | ||
|
|
93f0518b4b | ||
|
|
6da871fa64 | ||
|
|
d53cb0cbc9 | ||
|
|
8f0111e482 | ||
|
|
5525119778 | ||
|
|
6410600205 | ||
|
|
a5d44745d1 | ||
|
|
8c275cbc1c | ||
|
|
b79f69231c | ||
|
|
ff165595c4 | ||
|
|
12d851dc6f | ||
|
|
643f289c23 | ||
|
|
68e74ed1d2 | ||
|
|
f0ef0965c4 | ||
|
|
61ce532fdf | ||
|
|
d746e1bfb3 | ||
|
|
deccc41b9a | ||
|
|
4ffddfa2f6 | ||
|
|
2814c779bd | ||
|
|
4c73607799 | ||
|
|
d776f6eaf0 | ||
|
|
706ef01782 | ||
|
|
00c62cbd67 | ||
|
|
da8f3d6cc7 | ||
|
|
0bc95e51c2 | ||
|
|
727153e965 | ||
|
|
d00f54228d | ||
|
|
77c67802a3 | ||
|
|
7d68d177d7 | ||
|
|
9b20505dcd | ||
|
|
5f93e292b2 | ||
|
|
edd3e20f3c | ||
|
|
90cffa60d6 | ||
|
|
6171cd6867 | ||
|
|
fa731bf6c3 | ||
|
|
818fce324c | ||
|
|
1bc867e48d | ||
|
|
434b9f7a9f | ||
|
|
f54602dead | ||
|
|
fb546b41c1 | ||
|
|
e400d9f5fd | ||
|
|
f0fa8a2481 | ||
|
|
c3b0b49e3f | ||
|
|
45265b4f9b | ||
|
|
aa87a2a23d | ||
|
|
5a59b1da75 | ||
|
|
32aa0dd72f | ||
|
|
c1188b16a1 | ||
|
|
a02a60c658 | ||
| c5f9f5a2dc | |||
|
|
342b1bc8ef | ||
|
|
64158376f5 | ||
|
|
850d4ff056 | ||
|
|
f0cfe1c85a | ||
|
|
c8b615b3ee | ||
|
|
c67fdafb43 | ||
|
|
f66d277918 | ||
|
|
4ef7db20f8 | ||
|
|
e1216dfa76 | ||
|
|
340fa8a7cb | ||
|
|
a029455466 | ||
|
|
27f78c430b | ||
|
|
3d707e5e95 | ||
|
|
0406a2f614 | ||
|
|
a1c0e432ee | ||
|
|
57e57d9e43 | ||
|
|
e4e4188eaf | ||
|
|
f1553cc90e | ||
|
|
997e68c99a | ||
|
|
25663d9a7b | ||
|
|
1e55266396 | ||
|
|
810ae15991 | ||
|
|
271fec7f5e | ||
|
|
c43486791e | ||
|
|
499c03265f | ||
|
|
7eaa613d4d | ||
|
|
19db72031c | ||
|
|
671f9cca4b | ||
|
|
9ecdb80534 | ||
|
|
e973422ee1 | ||
|
|
8093c25b72 | ||
|
|
a7c9c620dd | ||
|
|
1e1d94ed73 | ||
|
|
7b8ef390ce | ||
|
|
87ade13234 | ||
|
|
32abde7f19 | ||
|
|
fe413af177 | ||
|
|
b4cd026fe5 | ||
|
|
a51b308cc8 | ||
|
|
1c09b42951 | ||
|
|
e42bb46563 | ||
|
|
a7788f9847 | ||
|
|
b597364419 | ||
|
|
a9a951d970 | ||
|
|
6ac879ec6a | ||
|
|
2422ef50b6 | ||
|
|
06dbf96b65 | ||
|
|
172046e78f | ||
|
|
7e8c49f0a0 | ||
|
|
f2ad6292f5 | ||
|
|
337e13b72e | ||
|
|
2ab2fc62dc | ||
|
|
786575c3de | ||
|
|
4cca194000 | ||
|
|
cd3ead0028 | ||
|
|
a239b95ca1 | ||
|
|
09574c0e82 | ||
|
|
0b6b01ef83 | ||
|
|
34145e459b | ||
|
|
207efca15c | ||
|
|
3e25c2ea46 | ||
|
|
2046678caa | ||
|
|
cb7e4e858b | ||
|
|
43ee4b9cb6 | ||
|
|
207c24a4fd | ||
|
|
6465ab3b6d | ||
|
|
cf624bc679 | ||
|
|
df55a776c7 | ||
|
|
07afe3887b | ||
|
|
25434ba84f | ||
|
|
9787dbd14f | ||
|
|
fd9081c80e | ||
|
|
e79c49019d | ||
|
|
5bc081a3af | ||
|
|
5976eb5186 | ||
|
|
b194bc05b1 | ||
|
|
18207fd79e | ||
|
|
7c1e0a51eb | ||
|
|
7196658166 | ||
|
|
187fe67ffa | ||
|
|
7136098c3c | ||
|
|
7979238029 | ||
|
|
fc38dff3b0 | ||
|
|
c590204cf9 | ||
|
|
284e49c807 | ||
|
|
43fcd3d1e2 | ||
|
|
a9f2d7df40 | ||
|
|
21a03d2b85 | ||
|
|
f123b8654a | ||
|
|
51cbe538e8 | ||
|
|
e247a2c4eb | ||
|
|
490b6684ac | ||
|
|
6fdeadf171 | ||
|
|
a88d491012 | ||
|
|
fd34d68933 | ||
|
|
215e3aab7b | ||
|
|
cd4feb3bab | ||
|
|
6b0af421dd | ||
|
|
9aeb4f2a96 | ||
|
|
9b1e789e62 | ||
|
|
406b163bcc | ||
|
|
6f2cae95e1 | ||
|
|
594a29b2db | ||
|
|
0d12464e30 | ||
|
|
ccd9ab70ee | ||
|
|
27f2f87e29 | ||
|
|
635eb9d36d | ||
|
|
f3e7f9bb8f | ||
|
|
2f69665056 | ||
|
|
559f7bc1b7 | ||
|
|
693f00caf5 | ||
|
|
822173979c | ||
|
|
9bce66f307 | ||
|
|
7a71e758b1 | ||
|
|
72fe0ca3e7 | ||
|
|
fd0570f0c9 | ||
|
|
e0037a0c8b | ||
|
|
c7c83282ee | ||
|
|
8f98d9792b | ||
|
|
111f7bd15e | ||
|
|
787af8de18 | ||
|
|
db6ebfe71b | ||
|
|
1cb490039f | ||
|
|
a152a64f1c | ||
|
|
08f50e56ac | ||
|
|
9ae221ca0c | ||
|
|
aca8da5891 | ||
|
|
34896560ea | ||
|
|
3597fbe382 | ||
|
|
0b262baf97 | ||
|
|
78b51ebe59 | ||
|
|
08a92468fe | ||
|
|
b84ed964f9 | ||
|
|
8bfe7b6b9d | ||
|
|
dbae173399 | ||
|
|
4d4dbcda4d | ||
|
|
fd4584a49d | ||
|
|
ceb9f795cb | ||
|
|
443c254d46 | ||
|
|
87fa150ced | ||
|
|
4cfdb8233f | ||
|
|
5e42cf76eb | ||
|
|
dccf6193da | ||
|
|
ee4fdf3f39 | ||
|
|
918b7f96db | ||
|
|
ef55345665 | ||
|
|
0a41dbb443 | ||
|
|
934ad32e52 | ||
|
|
b582f0f880 | ||
|
|
face3de44a | ||
|
|
8a7b9d776f | ||
|
|
a8c5d1095d | ||
|
|
9fa5028f6c | ||
|
|
0de3c089d2 | ||
|
|
919bc0138a | ||
|
|
a0210af5c6 | ||
|
|
888291db9a | ||
|
|
4fce663795 | ||
|
|
fc3384fb95 | ||
|
|
f9a30ca08e | ||
|
|
cbbe691f70 | ||
|
|
afbf0809c3 | ||
|
|
db8d4b4347 | ||
|
|
904ee7dfec | ||
|
|
bef616632c | ||
|
|
1d2e5d182e | ||
|
|
568ee1fa85 | ||
|
|
66633a7728 | ||
|
|
18283b44b2 | ||
|
|
278696b28e | ||
|
|
26efd09d45 | ||
|
|
ec9aba79ae | ||
|
|
07e42d81f4 | ||
|
|
d272afc128 | ||
|
|
6cf9fa2208 | ||
|
|
a72451cdbe | ||
|
|
e82489b158 | ||
|
|
e4c7fa6a1c | ||
|
|
48ed24dabf | ||
|
|
9ef060a2f2 | ||
|
|
255c41607f | ||
|
|
22da026888 | ||
|
|
def0a63008 | ||
|
|
6e62e123e8 | ||
|
|
262df56024 | ||
|
|
81cdf071a8 | ||
|
|
c5ce75888e | ||
|
|
fb232896a8 | ||
|
|
5efa462f19 | ||
|
|
225f3ab125 | ||
|
|
664fbfeb6e | ||
|
|
66f8ca0501 | ||
|
|
e977d63f08 | ||
|
|
08fc3cab38 | ||
|
|
a01885536c | ||
|
|
f7343674ee | ||
|
|
fc2adf98ba | ||
|
|
a3c57a5077 | ||
|
|
28b5dd0163 | ||
|
|
c0b69e4e6f | ||
|
|
a9111d78d3 | ||
|
|
cc91e22038 | ||
|
|
4555f69733 | ||
|
|
da8ba56dd1 | ||
|
|
4d6d5620b0 | ||
|
|
f7cad98f3e | ||
|
|
d978c4c3bf | ||
|
|
1c4b7810b1 | ||
|
|
a6ec43f81c | ||
|
|
d258acfc49 | ||
|
|
d9072402db | ||
|
|
1a706e3842 | ||
|
|
a227897504 | ||
|
|
0833d68e91 | ||
|
|
99bab6796c | ||
|
|
0544187057 | ||
|
|
e12e7b4d76 | ||
|
|
7609ac6f1e | ||
|
|
3c946a91e8 | ||
|
|
2389ebd87e | ||
|
|
90ad497a6f | ||
|
|
1bb0b6fe03 | ||
|
|
c16c1df6fd | ||
|
|
e460641711 | ||
|
|
1e980651a9 | ||
|
|
028076e79c | ||
|
|
e5b6a88551 | ||
|
|
b18b4f236f | ||
|
|
605d4e99b9 | ||
|
|
ad00b6465a | ||
|
|
537ebd05f2 | ||
|
|
2ee8769752 | ||
|
|
8d7f534d54 | ||
|
|
47bb62b051 | ||
|
|
50b8213781 | ||
|
|
fd1fe53b49 | ||
|
|
378def0a58 | ||
|
|
ed5f48b353 | ||
|
|
fa6c2c7683 | ||
|
|
3fadc9b481 | ||
|
|
c3d7fa0d26 | ||
|
|
5c16357fe2 | ||
|
|
ef2e6079ba | ||
|
|
18633288fb | ||
|
|
67daef7bcc | ||
|
|
5eb29dcfc4 | ||
|
|
d2fc922ee7 | ||
|
|
d35010c1cb | ||
|
|
bd4b65225c | ||
|
|
be95a62965 | ||
|
|
4336d524af | ||
|
|
ae7976fc01 | ||
|
|
72f9dc4c7c | ||
|
|
84760648fe | ||
|
|
b0df40d9a6 | ||
|
|
139217914d | ||
|
|
efa5795193 | ||
|
|
4f499aed01 | ||
|
|
a8ba831f5e | ||
|
|
a90405c25a | ||
|
|
4546fda8e9 | ||
|
|
b02f771146 | ||
|
|
dc94b26e50 | ||
|
|
4c32f37ede | ||
|
|
336a8b3bc2 | ||
|
|
faecea39c8 | ||
|
|
d08d5362be | ||
|
|
d4292d81f2 | ||
|
|
62893e33e9 | ||
|
|
5b07ecbd01 | ||
|
|
b5c1b9178d | ||
|
|
65ff7ab1c3 | ||
|
|
35fd991fdc | ||
|
|
57e1acba79 | ||
|
|
620d351946 | ||
|
|
de3c2656ef | ||
|
|
3b2e9b2485 | ||
|
|
75a3005d74 | ||
|
|
448f606054 | ||
|
|
e35c6f29fb | ||
|
|
85a1a48b00 | ||
|
|
45427d3202 | ||
|
|
93c7a05dac | ||
|
|
a34c38c9b9 | ||
|
|
3100b77a1a | ||
|
|
c8429069a3 | ||
|
|
01172217dc | ||
|
|
14b0e409f2 | ||
|
|
2107bae8dd | ||
|
|
433676226c | ||
|
|
f0c88234a0 | ||
|
|
393d711e5f | ||
|
|
cb24bd9c2c | ||
|
|
abc5c5a374 | ||
|
|
54c94f181a | ||
|
|
6641e7f5d1 | ||
|
|
f4a00f2b0f | ||
|
|
05d41f81e4 | ||
|
|
fdc289d888 | ||
|
|
0a2243e033 | ||
|
|
9d877d764f | ||
|
|
f5df29cf34 | ||
|
|
8008823ea5 | ||
|
|
6515de4bc0 | ||
|
|
8c5f535b79 | ||
|
|
3714be4f16 | ||
|
|
f24f565e58 | ||
|
|
036186fc12 | ||
|
|
d3853bd4e9 | ||
|
|
7253bac48a | ||
|
|
973fbeeba5 | ||
|
|
f22cefba97 | ||
|
|
a5abc37b17 | ||
|
|
b95fa7be56 | ||
|
|
f6cf87a52d | ||
|
|
51f36b2281 | ||
|
|
ddebd494c6 | ||
|
|
d0a8d2b1cd | ||
|
|
1731a0daf6 | ||
|
|
3487b3ee9e | ||
|
|
5834efb709 | ||
|
|
52bc6d060d | ||
|
|
35ca5f3aed | ||
|
|
ac2b6ea8db | ||
|
|
9827caa3e3 | ||
|
|
ebe2d6196c | ||
|
|
e4689dd3f8 | ||
|
|
1dba611b8e | ||
|
|
97cbea6f4d | ||
|
|
d9963b0631 | ||
|
|
8418303ce2 | ||
|
|
40952df965 | ||
|
|
4f2c51c480 | ||
|
|
fd31a0d6b0 | ||
|
|
9ad725a272 | ||
|
|
2b6172ba63 | ||
|
|
c521f9299d | ||
|
|
1e646f8df1 | ||
|
|
b5a436c1b7 | ||
|
|
4f25c7a3ea | ||
|
|
eadb8ff65b | ||
|
|
6a80e941a0 | ||
|
|
7fc9b42b3a | ||
|
|
0d857999bf | ||
|
|
8ba71b048e | ||
|
|
e07f6c1703 | ||
|
|
e4f38121d2 | ||
|
|
255ee3f151 | ||
|
|
e72dbaabe1 | ||
|
|
b39662450f | ||
|
|
98da0c0bec | ||
|
|
45dde325fd | ||
|
|
2967a8f798 | ||
|
|
d4bdc73948 | ||
|
|
37c2f6bb17 | ||
|
|
a8e4d749e3 | ||
|
|
3df16ee449 | ||
|
|
332c2f959b | ||
|
|
a1b89c9a3b | ||
|
|
d6921fdac0 | ||
|
|
4cb3c22221 | ||
|
|
cc1536b6e1 | ||
|
|
92a178cbf9 | ||
|
|
fbebce0a49 | ||
|
|
b13bb9819a | ||
|
|
bb505b8ed9 | ||
|
|
cf030bc711 | ||
|
|
6cb95c5cfc | ||
|
|
a277a4fdd5 | ||
|
|
388799d39d | ||
|
|
4acf7edf95 | ||
|
|
e39346d51e | ||
|
|
5ae6de4f1d | ||
|
|
e0f1427af7 | ||
|
|
69297bdb58 | ||
|
|
0fa2f2c2ff | ||
|
|
9efce46fff | ||
|
|
c356ecb402 | ||
|
|
4c6887e7ec | ||
|
|
6d338cab15 | ||
|
|
354fdd412f | ||
|
|
f3f6141e6a | ||
|
|
f2b43b704c | ||
|
|
de1478d7ba | ||
|
|
b9592eeb8c | ||
|
|
6a62f9c082 | ||
|
|
2e4a8b2e23 | ||
|
|
c5112ffa11 | ||
|
|
7b9fda4e81 | ||
|
|
278e531806 | ||
|
|
047de40642 | ||
|
|
4e671a1c21 | ||
|
|
f36c8ce280 | ||
|
|
e77f2c91d7 | ||
|
|
82b0d5ce5f | ||
|
|
6117035863 | ||
|
|
c86e31ad99 | ||
|
|
f506fe1c0e | ||
|
|
554dc06eda | ||
|
|
80e1dfd142 | ||
|
|
6db5cf60dc | ||
|
|
63d181a0ac | ||
|
|
73c4896cce | ||
|
|
5b1b5ab904 | ||
|
|
80a537bc4c | ||
|
|
2a8a1d3736 | ||
|
|
61fbfa0684 | ||
|
|
f06a6bfe7b | ||
|
|
587f81f511 | ||
|
|
435ca63d1b | ||
|
|
64bb660f44 | ||
|
|
8bf24de0b3 | ||
|
|
943ea633a4 | ||
|
|
b1d5f7d7e5 | ||
|
|
188b94ce19 | ||
|
|
515282abfe | ||
|
|
efbdb722e7 | ||
|
|
e980823294 | ||
|
|
3692f4fb3c | ||
|
|
3e645f3c79 | ||
|
|
6127763302 | ||
|
|
19a181b38f | ||
|
|
2818b0384c | ||
|
|
36faf8c2ea | ||
|
|
a208171250 | ||
|
|
b8a2b7cff6 | ||
|
|
2a08cbc1a0 | ||
|
|
62bc6c1fb1 | ||
|
|
1098650421 | ||
|
|
15d85c2f87 | ||
|
|
16fb3f0339 | ||
|
|
37f6dff065 | ||
|
|
baf8832fc9 | ||
|
|
b558e11ede | ||
|
|
103cdabff1 | ||
|
|
57e33c8f7d | ||
|
|
da0f65c2d3 | ||
|
|
6535c075f3 | ||
|
|
f3c0b9544c | ||
|
|
3609fd4745 | ||
|
|
622e140622 | ||
|
|
a4954c3825 | ||
|
|
b6e1b9c203 | ||
|
|
34a35c2658 | ||
|
|
90b7c9a17c | ||
|
|
c72297020b | ||
|
|
f07b601dce | ||
|
|
63c62a2aae | ||
|
|
6888a9d340 | ||
|
|
72bf9f76a3 | ||
|
|
c0c6213c7c | ||
|
|
652ef4bc82 | ||
|
|
c6eed12139 | ||
|
|
1132e25072 | ||
|
|
879e3a2b67 | ||
|
|
6ec207141f | ||
|
|
45c657ce79 | ||
|
|
888dc11c03 | ||
|
|
5e3159f800 | ||
|
|
570ec97eda | ||
|
|
09c75823e6 | ||
|
|
50c8c3b0bd | ||
|
|
3fb44312c7 | ||
|
|
67bdf2ab8b | ||
|
|
a56ed44e74 | ||
|
|
3c912c3812 | ||
|
|
0ceb87eee1 | ||
|
|
6510c10884 | ||
|
|
89da38cfa4 | ||
|
|
82b5d0e50b | ||
|
|
bb8789a9ad | ||
|
|
20345ab0dd | ||
|
|
d5dfb3de0c | ||
|
|
88aabb41e7 | ||
|
|
897059303d | ||
|
|
0b7607cf04 | ||
|
|
4a512f47de | ||
|
|
76a54d38e4 | ||
|
|
b9b03940a2 | ||
|
|
8370a97866 | ||
|
|
b659c77dbb | ||
|
|
e45b842a6c | ||
|
|
c2f22a4ad8 | ||
|
|
cb15a8676b | ||
|
|
32ba6d444b | ||
|
|
95b7a04041 | ||
|
|
d81ef64799 | ||
|
|
19269735ae | ||
|
|
f7957c8ea5 | ||
|
|
1e40797bc4 | ||
|
|
ad66f8af73 | ||
|
|
d436e61bdb | ||
|
|
c71e62746d | ||
|
|
d5b0ad5d80 | ||
|
|
34f2d7bc9a | ||
|
|
fb7f1b622b | ||
|
|
4a992e6e1c | ||
|
|
9593de8c0f | ||
|
|
8205be5220 | ||
|
|
39c43c4c02 | ||
|
|
8a9fa956e0 | ||
|
|
06e9c533e3 | ||
|
|
5bdcaf43db | ||
|
|
df1d13a155 | ||
|
|
6e7b19b090 | ||
|
|
279b73a477 | ||
|
|
74239303b3 | ||
|
|
134f390a5f | ||
|
|
8aa26b78bb | ||
|
|
301038664e | ||
|
|
ccad38f2db | ||
|
|
29dee42d34 | ||
|
|
f9135c81de | ||
|
|
9400635fd9 | ||
|
|
4102deceb3 | ||
|
|
86306740be | ||
|
|
8e63fc8b25 | ||
|
|
3219bd0307 | ||
|
|
bdb4430bb6 | ||
|
|
a574dbf89b | ||
|
|
47178370d5 | ||
|
|
ac67fddbcb | ||
|
|
e97fab3107 | ||
|
|
fee6f03ec2 | ||
|
|
1aff2ec112 | ||
|
|
57b3e9a8b2 | ||
|
|
35dad272eb | ||
|
|
d40c41048d | ||
|
|
03f59c94b4 | ||
|
|
87718f1c82 | ||
|
|
cbf7b69ef0 | ||
|
|
c56c976a22 | ||
|
|
3579d17a05 | ||
|
|
0f17bd23c7 | ||
|
|
db10bed951 | ||
|
|
071806f12b | ||
|
|
9cd7008efe | ||
|
|
14dc098761 | ||
|
|
8c6a895b19 | ||
|
|
01b8e69e4b | ||
|
|
11e91ac3fa | ||
|
|
70380b9a43 | ||
|
|
fa7a44f5b3 | ||
|
|
fb0329c0b5 | ||
|
|
c3d04fdd08 | ||
|
|
ebb0c97c51 | ||
|
|
aabe0f3594 | ||
|
|
7c21bf7aa1 | ||
|
|
de70d90603 | ||
|
|
31be738c10 | ||
|
|
759d268af0 | ||
|
|
f21811eb6a | ||
|
|
c643509c7e | ||
|
|
0860f8e6f9 | ||
|
|
e96b447e37 | ||
|
|
0eecd3b1fe | ||
|
|
b5b6ae100d | ||
|
|
8fd9bf10e5 | ||
|
|
9ac030169a | ||
|
|
569bd3b681 | ||
|
|
45bb461c32 | ||
|
|
105c3185f7 | ||
|
|
5565e4e30c | ||
|
|
70ae281f45 | ||
|
|
b518efd196 | ||
|
|
6e3a344caa | ||
|
|
2e3cbed520 | ||
|
|
5e2e7c81a6 | ||
|
|
cff59487ae | ||
|
|
cdcbfe7378 | ||
|
|
0c4ef8f079 | ||
|
|
c0e9dcff21 | ||
|
|
79eeb0fa2a | ||
|
|
46feb86a99 | ||
|
|
74f68c47d3 | ||
|
|
3c7a738ffc | ||
|
|
22d4a53d65 | ||
|
|
d319e2ed7b | ||
|
|
2cb07a8490 | ||
|
|
6900d4bbec | ||
|
|
73450bdbc7 | ||
|
|
776ff49ed2 | ||
|
|
00da6c88ae | ||
|
|
986f036d20 | ||
|
|
5699c43b74 | ||
|
|
b58b97a916 | ||
|
|
5f52f14094 | ||
|
|
5f8fa26bf3 | ||
|
|
a5c835cfeb | ||
|
|
ec6b67ffad | ||
|
|
3de28e3cef | ||
|
|
d2a649f5fa | ||
|
|
23d5aab1e8 | ||
|
|
cf8c6718dd | ||
|
|
b0c8249562 | ||
|
|
8cb0b1a7d6 | ||
|
|
7f9745c8d1 | ||
|
|
4e749cc8be | ||
|
|
70c9a7c18f | ||
|
|
11e2ee19ea | ||
|
|
a4cfab1242 | ||
|
|
be4738f59c | ||
|
|
b63c3da565 | ||
|
|
0b89f08d09 | ||
|
|
ac53153bea | ||
|
|
bc3187a3f6 | ||
|
|
4294710d9e | ||
|
|
476f18332a | ||
|
|
82a33460cf | ||
|
|
3b6268a4fc | ||
|
|
41425b3fa1 | ||
|
|
a964e3668d | ||
|
|
57804494ef | ||
|
|
9039a10c9a | ||
|
|
9e865bc37d | ||
|
|
54ee8bf7a0 | ||
|
|
629c8346d2 | ||
|
|
1bf2ff430a | ||
|
|
69be072a07 | ||
|
|
a2ca21a1a6 | ||
|
|
572c02bf6e | ||
|
|
80777b293f | ||
|
|
3c08834377 | ||
|
|
eeae12e3d4 | ||
|
|
992ac73068 | ||
|
|
e843779555 | ||
|
|
5f4ca240b4 | ||
|
|
79cd374f16 | ||
|
|
b137b32fc6 | ||
|
|
3cd2bfdef0 | ||
|
|
461dbdf0f8 | ||
|
|
9e8a6b6304 | ||
|
|
fd5ea89340 | ||
|
|
1d1d2b31cd | ||
|
|
d75656dad7 | ||
|
|
f0aa2fe0e0 | ||
|
|
ae847aea2b | ||
|
|
00ac5bf64f | ||
|
|
61e8024c65 | ||
|
|
ee5a370c01 | ||
|
|
659ce13e98 | ||
|
|
a7fde21300 | ||
|
|
a6bfab2d74 | ||
|
|
e948af1851 | ||
|
|
2062cc5d10 | ||
|
|
e85d10c6d9 | ||
|
|
0e0ab66d45 | ||
|
|
f2635c7fdc | ||
|
|
4d92bbe541 | ||
|
|
e6e1434fc1 | ||
|
|
5e689f94f4 | ||
|
|
c1b6d26b8e | ||
|
|
f72c5dba84 | ||
|
|
704007092c | ||
|
|
2f8c434429 | ||
|
|
b0c57e7ae3 | ||
|
|
0e57391b4d | ||
|
|
7ff1a93e72 | ||
|
|
d7eada7216 | ||
|
|
c435f71592 | ||
|
|
0dd6f01ef6 | ||
|
|
cd95b75563 | ||
|
|
4122e772c1 | ||
|
|
2fbe99909c | ||
|
|
d4f3d6209c | ||
|
|
641a51aa4f | ||
|
|
67afe84593 | ||
|
|
66f7c90c51 | ||
|
|
959117c391 | ||
| 5e810c704f | |||
|
|
675243061d | ||
|
|
246825d672 | ||
|
|
aa1a67d6c1 | ||
|
|
97b1848ba3 | ||
|
|
c4f6132aca | ||
|
|
a0de4f126f | ||
|
|
a8a96def97 | ||
|
|
eaddc30def | ||
|
|
aa17639e20 | ||
|
|
58d7ad494b | ||
|
|
2895f48bd6 | ||
|
|
8f6ea47501 | ||
|
|
3eb6237343 | ||
|
|
cb19940fa7 | ||
|
|
4bc7e9c8fe | ||
|
|
18ba24156c | ||
|
|
1d3c4d1762 | ||
|
|
51abc5032c | ||
|
|
69b3692841 | ||
|
|
d627e08419 | ||
|
|
bd9f1d1949 | ||
|
|
04db13d00e | ||
|
|
f88f0b4a76 | ||
|
|
07f9a8c0f6 | ||
|
|
5ba0209f39 | ||
|
|
ced439f4c4 | ||
|
|
cf44ec1191 | ||
|
|
e7458fad01 | ||
|
|
52dfdace88 | ||
|
|
a23631a8ca | ||
|
|
6a378dae0d | ||
|
|
0b4a8550e5 | ||
|
|
519601595c | ||
|
|
8dfd8ec02e | ||
|
|
4cef1135a3 | ||
|
|
a7bd52bd48 | ||
|
|
55df2e06e2 | ||
|
|
cfc9ebefb0 | ||
|
|
516518529c | ||
|
|
6b4eb1a1b0 | ||
|
|
5e3311a024 | ||
|
|
233a90e608 | ||
|
|
4b26e1c442 | ||
|
|
b216a62d1e | ||
|
|
978cb937c4 | ||
|
|
86adfc091b | ||
|
|
8f3a1dde34 | ||
|
|
9061e8f731 | ||
|
|
05be6e6729 | ||
|
|
156a05079e | ||
|
|
0e48497cd4 | ||
|
|
fbfed5bab1 | ||
|
|
66fb300873 | ||
|
|
6a86496385 | ||
|
|
ac10b73e69 | ||
|
|
689d0875b7 | ||
|
|
d9465b0954 | ||
|
|
25b9e5fa5a | ||
|
|
31922eac32 | ||
|
|
60d3467b1b | ||
|
|
ec1b5860fd | ||
|
|
00196cb7e2 | ||
|
|
92c68dfcbc | ||
|
|
1db56f4b29 | ||
|
|
038567280b | ||
|
|
022e6304a3 | ||
|
|
5dcd864c58 | ||
|
|
32790674d6 | ||
|
|
5d6205cb44 | ||
|
|
27c4da5b73 | ||
|
|
5d57e9bbcf | ||
|
|
9775fd4707 | ||
|
|
12d13bc2c0 | ||
|
|
3991a51fd6 | ||
|
|
90960d370d | ||
|
|
126fe9c711 | ||
|
|
770e63b8da | ||
|
|
e9b0dcd9f4 | ||
|
|
8040ad5fc7 | ||
|
|
24a08fe348 | ||
|
|
198eb453be | ||
|
|
e6a97e83ab | ||
|
|
9ab2262e86 | ||
|
|
29593a6eda | ||
|
|
27ce426f46 | ||
|
|
ca195b44cf | ||
|
|
a396d8e6ac | ||
|
|
d320f00e96 | ||
|
|
7a60e02d5c | ||
|
|
fb453ea9e5 | ||
|
|
87bff33c30 | ||
|
|
2693201cfd | ||
|
|
2dba4aab2b | ||
|
|
6caa725f5a | ||
|
|
198562c36c | ||
|
|
686a46f24c |
113
.appveyor.yml
Normal file
113
.appveyor.yml
Normal file
@@ -0,0 +1,113 @@
|
||||
# .appveyor.yml for use with EPICS Base ci-scripts
|
||||
# (see: https://github.com/epics-base/ci-scripts)
|
||||
|
||||
# This is YAML - indentation levels are crucial
|
||||
|
||||
#---------------------------------#
|
||||
# build cache #
|
||||
#---------------------------------#
|
||||
# The AppVeyor cache allowance is way too small (1GB per account across all
|
||||
# projects, branches and jobs) to be used for the dependency builds.
|
||||
|
||||
cache:
|
||||
- C:\Users\appveyor\.tools
|
||||
|
||||
#---------------------------------#
|
||||
# repository cloning #
|
||||
#---------------------------------#
|
||||
|
||||
init:
|
||||
# Set autocrlf to make batch files work
|
||||
- cmd: git config --global core.autocrlf true
|
||||
|
||||
clone_depth: 5
|
||||
|
||||
#---------------------------------#
|
||||
# build matrix configuration #
|
||||
#---------------------------------#
|
||||
|
||||
# Build Configurations: dll/static, regular/debug
|
||||
configuration:
|
||||
- dynamic
|
||||
- static
|
||||
- dynamic-debug
|
||||
- static-debug
|
||||
|
||||
# Environment variables: compiler toolchain, base version, setup file, ...
|
||||
environment:
|
||||
# common / default variables for all jobs
|
||||
SETUP_PATH: .ci-local
|
||||
EPICS_TEST_IMPRECISE_TIMING: YES
|
||||
BASE: 7.0
|
||||
|
||||
matrix:
|
||||
- CMP: vs2019
|
||||
BASE: 3.15
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||
- CMP: vs2019
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||
- CMP: vs2017
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
- CMP: vs2015
|
||||
- CMP: gcc
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||
# TODO: static linking w/ readline isn't working. Bypass auto-detect
|
||||
COMMANDLINE_LIBRARY: EPICS
|
||||
|
||||
# Platform: processor architecture
|
||||
platform: x64
|
||||
|
||||
# Matrix configuration: exclude sets of jobs
|
||||
matrix:
|
||||
exclude:
|
||||
# MinGW debug builds use the same libraries, unlike VS
|
||||
- configuration: dynamic-debug
|
||||
CMP: gcc
|
||||
- configuration: static-debug
|
||||
CMP: gcc
|
||||
|
||||
#---------------------------------#
|
||||
# building & testing #
|
||||
#---------------------------------#
|
||||
|
||||
install:
|
||||
- cmd: git submodule update --init --recursive
|
||||
- cmd: pip install git+https://github.com/mdavidsaver/ci-core-dumper#egg=ci-core-dumper
|
||||
- cmd: python .ci/cue.py prepare
|
||||
|
||||
build_script:
|
||||
- cmd: python .ci/cue.py build
|
||||
|
||||
test_script:
|
||||
- cmd: python -m ci_core_dumper install
|
||||
- cmd: python .ci/cue.py -T 20M test
|
||||
|
||||
on_finish:
|
||||
- ps: Get-ChildItem *.tap -Recurse -Force | % { Push-AppveyorArtifact $_.FullName -FileName $_.Name }
|
||||
- cmd: python .ci/cue.py -T 5M test-results
|
||||
|
||||
on_failure:
|
||||
- cmd: python -m ci_core_dumper report
|
||||
|
||||
#---------------------------------#
|
||||
# debugging #
|
||||
#---------------------------------#
|
||||
|
||||
## To connect by remote desktop to a failed build, uncomment the lines below.
|
||||
## You must connect within the usual build timeout limit (60 minutes),
|
||||
## so adjust the build matrix above to just build the config of interest.
|
||||
|
||||
#on_failure:
|
||||
# - ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
||||
# - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
||||
|
||||
#---------------------------------#
|
||||
# notifications #
|
||||
#---------------------------------#
|
||||
|
||||
notifications:
|
||||
- provider: Email
|
||||
to:
|
||||
- core-talk@aps.anl.gov
|
||||
on_build_success: false
|
||||
- provider: GitHubPullRequest
|
||||
1
.ci
Submodule
1
.ci
Submodule
Submodule .ci added at 20f8e05393
6
.ci-local/defaults.set
Normal file
6
.ci-local/defaults.set
Normal file
@@ -0,0 +1,6 @@
|
||||
# EPICS Base
|
||||
BASE_DIRNAME=base
|
||||
BASE_REPONAME=epics-base
|
||||
BASE_REPOOWNER=epics-base
|
||||
BASE_VARNAME=EPICS_BASE
|
||||
BASE_RECURSIVE=NO
|
||||
301
.github/workflows/ci-scripts-build.yml
vendored
Normal file
301
.github/workflows/ci-scripts-build.yml
vendored
Normal file
@@ -0,0 +1,301 @@
|
||||
# .github/workflows/ci-scripts-build.yml for use with EPICS Base ci-scripts
|
||||
# (see: https://github.com/epics-base/ci-scripts)
|
||||
|
||||
# This is YAML - indentation levels are crucial
|
||||
|
||||
# Workflow name, shared by all branches
|
||||
|
||||
name: pvData
|
||||
|
||||
# Trigger on pushes and PRs to any branch
|
||||
on:
|
||||
push:
|
||||
paths-ignore:
|
||||
- .appveyor.yml
|
||||
pull_request:
|
||||
|
||||
env:
|
||||
SETUP_PATH: .ci-local:.ci
|
||||
EPICS_TEST_IMPRECISE_TIMING: YES
|
||||
EPICS_TEST_TIMEOUT: 300 # 5 min
|
||||
|
||||
jobs:
|
||||
native:
|
||||
name: ${{ matrix.name }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
# Set environment variables from matrix parameters
|
||||
env:
|
||||
# NB: PVA modules build against both BASE 7.0 and 3.15
|
||||
BASE: ${{ matrix.base }}
|
||||
CMP: ${{ matrix.cmp }}
|
||||
BCFG: ${{ matrix.configuration }}
|
||||
CI_CROSS_TARGETS: ${{ matrix.cross }}
|
||||
EXTRA: ${{ matrix.extra }}
|
||||
TEST: ${{ matrix.test }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
# Job names also name artifacts, character limitations apply
|
||||
include:
|
||||
- name: "7.0 Ub gcc c++20 Werror"
|
||||
base: "7.0"
|
||||
os: ubuntu-latest
|
||||
cmp: gcc
|
||||
configuration: default
|
||||
# Turn all warnings into errors,
|
||||
# except for those we could not fix (yet).
|
||||
# Remove respective -Wno-error=... flag once it is fixed.
|
||||
extra: "CMD_CXXFLAGS=-std=c++20
|
||||
CMD_CPPFLAGS='-fdiagnostics-color
|
||||
-fstack-protector-strong
|
||||
-Wformat
|
||||
-Werror
|
||||
-Werror=format-security
|
||||
-Wno-error=deprecated-declarations
|
||||
-Wno-error=stringop-truncation
|
||||
-Wno-error=restrict
|
||||
-Wno-error=sizeof-pointer-memaccess
|
||||
-Wno-error=nonnull
|
||||
-Wno-error=dangling-pointer
|
||||
-Wno-error=format-overflow
|
||||
-Wno-error=stringop-overread
|
||||
-U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=3'
|
||||
CMD_LDFLAGS=-Wl,-z,relro"
|
||||
|
||||
- name: "7.0 Ub gcc C++11, static"
|
||||
base: "7.0"
|
||||
os: ubuntu-latest
|
||||
cmp: gcc
|
||||
configuration: static
|
||||
extra: "CMD_CXXFLAGS=-std=c++11"
|
||||
|
||||
- name: "7.0 Ub gcc u-char"
|
||||
base: "7.0"
|
||||
os: ubuntu-latest
|
||||
cmp: gcc
|
||||
configuration: static
|
||||
extra: "CMD_CFLAGS=-funsigned-char CMD_CXXFLAGS=-funsigned-char"
|
||||
|
||||
- name: "7.0 Ub clang"
|
||||
base: "7.0"
|
||||
os: ubuntu-latest
|
||||
cmp: clang
|
||||
configuration: default
|
||||
|
||||
- name: "7.0 Ub clang C++11"
|
||||
base: "7.0"
|
||||
os: ubuntu-latest
|
||||
cmp: clang
|
||||
configuration: default
|
||||
extra: "CMD_CXXFLAGS=-std=c++11"
|
||||
|
||||
- name: "7.0 MacOS clang"
|
||||
base: "7.0"
|
||||
os: macos-latest
|
||||
cmp: clang
|
||||
configuration: default
|
||||
|
||||
# Cross builds
|
||||
|
||||
- name: "3.15 Ub-22 gcc + MinGW"
|
||||
base: "3.15"
|
||||
os: ubuntu-22.04
|
||||
cmp: gcc
|
||||
configuration: default
|
||||
cross: "windows-x64-mingw"
|
||||
|
||||
- name: "7.0 Ub gcc + linux-aarch64"
|
||||
base: "7.0"
|
||||
os: ubuntu-latest
|
||||
cmp: gcc
|
||||
configuration: default
|
||||
cross: "linux-aarch64"
|
||||
|
||||
- name: "7.0 Ub gcc + linux-arm gnueabi"
|
||||
base: "7.0"
|
||||
os: ubuntu-latest
|
||||
cmp: gcc
|
||||
configuration: default
|
||||
cross: "linux-arm@arm-linux-gnueabi"
|
||||
|
||||
- name: "7.0 Ub gcc + linux-arm gnueabihf"
|
||||
base: "7.0"
|
||||
os: ubuntu-latest
|
||||
cmp: gcc
|
||||
configuration: default
|
||||
cross: "linux-arm@arm-linux-gnueabihf"
|
||||
|
||||
- name: "7.0 Ub gcc + MinGW"
|
||||
base: "7.0"
|
||||
os: ubuntu-latest
|
||||
cmp: gcc
|
||||
configuration: default
|
||||
cross: "windows-x64-mingw"
|
||||
|
||||
- name: "7.0 Ub gcc + MinGW, static"
|
||||
base: "7.0"
|
||||
os: ubuntu-latest
|
||||
cmp: gcc
|
||||
configuration: static
|
||||
cross: "windows-x64-mingw"
|
||||
|
||||
- name: "7.0 Ub-22 gcc + RT-4.9 pc386"
|
||||
base: "7.0"
|
||||
os: ubuntu-22.04
|
||||
cmp: gcc
|
||||
configuration: default
|
||||
cross: "RTEMS-pc386-qemu@4.9"
|
||||
|
||||
- name: "7.0 Ub-22 gcc + RT-4.10 pc386"
|
||||
base: "7.0"
|
||||
os: ubuntu-22.04
|
||||
cmp: gcc
|
||||
configuration: default
|
||||
cross: "RTEMS-pc386-qemu@4.10"
|
||||
test: NO
|
||||
|
||||
- name: "7.0 Ub-22 gcc + RT-5.1 pc686"
|
||||
base: "7.0"
|
||||
os: ubuntu-22.04
|
||||
cmp: gcc
|
||||
configuration: default
|
||||
cross: "RTEMS-pc686-qemu@5"
|
||||
|
||||
- name: "7.0 Ub-22 gcc + RT-5.1 beatnik,zynq_a9,uC5282"
|
||||
base: "7.0"
|
||||
os: ubuntu-22.04
|
||||
cmp: gcc
|
||||
configuration: default
|
||||
cross: "RTEMS-beatnik@5:RTEMS-xilinx_zynq_a9_qemu@5:RTEMS-uC5282@5"
|
||||
test: NO
|
||||
|
||||
# Windows builds
|
||||
|
||||
- name: "7.0 Win-22 MSC-22"
|
||||
base: "7.0"
|
||||
os: windows-2022
|
||||
cmp: vs2022
|
||||
configuration: default
|
||||
|
||||
- name: "7.0 Win-22 MSC-22 static"
|
||||
base: "7.0"
|
||||
os: windows-2022
|
||||
cmp: vs2022
|
||||
configuration: static
|
||||
|
||||
- name: "7.0 Win-22 MSC-22 debug"
|
||||
base: "7.0"
|
||||
os: windows-2022
|
||||
cmp: vs2022
|
||||
configuration: debug
|
||||
extra: "CMD_CXXFLAGS=-analyze"
|
||||
|
||||
- name: "7.0 Win-22 MinGW"
|
||||
base: "7.0"
|
||||
os: windows-2022
|
||||
cmp: gcc
|
||||
configuration: default
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
- name: Automatic core dumper analysis
|
||||
uses: mdavidsaver/ci-core-dumper@master
|
||||
- name: "apt-get install"
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get -y install qemu-system-x86 g++-mingw-w64-x86-64 gdb
|
||||
if: runner.os == 'Linux'
|
||||
- name: Prepare and compile dependencies
|
||||
run: python .ci/cue.py prepare
|
||||
- name: Build main module
|
||||
run: python .ci/cue.py build
|
||||
- name: Run main module tests
|
||||
run: python .ci/cue.py -T 60M test
|
||||
- name: Upload tapfiles Artifact
|
||||
if: ${{ always() }}
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: tapfiles ${{ matrix.name }}
|
||||
path: '**/O.*/*.tap'
|
||||
if-no-files-found: ignore
|
||||
- name: Collect and show test results
|
||||
if: ${{ always() }}
|
||||
run: python .ci/cue.py -T 5M test-results
|
||||
|
||||
docker:
|
||||
name: ${{ matrix.name }}
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: ${{ matrix.image }}
|
||||
# Set environment variables from matrix parameters
|
||||
env:
|
||||
BASE: ${{ matrix.base }}
|
||||
CMP: ${{ matrix.cmp }}
|
||||
BCFG: ${{ matrix.configuration }}
|
||||
EXTRA: ${{ matrix.extra }}
|
||||
TEST: ${{ matrix.test }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
# Job names also name artifacts, character limitations apply
|
||||
include:
|
||||
- name: "7.0 CentOS-8 gcc"
|
||||
base: "7.0"
|
||||
image: centos:8
|
||||
cmp: gcc
|
||||
configuration: default
|
||||
|
||||
- name: "7.0 Rocky-9 gcc"
|
||||
base: "7.0"
|
||||
image: rockylinux:9
|
||||
cmp: gcc
|
||||
configuration: default
|
||||
|
||||
- name: "7.0 Fedora-33 gcc"
|
||||
base: "7.0"
|
||||
image: fedora:33
|
||||
cmp: gcc
|
||||
configuration: default
|
||||
|
||||
- name: "7.0 Fedora gcc"
|
||||
base: "7.0"
|
||||
image: fedora:latest
|
||||
cmp: gcc
|
||||
configuration: default
|
||||
|
||||
steps:
|
||||
- name: "Fix repo URLs on CentOS-8"
|
||||
# centos:8 is frozen, repos are in the vault
|
||||
if: matrix.image=='centos:8'
|
||||
run: |
|
||||
sed -i -e "s|mirrorlist=|#mirrorlist=|" \
|
||||
-e "s|#baseurl=http://mirror|baseurl=http://vault|" \
|
||||
/etc/yum.repos.d/CentOS-Linux-{BaseOS,AppStream,Extras,Plus}.repo
|
||||
- name: "Redhat setup"
|
||||
run: |
|
||||
dnf -y install python3 gdb make perl gcc-c++ glibc-devel readline-devel ncurses-devel perl-devel perl-Test-Simple
|
||||
git --version || dnf -y install git
|
||||
python3 --version
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
- name: Automatic core dumper analysis
|
||||
uses: mdavidsaver/ci-core-dumper@master
|
||||
- name: Prepare and compile dependencies
|
||||
run: python3 .ci/cue.py prepare
|
||||
- name: Build main module
|
||||
run: python3 .ci/cue.py build
|
||||
- name: Run main module tests
|
||||
run: python3 .ci/cue.py -T 20M test
|
||||
- name: Upload tapfiles Artifact
|
||||
if: ${{ always() }}
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: tapfiles ${{ matrix.name }}
|
||||
path: '**/O.*/*.tap'
|
||||
if-no-files-found: ignore
|
||||
- name: Collect and show test results
|
||||
if: ${{ always() }}
|
||||
run: python3 .ci/cue.py -T 5M test-results
|
||||
17
.gitignore
vendored
Normal file
17
.gitignore
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
/cfg/
|
||||
/bin/
|
||||
/lib/
|
||||
/db/
|
||||
/dbd/
|
||||
/html/
|
||||
/include/
|
||||
/templates/
|
||||
/configure/*.local
|
||||
/configure/RELEASE.*
|
||||
/configure/CONFIG_SITE.*
|
||||
O.*/
|
||||
/QtC-*
|
||||
envPaths
|
||||
*.orig
|
||||
*.log
|
||||
.*.swp
|
||||
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
[submodule ".ci"]
|
||||
path = .ci
|
||||
url = https://github.com/epics-base/ci-scripts
|
||||
@@ -1,9 +0,0 @@
|
||||
QtC-pvData.creator.user
|
||||
bin
|
||||
lib
|
||||
doc
|
||||
include
|
||||
documentation/html
|
||||
./O.*
|
||||
configure/RELEASE.local
|
||||
configure/CONFIG_SITE.local
|
||||
4
.hgtags
4
.hgtags
@@ -1,4 +0,0 @@
|
||||
459f10877e5628241704f31437b4cbd342df0798 test1
|
||||
6e8a22d01e824702088195c08bf50bfb6f293de5 1.0-BETA
|
||||
d29d84f4c3f389f2accd497185b106c8541f95c9 1.1-SNAPSHOT
|
||||
a29729ca0ecd60b66f2d997031d97911377e44a7 marchtest
|
||||
17
.readthedocs.yml
Normal file
17
.readthedocs.yml
Normal file
@@ -0,0 +1,17 @@
|
||||
# .readthedocs.yml
|
||||
# Read the Docs configuration file
|
||||
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
|
||||
|
||||
# Required
|
||||
version: 2
|
||||
|
||||
# Build documentation in the documentation/ directory with Sphinx
|
||||
sphinx:
|
||||
configuration: documentation/conf.py
|
||||
|
||||
# Build documentation with MkDocs
|
||||
#mkdocs:
|
||||
# configuration: mkdocs.yml
|
||||
|
||||
# Optionally build your docs in additional formats such as PDF and ePub
|
||||
formats: all
|
||||
65
LICENSE
Normal file
65
LICENSE
Normal file
@@ -0,0 +1,65 @@
|
||||
Copyright and License Terms
|
||||
---------------------------
|
||||
|
||||
Copyright (c) 2006-2016 Martin R. Kraimer
|
||||
Copyright (c) 2006-2016 UChicago Argonne LLC, as Operator of Argonne
|
||||
National Laboratory.
|
||||
Copyright (c) 2006 Deutsches Elektronen-Synchrotron,
|
||||
Member of the Helmholtz Association, (DESY), HAMBURG, GERMANY.
|
||||
Copyright (c) 2007-2016 Control System Laboratory,
|
||||
(COSYLAB) Ljubljana Slovenia
|
||||
Copyright (c) 2010-2016 Brookhaven Science Associates, as Operator
|
||||
of Brookhaven National Laboratory
|
||||
Copyright (c) 2011-2016 Diamond Light Source Limited,
|
||||
(DLS) Didcot, United Kingdom
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
files (the "Software"), to deal in the Software without
|
||||
restriction, including without limitation the rights to use,
|
||||
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
________________________________________________________________________
|
||||
|
||||
Additional Disclaimers
|
||||
----------------------
|
||||
|
||||
This software is copyright in part by these institutions:
|
||||
|
||||
* Brookhaven Science Associates, as Operator of Brookhaven
|
||||
National Laboratory, New York, USA
|
||||
* Control System Laboratory, Ljubljana, Slovenia
|
||||
* Deutsches Elektronen-Synchroton, Member of the Helmholtz
|
||||
Association, Hamburg, Germany
|
||||
* Diamond Light Source Limited, Didcot, United Kingdom
|
||||
* Helmholtz-Zentrum Berlin fuer Materialien und Energie m.b.H.,
|
||||
Berlin, Germany.
|
||||
* UChicage Argonne LLC, as Operator of Argonne National Laboratory,
|
||||
Illinois, USA
|
||||
|
||||
In no event shall these institutions be liable to any party for direct,
|
||||
indirect, special, incidental, or consequential damages arising out of
|
||||
the use of this software, its documentation, or any derivatives thereof,
|
||||
even if advised of the possibility of such damage.
|
||||
|
||||
These institutions specifically disclaim any warranties, including, but
|
||||
not limited to, the implied warranties of merchantability, fitness for a
|
||||
particular purpose, and non-infringement. This software is provided on
|
||||
an "as is" basis, and these institutions have no obligation to provide
|
||||
maintenance, support, updates, enhancements, or modifications.
|
||||
|
||||
17
Makefile
17
Makefile
@@ -1,12 +1,17 @@
|
||||
#Makefile at top of application tree
|
||||
# Makefile for the EPICS V4 pvData module
|
||||
|
||||
TOP = .
|
||||
include $(TOP)/configure/CONFIG
|
||||
|
||||
DIRS += configure
|
||||
DIRS += pvDataApp
|
||||
pvDataApp_DEPEND_DIRS = configure
|
||||
|
||||
DIRS += src
|
||||
src_DEPEND_DIRS = configure
|
||||
|
||||
DIRS += testApp
|
||||
testApp_DEPEND_DIRS = pvDataApp
|
||||
testApp_DEPEND_DIRS = src
|
||||
|
||||
DIRS += examples
|
||||
examples_DEPEND_DIRS = src
|
||||
|
||||
include $(TOP)/configure/RULES_TOP
|
||||
|
||||
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
// ADD PREDEFINED MACROS HERE!
|
||||
@@ -1 +0,0 @@
|
||||
[General]
|
||||
@@ -1,66 +0,0 @@
|
||||
<!DOCTYPE QtCreatorProject>
|
||||
<qtcreator>
|
||||
<data>
|
||||
<variable>GenericProjectManager.GenericProject.Toolchain</variable>
|
||||
<value type="int">0</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.ActiveTarget</variable>
|
||||
<value type="int">0</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.EditorSettings</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value key="EditorConfiguration.Codec" type="QByteArray">System</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.Target.0</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Desktop</value>
|
||||
<value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">GenericProjectManager.GenericTarget</value>
|
||||
<value key="ProjectExplorer.Target.ActiveBuildConfiguration" type="int">0</value>
|
||||
<value key="ProjectExplorer.Target.ActiveRunConfiguration" type="int">0</value>
|
||||
<valuemap key="ProjectExplorer.Target.BuildConfiguration.0" type="QVariantMap">
|
||||
<value key="GenericProjectManager.GenericBuildConfiguration.BuildDirectory" type="QString">/home/mrk/hgwork/pvDataCPP</value>
|
||||
<valuemap key="ProjectExplorer.BuildConfiguration.BuildStep.0" type="QVariantMap">
|
||||
<valuelist key="GenericProjectManager.GenericMakeStep.BuildTargets" type="QVariantList">
|
||||
<value type="QString">all</value>
|
||||
</valuelist>
|
||||
<valuelist key="GenericProjectManager.GenericMakeStep.MakeArguments" type="QVariantList"/>
|
||||
<value key="GenericProjectManager.GenericMakeStep.MakeCommand" type="QString"></value>
|
||||
<value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Make</value>
|
||||
<value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">GenericProjectManager.GenericMakeStep</value>
|
||||
</valuemap>
|
||||
<value key="ProjectExplorer.BuildConfiguration.BuildStepsCount" type="int">1</value>
|
||||
<value key="ProjectExplorer.BuildConfiguration.CleanStepsCount" type="int">0</value>
|
||||
<value key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment" type="bool">false</value>
|
||||
<valuelist key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges" type="QVariantList"/>
|
||||
<value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">all</value>
|
||||
<value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">GenericProjectManager.GenericBuildConfiguration</value>
|
||||
</valuemap>
|
||||
<value key="ProjectExplorer.Target.BuildConfigurationCount" type="int">1</value>
|
||||
<valuemap key="ProjectExplorer.Target.RunConfiguration.0" type="QVariantMap">
|
||||
<valuelist key="ProjectExplorer.CustomExecutableRunConfiguration.Arguments" type="QVariantList"/>
|
||||
<value key="ProjectExplorer.CustomExecutableRunConfiguration.BaseEnvironmentBase" type="int">2</value>
|
||||
<value key="ProjectExplorer.CustomExecutableRunConfiguration.Executable" type="QString">/home/mrk/hgwork/pvDataCPP/bin/linux-x86/testIntrospect</value>
|
||||
<value key="ProjectExplorer.CustomExecutableRunConfiguration.UseTerminal" type="bool">false</value>
|
||||
<valuelist key="ProjectExplorer.CustomExecutableRunConfiguration.UserEnvironmentChanges" type="QVariantList"/>
|
||||
<value key="ProjectExplorer.CustomExecutableRunConfiguration.UserName" type="QString">testIntrospect</value>
|
||||
<value key="ProjectExplorer.CustomExecutableRunConfiguration.UserSetName" type="bool">true</value>
|
||||
<value key="ProjectExplorer.CustomExecutableRunConfiguration.WorkingDirectory" type="QString">$BUILDDIR</value>
|
||||
<value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">testIntrospect</value>
|
||||
<value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">ProjectExplorer.CustomExecutableRunConfiguration</value>
|
||||
</valuemap>
|
||||
<value key="ProjectExplorer.Target.RunConfigurationCount" type="int">1</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.TargetCount</variable>
|
||||
<value type="int">1</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.Updater.FileVersion</variable>
|
||||
<value type="int">4</value>
|
||||
</data>
|
||||
</qtcreator>
|
||||
@@ -1,85 +0,0 @@
|
||||
include/AbstractPVArray.h
|
||||
include/AbstractPVField.h
|
||||
include/AbstractPVScalar.h
|
||||
include/AbstractPVScalarArray.h
|
||||
include/BasePVBoolean.h
|
||||
include/BasePVBooleanArray.h
|
||||
include/BasePVByte.h
|
||||
include/BasePVByteArray.h
|
||||
include/BasePVDouble.h
|
||||
include/BasePVDoubleArray.h
|
||||
include/BasePVFloat.h
|
||||
include/BasePVFloatArray.h
|
||||
include/BasePVInt.h
|
||||
include/BasePVIntArray.h
|
||||
include/BasePVLong.h
|
||||
include/BasePVLongArray.h
|
||||
include/BasePVShort.h
|
||||
include/BasePVShortArray.h
|
||||
include/BasePVString.h
|
||||
include/BasePVStructure.h
|
||||
include/BasePVStructureArray.h
|
||||
include/bitSet.h
|
||||
include/byteBuffer.h
|
||||
include/convert.h
|
||||
include/factory.h
|
||||
include/lock.h
|
||||
include/noDefaultMethods.h
|
||||
include/pvData.h
|
||||
include/pvIntrospect.h
|
||||
include/requester.h
|
||||
include/serialize.h
|
||||
include/standardField.h
|
||||
pvDataApp/factory/AbstractPVArray.h
|
||||
pvDataApp/factory/AbstractPVField.h
|
||||
pvDataApp/factory/AbstractPVScalar.h
|
||||
pvDataApp/factory/AbstractPVScalarArray.h
|
||||
pvDataApp/factory/BasePVBoolean.h
|
||||
pvDataApp/factory/BasePVBooleanArray.h
|
||||
pvDataApp/factory/BasePVByte.h
|
||||
pvDataApp/factory/BasePVByteArray.h
|
||||
pvDataApp/factory/BasePVDouble.h
|
||||
pvDataApp/factory/BasePVDoubleArray.h
|
||||
pvDataApp/factory/BasePVFloat.h
|
||||
pvDataApp/factory/BasePVFloatArray.h
|
||||
pvDataApp/factory/BasePVInt.h
|
||||
pvDataApp/factory/BasePVIntArray.h
|
||||
pvDataApp/factory/BasePVLong.h
|
||||
pvDataApp/factory/BasePVLongArray.h
|
||||
pvDataApp/factory/BasePVShort.h
|
||||
pvDataApp/factory/BasePVShortArray.h
|
||||
pvDataApp/factory/BasePVString.h
|
||||
pvDataApp/factory/BasePVStringArray.h
|
||||
pvDataApp/factory/BasePVStructure.h
|
||||
pvDataApp/factory/BasePVStructureArray.h
|
||||
pvDataApp/factory/Convert.cpp
|
||||
pvDataApp/factory/factory.h
|
||||
pvDataApp/factory/FieldCreateFactory.cpp
|
||||
pvDataApp/factory/PVAuxInfoImpl.cpp
|
||||
pvDataApp/factory/PVDataCreateFactory.cpp
|
||||
pvDataApp/factory/StandardField.cpp
|
||||
pvDataApp/factory/TypeFunc.cpp
|
||||
pvDataApp/misc/bitSet.h
|
||||
pvDataApp/misc/byteBuffer.h
|
||||
pvDataApp/misc/lock.h
|
||||
pvDataApp/misc/noDefaultMethods.h
|
||||
pvDataApp/misc/requester.h
|
||||
pvDataApp/misc/serialize.h
|
||||
pvDataApp/pv/convert.h
|
||||
pvDataApp/pv/pvData.h
|
||||
pvDataApp/pv/pvIntrospect.h
|
||||
pvDataApp/pv/standardField.h
|
||||
pvDataApp/test/testIntrospect.cpp
|
||||
pvDataApp/test/testPVAuxInfo.cpp
|
||||
pvDataApp/test/testPVScalar.cpp
|
||||
pvDataApp/test/testPVScalarArray.cpp
|
||||
pvDataApp/test/testSimpleStructure.cpp
|
||||
pvDataApp/misc/epicsException.h
|
||||
pvDataApp/misc/byteBuffer.cpp
|
||||
pvDataApp/misc/bitSet.cpp
|
||||
pvDataApp/miscTest/testByteBuffer.cpp
|
||||
pvDataApp/miscTest/testBitSet.cpp
|
||||
pvDataApp/miscTest/testBaseException.cpp
|
||||
pvDataApp/misc/serializeHelper.h
|
||||
pvDataApp/misc/serializeHelper.cpp
|
||||
pvDataApp/pvTest/testIntrospect.cpp
|
||||
@@ -1,4 +0,0 @@
|
||||
include
|
||||
pvDataApp/factory
|
||||
pvDataApp/misc
|
||||
pvDataApp/pv
|
||||
82
README.html
82
README.html
@@ -1,82 +0,0 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
|
||||
<title>EPICS pvData C++</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1 style="text-align: center">EPICS pvData C++<br />
|
||||
Overview<br />
|
||||
2010.08.10</h1>
|
||||
CONTENTS
|
||||
<hr />
|
||||
|
||||
<h2 style="text-align: center">Introduction</h2>
|
||||
<hr />
|
||||
|
||||
<p>This project has the begining of the C++ implementation of pvData. The
|
||||
following is done:</p>
|
||||
<dl>
|
||||
<dt>introspection interfaces</dt>
|
||||
<dd>The introspection interfaces for clients are described.</dd>
|
||||
<dt>introspection implementation</dt>
|
||||
<dd>The following have been implemented: Type, ScalarType, Field,
|
||||
Scalar</dd>
|
||||
<dt>test</dt>
|
||||
<dd>A test of Scalar.</dd>
|
||||
<dt>As mentioned below there are problems with the current
|
||||
implementation.</dt>
|
||||
</dl>
|
||||
<hr />
|
||||
|
||||
<h2 style="text-align: center">Building</h2>
|
||||
<hr />
|
||||
|
||||
<p>The project is structured as an epics base client application. Edit
|
||||
configure/RELEASE so that it references your EPICS base and then just
|
||||
type:</p>
|
||||
<pre> make</pre>
|
||||
|
||||
<p>At the top. Then execute the test in the bin directory.</p>
|
||||
|
||||
<p>pvDataApp has the following sub directories:</p>
|
||||
<dl>
|
||||
<dt>pv</dt>
|
||||
<dd>pvData.h has the interface descriptions for client code.</dd>
|
||||
<dt>factory</dt>
|
||||
<dd>FieldCreateFactory.cpp has the current implementation</dd>
|
||||
<dt>test</dt>
|
||||
<dd>Has a test for the current implementation.</dd>
|
||||
</dl>
|
||||
<hr />
|
||||
|
||||
<h2 style="text-align: center">Questions about Classes</h2>
|
||||
<hr />
|
||||
|
||||
<p>The pure virtual classes defined in pvData.h now work. But there are still
|
||||
some things that are not so nice. Amoung these are:</p>
|
||||
<ul>
|
||||
<li>In FieldCreateFactory.cpp look for "WHY DO I". It asks why the derived
|
||||
class must also define methods defined in the base class. If it does not
|
||||
then a compilation error occurs. WHY??? </li>
|
||||
<li>The toString methods have an argument of "std::string &buf" instead
|
||||
of "std::string *". Does this seem correct?</li>
|
||||
<li>Can arguments and return descriptions be defined better?</li>
|
||||
<li>Is const present everywhere it should be? Remember that introspection
|
||||
classes are immutable.</li>
|
||||
<li>The code is NOT thread safe. When we decide for sure what thread/lock
|
||||
support to choose I will fix this.</li>
|
||||
</ul>
|
||||
|
||||
<p>HELP WILL BE GREATLY APPRECIATED. because I am still coming up to speed
|
||||
with c++</p>
|
||||
<hr />
|
||||
|
||||
<h2 style="text-align: center">Garbage Collection</h2>
|
||||
<hr />
|
||||
<p>Not yet implemented. Lets get class structure correct first.</p>
|
||||
</body>
|
||||
</html>
|
||||
16
README.md
Normal file
16
README.md
Normal file
@@ -0,0 +1,16 @@
|
||||
# pvaDataCPP
|
||||
|
||||
The EPICS **pvData** API provides a set of classes and utilities that form the core of the EPICS PVA implementation.
|
||||
|
||||
The pvDataCPP module is a part of the EPICS software toolkit that implements pvData structures as C++ class objects.
|
||||
|
||||
## Links
|
||||
|
||||
- General information about EPICS can be found at the
|
||||
[EPICS Controls website](https://epics-controls.org).
|
||||
- API documentation for this module can be found on its
|
||||
[Github Pages website](https://epics-base.github.io/pvDataCPP/).
|
||||
|
||||
## Building
|
||||
|
||||
This module is included as a submodule of a full EPICS 7 release and will be compiled during builds of that software.
|
||||
@@ -1,30 +1,29 @@
|
||||
# CONFIG
|
||||
# CONFIG - Load build configuration data
|
||||
#
|
||||
# Do not make changes to this file!
|
||||
|
||||
# You might want to change this to some shared set of rules, e.g.
|
||||
# RULES=/path/to/epics/support/modules/rules/x-y
|
||||
RULES=$(EPICS_BASE)
|
||||
# Allow user to override where the build rules come from
|
||||
RULES = $(EPICS_BASE)
|
||||
|
||||
# RELEASE files point to other application tops
|
||||
include $(TOP)/configure/RELEASE
|
||||
-include $(TOP)/configure/RELEASE.$(EPICS_HOST_ARCH)
|
||||
-include $(TOP)/configure/RELEASE.$(EPICS_HOST_ARCH).Common
|
||||
ifdef T_A
|
||||
-include $(TOP)/configure/RELEASE.Common.$(T_A)
|
||||
-include $(TOP)/configure/RELEASE.$(EPICS_HOST_ARCH).$(T_A)
|
||||
endif
|
||||
|
||||
CONFIG=$(RULES)/configure
|
||||
CONFIG = $(RULES)/configure
|
||||
include $(CONFIG)/CONFIG
|
||||
|
||||
# Override for definition in base
|
||||
# Override the Base definition:
|
||||
INSTALL_LOCATION = $(TOP)
|
||||
include $(TOP)/configure/CONFIG_SITE
|
||||
-include $(TOP)/configure/CONFIG_SITE.$(EPICS_HOST_ARCH)
|
||||
-include $(TOP)/configure/CONFIG_SITE.$(EPICS_HOST_ARCH).Common
|
||||
|
||||
# CONFIG_SITE files contain other build configuration settings
|
||||
include $(TOP)/configure/CONFIG_SITE
|
||||
-include $(TOP)/configure/CONFIG_SITE.$(EPICS_HOST_ARCH).Common
|
||||
ifdef T_A
|
||||
-include $(TOP)/configure/CONFIG_SITE.Common.$(T_A)
|
||||
-include $(TOP)/configure/CONFIG_SITE.$(EPICS_HOST_ARCH).$(T_A)
|
||||
|
||||
-include $(TOP)/configure/O.$(T_A)/CONFIG_APP_INCLUDE
|
||||
endif
|
||||
|
||||
|
||||
12
configure/CONFIG_PVDATA_VERSION
Normal file
12
configure/CONFIG_PVDATA_VERSION
Normal file
@@ -0,0 +1,12 @@
|
||||
# Version number for the PV Data API and shared library
|
||||
|
||||
EPICS_PVD_MAJOR_VERSION = 8
|
||||
EPICS_PVD_MINOR_VERSION = 0
|
||||
EPICS_PVD_MAINTENANCE_VERSION = 8
|
||||
|
||||
# Development flag, set to zero for release versions
|
||||
|
||||
EPICS_PVD_DEVELOPMENT_FLAG = 1
|
||||
|
||||
# Immediately after a release the MAINTENANCE_VERSION
|
||||
# will be incremented and the DEVELOPMENT_FLAG set to 1
|
||||
@@ -1,35 +1,35 @@
|
||||
# CONFIG_SITE
|
||||
|
||||
# Make any application-specific changes to the EPICS build
|
||||
# configuration variables in this file.
|
||||
# configuration variables in this file.
|
||||
#
|
||||
# Host/target specific settings can be specified in files named
|
||||
# CONFIG_SITE.$(EPICS_HOST_ARCH).Common
|
||||
# CONFIG_SITE.Common.$(T_A)
|
||||
# CONFIG_SITE.$(EPICS_HOST_ARCH).$(T_A)
|
||||
# CONFIG_SITE.$(EPICS_HOST_ARCH).Common
|
||||
# CONFIG_SITE.Common.$(T_A)
|
||||
# CONFIG_SITE.$(EPICS_HOST_ARCH).$(T_A)
|
||||
|
||||
# Set this when you only want to compile this application
|
||||
# for a subset of the cross-compiled target architectures
|
||||
# that Base is built for.
|
||||
#CROSS_COMPILER_TARGET_ARCHS = vxWorks-68040
|
||||
# CHECK_RELEASE controls the consistency checking of the support
|
||||
# applications pointed to by the RELEASE* files.
|
||||
# Normally CHECK_RELEASE should be set to YES.
|
||||
# Set CHECK_RELEASE to NO to disable checking completely.
|
||||
# Set CHECK_RELEASE to WARN to perform consistency checking but
|
||||
# continue building anyway if conflicts are found.
|
||||
CHECK_RELEASE = YES
|
||||
|
||||
# Set this when your IOC and the host use different paths
|
||||
# to access the application. This will be needed to boot
|
||||
# from a Microsoft FTP server or with some NFS mounts.
|
||||
# You must rebuild in the iocBoot directory for this to
|
||||
# take effect.
|
||||
#IOCS_APPL_TOP = <path to application top as seen by IOC>
|
||||
# To install files into a location other than $(TOP) define
|
||||
# INSTALL_LOCATION here.
|
||||
#INSTALL_LOCATION=</path/name/to/install/top>
|
||||
|
||||
# If you don't want to install into $(TOP) then
|
||||
# define INSTALL_LOCATION here
|
||||
#INSTALL_LOCATION=<fullpathname>
|
||||
USR_CPPFLAGS += -DPVD_INTERNAL
|
||||
|
||||
ifeq ($(EPICS_TEST_COVERAGE),1)
|
||||
-include $(TOP)/../CONFIG_SITE.local
|
||||
-include $(TOP)/configure/CONFIG_SITE.local
|
||||
|
||||
# MSVC - skip defining min()/max() macros
|
||||
USR_CPPFLAGS_WIN32 += -DNOMINMAX
|
||||
|
||||
ifdef WITH_COVERAGE
|
||||
USR_CPPFLAGS += --coverage
|
||||
USR_LDFLAGS += --coverage
|
||||
endif
|
||||
|
||||
INSTALL_INCLUDE = $(INSTALL_LOCATION)/include/pv
|
||||
USR_INCLUDES += -I $(INSTALL_LOCATION)/include
|
||||
|
||||
-include $(TOP)/configure/CONFIG_SITE.local
|
||||
|
||||
@@ -2,13 +2,7 @@ TOP=..
|
||||
|
||||
include $(TOP)/configure/CONFIG
|
||||
|
||||
# CHECK_RELEASE controls the consistency checking of the support
|
||||
# applications defined in the $(TOP)/configure/RELEASE* files.
|
||||
# Normally CHECK_RELEASE should be set to YES.
|
||||
# Set CHECK_RELEASE to NO to disable checking completely.
|
||||
# Set CHECK_RELEASE to WARN to perform consistency checking,
|
||||
# but continue the build even if conflicts are found.
|
||||
CHECK_RELEASE = YES
|
||||
CFG += CONFIG_PVDATA_VERSION
|
||||
|
||||
TARGETS = $(CONFIG_TARGETS)
|
||||
CONFIGS += $(subst ../,,$(wildcard $(CONFIG_INSTALLS)))
|
||||
|
||||
@@ -1,26 +1,38 @@
|
||||
#RELEASE Location of external products
|
||||
# RELEASE - Location of external support modules
|
||||
#
|
||||
# IF YOU MAKE ANY CHANGES to this file you MUST at least run
|
||||
# "gnumake" in this directory afterwards; you usually need
|
||||
# to run "gnumake rebuild" in the application's top level
|
||||
# directory each time this file is changed.
|
||||
# IF YOU CHANGE ANY PATHS in this file or make API changes to
|
||||
# any modules it refers to, you should do a "make rebuild" in
|
||||
# this application's top level directory.
|
||||
#
|
||||
# NOTE: The build does not check dependencies against files
|
||||
# that are outside this application, thus you should run
|
||||
# "gnumake distclean install" in the top directory each time
|
||||
# EPICS_BASE, SNCSEQ, or any other external module defined
|
||||
# in the RELEASE file is rebuilt.
|
||||
# The EPICS build process does not check dependencies against
|
||||
# any files from outside the application, so it is safest to
|
||||
# rebuild it completely if any modules it depends on change.
|
||||
#
|
||||
# Host/target specific settings can be specified in files named
|
||||
# Host- or target-specific settings can be given in files named
|
||||
# RELEASE.$(EPICS_HOST_ARCH).Common
|
||||
# RELEASE.Common.$(T_A)
|
||||
# RELEASE.$(EPICS_HOST_ARCH).$(T_A)
|
||||
#
|
||||
# This file is parsed by both GNUmake and an EPICS Perl script,
|
||||
# so it may ONLY contain definititions of paths to other support
|
||||
# modules, variable definitions that are used in module paths,
|
||||
# and include statements that pull in other RELEASE files.
|
||||
# Variables may be used before their values have been set.
|
||||
# Build variables that are NOT used in paths should be set in
|
||||
# the CONFIG_SITE file.
|
||||
|
||||
TEMPLATE_TOP=$(EPICS_BASE)/templates/makeBaseApp/top
|
||||
EPICS_BASE=/home/install/epics/base
|
||||
# Variables and paths to dependent modules:
|
||||
#MODULES = /path/to/modules
|
||||
#MYMODULE = $(MODULES)/my-module
|
||||
|
||||
# Create a file RELEASE.local containing the
|
||||
# location of your EPICS_BASE, e.g.
|
||||
# EPICS_BASE=/home/install/epics/base
|
||||
# If building the EPICS modules individually, set these:
|
||||
#EPICS_BASE = /path/to/base
|
||||
|
||||
# Set RULES here if you want to use build rules from elsewhere:
|
||||
#RULES = $(MODULES)/build-rules
|
||||
|
||||
# These allow developers to override the RELEASE variable settings
|
||||
# without having to modify the configure/RELEASE file itself.
|
||||
-include $(TOP)/../RELEASE.local
|
||||
-include $(TOP)/../RELEASE.$(EPICS_HOST_ARCH).local
|
||||
-include $(TOP)/configure/RELEASE.local
|
||||
|
||||
3
documentation/.gitignore
vendored
Normal file
3
documentation/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
*.tag
|
||||
*.db
|
||||
html/
|
||||
2367
documentation/Doxyfile
Normal file
2367
documentation/Doxyfile
Normal file
File diff suppressed because it is too large
Load Diff
16
documentation/Makefile
Normal file
16
documentation/Makefile
Normal file
@@ -0,0 +1,16 @@
|
||||
all: gen
|
||||
|
||||
clean:
|
||||
rm -rf doxygen_sqlite3.db html
|
||||
|
||||
gen: libstdc++.tag
|
||||
doxygen
|
||||
|
||||
commit: gen
|
||||
touch html/.nojekyll
|
||||
./commit-gh.sh documentation/html/ html/.nojekyll html/*.* html/search/*.*
|
||||
|
||||
libstdc++.tag:
|
||||
wget -O $@ https://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/libstdc++.tag
|
||||
|
||||
.PHONY: all clean gen commit
|
||||
14
documentation/TODO.md
Normal file
14
documentation/TODO.md
Normal file
@@ -0,0 +1,14 @@
|
||||
TODO
|
||||
===========
|
||||
|
||||
doxygen
|
||||
-------
|
||||
|
||||
There is a lot of public code that does not have doxygen tags.
|
||||
|
||||
valueAlarm
|
||||
---------
|
||||
|
||||
normativeTypes.html describes valueAlarm only for a value field that has type
|
||||
double.
|
||||
The implementation also supports all the numeric scalar types.
|
||||
7
documentation/_static/css/custom.css
Normal file
7
documentation/_static/css/custom.css
Normal file
@@ -0,0 +1,7 @@
|
||||
.wy-side-nav-search {
|
||||
background-color: #18334B;
|
||||
}
|
||||
|
||||
.wy-side-nav-search input[type="text"] {
|
||||
border-color: #18334b;
|
||||
}
|
||||
45
documentation/commit-gh.sh
Executable file
45
documentation/commit-gh.sh
Executable file
@@ -0,0 +1,45 @@
|
||||
#!/bin/sh
|
||||
set -e -x
|
||||
# Usage: commit-gh <sub-directory-prefix> <files...>
|
||||
#
|
||||
# Creates a commit containing only the files in the sub-directory provided as an argument
|
||||
#
|
||||
# Does not disturb the working copy or index
|
||||
|
||||
prefix="$1"
|
||||
shift
|
||||
|
||||
# Commit to this branch
|
||||
BRANCH=refs/heads/gh-pages
|
||||
|
||||
# Use the main branch description as the gh-pages commit message
|
||||
MSG=`git describe --tags --always`
|
||||
|
||||
# Scratch space
|
||||
TDIR=`mktemp -d -p $PWD`
|
||||
|
||||
# Automatic cleanup of scratch space
|
||||
trap 'rm -rf $TDIR' INT TERM QUIT EXIT
|
||||
|
||||
export GIT_INDEX_FILE="$TDIR/index"
|
||||
|
||||
# Add listed files to a new (empty) index
|
||||
git update-index --add "$@"
|
||||
|
||||
# Write the index into the repo, get tree hash
|
||||
TREE=`git write-tree --prefix="$prefix"`
|
||||
|
||||
echo "TREE $TREE"
|
||||
git cat-file -p $TREE
|
||||
|
||||
# Create a commit with our new tree
|
||||
# Reference current branch head as parent (if any)
|
||||
CMT=`git commit-tree -m "$MSG" $TREE`
|
||||
|
||||
echo "COMMIT $CMT"
|
||||
git cat-file -p $CMT
|
||||
|
||||
# Update the branch with the new commit tree hash
|
||||
git update-ref $BRANCH $CMT
|
||||
|
||||
echo "Done"
|
||||
78
documentation/conf.py
Normal file
78
documentation/conf.py
Normal file
@@ -0,0 +1,78 @@
|
||||
# Configuration file for the Sphinx documentation builder.
|
||||
#
|
||||
# This file only contains a selection of the most common options. For a full
|
||||
# list see the documentation:
|
||||
# http://www.sphinx-doc.org/en/master/config
|
||||
|
||||
# -- Path setup --------------------------------------------------------------
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
#
|
||||
# import os
|
||||
# import sys
|
||||
# sys.path.insert(0, os.path.abspath('.'))
|
||||
|
||||
|
||||
# -- Project information -----------------------------------------------------
|
||||
|
||||
project = 'EPICS Documentation'
|
||||
copyright = '2019, EPICS Controls.'
|
||||
author = 'EPICS'
|
||||
|
||||
|
||||
# -- General configuration ---------------------------------------------------
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
# ones.
|
||||
extensions = [
|
||||
'sphinx.ext.intersphinx',
|
||||
]
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
# This pattern also affects html_static_path and html_extra_path.
|
||||
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
|
||||
|
||||
# Intersphinx links to subprojects
|
||||
intersphinx_mapping = {
|
||||
'how-tos': ('https://docs.epics-controls.org/projects/how-tos/en/latest', None),
|
||||
}
|
||||
|
||||
|
||||
# -- Options for HTML output -------------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
#
|
||||
html_theme = 'sphinx_rtd_theme'
|
||||
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ['_static']
|
||||
|
||||
html_css_files = [
|
||||
'css/custom.css',
|
||||
]
|
||||
|
||||
master_doc = 'index'
|
||||
|
||||
html_theme_options = {
|
||||
'logo_only': True,
|
||||
}
|
||||
html_logo = "images/EPICS_white_logo_v02.png"
|
||||
|
||||
html_extra_path = ['../html']
|
||||
|
||||
|
||||
# -- Run Doxygen ------------------------------------------------------------
|
||||
|
||||
import subprocess
|
||||
subprocess.call('cd ..; mkdir -p html/doxygen; doxygen', shell=True)
|
||||
BIN
documentation/images/EPICS_white_logo_v02.png
Normal file
BIN
documentation/images/EPICS_white_logo_v02.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.5 KiB |
16
documentation/index.rst
Normal file
16
documentation/index.rst
Normal file
@@ -0,0 +1,16 @@
|
||||
pvData (C++) Library
|
||||
====================
|
||||
|
||||
.. toctree::
|
||||
:hidden:
|
||||
|
||||
EPICS Website <https://epics-controls.org>
|
||||
EPICS Documentation Home <https://docs.epics-controls.org>
|
||||
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
:caption: pvDataCPP
|
||||
|
||||
Reference Manual and API Documentation <https://docs.epics-controls.org/projects/pvdata-cpp/en/latest/doxygen>
|
||||
Source Code Repository on GitHub <https://github.com/epics-base/pvDataCPP>
|
||||
58
documentation/mainpage.dox
Normal file
58
documentation/mainpage.dox
Normal file
@@ -0,0 +1,58 @@
|
||||
#ifndef MAINPAGE_H
|
||||
#define MAINPAGE_H
|
||||
/**
|
||||
@mainpage pvDataCPP documentation
|
||||
|
||||
- This module is included in [EPICS Base releases](https://epics-controls.org/resources-and-support/base/) beginning with 7.0.1
|
||||
- It may also be [Downloaded](https://github.com/epics-base/pvDataCPP/releases) and built separately.
|
||||
- @htmlonly <a href="modules.html">API components</a> @endhtmlonly
|
||||
- @ref release_notes
|
||||
|
||||
The epics::pvData namespace.
|
||||
See pv/pvData.h header.
|
||||
|
||||
@code
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/createRequest.h>
|
||||
@endcode
|
||||
|
||||
- Type description epics::pvData::Field and sub-classes
|
||||
- Value container epics::pvData::PVField and sub-classes
|
||||
- POD array handling epics::pvData::shared_vector
|
||||
- pvRequest parsing epics::pvData::createRequest()
|
||||
|
||||
Define a structure type and create a container with default values.
|
||||
|
||||
@code
|
||||
namespace pvd = epics::pvData;
|
||||
pvd::StructureConstPtr stype(pvd::FieldBuilder::begin()
|
||||
->add("fld1", pvd::pvInt)
|
||||
->addNestedStructure("sub")
|
||||
->add("fld2", pvd::pvString)
|
||||
->endNested()
|
||||
->createStructure());
|
||||
|
||||
pvd::PVStructuretPtr value(stype->build());
|
||||
|
||||
value->getSubFieldT<pvd::PVInt>("fld1")->put(4); // store integer 4. would throw if not pvInt
|
||||
value->getSubFieldT<pvd::PVScalar>("sub.fld2")->putFrom(4.2); // convert and store string "4.2"
|
||||
@endcode
|
||||
|
||||
is equivalent to the following pseudo-code.
|
||||
|
||||
@code
|
||||
struct stype {
|
||||
pvd::int32 fld1;
|
||||
struct {
|
||||
std::string fld2;
|
||||
} sub;
|
||||
};
|
||||
stype value;
|
||||
value.fld1 = 4;
|
||||
value.fld2 = pvd::castUnsafe<std::string>(4.2);
|
||||
@endcode
|
||||
|
||||
*/
|
||||
|
||||
#endif /* MAINPAGE_H */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
491
documentation/release_notes.dox
Normal file
491
documentation/release_notes.dox
Normal file
@@ -0,0 +1,491 @@
|
||||
/**
|
||||
|
||||
@page release_notes Release Notes
|
||||
|
||||
Release 8.0.7 (Dec 2025)
|
||||
========================
|
||||
|
||||
- Compatible changes
|
||||
- Allow epics::pvData::Timer to be cancelled during callback execution.
|
||||
- Clang compiler warnings cleaned up.
|
||||
- Limit periodic timers to one catch-up after missing many events.
|
||||
|
||||
Release 8.0.6 (Dec 2023)
|
||||
========================
|
||||
|
||||
- Compatible changes
|
||||
- Actually enable JSON-5 output in PVStructure::Formatter::JSON when available.
|
||||
- Fix unaligned access issues for some ARM/Linux targets.
|
||||
|
||||
Release 8.0.5 (Sep 2022)
|
||||
========================
|
||||
|
||||
- Compatible changes
|
||||
- Internal changes to use the YAJL API for generating JSON and JSON-5 output.
|
||||
|
||||
Release 8.0.4 (Feb 2021)
|
||||
========================
|
||||
|
||||
- Incompatible changes
|
||||
- Remove ByteBuffer::align()
|
||||
- Compatible changes
|
||||
- Deprecate SerializableControl::alignBuffer() and DeserializableControl::alignData()
|
||||
- shared_vector_convert<>() fix convert of empty, untyped, array
|
||||
|
||||
Release 8.0.3 (July 2020)
|
||||
=========================
|
||||
|
||||
- Incompatible changes
|
||||
- Removed THROW_BASE_EXCEPTION_CAUSE() macro which has long ignored its cause.
|
||||
Any external users should switch to the functionally identical THROW_BASE_EXCEPTION_CAUSE()
|
||||
- Various printing of functions now conditionally escape strings
|
||||
including quote '\"' and similar charactors.
|
||||
|
||||
Release 8.0.2 (May 2020)
|
||||
========================
|
||||
|
||||
- Changes to documentation and unittests.
|
||||
No functional changes to library.
|
||||
|
||||
Release 8.0.1 (Nov 2019)
|
||||
==========================
|
||||
|
||||
- Incompatible changes
|
||||
- Requires Base >= 3.15
|
||||
- Bug fixes
|
||||
|
||||
Release 8.0.0 (July 2019)
|
||||
=========================
|
||||
|
||||
- Deprecations
|
||||
- ByteBuffer::getArray()
|
||||
- Removals
|
||||
- pv/localStaticLock.h
|
||||
- pv/pvCopy.h (see epics::pvData::PVRequestMapper)
|
||||
- Additions
|
||||
- Add {Structure,Union}::getFieldT
|
||||
|
||||
Release 7.1.3 (Apr 2019)
|
||||
========================
|
||||
|
||||
- Fix for array serialization error to/from big endian.
|
||||
https://github.com/epics-base/pvDataCPP/issues/65
|
||||
|
||||
Release 7.1.2 (Mar 2019)
|
||||
========================
|
||||
|
||||
- 7.1.1 tag pushed prematurely.
|
||||
|
||||
Release 7.1.1 (Mar 2019)
|
||||
========================
|
||||
|
||||
- Fixes
|
||||
- Init order issue with StandardField::getStandardField()
|
||||
- Build fix for Visual Studio 2013+
|
||||
|
||||
Release 7.1.0 (Nov 2018)
|
||||
========================
|
||||
|
||||
- Deprecations
|
||||
- BoundedString, BoundedScalarArray, and FixedScalarArray will be removed unless they are fixed.
|
||||
See https://github.com/epics-base/pvDataCPP/issues/52 for discussion.
|
||||
- pv/localStaticLock.h
|
||||
- pv/pvCopy.h (see epics::pvData::PVRequestMapper)
|
||||
- Removals
|
||||
- Remove previously deprecated executor.h, queue.h and timerFunction.h
|
||||
- Remove *HashFunction functors to "hash" Field sub-classes which were never fully implemented.
|
||||
- Fixes
|
||||
- Make thread safe getFieldCreate() and getPVDataCreate()
|
||||
- Workaround for MSVC pickyness that iterators be non-NULL, even when not de-referenced.
|
||||
- Fix alignment fault during (de)serialization on RTEMS/vxWorks.
|
||||
- Fix epics::pvData::shared_vector::swap() for void specialization.
|
||||
- Changes in several epics::pvData::Field sub-classes to return const ref. instead of a copy.
|
||||
- Additions
|
||||
- epics::pvData::shared_vector add c++11 move and construct for initializer list.
|
||||
- Add epics::pvData::AnyScalar::clear()
|
||||
- Add ctor epics::pvData::AnyScalar(ScalarType, const void*) to allow construction from an untyped buffer.
|
||||
- Add epics::pvData::Timer::close()
|
||||
- Allow epics::pvData::castUnsafe() from const char* without first allocating a std::string.
|
||||
- De-duplication of epics::pvData::Field instances is performed using a global hash table.
|
||||
Identical definitions will share a single instance. Allows O(0) comparision.
|
||||
- Add epics::pvData::PVRequestMapper to facilitate (partial) copying between PVStructure instances
|
||||
modified by a pvRequest.
|
||||
- Add shorthand notations epics::pvData::FieldBuilder::begin() and epics::pvData::Field::build()
|
||||
|
||||
Release 7.0.0 (Dec 2017)
|
||||
========================
|
||||
|
||||
- Removals
|
||||
- Remove requester.h, monitor.h, and destroyable.h.. Migrated to the pvAccessCPP module.
|
||||
- Previously deprecated monitorPlugin.h is removed.
|
||||
- Remove pv/messageQueue.h and epics::pvData::MessageQueue
|
||||
- Deprecate the following utility classes, to be removed in 8.0.
|
||||
- epics::pvData::Queue
|
||||
- epics::pvData::Executor
|
||||
- epics::pvData::TimeFunction
|
||||
- Additions
|
||||
- Add pv/pvdVersion.h which is included by pv/pvIntrospect.h
|
||||
- Add epics::pvData::createRequest() function. Alternative to epics::pvData::CreateRequest class which throws on error.
|
||||
- epics::pvData::FieldBuilder allow Structure defintion to be changed/appended
|
||||
- Add epics::pvData::ValueBuilder like FieldBuilder also sets initial values.
|
||||
- Can also be constructed using an existing PVStructure to allow "editing".
|
||||
- Add debugPtr.h wrapper with reference tracking to assist in troubleshooting shared_ptr related ref. loops.
|
||||
- Add @ref pvjson utilities
|
||||
- Add reftrack @ref pvd_reftrack
|
||||
- Add header typemap.h to facilitate boilerplate switch() over ScalarType
|
||||
- Add epics::auto_ptr typedef in help writing code supporting both c++98 and c++11 w/o copious deprecation warnings.
|
||||
|
||||
|
||||
Release 6.0.1
|
||||
=============
|
||||
|
||||
The changes since release 6.0.0 are:
|
||||
|
||||
* Fix "Problem building pvDataCPP for win32-x86-mingw" (issue #42)
|
||||
* In src/misc/bitSet.cpp #include "algorithm" required for MSVS 2015
|
||||
* In testApp/misc/testTypeCast.cpp print (u)int8 values as integers
|
||||
* Minor documentation updates
|
||||
|
||||
|
||||
Release 6.0.0 (Aug. 2016)
|
||||
=======================
|
||||
|
||||
The main changes since release 5.0.4 are:
|
||||
|
||||
* Linux shared library version added
|
||||
* Headers have been moved into pv directories
|
||||
* Bitset functions declared const where possible
|
||||
* Bitset::swap added
|
||||
* Requester::message has default implementation
|
||||
* Serialization/deserialization helpers added
|
||||
* Non-template getSubField char* overload added
|
||||
* MonitorPlugin deprecated
|
||||
* Field name validation performed
|
||||
* Now builds for Cygwin and MinGW targets
|
||||
* Fix for debug build issue.
|
||||
* New license file replaces LICENSE and COPYRIGHT
|
||||
|
||||
Shared library version added
|
||||
----------------------------
|
||||
|
||||
Linux shared library version numbers have been added by setting SHRLIB_VERSION
|
||||
(to 6.0 in this case). So shared object will be libpvData.so.6.0 instead of
|
||||
libpvData.so.
|
||||
|
||||
Headers have been moved into pv directories
|
||||
-------------------------------------------
|
||||
|
||||
E.g. src/property/alarm.h -> src/property/pv/alarm.h
|
||||
|
||||
This facilitates using some IDEs such as Qt Creator.
|
||||
|
||||
Requester::message has default implementation
|
||||
---------------------------------------------
|
||||
|
||||
Requester::message is no longer pure virtual. Default implementation sends
|
||||
string to std::cerr.
|
||||
|
||||
Serialization/deserialization helpers added
|
||||
-------------------------------------------
|
||||
|
||||
A helper function, serializeToVector, has been added which serializes a
|
||||
Serializable object into a standard vector of UInt8s.
|
||||
|
||||
Similarly a function deserializeFromVector deserializes a standard vector into
|
||||
a Deserializable object.
|
||||
|
||||
A function deserializeFromBuffer deserializes a ByteBuffer into a
|
||||
Deserializable object.
|
||||
|
||||
Field name validation performed
|
||||
-------------------------------
|
||||
|
||||
On creating a Structure or Union the field names are now validated.
|
||||
|
||||
Valid characters for a field name are upper or lowercase letters, numbers and
|
||||
underscores and intial numbers are invalid, i.e. names must be of the form
|
||||
[A-Za-z_][A-Za-z0-9_]*.
|
||||
|
||||
Now builds for Cygwin and MinGW targets
|
||||
---------------------------------------
|
||||
|
||||
Includes cross-compiling MinGW on Linux.
|
||||
|
||||
|
||||
Release 5.0.4
|
||||
=============
|
||||
|
||||
The changes since release 5.0.3 are:
|
||||
|
||||
* Fixed bitset serialization (issue #24)
|
||||
* Fixed truncation in BitSet::or_and (issue #27)
|
||||
|
||||
Fixed bitset serialization (issue #24)
|
||||
--------------------------------------
|
||||
|
||||
C++ bitset serialization was not consistent with the C++ deserialization and
|
||||
Java code in some instances (depending on the endianness of the serializer and
|
||||
deserializer) when the number of bits was 56-63 modulo 64. C++ serialization
|
||||
has been fixed.
|
||||
|
||||
Fix exposed issue in deserialization on 32-bit platforms which
|
||||
has also been corrected.
|
||||
|
||||
Fixed truncation in BitSet::or_and (issue #27)
|
||||
----------------------------------------------
|
||||
|
||||
If n, n1 and n2 words are used to store the values of the bitsets bitset,
|
||||
bitset1 and bitset2 respectively then max(n, min(n1,n2)) words are needed
|
||||
to store bitset.or_(bitset1, bitset2).
|
||||
|
||||
Previously min(n1,n2) words were used and the result would be truncated in
|
||||
some instances. This has been fixed.
|
||||
|
||||
|
||||
Release 5.0.3
|
||||
=============
|
||||
|
||||
The only change since release 5.0.2 is:
|
||||
|
||||
Fixed buffer overflow in PVUnion::serialize() (issue #20)
|
||||
---------------------------------------------------------
|
||||
|
||||
A PVUnion whose stored value was null was serialized without checking
|
||||
whether the buffer had sufficient capacity. This has been fixed by calling
|
||||
ensureBuffer().
|
||||
|
||||
|
||||
Release 5.0.2 (Sep. 2015)
|
||||
=========================
|
||||
|
||||
The main changes since release 4.0 are:
|
||||
|
||||
- Deprecated getXXXField() methods have been removed from PVStructure
|
||||
- Convert copy methods and equals operators (re)moved
|
||||
- Convert::copyUnion now always copies between subfields.
|
||||
- New method getSubFieldT, like getSubField except it throws an exception
|
||||
- findSubField method removed from PVStructure
|
||||
- New stream operators for Field and PVField are provided
|
||||
- New template versions of Structure::getField
|
||||
- Fixes for static initialisation order issues
|
||||
- CreateRequest prevents a possible SEGFAULT
|
||||
|
||||
|
||||
Deprecated getXXXField methods have been removed from PVStructure
|
||||
-------------------------------------------------------------------
|
||||
|
||||
The following methods have been removed from PVStructure
|
||||
|
||||
- getBooleanField
|
||||
- getByteField, getShortField, getIntField, getLongField
|
||||
- getUByteField, getUShortField, getUIntField, getULongField
|
||||
- getStringField
|
||||
- getStructureField, getUnionField
|
||||
- getScalarArrayField, getStructureArrayField, getUnionArrayField
|
||||
|
||||
Use template getSubField instead, e.g. use
|
||||
|
||||
getSubField< PVInt >(fieldName)
|
||||
|
||||
in place of
|
||||
|
||||
getIntField(fieldName)
|
||||
|
||||
|
||||
Convert copy methods and equals operators
|
||||
-----------------------------------------
|
||||
|
||||
Convert copy methods where moved and replaced with methods
|
||||
on PVField classes, i.e.
|
||||
|
||||
PVField::copy(const PVField& from)
|
||||
|
||||
Methods
|
||||
|
||||
PVField::copyUnchecked(const PVField& from)
|
||||
|
||||
were added to allow unchecked copies, to gain performance
|
||||
where checked are not needed (anymore).
|
||||
|
||||
In addition:
|
||||
- isCompatibleXXX methods were removed in favour of Field::operator==.
|
||||
- equals methods were remove in favour of PVField::operator==.
|
||||
- operator== methods where moved to pvIntrospect.h and pvData.h
|
||||
|
||||
|
||||
Convert::copyUnion
|
||||
-----------------
|
||||
|
||||
Before this method, depending on types for to and from,
|
||||
sometimes did a shallow copy, i.e. just made to shared_ptr for to
|
||||
share the same data as from.
|
||||
Now it always copies between the subfield of to and from.
|
||||
|
||||
|
||||
New method getSubFieldT, like getSubField except it throws an exception
|
||||
--------------------
|
||||
|
||||
PVStructure has a new template member
|
||||
|
||||
getSubFieldT(std::string const &fieldName)
|
||||
|
||||
that is like `getSubField()` except that it throws a runtime_error
|
||||
instead of returning null.
|
||||
|
||||
|
||||
findSubField method removed from PVStructure
|
||||
--------------------------------------------
|
||||
|
||||
This was mainly used in the implementation of getSubField. With a change to
|
||||
the latter, findSubField was removed.
|
||||
|
||||
|
||||
New stream operators
|
||||
--------------------
|
||||
|
||||
New steam operators are available for Field and PVField.
|
||||
Before to print a Field (or any extension) or a PVField (or any extension)
|
||||
it was necessary to have code like:
|
||||
|
||||
void print(StructureConstPtr struc, PVStructurePtr pv)
|
||||
{
|
||||
if(struc) {
|
||||
cout << *struc << endl;
|
||||
} else {
|
||||
cout << "nullptr\n"
|
||||
}
|
||||
if(pv) {
|
||||
cout << *.struc << endl;
|
||||
} else {
|
||||
cout << "nullptr\n"
|
||||
}
|
||||
}
|
||||
|
||||
Now it can be done as follows:
|
||||
|
||||
void print(StructureConstPtr struc, PVStructurePtr pv)
|
||||
{
|
||||
cout << struc << endl;
|
||||
cout << pv << endl;
|
||||
}
|
||||
|
||||
|
||||
New template version of Structure::getField
|
||||
--------------------------------------------
|
||||
|
||||
A new template getField method has been added to Structure
|
||||
|
||||
template<typename FT >
|
||||
std::tr1::shared_ptr< const FT > getField(std::string const &fieldName) const
|
||||
|
||||
Can be used, for example, as follows:
|
||||
|
||||
StructurePtr tsStruc = struc->getField<Structure>("timeStamp");
|
||||
|
||||
|
||||
Fixes for static initialisation order issues
|
||||
--------------------------------------------
|
||||
|
||||
Certain static builds (in particular Windows builds) of applications using
|
||||
pvData had issues due to PVStructure::DEFAULT_ID being used before being initialised. This has been fixed.
|
||||
|
||||
|
||||
CreateRequest change
|
||||
--------------------
|
||||
|
||||
createRequest could cause a SEGFAULT if passed a bad argument.
|
||||
This has been changed so the it returns a null pvStructure
|
||||
and provides an error.
|
||||
|
||||
|
||||
Release 4.0.3
|
||||
=============
|
||||
|
||||
The main changes since release 3.0.2 are:
|
||||
|
||||
- array semantics now enforce Copy On Write.
|
||||
- String no longer defined.
|
||||
- timeStamp and valueAlarm name changes
|
||||
- toString replaced by stream I/O
|
||||
- union is new type.
|
||||
- copy is new.
|
||||
- monitorPlugin is new.
|
||||
|
||||
New Semantics for Arrays
|
||||
--------
|
||||
|
||||
PVScalarArray, PVStructureArray, and PVUnionArray all enforce COW (Copy On Write) Semantics.
|
||||
In order to limit memory usage the storage for raw data is managed via a new shared_vector facility.
|
||||
This allows multiple instances of array data to use the shared raw data.
|
||||
COW is implemented via shared_vectors of const data, i. e. data that can not be modified.
|
||||
|
||||
|
||||
String no longer defined
|
||||
---------
|
||||
|
||||
This is replaced by std::string.
|
||||
|
||||
|
||||
timeStamp and valueAlarm name changes
|
||||
--------------
|
||||
|
||||
In timeStamp nanoSeconds is changed to nanoseconds.
|
||||
|
||||
In valueAlarm hysteresis is changed to hysteresis
|
||||
|
||||
|
||||
toString replaced by stream I/O
|
||||
---------
|
||||
|
||||
pvData.h and pvIntrospect no longer defines toString
|
||||
Instead they have stream support.
|
||||
pvIntrospect uses method dump and pvData uses dumpValue.
|
||||
For example:
|
||||
|
||||
PVDoublePtr pvValue;
|
||||
String buffer;
|
||||
pvValue->toString(&buffer);
|
||||
cout << buffer << endl;
|
||||
buffer.clear();
|
||||
pvValue->getField()->toString(&buffer);
|
||||
cout << buffer << evdl;
|
||||
|
||||
is replaced by
|
||||
|
||||
PVDoublePtr pvValue;
|
||||
cout << *pvValue << endl
|
||||
cout << *pvValue->getField() << endl;
|
||||
|
||||
|
||||
union is a new basic type.
|
||||
------------
|
||||
|
||||
There are two new basic types: union_t and unionArray.
|
||||
|
||||
A union is like a structure that has a single subfield.
|
||||
There are two flavors:
|
||||
|
||||
- *variant union* The field can have any type.
|
||||
- *union* The field can any of specified set of types.
|
||||
|
||||
The field type can be dynamically changed.
|
||||
|
||||
copy
|
||||
----
|
||||
|
||||
This consists of createRequest and pvCopy.
|
||||
createRequest was moved from pvAccess to here.
|
||||
pvCopy is moved from pvDatabaseCPP and now depends
|
||||
only on pvData, i.e. it no longer has any knowledge of PVRecord.
|
||||
|
||||
monitorPlugin
|
||||
-------------
|
||||
|
||||
This is for is for use by code that implements pvAccess monitors.
|
||||
This is prototype and is subject to debate.
|
||||
|
||||
Release 3.0.2
|
||||
==========
|
||||
This was the starting point for RELEASE_NOTES
|
||||
|
||||
*/
|
||||
14
examples/Makefile
Normal file
14
examples/Makefile
Normal file
@@ -0,0 +1,14 @@
|
||||
# Makefile for the examples
|
||||
# make sure they compile
|
||||
|
||||
TOP = ..
|
||||
include $(TOP)/configure/CONFIG
|
||||
|
||||
PROD_LIBS += pvData Com
|
||||
|
||||
TESTPROD_HOST += unittest
|
||||
unittest_SRCS += unittest.cpp
|
||||
|
||||
include $(TOP)/configure/RULES
|
||||
|
||||
|
||||
30
examples/unittest.cpp
Normal file
30
examples/unittest.cpp
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright information and license terms for this software can be
|
||||
* found in the file LICENSE that is included with the distribution
|
||||
*/
|
||||
/* c++ unittest skeleton */
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include <testMain.h>
|
||||
|
||||
#include <pv/pvUnitTest.h>
|
||||
#include <pv/epicsException.h>
|
||||
|
||||
namespace {
|
||||
void testCase1() {
|
||||
testEqual(1+1, 2);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
MAIN(testUnitTest)
|
||||
{
|
||||
testPlan(1);
|
||||
try {
|
||||
testCase1();
|
||||
}catch(std::exception& e){
|
||||
PRINT_EXCEPTION(e); // print stack trace if thrown with THROW_EXCEPTION()
|
||||
testAbort("Unhandled exception: %s", e.what());
|
||||
}
|
||||
return testDone();
|
||||
}
|
||||
70
jenkins/cloudbees_build
Normal file
70
jenkins/cloudbees_build
Normal file
@@ -0,0 +1,70 @@
|
||||
# pvData C++ implementation
|
||||
# Jenkins @ Cloudbees build script
|
||||
#
|
||||
# Jenkins invokes scripts with the "-ex" option. So the build is considered a failure
|
||||
# if any of the commands exits with a non-zero exit code.
|
||||
#
|
||||
# Author: Ralph Lange <ralph.lange@gmx.de>
|
||||
# Copyright (C) 2013 Helmholtz-Zentrum Berlin für Materialien und Energie GmbH
|
||||
# Copyright (C) 2014-2016 ITER Organization.
|
||||
# All rights reserved. Use is subject to license terms.
|
||||
|
||||
installTool () {
|
||||
local module=$1
|
||||
local version=$2
|
||||
|
||||
wget -nv https://openepics.ci.cloudbees.com/job/${module}-${version}_Build/lastSuccessfulBuild/artifact/${module,,}-${version}.CB-dist.tar.gz
|
||||
tar -xzf ${module,,}-${version}.CB-dist.tar.gz
|
||||
}
|
||||
|
||||
installE4 () {
|
||||
local module=$1
|
||||
local branch=$2
|
||||
|
||||
wget -nv https://openepics.ci.cloudbees.com/job/e4-cpp-${module}-${branch}-build/BASE=${BASE}/lastSuccessfulBuild/artifact/${module}.CB-dist.tar.gz
|
||||
tar -xzf ${module}.CB-dist.tar.gz
|
||||
}
|
||||
|
||||
###########################################
|
||||
# Defaults for EPICS Base
|
||||
|
||||
DEFAULT_BASE=3.15.4
|
||||
BASE=${BASE:-${DEFAULT_BASE}}
|
||||
|
||||
###########################################
|
||||
# Fetch and unpack dependencies
|
||||
|
||||
export STUFF=/tmp/stuff
|
||||
|
||||
rm -fr ${STUFF}
|
||||
mkdir -p ${STUFF}
|
||||
cd ${STUFF}
|
||||
|
||||
installTool Boost 1.61.0
|
||||
installTool Base ${BASE}
|
||||
|
||||
###########################################
|
||||
# Build
|
||||
|
||||
cd ${WORKSPACE}
|
||||
|
||||
export EPICS_BASE=${STUFF}
|
||||
export EPICS_HOST_ARCH=$(${EPICS_BASE}/startup/EpicsHostArch)
|
||||
export LD_LIBRARY_PATH=${EPICS_BASE}/lib/${EPICS_HOST_ARCH}
|
||||
export PATH=${STUFF}/bin:${PATH}
|
||||
|
||||
cat > configure/RELEASE.local << EOF
|
||||
EPICS_BASE=${EPICS_BASE}
|
||||
EOF
|
||||
|
||||
make distclean all
|
||||
|
||||
###########################################
|
||||
# Test
|
||||
|
||||
make runtests
|
||||
|
||||
###########################################
|
||||
# Create cache
|
||||
|
||||
tar czf pvData.CB-dist.tar.gz lib include cfg LICENSE
|
||||
66
jenkins/cloudbees_doc
Normal file
66
jenkins/cloudbees_doc
Normal file
@@ -0,0 +1,66 @@
|
||||
# pvData C++ implementation
|
||||
# Jenkins @ Cloudbees documentation generation and deployment
|
||||
#
|
||||
# Jenkins invokes scripts with the "-ex" option. So the build is considered a failure
|
||||
# if any of the commands exits with a non-zero exit code.
|
||||
#
|
||||
# Author: Ralph Lange <ralph.lange@gmx.de>
|
||||
# Copyright (C) 2013 Helmholtz-Zentrum Berlin für Materialien und Energie GmbH
|
||||
# Copyright (C) 2014-2016 ITER Organization.
|
||||
# All rights reserved. Use is subject to license terms.
|
||||
|
||||
installTool () {
|
||||
local module=$1
|
||||
local version=$2
|
||||
|
||||
wget -nv https://openepics.ci.cloudbees.com/job/${module}-${version}_Build/lastSuccessfulBuild/artifact/${module,,}-${version}.CB-dist.tar.gz
|
||||
tar -xzf ${module,,}-${version}.CB-dist.tar.gz
|
||||
}
|
||||
|
||||
installE4 () {
|
||||
local module=$1
|
||||
local branch=$2
|
||||
|
||||
wget -nv https://openepics.ci.cloudbees.com/job/e4-cpp-${module}-${branch}-build/BASE=${BASE}/lastSuccessfulBuild/artifact/${module}.CB-dist.tar.gz
|
||||
tar -xzf ${module}.CB-dist.tar.gz
|
||||
}
|
||||
|
||||
###########################################
|
||||
# Defaults for EPICS Base and parameters
|
||||
|
||||
BASE=3.15.4
|
||||
PUBLISH=${PUBLISH:-NO}
|
||||
BRANCH=${BRANCH:-master}
|
||||
|
||||
###########################################
|
||||
# Fetch and unpack dependencies
|
||||
|
||||
export STUFF=/tmp/stuff
|
||||
|
||||
rm -fr ${STUFF}
|
||||
mkdir -p ${STUFF}
|
||||
cd ${STUFF}
|
||||
|
||||
installTool Doxygen 1.8.11
|
||||
|
||||
###########################################
|
||||
# Generate
|
||||
|
||||
cd ${WORKSPACE}
|
||||
|
||||
installE4 pvData ${BRANCH}
|
||||
|
||||
export PATH=${STUFF}/bin:${PATH}
|
||||
|
||||
doxygen
|
||||
|
||||
###########################################
|
||||
# Publish
|
||||
|
||||
if [ "${PUBLISH}" != "NO" ]; then
|
||||
# Upload explicit dummy to ensure target directory exists
|
||||
echo "Created by CloudBees Jenkins upload job. Should be deleted as part of the job." > DUMMY
|
||||
rsync -q -e ssh DUMMY epics-jenkins@web.sourceforge.net:/home/project-web/epics-pvdata/htdocs/docbuild/pvDataCPP/${PUBLISH}/
|
||||
|
||||
rsync -aqP --delete -e ssh documentation epics-jenkins@web.sourceforge.net:/home/project-web/epics-pvdata/htdocs/docbuild/pvDataCPP/${PUBLISH}/
|
||||
fi
|
||||
@@ -1,108 +0,0 @@
|
||||
TOP = ..
|
||||
include $(TOP)/configure/CONFIG
|
||||
|
||||
PVDATA = $(TOP)/pvDataApp/
|
||||
|
||||
SRC_DIRS += $(PVDATA)/misc
|
||||
|
||||
INC += noDefaultMethods.h
|
||||
INC += linkedListVoid.h
|
||||
INC += linkedList.h
|
||||
INC += lock.h
|
||||
INC += requester.h
|
||||
INC += serialize.h
|
||||
INC += bitSet.h
|
||||
INC += byteBuffer.h
|
||||
INC += epicsException.h
|
||||
INC += serializeHelper.h
|
||||
INC += event.h
|
||||
INC += thread.h
|
||||
INC += executor.h
|
||||
INC += CDRMonitor.h
|
||||
INC += timeFunction.h
|
||||
INC += timer.h
|
||||
INC += queueVoid.h
|
||||
INC += queue.h
|
||||
INC += messageQueue.h
|
||||
INC += destroyable.h
|
||||
INC += status.h
|
||||
INC += sharedPtr.h
|
||||
|
||||
LIBSRCS += CDRMonitor.cpp
|
||||
#LIBSRCS += byteBuffer.cpp
|
||||
LIBSRCS += bitSet.cpp
|
||||
LIBSRCS += epicsException.cpp
|
||||
LIBSRCS += requester.cpp
|
||||
LIBSRCS += serializeHelper.cpp
|
||||
LIBSRCS += linkedListVoid.cpp
|
||||
LIBSRCS += event.cpp
|
||||
LIBSRCS += executor.cpp
|
||||
LIBSRCS += timeFunction.cpp
|
||||
LIBSRCS += timer.cpp
|
||||
LIBSRCS += queueVoid.cpp
|
||||
LIBSRCS += messageQueue.cpp
|
||||
LIBSRCS += status.cpp
|
||||
|
||||
SRC_DIRS += $(PVDATA)/pv
|
||||
|
||||
INC += pvType.h
|
||||
INC += pvIntrospect.h
|
||||
INC += pvData.h
|
||||
INC += convert.h
|
||||
INC += standardField.h
|
||||
INC += standardPVField.h
|
||||
|
||||
SRC_DIRS += $(PVDATA)/factory
|
||||
|
||||
INC += factory.h
|
||||
LIBSRCS += TypeFunc.cpp
|
||||
LIBSRCS += PVAuxInfoImpl.cpp
|
||||
LIBSRCS += FieldCreateFactory.cpp
|
||||
LIBSRCS += PVField.cpp
|
||||
LIBSRCS += PVScalar.cpp
|
||||
LIBSRCS += PVArray.cpp
|
||||
LIBSRCS += PVScalarArray.cpp
|
||||
LIBSRCS += PVStructure.cpp
|
||||
LIBSRCS += DefaultPVStructureArray.cpp
|
||||
LIBSRCS += PVDataCreateFactory.cpp
|
||||
LIBSRCS += Convert.cpp
|
||||
LIBSRCS += Compare.cpp
|
||||
LIBSRCS += StandardField.cpp
|
||||
LIBSRCS += StandardPVField.cpp
|
||||
|
||||
SRC_DIRS += $(PVDATA)/property
|
||||
|
||||
INC += alarm.h
|
||||
INC += pvAlarm.h
|
||||
INC += control.h
|
||||
INC += pvControl.h
|
||||
INC += display.h
|
||||
INC += pvDisplay.h
|
||||
INC += pvEnumerated.h
|
||||
INC += timeStamp.h
|
||||
INC += pvTimeStamp.h
|
||||
|
||||
LIBSRCS += alarm.cpp
|
||||
LIBSRCS += pvAlarm.cpp
|
||||
LIBSRCS += pvControl.cpp
|
||||
LIBSRCS += pvDisplay.cpp
|
||||
LIBSRCS += pvEnumerated.cpp
|
||||
LIBSRCS += timeStamp.cpp
|
||||
LIBSRCS += pvTimeStamp.cpp
|
||||
|
||||
SRC_DIRS += $(PVDATA)/pvMisc
|
||||
INC += bitSetUtil.h
|
||||
LIBSRCS += bitSetUtil.cpp
|
||||
|
||||
SRC_DIRS += $(PVDATA)/monitor
|
||||
INC += monitor.h
|
||||
INC += monitorQueue.h
|
||||
LIBSRCS += monitorQueue.cpp
|
||||
|
||||
|
||||
LIBRARY=pvData
|
||||
|
||||
pvData_LIBS += Com
|
||||
|
||||
include $(TOP)/configure/RULES
|
||||
|
||||
@@ -1,97 +0,0 @@
|
||||
|
||||
#include <pv/convert.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <sstream>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
// PVXXX object comparison
|
||||
|
||||
bool operator==(PVField& left, PVField& right)
|
||||
{
|
||||
return getConvert()->equals(left,right);
|
||||
}
|
||||
|
||||
// Introspection object comparision
|
||||
|
||||
/** Field equality conditions:
|
||||
* 1) same instance
|
||||
* 2) same type (field and scalar/element), same name, same subfields (if any)
|
||||
*/
|
||||
bool operator==(const Field& a, const Field& b)
|
||||
{
|
||||
if(&a==&b)
|
||||
return true;
|
||||
if(a.getType()!=b.getType())
|
||||
return false;
|
||||
switch(a.getType()) {
|
||||
case scalar: {
|
||||
const Scalar &A=static_cast<const Scalar&>(a);
|
||||
const Scalar &B=static_cast<const Scalar&>(b);
|
||||
return A==B;
|
||||
}
|
||||
case scalarArray: {
|
||||
const ScalarArray &A=static_cast<const ScalarArray&>(a);
|
||||
const ScalarArray &B=static_cast<const ScalarArray&>(b);
|
||||
return A==B;
|
||||
}
|
||||
case structure: {
|
||||
const Structure &A=static_cast<const Structure&>(a);
|
||||
const Structure &B=static_cast<const Structure&>(b);
|
||||
return A==B;
|
||||
}
|
||||
case structureArray: {
|
||||
const StructureArray &A=static_cast<const StructureArray&>(a);
|
||||
const StructureArray &B=static_cast<const StructureArray&>(b);
|
||||
return A==B;
|
||||
}
|
||||
default:
|
||||
throw std::logic_error("Invalid Field type in comparision");
|
||||
}
|
||||
}
|
||||
|
||||
bool operator==(const Scalar& a, const Scalar& b)
|
||||
{
|
||||
if(&a==&b)
|
||||
return true;
|
||||
return a.getScalarType()==b.getScalarType() && a.getFieldName()==b.getFieldName();
|
||||
}
|
||||
|
||||
bool operator==(const ScalarArray& a, const ScalarArray& b)
|
||||
{
|
||||
if(&a==&b)
|
||||
return true;
|
||||
return a.getElementType()==b.getElementType() && a.getFieldName()==b.getFieldName();
|
||||
}
|
||||
|
||||
bool operator==(const Structure& a, const Structure& b)
|
||||
{
|
||||
if(&a==&b)
|
||||
return true;
|
||||
int nflds=a.getNumberFields();
|
||||
if (b.getNumberFields()!=nflds)
|
||||
return false;
|
||||
if (a.getFieldName()!=b.getFieldName())
|
||||
return false;
|
||||
|
||||
// std::equals does not work, since FieldConstPtrArray is an array of shared_pointers
|
||||
FieldConstPtrArray af = a.getFields();
|
||||
FieldConstPtrArray bf = b.getFields();
|
||||
for (int i = 0; i < nflds; i++)
|
||||
if (*(af[i].get()) != *(bf[i].get()))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool operator==(const StructureArray& a, const StructureArray& b)
|
||||
{
|
||||
return a.structure() == b.structure();
|
||||
}
|
||||
|
||||
namespace nconvert {
|
||||
|
||||
} // namespace nconvert
|
||||
|
||||
}} // namespace epics::pvData
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,251 +0,0 @@
|
||||
/*PVStructureArray.cpp*/
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/convert.h>
|
||||
#include <pv/factory.h>
|
||||
#include <pv/serializeHelper.h>
|
||||
#include "DefaultPVStructureArray.h"
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using std::tr1::const_pointer_cast;
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
BasePVStructureArray::BasePVStructureArray(
|
||||
PVStructure *parent,StructureArrayConstPtr structureArray)
|
||||
: PVStructureArray(parent,structureArray),
|
||||
structureArray(structureArray),
|
||||
structureArrayData(new StructureArrayData()),
|
||||
value(new PVStructurePtr[0])
|
||||
{
|
||||
}
|
||||
|
||||
BasePVStructureArray::~BasePVStructureArray()
|
||||
{
|
||||
delete structureArrayData;
|
||||
int number = getCapacity();
|
||||
for(int i=0; i<number; i++) {
|
||||
if(value[i]!=0) {
|
||||
delete value[i];
|
||||
}
|
||||
}
|
||||
delete[] value;
|
||||
}
|
||||
|
||||
int BasePVStructureArray::append(int number)
|
||||
{
|
||||
int currentLength = getCapacity();
|
||||
int newLength = currentLength + number;
|
||||
setCapacity(newLength);
|
||||
StructureConstPtr structure = structureArray->getStructure();
|
||||
for(int i=currentLength; i<newLength; i++) {
|
||||
value[i] = getPVDataCreate()->createPVStructure(0,structure);
|
||||
}
|
||||
return newLength;
|
||||
}
|
||||
|
||||
bool BasePVStructureArray::remove(int offset,int number)
|
||||
{
|
||||
int length = getCapacity();
|
||||
if(offset+number>length) return false;
|
||||
for(int i=offset;i<offset+number;i++) {
|
||||
if(value[i]!=0) {
|
||||
delete value[i];
|
||||
value[i] = 0;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void BasePVStructureArray::compress() {
|
||||
int length = getCapacity();
|
||||
int newLength = 0;
|
||||
for(int i=0; i<length; i++) {
|
||||
if(value[i]!=0) {
|
||||
newLength++;
|
||||
continue;
|
||||
}
|
||||
// find first non 0
|
||||
int notNull = 0;
|
||||
for(int j=i+1;j<length;j++) {
|
||||
if(value[j]!=0) {
|
||||
notNull = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(notNull!=0) {
|
||||
value[i] = value[notNull];
|
||||
value[notNull] = 0;
|
||||
newLength++;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
setCapacity(newLength);
|
||||
}
|
||||
|
||||
void BasePVStructureArray::setCapacity(int capacity) {
|
||||
if(getCapacity()==capacity) return;
|
||||
if(!isCapacityMutable()) {
|
||||
std::string message("not capacityMutable");
|
||||
PVField::message(message, errorMessage);
|
||||
return;
|
||||
}
|
||||
int length = getCapacity();
|
||||
int numRemove = length - capacity;
|
||||
if(numRemove>0) remove(length,numRemove);
|
||||
PVStructurePtrArray newValue = new PVStructurePtr[capacity];
|
||||
int limit = length;
|
||||
if(length>capacity) limit = capacity;
|
||||
for(int i=0; i<limit; i++) newValue[i] = value[i];
|
||||
for(int i=limit; i<capacity; i++) newValue[i] = 0;
|
||||
if(length>capacity) length = capacity;
|
||||
delete[] value;
|
||||
value = newValue;
|
||||
setCapacityLength(capacity,length);
|
||||
}
|
||||
|
||||
|
||||
StructureArrayConstPtr BasePVStructureArray::getStructureArray()
|
||||
{
|
||||
return structureArray;
|
||||
}
|
||||
|
||||
int BasePVStructureArray::get(
|
||||
int offset, int len, StructureArrayData *data)
|
||||
{
|
||||
int n = len;
|
||||
int length = getLength();
|
||||
if(offset+len > length) {
|
||||
n = length - offset;
|
||||
if(n<0) n = 0;
|
||||
}
|
||||
data->data = value;
|
||||
data->offset = offset;
|
||||
return n;
|
||||
}
|
||||
|
||||
int BasePVStructureArray::put(int offset,int len,
|
||||
PVStructurePtrArray from, int fromOffset)
|
||||
{
|
||||
if(isImmutable()) {
|
||||
message(String("field is immutable"), errorMessage);
|
||||
return 0;
|
||||
}
|
||||
if(from==value) return len;
|
||||
if(len<1) return 0;
|
||||
int length = getLength();
|
||||
int capacity = getCapacity();
|
||||
if(offset+len > length) {
|
||||
int newlength = offset + len;
|
||||
if(newlength>capacity) {
|
||||
setCapacity(newlength);
|
||||
capacity = getCapacity();
|
||||
newlength = capacity;
|
||||
len = newlength - offset;
|
||||
if(len<=0) return 0;
|
||||
}
|
||||
length = newlength;
|
||||
setLength(length);
|
||||
}
|
||||
StructureConstPtr structure = structureArray->getStructure();
|
||||
for(int i=0; i<len; i++) {
|
||||
if(value[i+offset]!=0) delete value[i+offset];
|
||||
PVStructurePtr frompv = from[i+fromOffset];
|
||||
if(frompv==0) {
|
||||
value[i+offset] = 0;
|
||||
continue;
|
||||
}
|
||||
if(frompv->getStructure()!=structure) {
|
||||
throw std::invalid_argument(String(
|
||||
"Element is not a compatible structure"));
|
||||
}
|
||||
value[i+offset] = frompv;
|
||||
}
|
||||
postPut();
|
||||
return len;
|
||||
}
|
||||
|
||||
void BasePVStructureArray::shareData(
|
||||
PVStructurePtrArray newValue,int capacity,int length)
|
||||
{
|
||||
for(int i=0; i<getLength(); i++) {
|
||||
if(value[i]!=0) delete value[i];
|
||||
}
|
||||
delete[] value;
|
||||
value = newValue;
|
||||
setCapacity(capacity);
|
||||
setLength(length);
|
||||
}
|
||||
|
||||
void BasePVStructureArray::serialize(ByteBuffer *pbuffer,
|
||||
SerializableControl *pflusher) const {
|
||||
serialize(pbuffer, pflusher, 0, getLength());
|
||||
}
|
||||
|
||||
void BasePVStructureArray::deserialize(ByteBuffer *pbuffer,
|
||||
DeserializableControl *pcontrol) {
|
||||
int size = SerializeHelper::readSize(pbuffer, pcontrol);
|
||||
if(size>=0) {
|
||||
// prepare array, if necessary
|
||||
if(size>getCapacity()) setCapacity(size);
|
||||
for(int i = 0; i<size; i++) {
|
||||
pcontrol->ensureData(1);
|
||||
int8 temp = pbuffer->getByte();
|
||||
if(temp==0) {
|
||||
if (value[i]) {
|
||||
delete value[i];
|
||||
value[i] = NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(value[i]==NULL) {
|
||||
value[i] = getPVDataCreate()->createPVStructure(
|
||||
NULL, structureArray->getStructure());
|
||||
}
|
||||
value[i]->deserialize(pbuffer, pcontrol);
|
||||
}
|
||||
}
|
||||
setLength(size);
|
||||
postPut();
|
||||
}
|
||||
}
|
||||
|
||||
void BasePVStructureArray::serialize(ByteBuffer *pbuffer,
|
||||
SerializableControl *pflusher, int offset, int count) const {
|
||||
// cache
|
||||
int length = getLength();
|
||||
|
||||
// check bounds
|
||||
if(offset<0)
|
||||
offset = 0;
|
||||
else if(offset>length) offset = length;
|
||||
if(count<0) count = length;
|
||||
|
||||
int maxCount = length-offset;
|
||||
if(count>maxCount) count = maxCount;
|
||||
|
||||
// write
|
||||
SerializeHelper::writeSize(count, pbuffer, pflusher);
|
||||
for(int i = 0; i<count; i++) {
|
||||
if(pbuffer->getRemaining()<1) pflusher->flushSerializeBuffer();
|
||||
PVStructure* pvStructure = value[i+offset];
|
||||
if(pvStructure==NULL) {
|
||||
pbuffer->putByte(0);
|
||||
}
|
||||
else {
|
||||
pbuffer->putByte(1);
|
||||
pvStructure->serialize(pbuffer, pflusher);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}}
|
||||
@@ -1,48 +0,0 @@
|
||||
/*DefaultPVStructureArray.h*/
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
#ifndef DEFAULTPVSTRUCTUREARRAY_H
|
||||
#define DEFAULTPVSTRUCTUREARRAY_H
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/convert.h>
|
||||
#include <pv/factory.h>
|
||||
#include <pv/serializeHelper.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
class BasePVStructureArray : public PVStructureArray {
|
||||
public:
|
||||
BasePVStructureArray(PVStructure *parent,
|
||||
StructureArrayConstPtr structureArray);
|
||||
virtual ~BasePVStructureArray();
|
||||
virtual StructureArrayConstPtr getStructureArray();
|
||||
virtual int append(int number);
|
||||
virtual bool remove(int offset,int number);
|
||||
virtual void compress();
|
||||
virtual void setCapacity(int capacity);
|
||||
virtual int get(int offset, int length,
|
||||
StructureArrayData *data);
|
||||
virtual int put(int offset,int length,
|
||||
PVStructurePtrArray from, int fromOffset);
|
||||
virtual void shareData( PVStructurePtrArray value,int capacity,int length);
|
||||
virtual void serialize(ByteBuffer *pbuffer,
|
||||
SerializableControl *pflusher) const;
|
||||
virtual void deserialize(ByteBuffer *buffer,
|
||||
DeserializableControl *pflusher);
|
||||
virtual void serialize(ByteBuffer *pbuffer,
|
||||
SerializableControl *pflusher, int offset, int count) const;
|
||||
private:
|
||||
StructureArrayConstPtr structureArray;
|
||||
StructureArrayData *structureArrayData;
|
||||
PVStructurePtrArray value;
|
||||
};
|
||||
}}
|
||||
|
||||
#endif /*DEFAULTPVSTRUCTUREARRAY_H*/
|
||||
@@ -1,260 +0,0 @@
|
||||
/*FieldCreateFactory.cpp*/
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <pv/lock.h>
|
||||
#include <pv/pvIntrospect.h>
|
||||
#include <pv/convert.h>
|
||||
#include <pv/factory.h>
|
||||
#include <pv/CDRMonitor.h>
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
static DebugLevel debugLevel = lowDebug;
|
||||
|
||||
static void newLine(StringBuilder buffer, int indentLevel)
|
||||
{
|
||||
*buffer += "\n";
|
||||
for(int i=0; i<indentLevel; i++) *buffer += " ";
|
||||
}
|
||||
|
||||
PVDATA_REFCOUNT_MONITOR_DEFINE(field);
|
||||
|
||||
Field::Field(String fieldName,Type type)
|
||||
:m_fieldName(fieldName)
|
||||
,m_type(type)
|
||||
{
|
||||
PVDATA_REFCOUNT_MONITOR_CONSTRUCT(field);
|
||||
}
|
||||
|
||||
Field::~Field() {
|
||||
PVDATA_REFCOUNT_MONITOR_DESTRUCT(field);
|
||||
// note that compiler automatically calls destructor for fieldName
|
||||
if(debugLevel==highDebug) printf("~Field %s\n",m_fieldName.c_str());
|
||||
}
|
||||
|
||||
void Field::renameField(String newName)
|
||||
{
|
||||
m_fieldName = newName;
|
||||
}
|
||||
|
||||
void Field::toString(StringBuilder buffer,int indentLevel) const{
|
||||
*buffer += " ";
|
||||
*buffer += m_fieldName.c_str();
|
||||
}
|
||||
|
||||
Scalar::Scalar(String fieldName,ScalarType scalarType)
|
||||
: Field(fieldName,scalar),scalarType(scalarType){}
|
||||
|
||||
Scalar::~Scalar(){}
|
||||
|
||||
void Scalar::toString(StringBuilder buffer,int indentLevel) const{
|
||||
ScalarTypeFunc::toString(buffer,scalarType);
|
||||
Field::toString(buffer,indentLevel);
|
||||
}
|
||||
|
||||
|
||||
ScalarArray::ScalarArray(String fieldName,ScalarType elementType)
|
||||
: Field(fieldName,scalarArray),elementType(elementType){}
|
||||
|
||||
ScalarArray::~ScalarArray() {}
|
||||
|
||||
void ScalarArray::toString(StringBuilder buffer,int indentLevel) const{
|
||||
ScalarTypeFunc::toString(buffer,elementType);
|
||||
*buffer += "[]";
|
||||
Field::toString(buffer,indentLevel);
|
||||
}
|
||||
|
||||
StructureArray::StructureArray(String fieldName,StructureConstPtr structure)
|
||||
: Field(fieldName,structureArray),pstructure(structure)
|
||||
{
|
||||
}
|
||||
|
||||
StructureArray::~StructureArray() {
|
||||
if(debugLevel==highDebug) printf("~StructureArray\n");
|
||||
}
|
||||
|
||||
void StructureArray::toString(StringBuilder buffer,int indentLevel) const {
|
||||
*buffer += "structure[]";
|
||||
Field::toString(buffer,indentLevel);
|
||||
newLine(buffer,indentLevel + 1);
|
||||
pstructure->toString(buffer,indentLevel + 1);
|
||||
}
|
||||
|
||||
|
||||
Structure::Structure (String fieldName,
|
||||
int numberFields, FieldConstPtrArray infields)
|
||||
: Field(fieldName,structure),
|
||||
numberFields(numberFields),
|
||||
fields(infields)
|
||||
{
|
||||
for(int i=0; i<numberFields; i++) {
|
||||
String name = fields[i]->getFieldName();
|
||||
// look for duplicates
|
||||
for(int j=i+1; j<numberFields; j++) {
|
||||
String otherName = fields[j]->getFieldName();
|
||||
int result = name.compare(otherName);
|
||||
if(result==0) {
|
||||
String message("duplicate fieldName ");
|
||||
message += name;
|
||||
delete[] fields;
|
||||
throw std::invalid_argument(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Structure::~Structure() {
|
||||
if(debugLevel==highDebug)
|
||||
printf("~Structure %s\n",Field::getFieldName().c_str());
|
||||
|
||||
delete[] fields;
|
||||
}
|
||||
|
||||
FieldConstPtr Structure::getField(String fieldName) const {
|
||||
for(int i=0; i<numberFields; i++) {
|
||||
FieldConstPtr pfield = fields[i];
|
||||
int result = fieldName.compare(pfield->getFieldName());
|
||||
if(result==0) return pfield;
|
||||
}
|
||||
return FieldConstPtr();
|
||||
}
|
||||
|
||||
int Structure::getFieldIndex(String fieldName) const {
|
||||
for(int i=0; i<numberFields; i++) {
|
||||
FieldConstPtr pfield = fields[i];
|
||||
int result = fieldName.compare(pfield->getFieldName());
|
||||
if(result==0) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void Structure::appendField(FieldConstPtr field)
|
||||
{
|
||||
FieldConstPtr *newFields = new FieldConstPtr[numberFields+1];
|
||||
for(int i=0; i<numberFields; i++) newFields[i] = fields[i];
|
||||
newFields[numberFields] = field;
|
||||
delete[] fields;
|
||||
fields = newFields;
|
||||
numberFields++;
|
||||
}
|
||||
|
||||
void Structure::appendFields(int numberNew,FieldConstPtrArray nfields)
|
||||
{
|
||||
FieldConstPtr *newFields = new FieldConstPtr[numberFields+numberNew];
|
||||
for(int i=0; i<numberFields; i++) newFields[i] = fields[i];
|
||||
for(int i=0; i<numberNew; i++) newFields[numberFields+i] = nfields[i];
|
||||
delete[] fields;
|
||||
fields = newFields;
|
||||
numberFields += numberNew;
|
||||
}
|
||||
|
||||
void Structure::removeField(int index)
|
||||
{
|
||||
if(index<0 || index>=numberFields) {
|
||||
throw std::invalid_argument(
|
||||
String("Structure::removeField index out of bounds"));
|
||||
}
|
||||
FieldConstPtr *newFields = new FieldConstPtr[numberFields-1];
|
||||
|
||||
int ind=0;
|
||||
for(int i=0; i<numberFields; i++) {
|
||||
if(i==index) continue;
|
||||
newFields[ind++] = fields[i];
|
||||
}
|
||||
delete[] fields;
|
||||
fields = newFields;
|
||||
--numberFields;
|
||||
}
|
||||
|
||||
void Structure::toString(StringBuilder buffer,int indentLevel) const{
|
||||
*buffer += "structure";
|
||||
Field::toString(buffer,indentLevel);
|
||||
newLine(buffer,indentLevel+1);
|
||||
for(int i=0; i<numberFields; i++) {
|
||||
FieldConstPtr pfield = fields[i];
|
||||
pfield->toString(buffer,indentLevel+1);
|
||||
if(i<numberFields-1) newLine(buffer,indentLevel+1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ScalarConstPtr FieldCreate::createScalar(String fieldName,
|
||||
ScalarType scalarType) const
|
||||
{
|
||||
ScalarConstPtr scalar(new Scalar(fieldName,scalarType), Field::Deleter());
|
||||
return scalar;
|
||||
}
|
||||
|
||||
ScalarArrayConstPtr FieldCreate::createScalarArray(
|
||||
String fieldName,ScalarType elementType) const
|
||||
{
|
||||
ScalarArrayConstPtr scalarArray(new ScalarArray(fieldName,elementType), Field::Deleter());
|
||||
return scalarArray;
|
||||
}
|
||||
StructureConstPtr FieldCreate::createStructure (
|
||||
String fieldName,int numberFields,
|
||||
FieldConstPtr fields[]) const
|
||||
{
|
||||
StructureConstPtr structure(new Structure(
|
||||
fieldName,numberFields,fields), Field::Deleter());
|
||||
return structure;
|
||||
}
|
||||
StructureArrayConstPtr FieldCreate::createStructureArray(
|
||||
String fieldName,StructureConstPtr structure) const
|
||||
{
|
||||
StructureArrayConstPtr structureArray(new StructureArray(fieldName,structure), Field::Deleter());
|
||||
return structureArray;
|
||||
}
|
||||
|
||||
FieldConstPtr FieldCreate::create(String fieldName,
|
||||
FieldConstPtr pfield) const
|
||||
{
|
||||
FieldConstPtr ret;
|
||||
Type type = pfield->getType();
|
||||
switch(type) {
|
||||
case scalar: {
|
||||
ScalarConstPtr pscalar = static_pointer_cast<const Scalar>(pfield);
|
||||
return createScalar(fieldName,pscalar->getScalarType());
|
||||
}
|
||||
case scalarArray: {
|
||||
ScalarArrayConstPtr pscalarArray = static_pointer_cast<const ScalarArray>(pfield);
|
||||
return createScalarArray(fieldName,pscalarArray->getElementType());
|
||||
}
|
||||
case structure: {
|
||||
StructureConstPtr pstructure = static_pointer_cast<const Structure>(pfield);
|
||||
return createStructure(fieldName,pstructure->getNumberFields(),pstructure->getFields());
|
||||
}
|
||||
case structureArray: {
|
||||
StructureArrayConstPtr pstructureArray = static_pointer_cast<const StructureArray>(pfield);
|
||||
return createStructureArray(fieldName,pstructureArray->getStructure());
|
||||
}
|
||||
}
|
||||
String message("field ");
|
||||
message += fieldName;
|
||||
THROW_EXCEPTION2(std::logic_error, message);
|
||||
}
|
||||
|
||||
static FieldCreate* fieldCreate = 0;
|
||||
|
||||
FieldCreate::FieldCreate()
|
||||
{
|
||||
}
|
||||
|
||||
FieldCreate * getFieldCreate() {
|
||||
static Mutex mutex;
|
||||
Lock xx(mutex);
|
||||
|
||||
if(fieldCreate==0) fieldCreate = new FieldCreate();
|
||||
return fieldCreate;
|
||||
}
|
||||
|
||||
}}
|
||||
@@ -1,89 +0,0 @@
|
||||
/*PVArray.cpp*/
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/factory.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
class PVArrayPvt {
|
||||
public:
|
||||
PVArrayPvt() : length(0),capacity(0),capacityMutable(true)
|
||||
{}
|
||||
int length;
|
||||
int capacity;
|
||||
bool capacityMutable;
|
||||
};
|
||||
|
||||
PVArray::PVArray(PVStructure *parent,FieldConstPtr field)
|
||||
: PVField(parent,field),pImpl(new PVArrayPvt())
|
||||
{ }
|
||||
|
||||
PVArray::~PVArray()
|
||||
{
|
||||
delete pImpl;
|
||||
}
|
||||
|
||||
int PVArray::getLength() const {return pImpl->length;}
|
||||
|
||||
int PVArray::getCapacity() const {return pImpl->capacity;}
|
||||
|
||||
static String fieldImmutable("field is immutable");
|
||||
|
||||
void PVArray::setLength(int length) {
|
||||
if(length==pImpl->length) return;
|
||||
if(PVField::isImmutable()) {
|
||||
PVField::message(fieldImmutable,errorMessage);
|
||||
return;
|
||||
}
|
||||
if(length>pImpl->capacity) this->setCapacity(length);
|
||||
if(length>pImpl->capacity) length = pImpl->capacity;
|
||||
pImpl->length = length;
|
||||
}
|
||||
|
||||
void PVArray::setCapacityLength(int capacity,int length) {
|
||||
pImpl->capacity = capacity;
|
||||
pImpl->length = length;
|
||||
}
|
||||
|
||||
|
||||
bool PVArray::isCapacityMutable()
|
||||
{
|
||||
if(PVField::isImmutable()) {
|
||||
return false;
|
||||
}
|
||||
return pImpl->capacityMutable;
|
||||
}
|
||||
|
||||
void PVArray::setCapacityMutable(bool isMutable)
|
||||
{
|
||||
if(isMutable && PVField::isImmutable()) {
|
||||
PVField::message(fieldImmutable,errorMessage);
|
||||
return;
|
||||
}
|
||||
pImpl->capacityMutable = isMutable;
|
||||
}
|
||||
|
||||
static String capacityImmutable("capacity is immutable");
|
||||
|
||||
void PVArray::setCapacity(int capacity) {
|
||||
if(PVField::isImmutable()) {
|
||||
PVField::message(fieldImmutable,errorMessage);
|
||||
return;
|
||||
}
|
||||
if(pImpl->capacityMutable==false) {
|
||||
PVField::message(capacityImmutable,errorMessage);
|
||||
return;
|
||||
}
|
||||
pImpl->capacity = capacity;
|
||||
}
|
||||
|
||||
}}
|
||||
@@ -1,102 +0,0 @@
|
||||
/*PVAuxInfo.cpp*/
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <pv/noDefaultMethods.h>
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/convert.h>
|
||||
#include <pv/factory.h>
|
||||
#include <pv/lock.h>
|
||||
#include <pv/CDRMonitor.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
PVDATA_REFCOUNT_MONITOR_DEFINE(pvAuxInfo);
|
||||
|
||||
PVAuxInfo::PVAuxInfo(PVField *pvField)
|
||||
: pvField(pvField),lengthInfo(1),numberInfo(0),
|
||||
pvInfos(new PVScalar *[1])
|
||||
{
|
||||
PVDATA_REFCOUNT_MONITOR_CONSTRUCT(pvAuxInfo);
|
||||
}
|
||||
|
||||
PVAuxInfo::~PVAuxInfo()
|
||||
{
|
||||
PVDATA_REFCOUNT_MONITOR_DESTRUCT(pvAuxInfo);
|
||||
for(int i=0; i<numberInfo; i++) delete pvInfos[i];
|
||||
delete[] pvInfos;
|
||||
}
|
||||
|
||||
|
||||
PVField * PVAuxInfo::getPVField() {
|
||||
return pvField;
|
||||
}
|
||||
|
||||
PVScalar * PVAuxInfo::createInfo(String key,ScalarType scalarType)
|
||||
{
|
||||
for(int i=0; i<numberInfo; i++) {
|
||||
PVScalar *pvScalar = pvInfos[i];
|
||||
if(key.compare(pvScalar->getField()->getFieldName())==0) {
|
||||
String message("AuxoInfo:create key ");
|
||||
message += key.c_str();
|
||||
message += " already exists with scalarType ";
|
||||
ScalarTypeFunc::toString(&message,scalarType);
|
||||
pvField->message(message,errorMessage);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if(lengthInfo==numberInfo) {
|
||||
int newLength = lengthInfo+4;
|
||||
PVScalar ** newInfos = new PVScalar *[newLength];
|
||||
lengthInfo = newLength;
|
||||
for(int i=0; i<numberInfo; i++) newInfos[i] = pvInfos[i];
|
||||
for(int i= numberInfo; i<lengthInfo; i++) newInfos[i] = 0;
|
||||
delete[] pvInfos;
|
||||
pvInfos = newInfos;
|
||||
}
|
||||
PVScalar *pvScalar = getPVDataCreate()->createPVScalar(0,key,scalarType);
|
||||
pvInfos[numberInfo++] = pvScalar;
|
||||
return pvScalar;
|
||||
}
|
||||
|
||||
PVScalar * PVAuxInfo::getInfo(String key)
|
||||
{
|
||||
for(int i=0; i<numberInfo; i++) {
|
||||
PVScalar *pvScalar = pvInfos[i];
|
||||
if(key.compare(pvScalar->getField()->getFieldName())==0) return pvScalar;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
PVScalar * PVAuxInfo::getInfo(int index)
|
||||
{
|
||||
if(index<0 || index>=numberInfo) return 0;
|
||||
return pvInfos[index];
|
||||
}
|
||||
|
||||
int PVAuxInfo::getNumberInfo() { return numberInfo;}
|
||||
|
||||
void PVAuxInfo::toString(StringBuilder buf)
|
||||
{
|
||||
PVAuxInfo::toString(buf,0);
|
||||
}
|
||||
|
||||
void PVAuxInfo::toString(StringBuilder buf,int indentLevel)
|
||||
{
|
||||
if(numberInfo==0) return;
|
||||
Convert *convert = getConvert();
|
||||
convert->newLine(buf,indentLevel);
|
||||
*buf += "auxInfo";
|
||||
for(int i=0; i<numberInfo; i++) {
|
||||
convert->newLine(buf,indentLevel+1);
|
||||
PVScalar *value = pvInfos[i];
|
||||
value->toString(buf,indentLevel + 1);
|
||||
}
|
||||
}
|
||||
}}
|
||||
@@ -1,601 +0,0 @@
|
||||
/*PVDataCreateFactory.cpp*/
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
#ifdef _WIN32
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <pv/lock.h>
|
||||
#include <pv/pvIntrospect.h>
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/convert.h>
|
||||
#include <pv/factory.h>
|
||||
#include <pv/serializeHelper.h>
|
||||
#include "DefaultPVStructureArray.h"
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using std::tr1::const_pointer_cast;
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
static Convert* convert = 0;
|
||||
static FieldCreate * fieldCreate = 0;
|
||||
static PVDataCreate* pvDataCreate = 0;
|
||||
|
||||
/** Default storage for scalar values
|
||||
*/
|
||||
template<typename T>
|
||||
class BasePVScalar : public PVScalarValue<T> {
|
||||
public:
|
||||
typedef T value_type;
|
||||
typedef T* pointer;
|
||||
typedef const T* const_pointer;
|
||||
|
||||
BasePVScalar(PVStructure *parent,ScalarConstPtr scalar);
|
||||
virtual ~BasePVScalar();
|
||||
virtual T get();
|
||||
virtual void put(T val);
|
||||
virtual void serialize(ByteBuffer *pbuffer,
|
||||
SerializableControl *pflusher) const;
|
||||
virtual void deserialize(ByteBuffer *pbuffer,
|
||||
DeserializableControl *pflusher);
|
||||
private:
|
||||
T value;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
BasePVScalar<T>::BasePVScalar(PVStructure *parent,ScalarConstPtr scalar)
|
||||
: PVScalarValue<T>(parent,scalar),value(0)
|
||||
{}
|
||||
//Note: '0' is a suitable default for all POD types (not String)
|
||||
|
||||
template<typename T>
|
||||
BasePVScalar<T>::~BasePVScalar() {}
|
||||
|
||||
template<typename T>
|
||||
T BasePVScalar<T>::get() { return value;}
|
||||
|
||||
template<typename T>
|
||||
void BasePVScalar<T>::put(T val){value = val;}
|
||||
|
||||
template<typename T>
|
||||
void BasePVScalar<T>::serialize(ByteBuffer *pbuffer,
|
||||
SerializableControl *pflusher) const {
|
||||
pflusher->ensureBuffer(sizeof(T));
|
||||
pbuffer->put<T>(value);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void BasePVScalar<T>::deserialize(ByteBuffer *pbuffer,
|
||||
DeserializableControl *pflusher)
|
||||
{
|
||||
pflusher->ensureData(sizeof(T));
|
||||
value = pbuffer->get<T>();
|
||||
}
|
||||
|
||||
typedef BasePVScalar<bool> BasePVBoolean;
|
||||
typedef BasePVScalar<int8> BasePVByte;
|
||||
typedef BasePVScalar<int16> BasePVShort;
|
||||
typedef BasePVScalar<int32> BasePVInt;
|
||||
typedef BasePVScalar<int64> BasePVLong;
|
||||
typedef BasePVScalar<float> BasePVFloat;
|
||||
typedef BasePVScalar<double> BasePVDouble;
|
||||
|
||||
// BasePVString is special case, since it implements SerializableArray
|
||||
class BasePVString : public PVString {
|
||||
public:
|
||||
typedef String value_type;
|
||||
typedef String* pointer;
|
||||
typedef const String* const_pointer;
|
||||
|
||||
BasePVString(PVStructure *parent,ScalarConstPtr scalar);
|
||||
virtual ~BasePVString();
|
||||
virtual String get();
|
||||
virtual void put(String val);
|
||||
virtual void serialize(ByteBuffer *pbuffer,
|
||||
SerializableControl *pflusher) const;
|
||||
virtual void deserialize(ByteBuffer *pbuffer,
|
||||
DeserializableControl *pflusher);
|
||||
virtual void serialize(ByteBuffer *pbuffer,
|
||||
SerializableControl *pflusher, int offset, int count) const;
|
||||
private:
|
||||
String value;
|
||||
};
|
||||
|
||||
BasePVString::BasePVString(PVStructure *parent,ScalarConstPtr scalar)
|
||||
: PVString(parent,scalar),value()
|
||||
{}
|
||||
|
||||
BasePVString::~BasePVString() {}
|
||||
|
||||
String BasePVString::get() { return value;}
|
||||
|
||||
void BasePVString::put(String val){value = val;}
|
||||
|
||||
void BasePVString::serialize(ByteBuffer *pbuffer,
|
||||
SerializableControl *pflusher) const
|
||||
{
|
||||
SerializeHelper::serializeString(value, pbuffer, pflusher);
|
||||
}
|
||||
|
||||
void BasePVString::deserialize(ByteBuffer *pbuffer,
|
||||
DeserializableControl *pflusher)
|
||||
{
|
||||
value = SerializeHelper::deserializeString(pbuffer, pflusher);
|
||||
}
|
||||
|
||||
void BasePVString::serialize(ByteBuffer *pbuffer,
|
||||
SerializableControl *pflusher, int offset, int count) const
|
||||
{
|
||||
// check bounds
|
||||
const int length = /*(value == null) ? 0 :*/ value.length();
|
||||
if (offset < 0) offset = 0;
|
||||
else if (offset > length) offset = length;
|
||||
if (count < 0) count = length;
|
||||
|
||||
const int maxCount = length - offset;
|
||||
if (count > maxCount)
|
||||
count = maxCount;
|
||||
|
||||
// write
|
||||
SerializeHelper::serializeSubstring(value, offset, count, pbuffer, pflusher);
|
||||
}
|
||||
|
||||
/** Default storage for arrays
|
||||
*/
|
||||
template<typename T>
|
||||
class DefaultPVArray : public PVValueArray<T> {
|
||||
public:
|
||||
typedef T value_type;
|
||||
typedef T* pointer;
|
||||
typedef const T* const_pointer;
|
||||
|
||||
DefaultPVArray(PVStructure *parent,ScalarArrayConstPtr scalarArray);
|
||||
virtual ~DefaultPVArray();
|
||||
virtual void setCapacity(int capacity);
|
||||
virtual int get(int offset, int length, PVArrayData<T> *data) ;
|
||||
virtual int put(int offset,int length, pointer from,
|
||||
int fromOffset);
|
||||
virtual void shareData(pointer value,int capacity,int length);
|
||||
// from Serializable
|
||||
virtual void serialize(ByteBuffer *pbuffer,SerializableControl *pflusher) const;
|
||||
virtual void deserialize(ByteBuffer *pbuffer,DeserializableControl *pflusher);
|
||||
virtual void serialize(ByteBuffer *pbuffer,
|
||||
SerializableControl *pflusher, int offset, int count) const;
|
||||
private:
|
||||
pointer value;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
DefaultPVArray<T>::DefaultPVArray(PVStructure *parent,
|
||||
ScalarArrayConstPtr scalarArray)
|
||||
: PVValueArray<T>(parent,scalarArray),value(new T[0])
|
||||
{ }
|
||||
|
||||
template<typename T>
|
||||
DefaultPVArray<T>::~DefaultPVArray()
|
||||
{
|
||||
delete[] value;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void DefaultPVArray<T>::setCapacity(int capacity)
|
||||
{
|
||||
if(PVArray::getCapacity()==capacity) return;
|
||||
if(!PVArray::isCapacityMutable()) {
|
||||
std::string message("not capacityMutable");
|
||||
PVField::message(message, errorMessage);
|
||||
return;
|
||||
}
|
||||
int length = PVArray::getLength();
|
||||
if(length>capacity) length = capacity;
|
||||
T *newValue = new T[capacity];
|
||||
for(int i=0; i<length; i++) newValue[i] = value[i];
|
||||
delete[]value;
|
||||
value = newValue;
|
||||
PVArray::setCapacityLength(capacity,length);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
int DefaultPVArray<T>::get(int offset, int len, PVArrayData<T> *data)
|
||||
{
|
||||
int n = len;
|
||||
int length = this->getLength();
|
||||
if(offset+len > length) {
|
||||
n = length-offset;
|
||||
if(n<0) n = 0;
|
||||
}
|
||||
data->data = value;
|
||||
data->offset = offset;
|
||||
return n;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
int DefaultPVArray<T>::put(int offset,int len,
|
||||
pointer from,int fromOffset)
|
||||
{
|
||||
if(PVField::isImmutable()) {
|
||||
PVField::message("field is immutable",errorMessage);
|
||||
return 0;
|
||||
}
|
||||
if(from==value) return len;
|
||||
if(len<1) return 0;
|
||||
int length = this->getLength();
|
||||
int capacity = this->getCapacity();
|
||||
if(offset+len > length) {
|
||||
int newlength = offset + len;
|
||||
if(newlength>capacity) {
|
||||
setCapacity(newlength);
|
||||
newlength = this->getCapacity();
|
||||
len = newlength - offset;
|
||||
if(len<=0) return 0;
|
||||
}
|
||||
length = newlength;
|
||||
}
|
||||
for(int i=0;i<len;i++) {
|
||||
value[i+offset] = from[i+fromOffset];
|
||||
}
|
||||
this->setLength(length);
|
||||
this->postPut();
|
||||
return len;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void DefaultPVArray<T>::shareData(pointer shareValue,int capacity,int length)
|
||||
{
|
||||
delete[] value;
|
||||
value = shareValue;
|
||||
PVArray::setCapacityLength(capacity,length);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void DefaultPVArray<T>::serialize(ByteBuffer *pbuffer,
|
||||
SerializableControl *pflusher) const {
|
||||
serialize(pbuffer, pflusher, 0, this->getLength());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void DefaultPVArray<T>::deserialize(ByteBuffer *pbuffer,
|
||||
DeserializableControl *pcontrol) {
|
||||
int size = SerializeHelper::readSize(pbuffer, pcontrol);
|
||||
// if (size>0) { pcontrol->ensureData(sizeof(T)-1); pbuffer->align(sizeof(T)); }
|
||||
if(size>=0) {
|
||||
// prepare array, if necessary
|
||||
if(size>this->getCapacity()) this->setCapacity(size);
|
||||
// retrieve value from the buffer
|
||||
int i = 0;
|
||||
while(true) {
|
||||
/*
|
||||
int maxIndex = std::min(size-i, (int)(pbuffer->getRemaining()/sizeof(T)))+i;
|
||||
for(; i<maxIndex; i++)
|
||||
value[i] = pbuffer->get<T>();
|
||||
*/
|
||||
int maxCount = std::min(size-i, (int)(pbuffer->getRemaining()/sizeof(T)));
|
||||
pbuffer->getArray<T>(&value[i], maxCount);
|
||||
i += maxCount;
|
||||
|
||||
if(i<size)
|
||||
pcontrol->ensureData(sizeof(T)); // this is not OK since can exceen max local buffer (size-i)*sizeof(T));
|
||||
else
|
||||
break;
|
||||
}
|
||||
// set new length
|
||||
this->setLength(size);
|
||||
PVField::postPut();
|
||||
}
|
||||
// TODO null arrays (size == -1) not supported
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void DefaultPVArray<T>::serialize(ByteBuffer *pbuffer,
|
||||
SerializableControl *pflusher, int offset, int count) const {
|
||||
// cache
|
||||
int length = this->getLength();
|
||||
|
||||
// check bounds
|
||||
if(offset<0)
|
||||
offset = 0;
|
||||
else if(offset>length) offset = length;
|
||||
if(count<0) count = length;
|
||||
|
||||
int maxCount = length-offset;
|
||||
if(count>maxCount) count = maxCount;
|
||||
|
||||
// write
|
||||
SerializeHelper::writeSize(count, pbuffer, pflusher);
|
||||
//if (count == 0) return; pcontrol->ensureData(sizeof(T)-1); pbuffer->align(sizeof(T));
|
||||
int end = offset+count;
|
||||
int i = offset;
|
||||
while(true) {
|
||||
|
||||
/*
|
||||
int maxIndex = std::min<int>(end-i, (int)(pbuffer->getRemaining()/sizeof(T)))+i;
|
||||
for(; i<maxIndex; i++)
|
||||
pbuffer->put<T>(value[i]);
|
||||
*/
|
||||
|
||||
int maxCount = std::min<int>(end-i, (int)(pbuffer->getRemaining()/sizeof(T)));
|
||||
pbuffer->putArray<T>(&value[i], maxCount);
|
||||
i += maxCount;
|
||||
|
||||
if(i<end)
|
||||
pflusher->flushSerializeBuffer();
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// specializations for String
|
||||
|
||||
template<>
|
||||
void DefaultPVArray<String>::deserialize(ByteBuffer *pbuffer,
|
||||
DeserializableControl *pcontrol) {
|
||||
int size = SerializeHelper::readSize(pbuffer, pcontrol);
|
||||
if(size>=0) {
|
||||
// prepare array, if necessary
|
||||
if(size>getCapacity()) setCapacity(size);
|
||||
// retrieve value from the buffer
|
||||
for(int i = 0; i<size; i++)
|
||||
value[i] = SerializeHelper::deserializeString(pbuffer,
|
||||
pcontrol);
|
||||
// set new length
|
||||
setLength(size);
|
||||
postPut();
|
||||
}
|
||||
// TODO null arrays (size == -1) not supported
|
||||
}
|
||||
|
||||
template<>
|
||||
void DefaultPVArray<String>::serialize(ByteBuffer *pbuffer,
|
||||
SerializableControl *pflusher, int offset, int count) const {
|
||||
int length = getLength();
|
||||
|
||||
// check bounds
|
||||
if(offset<0)
|
||||
offset = 0;
|
||||
else if(offset>length) offset = length;
|
||||
if(count<0) count = length;
|
||||
|
||||
int maxCount = length-offset;
|
||||
if(count>maxCount) count = maxCount;
|
||||
|
||||
// write
|
||||
SerializeHelper::writeSize(count, pbuffer, pflusher);
|
||||
int end = offset+count;
|
||||
for(int i = offset; i<end; i++)
|
||||
SerializeHelper::serializeString(value[i], pbuffer, pflusher);
|
||||
}
|
||||
|
||||
typedef DefaultPVArray<bool> DefaultPVBooleanArray;
|
||||
typedef DefaultPVArray<int8> BasePVByteArray;
|
||||
typedef DefaultPVArray<int16> BasePVShortArray;
|
||||
typedef DefaultPVArray<int32> BasePVIntArray;
|
||||
typedef DefaultPVArray<int64> BasePVLongArray;
|
||||
typedef DefaultPVArray<float> BasePVFloatArray;
|
||||
typedef DefaultPVArray<double> BasePVDoubleArray;
|
||||
typedef DefaultPVArray<String> BasePVStringArray;
|
||||
|
||||
// Factory
|
||||
|
||||
PVDataCreate::PVDataCreate(){ }
|
||||
|
||||
PVField *PVDataCreate::createPVField(PVStructure *parent,
|
||||
FieldConstPtr field)
|
||||
{
|
||||
switch(field->getType()) {
|
||||
case scalar: {
|
||||
ScalarConstPtr xx = static_pointer_cast<const Scalar>(field);
|
||||
return createPVScalar(parent,xx);
|
||||
}
|
||||
case scalarArray: {
|
||||
ScalarArrayConstPtr xx = static_pointer_cast<const ScalarArray>(field);
|
||||
return (PVField *)createPVScalarArray(parent,xx);
|
||||
}
|
||||
case structure: {
|
||||
StructureConstPtr xx = static_pointer_cast<const Structure>(field);
|
||||
return (PVField *)createPVStructure(parent,xx);
|
||||
}
|
||||
case structureArray: {
|
||||
StructureArrayConstPtr xx = static_pointer_cast<const StructureArray>(field);
|
||||
return createPVStructureArray(parent,xx);
|
||||
}
|
||||
}
|
||||
String message("PVDataCreate::createPVField should never get here");
|
||||
throw std::logic_error(message);
|
||||
}
|
||||
|
||||
PVField *PVDataCreate::createPVField(PVStructure *parent,
|
||||
String fieldName,PVField * fieldToClone)
|
||||
{
|
||||
switch(fieldToClone->getField()->getType()) {
|
||||
case scalar:
|
||||
return createPVScalar(parent,fieldName,(PVScalar*)fieldToClone);
|
||||
case scalarArray:
|
||||
return (PVField *)createPVScalarArray(parent,fieldName,
|
||||
(PVScalarArray *)fieldToClone);
|
||||
case structure:
|
||||
return (PVField *)createPVStructure(parent,fieldName,
|
||||
(PVStructure *)fieldToClone);
|
||||
case structureArray:
|
||||
String message(
|
||||
"PVDataCreate::createPVField structureArray not valid fieldToClone");
|
||||
throw std::invalid_argument(message);
|
||||
}
|
||||
String message("PVDataCreate::createPVField should never get here");
|
||||
throw std::logic_error(message);
|
||||
}
|
||||
|
||||
PVScalar *PVDataCreate::createPVScalar(PVStructure *parent,ScalarConstPtr scalar)
|
||||
{
|
||||
ScalarType scalarType = scalar->getScalarType();
|
||||
switch(scalarType) {
|
||||
case pvBoolean:
|
||||
return new BasePVBoolean(parent,scalar);
|
||||
case pvByte:
|
||||
return new BasePVByte(parent,scalar);
|
||||
case pvShort:
|
||||
return new BasePVShort(parent,scalar);
|
||||
case pvInt:
|
||||
return new BasePVInt(parent,scalar);
|
||||
case pvLong:
|
||||
return new BasePVLong(parent,scalar);
|
||||
case pvFloat:
|
||||
return new BasePVFloat(parent,scalar);
|
||||
case pvDouble:
|
||||
return new BasePVDouble(parent,scalar);
|
||||
case pvString:
|
||||
return new BasePVString(parent,scalar);
|
||||
}
|
||||
String message("PVDataCreate::createPVScalar should never get here");
|
||||
throw std::logic_error(message);
|
||||
}
|
||||
|
||||
PVScalar *PVDataCreate::createPVScalar(PVStructure *parent,
|
||||
String fieldName,ScalarType scalarType)
|
||||
{
|
||||
ScalarConstPtr scalar = fieldCreate->createScalar(fieldName,scalarType);
|
||||
return createPVScalar(parent,scalar);
|
||||
}
|
||||
|
||||
|
||||
PVScalar *PVDataCreate::createPVScalar(PVStructure *parent,
|
||||
String fieldName,PVScalar * scalarToClone)
|
||||
{
|
||||
PVScalar *pvScalar = createPVScalar(parent,fieldName,
|
||||
scalarToClone->getScalar()->getScalarType());
|
||||
convert->copyScalar(scalarToClone, pvScalar);
|
||||
PVAuxInfo *from = scalarToClone->getPVAuxInfo();
|
||||
PVAuxInfo *to = pvScalar->getPVAuxInfo();
|
||||
int numberInfo = from->getNumberInfo();
|
||||
for(int i=0; i<numberInfo; i++) {
|
||||
PVScalar *pvFrom = from->getInfo(i);
|
||||
ScalarConstPtr scalar = pvFrom->getScalar();
|
||||
PVScalar *pvTo = to->createInfo(scalar->getFieldName(),scalar->getScalarType());
|
||||
convert->copyScalar(pvFrom,pvTo);
|
||||
}
|
||||
return pvScalar;
|
||||
}
|
||||
|
||||
PVScalarArray *PVDataCreate::createPVScalarArray(PVStructure *parent,
|
||||
ScalarArrayConstPtr scalarArray)
|
||||
{
|
||||
switch(scalarArray->getElementType()) {
|
||||
case pvBoolean:
|
||||
return new DefaultPVBooleanArray(parent,scalarArray);
|
||||
case pvByte:
|
||||
return new BasePVByteArray(parent,scalarArray);
|
||||
case pvShort:
|
||||
return new BasePVShortArray(parent,scalarArray);
|
||||
case pvInt:
|
||||
return new BasePVIntArray(parent,scalarArray);
|
||||
case pvLong:
|
||||
return new BasePVLongArray(parent,scalarArray);
|
||||
case pvFloat:
|
||||
return new BasePVFloatArray(parent,scalarArray);
|
||||
case pvDouble:
|
||||
return new BasePVDoubleArray(parent,scalarArray);
|
||||
case pvString:
|
||||
return new BasePVStringArray(parent,scalarArray);
|
||||
}
|
||||
String message("PVDataCreate::createPVScalarArray should never get here");
|
||||
throw std::logic_error(message);
|
||||
|
||||
}
|
||||
|
||||
PVScalarArray *PVDataCreate::createPVScalarArray(PVStructure *parent,
|
||||
String fieldName,ScalarType elementType)
|
||||
{
|
||||
return createPVScalarArray(parent,
|
||||
fieldCreate->createScalarArray(fieldName, elementType));
|
||||
}
|
||||
|
||||
PVScalarArray *PVDataCreate::createPVScalarArray(PVStructure *parent,
|
||||
String fieldName,PVScalarArray * arrayToClone)
|
||||
{
|
||||
PVScalarArray *pvArray = createPVScalarArray(parent,fieldName,
|
||||
arrayToClone->getScalarArray()->getElementType());
|
||||
convert->copyScalarArray(arrayToClone,0, pvArray,0,arrayToClone->getLength());
|
||||
PVAuxInfo *from = arrayToClone->getPVAuxInfo();
|
||||
PVAuxInfo *to = pvArray->getPVAuxInfo();
|
||||
int numberInfo = from->getNumberInfo();
|
||||
for(int i=0; i<numberInfo; i++) {
|
||||
PVScalar *pvFrom = from->getInfo(i);
|
||||
ScalarConstPtr scalar = pvFrom->getScalar();
|
||||
PVScalar *pvTo = to->createInfo(scalar->getFieldName(),scalar->getScalarType());
|
||||
convert->copyScalar(pvFrom,pvTo);
|
||||
}
|
||||
return pvArray;
|
||||
}
|
||||
|
||||
PVStructureArray *PVDataCreate::createPVStructureArray(PVStructure *parent,
|
||||
StructureArrayConstPtr structureArray)
|
||||
{
|
||||
return new BasePVStructureArray(parent,structureArray);
|
||||
}
|
||||
|
||||
PVStructure *PVDataCreate::createPVStructure(PVStructure *parent,
|
||||
StructureConstPtr structure)
|
||||
{
|
||||
PVStructure *pvStructure = new PVStructure(parent,structure);
|
||||
return pvStructure;
|
||||
}
|
||||
|
||||
PVStructure *PVDataCreate::createPVStructure(PVStructure *parent,
|
||||
String fieldName,int numberFields,FieldConstPtrArray fields)
|
||||
{
|
||||
StructureConstPtr structure = fieldCreate->createStructure(
|
||||
fieldName,numberFields, fields);
|
||||
return new PVStructure(parent,structure);
|
||||
}
|
||||
|
||||
PVStructure *PVDataCreate::createPVStructure(PVStructure *parent,
|
||||
String fieldName,int numberFields,PVFieldPtrArray pvFields)
|
||||
{
|
||||
FieldConstPtrArray fields = new FieldConstPtr[numberFields];
|
||||
for(int i=0; i<numberFields;i++) {
|
||||
fields[i] = pvFields[i]->getField();
|
||||
}
|
||||
StructureConstPtr structure = fieldCreate->createStructure(
|
||||
fieldName,numberFields,fields);
|
||||
PVStructure *pvStructure = new PVStructure(parent,structure,pvFields);
|
||||
return pvStructure;
|
||||
}
|
||||
|
||||
PVStructure *PVDataCreate::createPVStructure(PVStructure *parent,
|
||||
String fieldName,PVStructure *structToClone)
|
||||
{
|
||||
FieldConstPtrArray fields = 0;
|
||||
int numberFields = 0;
|
||||
PVStructure *pvStructure = 0;;
|
||||
if(structToClone==0) {
|
||||
fields = new FieldConstPtr[0];
|
||||
StructureConstPtr structure = fieldCreate->createStructure(
|
||||
fieldName,numberFields,fields);
|
||||
pvStructure = new PVStructure(parent,structure);
|
||||
} else {
|
||||
StructureConstPtr structure = structToClone->getStructure();
|
||||
pvStructure = new PVStructure(parent,structure);
|
||||
convert->copyStructure(structToClone,pvStructure);
|
||||
}
|
||||
return pvStructure;
|
||||
}
|
||||
|
||||
PVDataCreate * getPVDataCreate() {
|
||||
static Mutex mutex;
|
||||
Lock xx(mutex);
|
||||
|
||||
if(pvDataCreate==0){
|
||||
pvDataCreate = new PVDataCreate();
|
||||
convert = getConvert();
|
||||
fieldCreate = getFieldCreate();
|
||||
}
|
||||
return pvDataCreate;
|
||||
}
|
||||
|
||||
}}
|
||||
@@ -1,255 +0,0 @@
|
||||
/*PVField.cpp*/
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <pv/lock.h>
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/factory.h>
|
||||
#include <pv/convert.h>
|
||||
#include <pv/CDRMonitor.h>
|
||||
|
||||
using std::tr1::const_pointer_cast;
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
static String notImplemented("not implemented");
|
||||
|
||||
PVDATA_REFCOUNT_MONITOR_DEFINE(pvField);
|
||||
|
||||
class PVFieldPvt {
|
||||
public:
|
||||
PVFieldPvt(PVStructure *parent,FieldConstPtr field);
|
||||
~PVFieldPvt();
|
||||
PVStructure *parent;
|
||||
FieldConstPtr field;
|
||||
int fieldOffset;
|
||||
int nextFieldOffset;
|
||||
PVAuxInfo *pvAuxInfo;
|
||||
bool immutable;
|
||||
Requester *requester;
|
||||
PostHandler *postHandler;
|
||||
Convert *convert;
|
||||
};
|
||||
|
||||
PVFieldPvt::PVFieldPvt(PVStructure *parent,FieldConstPtr field)
|
||||
: parent(parent),field(field),
|
||||
fieldOffset(0), nextFieldOffset(0),
|
||||
pvAuxInfo(0),
|
||||
immutable(false),requester(0),postHandler(0),
|
||||
convert(getConvert())
|
||||
{
|
||||
}
|
||||
|
||||
PVFieldPvt::~PVFieldPvt()
|
||||
{
|
||||
if(pvAuxInfo!=0) delete pvAuxInfo;
|
||||
}
|
||||
|
||||
|
||||
|
||||
PVField::PVField(PVStructure *parent,FieldConstPtr field)
|
||||
: pImpl(new PVFieldPvt(parent,field))
|
||||
{
|
||||
PVDATA_REFCOUNT_MONITOR_CONSTRUCT(pvField);
|
||||
}
|
||||
|
||||
PVField::~PVField()
|
||||
{
|
||||
PVDATA_REFCOUNT_MONITOR_DESTRUCT(pvField);
|
||||
delete pImpl;
|
||||
}
|
||||
|
||||
void PVField::message(String fieldName,String message,MessageType messageType)
|
||||
{
|
||||
if(pImpl->parent!=0) {
|
||||
String parentName = pImpl->parent->getField()->getFieldName();
|
||||
if(parentName.length()>0) {
|
||||
fieldName = parentName + "." + fieldName;
|
||||
}
|
||||
pImpl->parent->message(fieldName,message,messageType);
|
||||
return;
|
||||
}
|
||||
if(pImpl->requester) {
|
||||
String mess = fieldName + " " + message;
|
||||
pImpl->requester->message(mess,messageType);
|
||||
} else {
|
||||
printf("%s %s %s\n",
|
||||
messageTypeName[messageType].c_str(),
|
||||
fieldName.c_str(),
|
||||
message.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void PVField::message(String message,MessageType messageType)
|
||||
{
|
||||
PVField::message(pImpl->field->getFieldName(),message,messageType);
|
||||
}
|
||||
void PVField::setRequester(Requester *requester)
|
||||
{
|
||||
if(pImpl->parent!=0) {
|
||||
throw std::logic_error(String(
|
||||
"PVField::setRequester only legal for top level structure"));
|
||||
}
|
||||
if(pImpl->requester!=0) {
|
||||
if(pImpl->requester==requester) return;
|
||||
throw std::logic_error(String(
|
||||
"PVField::setRequester requester is already present"));
|
||||
}
|
||||
pImpl->requester = requester;
|
||||
}
|
||||
|
||||
int PVField::getFieldOffset()
|
||||
{
|
||||
if(pImpl->nextFieldOffset==0) computeOffset(this);
|
||||
return pImpl->fieldOffset;
|
||||
}
|
||||
|
||||
int PVField::getNextFieldOffset()
|
||||
{
|
||||
if(pImpl->nextFieldOffset==0) computeOffset(this);
|
||||
return pImpl->nextFieldOffset;
|
||||
}
|
||||
|
||||
int PVField::getNumberFields()
|
||||
{
|
||||
if(pImpl->nextFieldOffset==0) computeOffset(this);
|
||||
return (pImpl->nextFieldOffset - pImpl->fieldOffset);
|
||||
}
|
||||
|
||||
PVAuxInfo * PVField::getPVAuxInfo(){
|
||||
if(pImpl->pvAuxInfo==0) {
|
||||
pImpl->pvAuxInfo = new PVAuxInfo(this);
|
||||
}
|
||||
return pImpl->pvAuxInfo;
|
||||
}
|
||||
|
||||
bool PVField::isImmutable() {return pImpl->immutable;}
|
||||
|
||||
void PVField::setImmutable() {pImpl->immutable = true;}
|
||||
|
||||
FieldConstPtr PVField::getField() {return pImpl->field;}
|
||||
|
||||
PVStructure * PVField::getParent() {return pImpl->parent;}
|
||||
|
||||
|
||||
bool PVField::renameField(String newName)
|
||||
{
|
||||
if(pImpl->parent!=0) {
|
||||
StructureConstPtr structure = pImpl->parent->getStructure();
|
||||
int index = structure->getFieldIndex(newName);
|
||||
if(index>=0) return false;
|
||||
}
|
||||
Field::shared_pointer field(const_pointer_cast<Field>(pImpl->field));
|
||||
field->renameField(newName);
|
||||
return true;
|
||||
}
|
||||
|
||||
void PVField::postPut()
|
||||
{
|
||||
if(pImpl->postHandler!=0) pImpl->postHandler->postPut();
|
||||
}
|
||||
|
||||
void PVField::setPostHandler(PostHandler *postHandler)
|
||||
{
|
||||
if(pImpl->postHandler!=0) {
|
||||
if(postHandler==pImpl->postHandler) return;
|
||||
String message(
|
||||
"PVField::setPostHandler a postHandler is already registered");
|
||||
throw std::logic_error(message);
|
||||
}
|
||||
pImpl->postHandler = postHandler;
|
||||
}
|
||||
|
||||
void PVField::setParent(PVStructure * parent)
|
||||
{
|
||||
pImpl->parent = parent;
|
||||
}
|
||||
|
||||
bool PVField::equals(PVField &pv)
|
||||
{
|
||||
return pImpl->convert->equals(*this,pv);
|
||||
}
|
||||
|
||||
void PVField::toString(StringBuilder buf) {toString(buf,0);}
|
||||
|
||||
void PVField::toString(StringBuilder buf,int indentLevel)
|
||||
{
|
||||
pImpl->convert->getString(buf,this,indentLevel);
|
||||
if(pImpl->pvAuxInfo==0) return;
|
||||
pImpl->pvAuxInfo->toString(buf,indentLevel);
|
||||
}
|
||||
|
||||
void PVField::computeOffset(PVField * pvField) {
|
||||
PVStructure *pvTop = pvField->getParent();
|
||||
if(pvTop==0) {
|
||||
if(pvField->getField()->getType()!=structure) {
|
||||
pvField->pImpl->fieldOffset = 0;
|
||||
pvField->pImpl->nextFieldOffset = 1;
|
||||
return;
|
||||
}
|
||||
pvTop = static_cast<PVStructure *>(pvField);
|
||||
} else {
|
||||
while(pvTop->getParent()!=0) pvTop = pvTop->getParent();
|
||||
}
|
||||
int offset = 0;
|
||||
int nextOffset = 1;
|
||||
PVFieldPtrArray pvFields = pvTop->getPVFields();
|
||||
for(int i=0; i < pvTop->getStructure()->getNumberFields(); i++) {
|
||||
offset = nextOffset;
|
||||
PVField *pvField = pvFields[i];
|
||||
FieldConstPtr field = pvField->getField();
|
||||
switch(field->getType()) {
|
||||
case scalar:
|
||||
case scalarArray:
|
||||
case structureArray:{
|
||||
nextOffset++;
|
||||
pvField->pImpl->fieldOffset = offset;
|
||||
pvField->pImpl->nextFieldOffset = nextOffset;
|
||||
break;
|
||||
}
|
||||
case structure: {
|
||||
pvField->computeOffset(pvField,offset);
|
||||
nextOffset = pvField->getNextFieldOffset();
|
||||
}
|
||||
}
|
||||
}
|
||||
PVField *top = (PVField *)pvTop;
|
||||
top->pImpl->fieldOffset = 0;
|
||||
top->pImpl->nextFieldOffset = nextOffset;
|
||||
}
|
||||
|
||||
void PVField::computeOffset(PVField * pvField,int offset) {
|
||||
int beginOffset = offset;
|
||||
int nextOffset = offset + 1;
|
||||
PVStructure *pvStructure = static_cast<PVStructure *>(pvField);
|
||||
PVFieldPtrArray pvFields = pvStructure->getPVFields();
|
||||
for(int i=0; i < pvStructure->getStructure()->getNumberFields(); i++) {
|
||||
offset = nextOffset;
|
||||
PVField *pvSubField = pvFields[i];
|
||||
FieldConstPtr field = pvSubField->getField();
|
||||
switch(field->getType()) {
|
||||
case scalar:
|
||||
case scalarArray:
|
||||
case structureArray: {
|
||||
nextOffset++;
|
||||
pvSubField->pImpl->fieldOffset = offset;
|
||||
pvSubField->pImpl->nextFieldOffset = nextOffset;
|
||||
break;
|
||||
}
|
||||
case structure: {
|
||||
pvSubField->computeOffset(pvSubField,offset);
|
||||
nextOffset = pvSubField->getNextFieldOffset();
|
||||
}
|
||||
}
|
||||
}
|
||||
pvField->pImpl->fieldOffset = beginOffset;
|
||||
pvField->pImpl->nextFieldOffset = nextOffset;
|
||||
}
|
||||
|
||||
}}
|
||||
@@ -1,28 +0,0 @@
|
||||
/*PVScalar.cpp*/
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/factory.h>
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
PVScalar::~PVScalar() {}
|
||||
|
||||
PVScalar::PVScalar(PVStructure *parent,ScalarConstPtr scalar)
|
||||
: PVField(parent,scalar) {}
|
||||
|
||||
ScalarConstPtr PVScalar::getScalar()
|
||||
{
|
||||
return static_pointer_cast<const Scalar>(PVField::getField());
|
||||
}
|
||||
|
||||
}}
|
||||
@@ -1,29 +0,0 @@
|
||||
/*PVScalarArray.cpp*/
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/factory.h>
|
||||
|
||||
using std::tr1::static_pointer_cast;using std::tr1::static_pointer_cast;
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
PVScalarArray::~PVScalarArray() {}
|
||||
|
||||
PVScalarArray::PVScalarArray(PVStructure *parent,
|
||||
ScalarArrayConstPtr scalarArray)
|
||||
: PVArray(parent,scalarArray) {}
|
||||
|
||||
ScalarArrayConstPtr PVScalarArray::getScalarArray()
|
||||
{
|
||||
return static_pointer_cast<const ScalarArray>(PVField::getField());
|
||||
}
|
||||
|
||||
}}
|
||||
@@ -1,567 +0,0 @@
|
||||
/*PVStructure.cpp*/
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <vector>
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/pvIntrospect.h>
|
||||
#include <pv/convert.h>
|
||||
#include <pv/factory.h>
|
||||
#include <pv/bitSet.h>
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using std::tr1::const_pointer_cast;
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
class PVStructurePvt {
|
||||
public:
|
||||
PVStructurePvt();
|
||||
~PVStructurePvt();
|
||||
|
||||
int numberFields;
|
||||
PVFieldPtrArray pvFields;
|
||||
String extendsStructureName;
|
||||
};
|
||||
|
||||
PVStructurePvt::PVStructurePvt()
|
||||
: numberFields(0), pvFields(0),extendsStructureName("")
|
||||
{
|
||||
}
|
||||
|
||||
PVStructurePvt::~PVStructurePvt()
|
||||
{
|
||||
for(int i=0; i<numberFields; i++) {
|
||||
delete pvFields[i];
|
||||
}
|
||||
if (pvFields) delete[] pvFields;
|
||||
}
|
||||
|
||||
static PVField *findSubField(String fieldName,PVStructure *pvStructure);
|
||||
|
||||
PVStructure::PVStructure(PVStructure *parent,StructureConstPtr structurePtr)
|
||||
: PVField(parent,structurePtr),pImpl(new PVStructurePvt())
|
||||
{
|
||||
int numberFields = structurePtr->getNumberFields();
|
||||
FieldConstPtrArray fields = structurePtr->getFields();
|
||||
pImpl->numberFields = numberFields;
|
||||
pImpl->pvFields = new PVFieldPtr[numberFields];
|
||||
PVFieldPtrArray pvFields = pImpl->pvFields;
|
||||
PVDataCreate *pvDataCreate = getPVDataCreate();
|
||||
for(int i=0; i<numberFields; i++) {
|
||||
pvFields[i] = pvDataCreate->createPVField(this,fields[i]);
|
||||
}
|
||||
}
|
||||
|
||||
PVStructure::PVStructure(PVStructure *parent,StructureConstPtr structurePtr,
|
||||
PVFieldPtrArray pvFields
|
||||
)
|
||||
: PVField(parent,structurePtr),pImpl(new PVStructurePvt())
|
||||
{
|
||||
int numberFields = structurePtr->getNumberFields();
|
||||
pImpl->numberFields = numberFields;
|
||||
pImpl->pvFields = pvFields;
|
||||
for(int i=0; i<numberFields; i++) {
|
||||
PVField *pvField = pvFields[i];
|
||||
setParentPvt(pvField,this);
|
||||
}
|
||||
}
|
||||
|
||||
void PVStructure::setParentPvt(PVField *pvField,PVStructure *parent)
|
||||
{
|
||||
pvField->setParent(parent);
|
||||
if(pvField->getField()->getType()==structure) {
|
||||
PVStructure *subStructure = static_cast<PVStructure*>(pvField);
|
||||
PVFieldPtr *subFields = subStructure->getPVFields();
|
||||
int numberFields = subStructure->getStructure()->getNumberFields();
|
||||
for(int i=0; i<numberFields; i++) {
|
||||
PVField *subField = static_cast<PVField*>(subFields[i]);
|
||||
setParentPvt(subField,subStructure);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PVStructure::~PVStructure()
|
||||
{
|
||||
delete pImpl;
|
||||
}
|
||||
|
||||
StructureConstPtr PVStructure::getStructure()
|
||||
{
|
||||
return static_pointer_cast<const Structure>(PVField::getField());
|
||||
}
|
||||
|
||||
PVFieldPtrArray PVStructure::getPVFields()
|
||||
{
|
||||
return pImpl->pvFields;
|
||||
}
|
||||
|
||||
PVFieldPtr PVStructure::getSubField(String fieldName)
|
||||
{
|
||||
return findSubField(fieldName,this);
|
||||
}
|
||||
|
||||
PVFieldPtr PVStructure::getSubField(int fieldOffset)
|
||||
{
|
||||
if(fieldOffset<=getFieldOffset()) {
|
||||
if(fieldOffset==getFieldOffset()) return this;
|
||||
return 0;
|
||||
}
|
||||
if(fieldOffset>getNextFieldOffset()) return 0;
|
||||
int numFields = pImpl->numberFields;
|
||||
PVFieldPtrArray pvFields = pImpl->pvFields;
|
||||
for(int i=0; i<numFields; i++) {
|
||||
PVField *pvField = pvFields[i];
|
||||
if(pvField->getFieldOffset()==fieldOffset) return pvField;
|
||||
if(pvField->getNextFieldOffset()<=fieldOffset) continue;
|
||||
if(pvField->getField()->getType()==structure) {
|
||||
return ((PVStructure*)pvField)->getSubField(fieldOffset);
|
||||
}
|
||||
}
|
||||
String message("PVStructure.getSubField: Logic error");
|
||||
throw std::logic_error(message);
|
||||
}
|
||||
|
||||
void PVStructure::appendPVField(PVFieldPtr pvField)
|
||||
{
|
||||
Structure::shared_pointer structure = const_pointer_cast<Structure>(getStructure());
|
||||
structure->appendField(pvField->getField());
|
||||
int origLength = pImpl->numberFields;
|
||||
PVFieldPtrArray oldPVFields = pImpl->pvFields;
|
||||
PVFieldPtrArray newPVFields = new PVFieldPtr[origLength + 1];
|
||||
for(int i=0; i<origLength; i++) {
|
||||
newPVFields[i] = oldPVFields[i];
|
||||
}
|
||||
// note that origLength IS new element
|
||||
newPVFields[origLength] = pvField;
|
||||
delete[] pImpl->pvFields;
|
||||
pImpl->pvFields = newPVFields;
|
||||
pImpl->numberFields = origLength + 1;
|
||||
}
|
||||
|
||||
void PVStructure::appendPVFields(int numberNewFields,PVFieldPtrArray pvFields)
|
||||
{
|
||||
if (numberNewFields<0)
|
||||
throw std::logic_error("Number of fields must be >=0");
|
||||
|
||||
Structure::shared_pointer structure = const_pointer_cast<Structure>(getStructure());
|
||||
std::vector<FieldConstPtr> fields(numberNewFields);
|
||||
for(int i=0; i<numberNewFields; i++) fields[i] = pvFields[i]->getField();
|
||||
structure->appendFields(numberNewFields,&fields[0]);
|
||||
int origLength = pImpl->numberFields;
|
||||
PVFieldPtrArray oldPVFields = pImpl->pvFields;
|
||||
int numberFields = origLength + numberNewFields;
|
||||
PVFieldPtrArray newPVFields = new PVFieldPtr[numberFields];
|
||||
for(int i=0; i<origLength; i++) {
|
||||
newPVFields[i] = oldPVFields[i];
|
||||
}
|
||||
for(int i=0; i<numberNewFields; i++) {
|
||||
newPVFields[i+origLength] = pvFields[i];
|
||||
}
|
||||
delete[] pImpl->pvFields;
|
||||
pImpl->pvFields = newPVFields;
|
||||
pImpl->numberFields = numberFields;
|
||||
}
|
||||
|
||||
void PVStructure::removePVField(String fieldName)
|
||||
{
|
||||
PVField *pvField = getSubField(fieldName);
|
||||
if(pvField==0) {
|
||||
String message("removePVField ");
|
||||
message += fieldName + " does not exist";
|
||||
this->message(message, errorMessage);
|
||||
return;
|
||||
}
|
||||
int origLength = pImpl->numberFields;
|
||||
int newLength = origLength - 1;
|
||||
PVFieldPtrArray origPVFields = pImpl->pvFields;
|
||||
PVFieldPtrArray newPVFields = new PVFieldPtr[newLength];
|
||||
int newIndex = 0;
|
||||
int indRemove = -1;
|
||||
for(int i=0; i<origLength; i++) {
|
||||
if(origPVFields[i]==pvField) {
|
||||
indRemove = i;
|
||||
} else {
|
||||
newPVFields[newIndex++] = origPVFields[i];
|
||||
}
|
||||
}
|
||||
Structure *structure = const_cast<Structure *>(getStructure().get());
|
||||
structure->removeField(indRemove);
|
||||
delete origPVFields[indRemove];
|
||||
delete[] pImpl->pvFields;
|
||||
pImpl->pvFields = newPVFields;
|
||||
pImpl->numberFields = newLength;
|
||||
}
|
||||
|
||||
PVBoolean *PVStructure::getBooleanField(String fieldName)
|
||||
{
|
||||
PVField *pvField = findSubField(fieldName,this);
|
||||
if(pvField==0) {
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not exist";
|
||||
this->message(message, errorMessage);
|
||||
return 0;
|
||||
}
|
||||
if(pvField->getField()->getType()==scalar) {
|
||||
ScalarConstPtr pscalar = static_pointer_cast<const Scalar>(
|
||||
pvField->getField());
|
||||
if(pscalar->getScalarType()==pvBoolean) {
|
||||
return (PVBoolean*)pvField;
|
||||
}
|
||||
}
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not have type boolean ";
|
||||
this->message(message, errorMessage);
|
||||
return 0;
|
||||
}
|
||||
|
||||
PVByte *PVStructure::getByteField(String fieldName)
|
||||
{
|
||||
PVField *pvField = findSubField(fieldName,this);
|
||||
if(pvField==0) {
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not exist";
|
||||
this->message(message, errorMessage);
|
||||
return 0;
|
||||
}
|
||||
if(pvField->getField()->getType()==scalar) {
|
||||
ScalarConstPtr pscalar = static_pointer_cast<const Scalar>(
|
||||
pvField->getField());
|
||||
if(pscalar->getScalarType()==pvByte) {
|
||||
return (PVByte*)pvField;
|
||||
}
|
||||
}
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not have type byte ";
|
||||
this->message(message, errorMessage);
|
||||
return 0;
|
||||
}
|
||||
|
||||
PVShort *PVStructure::getShortField(String fieldName)
|
||||
{
|
||||
PVField *pvField = findSubField(fieldName,this);
|
||||
if(pvField==0) {
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not exist";
|
||||
this->message(message, errorMessage);
|
||||
return 0;
|
||||
}
|
||||
if(pvField->getField()->getType()==scalar) {
|
||||
ScalarConstPtr pscalar = static_pointer_cast<const Scalar>(
|
||||
pvField->getField());
|
||||
if(pscalar->getScalarType()==pvShort) {
|
||||
return (PVShort*)pvField;
|
||||
}
|
||||
}
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not have type short ";
|
||||
this->message(message, errorMessage);
|
||||
return 0;
|
||||
}
|
||||
|
||||
PVInt *PVStructure::getIntField(String fieldName)
|
||||
{
|
||||
PVField *pvField = findSubField(fieldName,this);
|
||||
if(pvField==0) {
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not exist";
|
||||
this->message(message, errorMessage);
|
||||
return 0;
|
||||
}
|
||||
if(pvField->getField()->getType()==scalar) {
|
||||
ScalarConstPtr pscalar = static_pointer_cast<const Scalar>(
|
||||
pvField->getField());
|
||||
if(pscalar->getScalarType()==pvInt) {
|
||||
return (PVInt*)pvField;
|
||||
}
|
||||
}
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not have type int ";
|
||||
this->message(message, errorMessage);
|
||||
return 0;
|
||||
}
|
||||
|
||||
PVLong *PVStructure::getLongField(String fieldName)
|
||||
{
|
||||
PVField *pvField = findSubField(fieldName,this);
|
||||
if(pvField==0) {
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not exist";
|
||||
this->message(message, errorMessage);
|
||||
return 0;
|
||||
}
|
||||
if(pvField->getField()->getType()==scalar) {
|
||||
ScalarConstPtr pscalar = static_pointer_cast<const Scalar>(
|
||||
pvField->getField());
|
||||
if(pscalar->getScalarType()==pvLong) {
|
||||
return (PVLong*)pvField;
|
||||
}
|
||||
}
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not have type long ";
|
||||
this->message(message, errorMessage);
|
||||
return 0;
|
||||
}
|
||||
|
||||
PVFloat *PVStructure::getFloatField(String fieldName)
|
||||
{
|
||||
PVField *pvField = findSubField(fieldName,this);
|
||||
if(pvField==0) {
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not exist";
|
||||
this->message(message, errorMessage);
|
||||
return 0;
|
||||
}
|
||||
if(pvField->getField()->getType()==scalar) {
|
||||
ScalarConstPtr pscalar = static_pointer_cast<const Scalar>(
|
||||
pvField->getField());
|
||||
if(pscalar->getScalarType()==pvFloat) {
|
||||
return (PVFloat*)pvField;
|
||||
}
|
||||
}
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not have type float ";
|
||||
this->message(message, errorMessage);
|
||||
return 0;
|
||||
}
|
||||
|
||||
PVDouble *PVStructure::getDoubleField(String fieldName)
|
||||
{
|
||||
PVField *pvField = findSubField(fieldName,this);
|
||||
if(pvField==0) {
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not exist";
|
||||
this->message(message, errorMessage);
|
||||
return 0;
|
||||
}
|
||||
if(pvField->getField()->getType()==scalar) {
|
||||
ScalarConstPtr pscalar = static_pointer_cast<const Scalar>(
|
||||
pvField->getField());
|
||||
if(pscalar->getScalarType()==pvDouble) {
|
||||
return (PVDouble*)pvField;
|
||||
}
|
||||
}
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not have type double ";
|
||||
this->message(message, errorMessage);
|
||||
return 0;
|
||||
}
|
||||
|
||||
PVString *PVStructure::getStringField(String fieldName)
|
||||
{
|
||||
PVField *pvField = findSubField(fieldName,this);
|
||||
if(pvField==0) {
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not exist";
|
||||
this->message(message, errorMessage);
|
||||
return 0;
|
||||
}
|
||||
if(pvField->getField()->getType()==scalar) {
|
||||
ScalarConstPtr pscalar = static_pointer_cast<const Scalar>(
|
||||
pvField->getField());
|
||||
if(pscalar->getScalarType()==pvString) {
|
||||
return (PVString*)pvField;
|
||||
}
|
||||
}
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not have type string ";
|
||||
this->message(message, errorMessage);
|
||||
return 0;
|
||||
}
|
||||
|
||||
PVStructure *PVStructure::getStructureField(String fieldName)
|
||||
{
|
||||
PVField *pvField = findSubField(fieldName,this);
|
||||
if(pvField==0) {
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not exist";
|
||||
this->message(message, errorMessage);
|
||||
return 0;
|
||||
}
|
||||
if(pvField->getField()->getType()==structure) {
|
||||
return((PVStructure *)pvField);
|
||||
}
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not have type structure ";
|
||||
this->message(message, errorMessage);
|
||||
return 0;
|
||||
}
|
||||
|
||||
PVScalarArray *PVStructure::getScalarArrayField(
|
||||
String fieldName,ScalarType elementType)
|
||||
{
|
||||
PVField *pvField = findSubField(fieldName,this);
|
||||
if(pvField==0) {
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not exist";
|
||||
this->message(message, errorMessage);
|
||||
return 0;
|
||||
}
|
||||
FieldConstPtr field = pvField->getField();
|
||||
Type type = field->getType();
|
||||
if(type!=scalarArray) {
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not have type array ";
|
||||
this->message(message, errorMessage);
|
||||
return 0;
|
||||
}
|
||||
ScalarArrayConstPtr pscalarArray
|
||||
= static_pointer_cast<const ScalarArray>(pvField->getField());
|
||||
if(pscalarArray->getElementType()!=elementType) {
|
||||
String message("fieldName ");
|
||||
message += fieldName + " is array but does not have elementType ";
|
||||
ScalarTypeFunc::toString(&message,elementType);
|
||||
this->message(message, errorMessage);
|
||||
return 0;
|
||||
}
|
||||
return (PVScalarArray*)pvField;
|
||||
}
|
||||
|
||||
PVStructureArray *PVStructure::getStructureArrayField(
|
||||
String fieldName)
|
||||
{
|
||||
PVField *pvField = findSubField(fieldName,this);
|
||||
if(pvField==0) {
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not exist";
|
||||
this->message(message, errorMessage);
|
||||
return 0;
|
||||
}
|
||||
if(pvField->getField()->getType()==structureArray) {
|
||||
return((PVStructureArray *)pvField);
|
||||
}
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not have type structureArray ";
|
||||
this->message(message, errorMessage);
|
||||
return 0;
|
||||
}
|
||||
|
||||
String PVStructure::getExtendsStructureName()
|
||||
{
|
||||
return pImpl->extendsStructureName;
|
||||
}
|
||||
|
||||
bool PVStructure::putExtendsStructureName(
|
||||
String extendsStructureName)
|
||||
{
|
||||
if(pImpl->extendsStructureName.length()!=0) return false;
|
||||
pImpl->extendsStructureName = extendsStructureName;
|
||||
return true;
|
||||
}
|
||||
|
||||
void PVStructure::serialize(ByteBuffer *pbuffer,
|
||||
SerializableControl *pflusher) const {
|
||||
for(int i = 0; i<pImpl->numberFields; i++)
|
||||
pImpl->pvFields[i]->serialize(pbuffer, pflusher);
|
||||
}
|
||||
|
||||
void PVStructure::deserialize(ByteBuffer *pbuffer,
|
||||
DeserializableControl *pcontrol) {
|
||||
for(int i = 0; i<pImpl->numberFields; i++)
|
||||
pImpl->pvFields[i]->deserialize(pbuffer, pcontrol);
|
||||
|
||||
}
|
||||
|
||||
void PVStructure::serialize(ByteBuffer *pbuffer,
|
||||
SerializableControl *pflusher, BitSet *pbitSet) const {
|
||||
int offset = const_cast<PVStructure*>(this)->getFieldOffset();
|
||||
int numberFields = const_cast<PVStructure*>(this)->getNumberFields();
|
||||
int next = pbitSet->nextSetBit(offset);
|
||||
|
||||
// no more changes or no changes in this structure
|
||||
if(next<0||next>=offset+numberFields) return;
|
||||
|
||||
// entire structure
|
||||
if(offset==next) {
|
||||
serialize(pbuffer, pflusher);
|
||||
return;
|
||||
}
|
||||
|
||||
for(int i = 0; i<pImpl->numberFields; i++) {
|
||||
PVField* pvField = pImpl->pvFields[i];
|
||||
offset = pvField->getFieldOffset();
|
||||
numberFields = pvField->getNumberFields();
|
||||
next = pbitSet->nextSetBit(offset);
|
||||
// no more changes
|
||||
if(next<0) return;
|
||||
// no change in this pvField
|
||||
if(next>=offset+numberFields) continue;
|
||||
|
||||
// serialize field or fields
|
||||
if(numberFields==1)
|
||||
pvField->serialize(pbuffer, pflusher);
|
||||
else
|
||||
((PVStructure*)pvField)->serialize(pbuffer, pflusher,
|
||||
pbitSet);
|
||||
}
|
||||
}
|
||||
|
||||
void PVStructure::deserialize(ByteBuffer *pbuffer,
|
||||
DeserializableControl *pcontrol, BitSet *pbitSet) {
|
||||
int offset = getFieldOffset();
|
||||
int numberFields = getNumberFields();
|
||||
int next = pbitSet->nextSetBit(offset);
|
||||
|
||||
// no more changes or no changes in this structure
|
||||
if(next<0||next>=offset+numberFields) return;
|
||||
|
||||
// entire structure
|
||||
if(offset==next) {
|
||||
deserialize(pbuffer, pcontrol);
|
||||
return;
|
||||
}
|
||||
|
||||
for(int i = 0; i<pImpl->numberFields; i++) {
|
||||
PVField* pvField = pImpl->pvFields[i];
|
||||
offset = pvField->getFieldOffset();
|
||||
numberFields = pvField->getNumberFields();
|
||||
next = pbitSet->nextSetBit(offset);
|
||||
// no more changes
|
||||
if(next<0) return;
|
||||
// no change in this pvField
|
||||
if(next>=offset+numberFields) continue;
|
||||
|
||||
// deserialize field or fields
|
||||
if(numberFields==1)
|
||||
pvField->deserialize(pbuffer, pcontrol);
|
||||
else
|
||||
((PVStructure*)pvField)->deserialize(pbuffer, pcontrol,
|
||||
pbitSet);
|
||||
}
|
||||
}
|
||||
|
||||
static PVField *findSubField(String fieldName,PVStructure *pvStructure) {
|
||||
if( fieldName.length()<1) return 0;
|
||||
String::size_type index = fieldName.find('.');
|
||||
String name = fieldName;
|
||||
String restOfName = String();
|
||||
if(index>0) {
|
||||
name = fieldName.substr(0, index);
|
||||
if(fieldName.length()>index) {
|
||||
restOfName = fieldName.substr(index+1);
|
||||
}
|
||||
}
|
||||
PVFieldPtrArray pvFields = pvStructure->getPVFields();
|
||||
PVField *pvField = 0;
|
||||
int numFields = pvStructure->getStructure()->getNumberFields();
|
||||
for(int i=0; i<numFields; i++) {
|
||||
PVField *pvf = pvFields[i];
|
||||
int result = pvf->getField()->getFieldName().compare(name);
|
||||
if(result==0) {
|
||||
pvField = pvf;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(pvField==0) return 0;
|
||||
if(restOfName.length()==0) return pvField;
|
||||
if(pvField->getField()->getType()!=structure) return 0;
|
||||
return findSubField(restOfName,(PVStructure*)pvField);
|
||||
}
|
||||
|
||||
}}
|
||||
@@ -1,501 +0,0 @@
|
||||
/* StandardField.cpp */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <stdexcept>
|
||||
#include <epicsThread.h>
|
||||
#include <epicsExit.h>
|
||||
#include <pv/lock.h>
|
||||
#include <pv/pvIntrospect.h>
|
||||
#include <pv/standardField.h>
|
||||
#include <pv/CDRMonitor.h>
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
static StandardField* standardField = 0;
|
||||
|
||||
static String notImplemented("not implemented");
|
||||
static FieldCreate* fieldCreate = 0;
|
||||
static String valueFieldName("value");
|
||||
|
||||
// following are preallocated structures
|
||||
|
||||
static StructureConstPtr alarmField;
|
||||
static StructureConstPtr timeStampField;
|
||||
static StructureConstPtr displayField;
|
||||
static StructureConstPtr controlField;
|
||||
static StructureConstPtr booleanAlarmField;
|
||||
static StructureConstPtr byteAlarmField;
|
||||
static StructureConstPtr shortAlarmField;
|
||||
static StructureConstPtr intAlarmField;
|
||||
static StructureConstPtr longAlarmField;
|
||||
static StructureConstPtr floatAlarmField;
|
||||
static StructureConstPtr doubleAlarmField;
|
||||
static StructureConstPtr enumeratedAlarmField;
|
||||
|
||||
|
||||
static void createAlarm() {
|
||||
FieldConstPtrArray fields = new FieldConstPtr[3];
|
||||
fields[0] = fieldCreate->createScalar(String("severity"),pvInt);
|
||||
fields[1] = fieldCreate->createScalar(String("status"),pvInt);
|
||||
fields[2] = fieldCreate->createScalar(String("message"),pvString);
|
||||
alarmField = fieldCreate->createStructure(String("alarm"),3,fields);
|
||||
}
|
||||
|
||||
static void createTimeStamp() {
|
||||
FieldConstPtrArray fields = new FieldConstPtr[3];
|
||||
fields[0] = fieldCreate->createScalar(String("secondsPastEpoch"),pvLong);
|
||||
fields[1] = fieldCreate->createScalar(String("nanoSeconds"),pvInt);
|
||||
fields[2] = fieldCreate->createScalar(String("userTag"),pvInt);
|
||||
timeStampField = fieldCreate->createStructure(String("timeStamp"),3,fields);
|
||||
}
|
||||
|
||||
static void createDisplay() {
|
||||
FieldConstPtrArray limitFields = new FieldConstPtr[2];
|
||||
limitFields[0] = fieldCreate->createScalar(String("low"),pvDouble);
|
||||
limitFields[1] = fieldCreate->createScalar(String("high"),pvDouble);
|
||||
FieldConstPtrArray fields = new FieldConstPtr[4];
|
||||
fields[0] = fieldCreate->createScalar(String("description"),pvString);
|
||||
fields[1] = fieldCreate->createScalar(String("format"),pvString);
|
||||
fields[2] = fieldCreate->createScalar(String("units"),pvString);
|
||||
fields[3] = fieldCreate->createStructure(String("limit"),2,limitFields);
|
||||
displayField = fieldCreate->createStructure(String("display"),4,fields);
|
||||
}
|
||||
|
||||
static void createControl() {
|
||||
FieldConstPtrArray limitFields = new FieldConstPtr[2];
|
||||
limitFields[0] = fieldCreate->createScalar(String("low"),pvDouble);
|
||||
limitFields[1] = fieldCreate->createScalar(String("high"),pvDouble);
|
||||
FieldConstPtrArray fields = new FieldConstPtr[2];
|
||||
fields[0] = fieldCreate->createStructure(String("limit"),2,limitFields);
|
||||
fields[1] = fieldCreate->createScalar(String("minStep"),pvDouble);
|
||||
controlField = fieldCreate->createStructure(String("control"),2,fields);
|
||||
}
|
||||
|
||||
static void createBooleanAlarm() {
|
||||
FieldConstPtrArray fields = new FieldConstPtr[4];
|
||||
fields[0] = fieldCreate->createScalar(String("active"),pvBoolean);
|
||||
fields[1] = fieldCreate->createScalar(String("falseSeverity"),pvInt);
|
||||
fields[2] = fieldCreate->createScalar(String("trueSeverity"),pvInt);
|
||||
fields[3] = fieldCreate->createScalar(String("changeStateSeverity"),pvInt);
|
||||
booleanAlarmField = fieldCreate->createStructure(String("valueAlarm"),4,fields);
|
||||
}
|
||||
|
||||
static void createByteAlarm() {
|
||||
int numFields = 10;
|
||||
FieldConstPtrArray fields = new FieldConstPtr[numFields];
|
||||
fields[0] = fieldCreate->createScalar(String("active"),pvBoolean);
|
||||
fields[1] = fieldCreate->createScalar(String("lowAlarmLimit"),pvByte);
|
||||
fields[2] = fieldCreate->createScalar(String("lowWarningLimit"),pvByte);
|
||||
fields[3] = fieldCreate->createScalar(String("highWarningLimit"),pvByte);
|
||||
fields[4] = fieldCreate->createScalar(String("highAlarmLimit"),pvByte);
|
||||
fields[5] = fieldCreate->createScalar(String("lowAlarmSeverity"),pvInt);
|
||||
fields[6] = fieldCreate->createScalar(String("lowWarningSeverity"),pvInt);
|
||||
fields[7] = fieldCreate->createScalar(String("highWarningSeverity"),pvInt);
|
||||
fields[8] = fieldCreate->createScalar(String("highAlarmSeverity"),pvInt);
|
||||
fields[9] = fieldCreate->createScalar(String("hystersis"),pvByte);
|
||||
byteAlarmField = fieldCreate->createStructure(String("valueAlarm"),numFields,fields);
|
||||
}
|
||||
|
||||
static void createShortAlarm() {
|
||||
int numFields = 10;
|
||||
FieldConstPtrArray fields = new FieldConstPtr[numFields];
|
||||
fields[0] = fieldCreate->createScalar(String("active"),pvBoolean);
|
||||
fields[1] = fieldCreate->createScalar(String("lowAlarmLimit"),pvShort);
|
||||
fields[2] = fieldCreate->createScalar(String("lowWarningLimit"),pvShort);
|
||||
fields[3] = fieldCreate->createScalar(String("highWarningLimit"),pvShort);
|
||||
fields[4] = fieldCreate->createScalar(String("highAlarmLimit"),pvShort);
|
||||
fields[5] = fieldCreate->createScalar(String("lowAlarmSeverity"),pvInt);
|
||||
fields[6] = fieldCreate->createScalar(String("lowWarningSeverity"),pvInt);
|
||||
fields[7] = fieldCreate->createScalar(String("highWarningSeverity"),pvInt);
|
||||
fields[8] = fieldCreate->createScalar(String("highAlarmSeverity"),pvInt);
|
||||
fields[9] = fieldCreate->createScalar(String("hystersis"),pvShort);
|
||||
shortAlarmField = fieldCreate->createStructure(String("valueAlarm"),numFields,fields);
|
||||
}
|
||||
|
||||
static void createIntAlarm() {
|
||||
int numFields = 10;
|
||||
FieldConstPtrArray fields = new FieldConstPtr[numFields];
|
||||
fields[0] = fieldCreate->createScalar(String("active"),pvBoolean);
|
||||
fields[1] = fieldCreate->createScalar(String("lowAlarmLimit"),pvInt);
|
||||
fields[2] = fieldCreate->createScalar(String("lowWarningLimit"),pvInt);
|
||||
fields[3] = fieldCreate->createScalar(String("highWarningLimit"),pvInt);
|
||||
fields[4] = fieldCreate->createScalar(String("highAlarmLimit"),pvInt);
|
||||
fields[5] = fieldCreate->createScalar(String("lowAlarmSeverity"),pvInt);
|
||||
fields[6] = fieldCreate->createScalar(String("lowWarningSeverity"),pvInt);
|
||||
fields[7] = fieldCreate->createScalar(String("highWarningSeverity"),pvInt);
|
||||
fields[8] = fieldCreate->createScalar(String("highAlarmSeverity"),pvInt);
|
||||
fields[9] = fieldCreate->createScalar(String("hystersis"),pvInt);
|
||||
intAlarmField = fieldCreate->createStructure(String("valueAlarm"),numFields,fields);
|
||||
}
|
||||
|
||||
static void createLongAlarm() {
|
||||
int numFields = 10;
|
||||
FieldConstPtrArray fields = new FieldConstPtr[numFields];
|
||||
fields[0] = fieldCreate->createScalar(String("active"),pvBoolean);
|
||||
fields[1] = fieldCreate->createScalar(String("lowAlarmLimit"),pvLong);
|
||||
fields[2] = fieldCreate->createScalar(String("lowWarningLimit"),pvLong);
|
||||
fields[3] = fieldCreate->createScalar(String("highWarningLimit"),pvLong);
|
||||
fields[4] = fieldCreate->createScalar(String("highAlarmLimit"),pvLong);
|
||||
fields[5] = fieldCreate->createScalar(String("lowAlarmSeverity"),pvInt);
|
||||
fields[6] = fieldCreate->createScalar(String("lowWarningSeverity"),pvInt);
|
||||
fields[7] = fieldCreate->createScalar(String("highWarningSeverity"),pvInt);
|
||||
fields[8] = fieldCreate->createScalar(String("highAlarmSeverity"),pvInt);
|
||||
fields[9] = fieldCreate->createScalar(String("hystersis"),pvLong);
|
||||
longAlarmField = fieldCreate->createStructure(String("valueAlarm"),numFields,fields);
|
||||
}
|
||||
|
||||
static void createFloatAlarm() {
|
||||
int numFields = 10;
|
||||
FieldConstPtrArray fields = new FieldConstPtr[numFields];
|
||||
fields[0] = fieldCreate->createScalar(String("active"),pvBoolean);
|
||||
fields[1] = fieldCreate->createScalar(String("lowAlarmLimit"),pvFloat);
|
||||
fields[2] = fieldCreate->createScalar(String("lowWarningLimit"),pvFloat);
|
||||
fields[3] = fieldCreate->createScalar(String("highWarningLimit"),pvFloat);
|
||||
fields[4] = fieldCreate->createScalar(String("highAlarmLimit"),pvFloat);
|
||||
fields[5] = fieldCreate->createScalar(String("lowAlarmSeverity"),pvInt);
|
||||
fields[6] = fieldCreate->createScalar(String("lowWarningSeverity"),pvInt);
|
||||
fields[7] = fieldCreate->createScalar(String("highWarningSeverity"),pvInt);
|
||||
fields[8] = fieldCreate->createScalar(String("highAlarmSeverity"),pvInt);
|
||||
fields[9] = fieldCreate->createScalar(String("hystersis"),pvFloat);
|
||||
floatAlarmField = fieldCreate->createStructure(String("valueAlarm"),numFields,fields);
|
||||
}
|
||||
|
||||
static void createDoubleAlarm() {
|
||||
int numFields = 10;
|
||||
FieldConstPtrArray fields = new FieldConstPtr[numFields];
|
||||
fields[0] = fieldCreate->createScalar(String("active"),pvBoolean);
|
||||
fields[1] = fieldCreate->createScalar(String("lowAlarmLimit"),pvDouble);
|
||||
fields[2] = fieldCreate->createScalar(String("lowWarningLimit"),pvDouble);
|
||||
fields[3] = fieldCreate->createScalar(String("highWarningLimit"),pvDouble);
|
||||
fields[4] = fieldCreate->createScalar(String("highAlarmLimit"),pvDouble);
|
||||
fields[5] = fieldCreate->createScalar(String("lowAlarmSeverity"),pvInt);
|
||||
fields[6] = fieldCreate->createScalar(String("lowWarningSeverity"),pvInt);
|
||||
fields[7] = fieldCreate->createScalar(String("highWarningSeverity"),pvInt);
|
||||
fields[8] = fieldCreate->createScalar(String("highAlarmSeverity"),pvInt);
|
||||
fields[9] = fieldCreate->createScalar(String("hystersis"),pvDouble);
|
||||
doubleAlarmField = fieldCreate->createStructure(String("valueAlarm"),numFields,fields);
|
||||
}
|
||||
|
||||
static void createEnumeratedAlarm() {
|
||||
int numFields = 3;
|
||||
FieldConstPtrArray fields = new FieldConstPtr[numFields];
|
||||
fields[0] = fieldCreate->createScalar(String("active"),pvBoolean);
|
||||
fields[1] = fieldCreate->createScalar(String("stateSeverity"),pvInt);
|
||||
fields[2] = fieldCreate->createScalar(String("changeStateSeverity"),pvInt);
|
||||
enumeratedAlarmField = fieldCreate->createStructure(String("valueAlarm"),numFields,fields);
|
||||
}
|
||||
|
||||
static StructureConstPtr createProperties(String fieldName,FieldConstPtr field,String properties) {
|
||||
bool gotAlarm = false;
|
||||
bool gotTimeStamp = false;
|
||||
bool gotDisplay = false;
|
||||
bool gotControl = false;
|
||||
bool gotValueAlarm = false;
|
||||
int numProp = 0;
|
||||
if(properties.find("alarm")!=String::npos) { gotAlarm = true; numProp++; }
|
||||
if(properties.find("timeStamp")!=String::npos) { gotTimeStamp = true; numProp++; }
|
||||
if(properties.find("display")!=String::npos) { gotDisplay = true; numProp++; }
|
||||
if(properties.find("control")!=String::npos) { gotControl = true; numProp++; }
|
||||
if(properties.find("valueAlarm")!=String::npos) { gotValueAlarm = true; numProp++; }
|
||||
StructureConstPtr valueAlarm;
|
||||
Type type= field->getType();
|
||||
while(gotValueAlarm) {
|
||||
if(type==scalar) {
|
||||
ScalarConstPtr scalar = static_pointer_cast<const Scalar>(field);
|
||||
ScalarType scalarType = scalar->getScalarType();
|
||||
switch(scalarType) {
|
||||
case pvBoolean: valueAlarm = booleanAlarmField; break;
|
||||
case pvByte: valueAlarm = byteAlarmField; break;
|
||||
case pvShort: valueAlarm = shortAlarmField; break;
|
||||
case pvInt: valueAlarm = intAlarmField; break;
|
||||
case pvLong: valueAlarm = longAlarmField; break;
|
||||
case pvFloat: valueAlarm = floatAlarmField; break;
|
||||
case pvDouble: valueAlarm = doubleAlarmField; break;
|
||||
default:
|
||||
throw std::logic_error(String("valueAlarm property for illegal type"));
|
||||
}
|
||||
break;
|
||||
}
|
||||
if(type==structure) {
|
||||
StructureConstPtr structurePtr = static_pointer_cast<const Structure>(field);
|
||||
if(structurePtr->getNumberFields()==2) {
|
||||
FieldConstPtrArray fields = structurePtr->getFields();
|
||||
FieldConstPtr first = fields[0];
|
||||
FieldConstPtr second = fields[1];
|
||||
String nameFirst = first->getFieldName();
|
||||
String nameSecond = second->getFieldName();
|
||||
int compareFirst = nameFirst.compare("index");
|
||||
int compareSecond = nameSecond.compare("choices");
|
||||
if(compareFirst==0 && compareSecond==0) {
|
||||
if(first->getType()==scalar
|
||||
&& second->getType()==scalarArray) {
|
||||
ScalarConstPtr scalarFirst = static_pointer_cast<const Scalar>(first);
|
||||
ScalarArrayConstPtr scalarArraySecond =
|
||||
static_pointer_cast<const ScalarArray>(second);
|
||||
if(scalarFirst->getScalarType()==pvInt
|
||||
&& scalarArraySecond->getElementType()==pvString) {
|
||||
valueAlarm = enumeratedAlarmField;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
throw std::logic_error(String("valueAlarm property for illegal type"));
|
||||
}
|
||||
int numFields = numProp+1;
|
||||
FieldConstPtrArray fields = new FieldConstPtr[numFields];
|
||||
int next = 0;
|
||||
fields[next++] = field;
|
||||
if(gotAlarm) {fields[next++] = alarmField;}
|
||||
if(gotTimeStamp) {fields[next++] = timeStampField;}
|
||||
if(gotDisplay) {fields[next++] = displayField;}
|
||||
if(gotControl) {fields[next++] = controlField;}
|
||||
if(gotValueAlarm) {fields[next++] = valueAlarm;}
|
||||
return fieldCreate->createStructure(fieldName,numFields,fields);
|
||||
}
|
||||
|
||||
|
||||
ScalarConstPtr StandardField::scalar(String fieldName,ScalarType type)
|
||||
{
|
||||
return fieldCreate->createScalar(fieldName,type);
|
||||
}
|
||||
|
||||
StructureConstPtr StandardField::scalar(
|
||||
String fieldName,ScalarType type,String properties)
|
||||
{
|
||||
ScalarConstPtr field = fieldCreate->createScalar(valueFieldName,type);
|
||||
return createProperties(fieldName,field,properties);
|
||||
}
|
||||
|
||||
ScalarArrayConstPtr StandardField::scalarArray(
|
||||
String fieldName,ScalarType elementType)
|
||||
{
|
||||
return fieldCreate->createScalarArray(fieldName,elementType);
|
||||
}
|
||||
|
||||
StructureConstPtr StandardField::scalarArray(
|
||||
String fieldName,ScalarType elementType, String properties)
|
||||
{
|
||||
ScalarArrayConstPtr field = fieldCreate->createScalarArray(
|
||||
valueFieldName,elementType);
|
||||
return createProperties(fieldName,field,properties);
|
||||
}
|
||||
|
||||
StructureArrayConstPtr StandardField::structureArray(
|
||||
String fieldName,StructureConstPtr structure)
|
||||
{
|
||||
return fieldCreate->createStructureArray(fieldName,structure);
|
||||
}
|
||||
|
||||
StructureConstPtr StandardField::structureArray(
|
||||
String fieldName,StructureConstPtr structure,String properties)
|
||||
{
|
||||
StructureArrayConstPtr field = fieldCreate->createStructureArray(
|
||||
valueFieldName,structure);
|
||||
return createProperties(fieldName,field,properties);
|
||||
}
|
||||
|
||||
StructureConstPtr StandardField::structure(
|
||||
String fieldName,int numFields,FieldConstPtrArray fields)
|
||||
{
|
||||
return fieldCreate->createStructure(fieldName,numFields,fields);
|
||||
}
|
||||
|
||||
StructureConstPtr StandardField::enumerated(String fieldName)
|
||||
{
|
||||
FieldConstPtrArray fields = new FieldConstPtr[2];
|
||||
fields[0] = fieldCreate->createScalar(String("index"),pvInt);
|
||||
fields[1] = fieldCreate->createScalarArray(String("choices"),pvString);
|
||||
return fieldCreate->createStructure(fieldName,2,fields);
|
||||
}
|
||||
|
||||
StructureConstPtr StandardField::enumerated(
|
||||
String fieldName,String properties)
|
||||
{
|
||||
StructureConstPtr field = standardField->enumerated(valueFieldName);
|
||||
return createProperties(fieldName,field,properties);
|
||||
}
|
||||
|
||||
ScalarConstPtr StandardField::scalarValue(ScalarType type)
|
||||
{
|
||||
return fieldCreate->createScalar(valueFieldName,type);
|
||||
}
|
||||
|
||||
StructureConstPtr StandardField::scalarValue(ScalarType type,String properties)
|
||||
{
|
||||
ScalarConstPtr field = fieldCreate->createScalar(valueFieldName,type);
|
||||
return createProperties(valueFieldName,field,properties);
|
||||
}
|
||||
|
||||
ScalarArrayConstPtr StandardField::scalarArrayValue(ScalarType elementType)
|
||||
{
|
||||
return fieldCreate->createScalarArray(valueFieldName,elementType);
|
||||
}
|
||||
|
||||
StructureConstPtr StandardField::scalarArrayValue(
|
||||
ScalarType elementType, String properties)
|
||||
{
|
||||
ScalarArrayConstPtr field = fieldCreate->createScalarArray(
|
||||
valueFieldName,elementType);
|
||||
return createProperties(valueFieldName,field,properties);
|
||||
|
||||
}
|
||||
|
||||
StructureArrayConstPtr StandardField::structureArrayValue(
|
||||
StructureConstPtr structure)
|
||||
{
|
||||
return fieldCreate->createStructureArray(valueFieldName,structure);
|
||||
}
|
||||
|
||||
StructureConstPtr StandardField::structureArrayValue(
|
||||
StructureConstPtr structure,String properties)
|
||||
{
|
||||
StructureArrayConstPtr field = fieldCreate->createStructureArray(
|
||||
valueFieldName,structure);
|
||||
return createProperties(valueFieldName,field,properties);
|
||||
|
||||
}
|
||||
|
||||
StructureConstPtr StandardField::structureValue(
|
||||
int numFields,FieldConstPtrArray fields)
|
||||
{
|
||||
return fieldCreate->createStructure(valueFieldName,numFields,fields);
|
||||
}
|
||||
|
||||
StructureConstPtr StandardField::enumeratedValue()
|
||||
{
|
||||
FieldConstPtrArray fields = new FieldConstPtr[2];
|
||||
fields[0] = fieldCreate->createScalar(String("index"),pvInt);
|
||||
fields[1] = fieldCreate->createScalarArray(String("choices"),pvString);
|
||||
return fieldCreate->createStructure(valueFieldName,2,fields);
|
||||
}
|
||||
|
||||
StructureConstPtr StandardField::enumeratedValue( String properties)
|
||||
{
|
||||
StructureConstPtr field = standardField->enumerated(valueFieldName);
|
||||
return createProperties(valueFieldName,field,properties);
|
||||
}
|
||||
|
||||
StructureConstPtr StandardField::alarm()
|
||||
{
|
||||
return alarmField;
|
||||
}
|
||||
|
||||
StructureConstPtr StandardField::timeStamp()
|
||||
{
|
||||
return timeStampField;
|
||||
}
|
||||
|
||||
StructureConstPtr StandardField::display()
|
||||
{
|
||||
return displayField;
|
||||
}
|
||||
|
||||
StructureConstPtr StandardField::control()
|
||||
{
|
||||
return controlField;
|
||||
}
|
||||
|
||||
StructureConstPtr StandardField::booleanAlarm()
|
||||
{
|
||||
return booleanAlarmField;
|
||||
}
|
||||
|
||||
StructureConstPtr StandardField::byteAlarm()
|
||||
{
|
||||
return byteAlarmField;
|
||||
}
|
||||
|
||||
StructureConstPtr StandardField::shortAlarm()
|
||||
{
|
||||
return shortAlarmField;
|
||||
}
|
||||
|
||||
StructureConstPtr StandardField::intAlarm()
|
||||
{
|
||||
return intAlarmField;
|
||||
}
|
||||
|
||||
StructureConstPtr StandardField::longAlarm()
|
||||
{
|
||||
return longAlarmField;
|
||||
}
|
||||
|
||||
StructureConstPtr StandardField::floatAlarm()
|
||||
{
|
||||
return floatAlarmField;
|
||||
}
|
||||
|
||||
StructureConstPtr StandardField::doubleAlarm()
|
||||
{
|
||||
return doubleAlarmField;
|
||||
}
|
||||
|
||||
StructureConstPtr StandardField::enumeratedAlarm()
|
||||
{
|
||||
return enumeratedAlarmField;
|
||||
}
|
||||
|
||||
void StandardField::init()
|
||||
{
|
||||
createAlarm();
|
||||
createTimeStamp();
|
||||
createDisplay();
|
||||
createControl();
|
||||
createBooleanAlarm();
|
||||
createByteAlarm();
|
||||
createShortAlarm();
|
||||
createIntAlarm();
|
||||
createLongAlarm();
|
||||
createFloatAlarm();
|
||||
createDoubleAlarm();
|
||||
createEnumeratedAlarm();
|
||||
}
|
||||
|
||||
|
||||
StandardField::StandardField(){init();}
|
||||
|
||||
StandardField::~StandardField(){
|
||||
}
|
||||
|
||||
static void myDeleteStatic(void*)
|
||||
{
|
||||
alarmField.reset();
|
||||
timeStampField.reset();
|
||||
displayField.reset();
|
||||
controlField.reset();
|
||||
booleanAlarmField.reset();
|
||||
byteAlarmField.reset();
|
||||
shortAlarmField.reset();
|
||||
intAlarmField.reset();
|
||||
longAlarmField.reset();
|
||||
floatAlarmField.reset();
|
||||
doubleAlarmField.reset();
|
||||
enumeratedAlarmField.reset();
|
||||
|
||||
}
|
||||
|
||||
static void myInitStatic(void*)
|
||||
{
|
||||
standardField = new StandardField();
|
||||
fieldCreate = getFieldCreate();
|
||||
epicsAtExit(&myDeleteStatic,0);
|
||||
}
|
||||
|
||||
static
|
||||
epicsThreadOnceId myInitOnce = EPICS_THREAD_ONCE_INIT;
|
||||
|
||||
StandardField * getStandardField() {
|
||||
epicsThreadOnce(&myInitOnce,&myInitStatic,0);
|
||||
return standardField;
|
||||
}
|
||||
|
||||
}}
|
||||
@@ -1,353 +0,0 @@
|
||||
/* StandardPVField.cpp */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <epicsThread.h>
|
||||
#include <epicsExit.h>
|
||||
#include <pv/lock.h>
|
||||
#include <pv/pvIntrospect.h>
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/convert.h>
|
||||
#include <pv/standardField.h>
|
||||
#include <pv/standardPVField.h>
|
||||
#include <pv/CDRMonitor.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
static StandardField *standardField = 0;
|
||||
|
||||
static String notImplemented("not implemented");
|
||||
static FieldCreate* fieldCreate = 0;
|
||||
static PVDataCreate* pvDataCreate = 0;
|
||||
static StandardPVField *standardPVField = 0;
|
||||
|
||||
static void addExtendsStructureName(PVStructure *pvStructure,String properties)
|
||||
{
|
||||
bool gotAlarm = false;
|
||||
bool gotTimeStamp = false;
|
||||
bool gotDisplay = false;
|
||||
bool gotControl = false;
|
||||
if(properties.find("alarm")!=String::npos) gotAlarm = true;
|
||||
if(properties.find("timeStamp")!=String::npos) gotTimeStamp = true;
|
||||
if(properties.find("display")!=String::npos) gotDisplay = true;
|
||||
if(properties.find("control")!=String::npos) gotControl = true;
|
||||
if(gotAlarm) {
|
||||
PVStructure *pv = pvStructure->getStructureField(String("alarm"));
|
||||
if(pv!=0) pv->putExtendsStructureName(String("alarm"));
|
||||
}
|
||||
if(gotTimeStamp) {
|
||||
PVStructure *pv = pvStructure->getStructureField(String("timeStamp"));
|
||||
if(pv!=0) pv->putExtendsStructureName(String("timeStamp"));
|
||||
}
|
||||
if(gotDisplay) {
|
||||
PVStructure *pv = pvStructure->getStructureField(String("display"));
|
||||
if(pv!=0) pv->putExtendsStructureName(String("display"));
|
||||
}
|
||||
if(gotControl) {
|
||||
PVStructure *pv = pvStructure->getStructureField(String("control"));
|
||||
if(pv!=0) pv->putExtendsStructureName(String("control"));
|
||||
}
|
||||
}
|
||||
|
||||
StandardPVField::StandardPVField(){}
|
||||
|
||||
StandardPVField::~StandardPVField(){}
|
||||
|
||||
|
||||
PVScalar * StandardPVField::scalar(PVStructure *parent,
|
||||
String fieldName,ScalarType type)
|
||||
{
|
||||
ScalarConstPtr field = standardField->scalar(fieldName,type);
|
||||
return pvDataCreate->createPVScalar(parent,field);
|
||||
}
|
||||
|
||||
PVStructure * StandardPVField::scalar(PVStructure *parent,
|
||||
String fieldName,ScalarType type,String properties)
|
||||
{
|
||||
StructureConstPtr field = standardField->scalar(fieldName,type,properties);
|
||||
PVStructure * pvStructure = pvDataCreate->createPVStructure(parent,field);
|
||||
addExtendsStructureName(pvStructure,properties);
|
||||
return pvStructure;
|
||||
}
|
||||
|
||||
PVScalarArray * StandardPVField::scalarArray(PVStructure *parent,
|
||||
String fieldName,ScalarType elementType)
|
||||
{
|
||||
ScalarArrayConstPtr field = standardField->scalarArray(
|
||||
fieldName,elementType);
|
||||
return pvDataCreate->createPVScalarArray(parent,field);
|
||||
}
|
||||
|
||||
PVStructure * StandardPVField::scalarArray(PVStructure *parent,
|
||||
String fieldName,ScalarType elementType, String properties)
|
||||
{
|
||||
StructureConstPtr field = standardField->scalarArray(
|
||||
fieldName,elementType,properties);
|
||||
PVStructure * pvStructure = pvDataCreate->createPVStructure(parent,field);
|
||||
addExtendsStructureName(pvStructure,properties);
|
||||
return pvStructure;
|
||||
}
|
||||
|
||||
PVStructureArray * StandardPVField::structureArray(PVStructure *parent,
|
||||
String fieldName,StructureConstPtr structure)
|
||||
{
|
||||
StructureArrayConstPtr field = standardField->structureArray(
|
||||
fieldName,structure);
|
||||
return pvDataCreate->createPVStructureArray(parent,field);
|
||||
}
|
||||
|
||||
PVStructure* StandardPVField::structureArray(PVStructure *parent,
|
||||
String fieldName,StructureConstPtr structure,String properties)
|
||||
{
|
||||
StructureConstPtr field = standardField->structureArray(
|
||||
fieldName,structure,properties);
|
||||
PVStructure * pvStructure = pvDataCreate->createPVStructure(parent,field);
|
||||
addExtendsStructureName(pvStructure,properties);
|
||||
return pvStructure;
|
||||
}
|
||||
|
||||
PVStructure * StandardPVField::enumerated(PVStructure *parent,
|
||||
String fieldName,StringArray choices,int number)
|
||||
{
|
||||
StructureConstPtr field = standardField->enumerated(fieldName);
|
||||
PVStructure *pvStructure = pvDataCreate->createPVStructure(parent,field);
|
||||
PVScalarArray *pvScalarArray = pvStructure->getScalarArrayField(
|
||||
"choices",pvString);
|
||||
if(pvScalarArray==0) {
|
||||
throw std::logic_error(String("StandardPVField::enumerated"));
|
||||
}
|
||||
PVStringArray *pvChoices = static_cast<PVStringArray *>(pvScalarArray);
|
||||
pvChoices->put(0,number,choices,0);
|
||||
return pvStructure;
|
||||
}
|
||||
|
||||
PVStructure * StandardPVField::enumerated(PVStructure *parent,
|
||||
String fieldName,StringArray choices,int number, String properties)
|
||||
{
|
||||
StructureConstPtr field = standardField->enumerated(
|
||||
fieldName,properties);
|
||||
PVStructure *pvStructure = pvDataCreate->createPVStructure(parent,field);
|
||||
addExtendsStructureName(pvStructure,properties);
|
||||
PVScalarArray *pvScalarArray = pvStructure->getScalarArrayField(
|
||||
fieldName += ".choices",pvString);
|
||||
if(pvScalarArray==0) {
|
||||
throw std::logic_error(String("StandardPVField::enumerated"));
|
||||
}
|
||||
PVStringArray *pvChoices = static_cast<PVStringArray *>(pvScalarArray);
|
||||
pvChoices->put(0,number,choices,0);
|
||||
return pvStructure;
|
||||
}
|
||||
|
||||
PVScalar * StandardPVField::scalarValue(PVStructure *parent,
|
||||
ScalarType scalarType)
|
||||
{
|
||||
ScalarConstPtr field = standardField->scalarValue(scalarType);
|
||||
return pvDataCreate->createPVScalar(parent,field);
|
||||
}
|
||||
|
||||
PVStructure * StandardPVField::scalarValue(PVStructure *parent,
|
||||
ScalarType type,String properties)
|
||||
{
|
||||
StructureConstPtr field = standardField->scalarValue(type,properties);
|
||||
PVStructure * pvStructure = pvDataCreate->createPVStructure(parent,field);
|
||||
addExtendsStructureName(pvStructure,properties);
|
||||
return pvStructure;
|
||||
}
|
||||
|
||||
PVScalarArray * StandardPVField::scalarArrayValue(PVStructure *parent,
|
||||
ScalarType elementType)
|
||||
{
|
||||
ScalarArrayConstPtr scalarArray =
|
||||
standardField->scalarArrayValue(elementType);
|
||||
return pvDataCreate->createPVScalarArray(0,scalarArray);
|
||||
}
|
||||
|
||||
PVStructure * StandardPVField::scalarArrayValue(PVStructure *parent,
|
||||
ScalarType elementType, String properties)
|
||||
{
|
||||
StructureConstPtr field = standardField->scalarArrayValue(
|
||||
elementType,properties);
|
||||
PVStructure * pvStructure = pvDataCreate->createPVStructure(parent,field);
|
||||
addExtendsStructureName(pvStructure,properties);
|
||||
return pvStructure;
|
||||
}
|
||||
|
||||
PVStructureArray * StandardPVField::structureArrayValue(PVStructure *parent,
|
||||
StructureConstPtr structure)
|
||||
{
|
||||
StructureArrayConstPtr field = standardField->structureArrayValue(
|
||||
structure);
|
||||
return pvDataCreate->createPVStructureArray(parent,field);
|
||||
}
|
||||
|
||||
PVStructure * StandardPVField::structureArrayValue(PVStructure *parent,
|
||||
StructureConstPtr structure,String properties)
|
||||
{
|
||||
StructureConstPtr field = standardField->structureArrayValue(
|
||||
structure,properties);
|
||||
PVStructure * pvStructure = pvDataCreate->createPVStructure(parent,field);
|
||||
addExtendsStructureName(pvStructure,properties);
|
||||
return pvStructure;
|
||||
}
|
||||
|
||||
PVStructure * StandardPVField::enumeratedValue(PVStructure *parent,
|
||||
StringArray choices,int number)
|
||||
{
|
||||
StructureConstPtr field = standardField->enumeratedValue();
|
||||
PVStructure *pvStructure = pvDataCreate->createPVStructure(parent,field);
|
||||
PVScalarArray *pvScalarArray = pvStructure->getScalarArrayField(
|
||||
"choices",pvString);
|
||||
if(pvScalarArray==0) {
|
||||
throw std::logic_error(String("StandardPVField::enumerated"));
|
||||
}
|
||||
PVStringArray *pvChoices = static_cast<PVStringArray *>(pvScalarArray);
|
||||
pvChoices->put(0,number,choices,0);
|
||||
return pvStructure;
|
||||
}
|
||||
|
||||
PVStructure * StandardPVField::enumeratedValue(PVStructure *parent,
|
||||
StringArray choices, int number,String properties)
|
||||
{
|
||||
StructureConstPtr field = standardField->enumeratedValue( properties);
|
||||
PVStructure *pvStructure = pvDataCreate->createPVStructure(parent,field);
|
||||
addExtendsStructureName(pvStructure,properties);
|
||||
PVScalarArray *pvScalarArray = pvStructure->getScalarArrayField(
|
||||
String("value.choices"),pvString);
|
||||
if(pvScalarArray==0) {
|
||||
throw std::logic_error(String("StandardPVField::enumerated"));
|
||||
}
|
||||
PVStringArray *pvChoices = static_cast<PVStringArray *>(pvScalarArray);
|
||||
pvChoices->put(0,number,choices,0);
|
||||
return pvStructure;
|
||||
}
|
||||
|
||||
PVStructure * StandardPVField::alarm(PVStructure *parent)
|
||||
{
|
||||
StructureConstPtr field = standardField->alarm();
|
||||
return pvDataCreate->createPVStructure(parent,field);
|
||||
}
|
||||
|
||||
PVStructure * StandardPVField::timeStamp(PVStructure *parent)
|
||||
{
|
||||
StructureConstPtr field = standardField->timeStamp();
|
||||
return pvDataCreate->createPVStructure(parent,field);
|
||||
}
|
||||
|
||||
PVStructure * StandardPVField::display(PVStructure *parent)
|
||||
{
|
||||
StructureConstPtr field = standardField->display();
|
||||
return pvDataCreate->createPVStructure(parent,field);
|
||||
}
|
||||
|
||||
PVStructure * StandardPVField::control(PVStructure *parent)
|
||||
{
|
||||
StructureConstPtr field = standardField->control();
|
||||
return pvDataCreate->createPVStructure(parent,field);
|
||||
}
|
||||
|
||||
PVStructure * StandardPVField::booleanAlarm(PVStructure *parent)
|
||||
{
|
||||
StructureConstPtr field = standardField->booleanAlarm();
|
||||
return pvDataCreate->createPVStructure(parent,field);
|
||||
}
|
||||
|
||||
PVStructure * StandardPVField::byteAlarm(PVStructure *parent)
|
||||
{
|
||||
StructureConstPtr field = standardField->byteAlarm();
|
||||
return pvDataCreate->createPVStructure(parent,field);
|
||||
}
|
||||
|
||||
PVStructure * StandardPVField::shortAlarm(PVStructure *parent)
|
||||
{
|
||||
StructureConstPtr field = standardField->shortAlarm();
|
||||
return pvDataCreate->createPVStructure(parent,field);
|
||||
}
|
||||
|
||||
PVStructure * StandardPVField::intAlarm(PVStructure *parent)
|
||||
{
|
||||
StructureConstPtr field = standardField->intAlarm();
|
||||
return pvDataCreate->createPVStructure(parent,field);
|
||||
}
|
||||
|
||||
PVStructure * StandardPVField::longAlarm(PVStructure *parent)
|
||||
{
|
||||
StructureConstPtr field = standardField->longAlarm();
|
||||
return pvDataCreate->createPVStructure(parent,field);
|
||||
}
|
||||
|
||||
PVStructure * StandardPVField::floatAlarm(PVStructure *parent)
|
||||
{
|
||||
StructureConstPtr field = standardField->floatAlarm();
|
||||
return pvDataCreate->createPVStructure(parent,field);
|
||||
}
|
||||
|
||||
PVStructure * StandardPVField::doubleAlarm(PVStructure *parent)
|
||||
{
|
||||
StructureConstPtr field = standardField->doubleAlarm();
|
||||
return pvDataCreate->createPVStructure(parent,field);
|
||||
}
|
||||
|
||||
PVStructure * StandardPVField::enumeratedAlarm(PVStructure *parent)
|
||||
{
|
||||
StructureConstPtr field = standardField->enumeratedAlarm();
|
||||
return pvDataCreate->createPVStructure(parent,field);
|
||||
}
|
||||
|
||||
PVStructure * StandardPVField::powerSupply(PVStructure *parent)
|
||||
{
|
||||
StructureConstPtr alarmField = standardField->alarm();
|
||||
StructureConstPtr timeStampField = standardField->timeStamp();
|
||||
StructureConstPtr voltageField = standardField->scalar(
|
||||
String("voltage"),pvDouble,String("alarm"));
|
||||
StructureConstPtr powerField = standardField->scalar(
|
||||
String("power"),pvDouble,String("alarm"));
|
||||
StructureConstPtr currentField = standardField->scalar(
|
||||
String("current"),pvDouble,String("alarm"));
|
||||
FieldConstPtr fields[3];
|
||||
fields[0] = voltageField;
|
||||
fields[1] = powerField;
|
||||
fields[2] = currentField;
|
||||
StructureConstPtr valueField = standardField->structureValue( 3,fields);
|
||||
fields[0] = alarmField;
|
||||
fields[1] = timeStampField;
|
||||
fields[2] = valueField;
|
||||
StructureConstPtr structureField = standardField->structureValue(3,fields);
|
||||
return pvDataCreate->createPVStructure(parent,structureField);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class StandardPVFieldExt : public StandardPVField {
|
||||
public:
|
||||
StandardPVFieldExt(): StandardPVField(){};
|
||||
};
|
||||
|
||||
static void myDeleteStatic(void*)
|
||||
{
|
||||
delete standardPVField;
|
||||
}
|
||||
|
||||
static void myInitStatic(void*)
|
||||
{
|
||||
fieldCreate = getFieldCreate();
|
||||
pvDataCreate = getPVDataCreate();
|
||||
standardField = getStandardField();
|
||||
standardPVField = new StandardPVFieldExt();
|
||||
epicsAtExit(&myDeleteStatic, 0);
|
||||
}
|
||||
|
||||
static
|
||||
epicsThreadOnceId myInitOnce = EPICS_THREAD_ONCE_INIT;
|
||||
|
||||
StandardPVField * getStandardPVField() {
|
||||
epicsThreadOnce(&myInitOnce, &myInitStatic, 0);
|
||||
return standardPVField;
|
||||
}
|
||||
|
||||
}}
|
||||
@@ -1,73 +0,0 @@
|
||||
/*TypeFunc.cpp*/
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
|
||||
#include <pv/pvIntrospect.h>
|
||||
#include <pv/epicsException.h>
|
||||
|
||||
#include "dbDefs.h" // for NELEMENTS
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
namespace TypeFunc {
|
||||
static const char* names[] = {
|
||||
"scalar", "scalarArray", "structure", "structureArray",
|
||||
};
|
||||
const char* name(Type t) {
|
||||
if (t<int(pvBoolean) || t>int(pvString))
|
||||
THROW_EXCEPTION2(std::invalid_argument, "logic error unknown Type");
|
||||
return names[t];
|
||||
}
|
||||
void toString(StringBuilder buf,const Type type) {
|
||||
*buf += name(type);
|
||||
}
|
||||
} // namespace TypeFunc
|
||||
|
||||
|
||||
namespace ScalarTypeFunc {
|
||||
bool isInteger(ScalarType type) {
|
||||
if(type>=pvByte && type<=pvLong) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isNumeric(ScalarType type) {
|
||||
if(type>=pvByte && type<=pvDouble) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isPrimitive(ScalarType type) {
|
||||
if(type>=pvBoolean && type<=pvDouble) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static const char* names[] = {
|
||||
"boolean", "byte", "short", "int", "long",
|
||||
"float", "double", "string",
|
||||
};
|
||||
ScalarType getScalarType(String pvalue) {
|
||||
for(size_t i=0; i<NELEMENTS(names); i++)
|
||||
if(pvalue==names[i])
|
||||
return ScalarType(i);
|
||||
THROW_EXCEPTION2(std::invalid_argument, "error unknown ScalarType");
|
||||
}
|
||||
|
||||
const char* name(ScalarType t) {
|
||||
if (t<pvBoolean || t>pvString)
|
||||
THROW_EXCEPTION2(std::invalid_argument, "error unknown ScalarType");
|
||||
return names[t];
|
||||
}
|
||||
|
||||
void toString(StringBuilder buf,const ScalarType scalarType) {
|
||||
*buf += name(scalarType);
|
||||
}
|
||||
|
||||
} // namespace ScalarTypeFunc
|
||||
|
||||
}}
|
||||
@@ -1,15 +0,0 @@
|
||||
/*factory.h*/
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
#ifndef FACTORY_H
|
||||
#define FACTORY_H
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
enum DebugLevel{noDebug,lowDebug,highDebug};
|
||||
|
||||
}}
|
||||
#endif /*FACTORY_H */
|
||||
@@ -1,160 +0,0 @@
|
||||
/* CDRMonitor.cpp */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <epicsThread.h>
|
||||
|
||||
#include <pv/noDefaultMethods.h>
|
||||
#include <pv/lock.h>
|
||||
#include <pv/pvType.h>
|
||||
#include <pv/linkedList.h>
|
||||
#include <pv/CDRMonitor.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <BaseTsd.h>
|
||||
typedef SSIZE_T ssize_t;
|
||||
#endif
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
static
|
||||
epicsThreadOnceId monitorInit = EPICS_THREAD_ONCE_INIT;
|
||||
|
||||
// Must use a pointer w/ lazy init due to lack of
|
||||
// initialization order guarantees
|
||||
CDRMonitor* CDRMonitor::theone = 0;
|
||||
|
||||
CDRMonitor&
|
||||
CDRMonitor::get()
|
||||
{
|
||||
epicsThreadOnce(&monitorInit, &CDRMonitor::init, 0);
|
||||
assert(theone);
|
||||
return *theone;
|
||||
}
|
||||
|
||||
void
|
||||
CDRMonitor::init(void *)
|
||||
{
|
||||
//BUG: No idea how to handle allocation failure at this stage.
|
||||
theone=new CDRMonitor;
|
||||
}
|
||||
|
||||
void
|
||||
CDRMonitor::destroy()
|
||||
{
|
||||
if (theone)
|
||||
{
|
||||
CDRNode *node = theone->first();
|
||||
while (node)
|
||||
{
|
||||
CDRNode* tmp = node;
|
||||
node = node->next();
|
||||
delete tmp;
|
||||
}
|
||||
delete theone;
|
||||
theone = 0;
|
||||
}
|
||||
}
|
||||
|
||||
CDRMonitor::CDRMonitor()
|
||||
:firstNode(0)
|
||||
{}
|
||||
|
||||
CDRCount
|
||||
CDRMonitor::current()
|
||||
{
|
||||
CDRCount total;
|
||||
for(CDRNode *cur=first(); !!cur; cur=cur->next())
|
||||
{
|
||||
total+=cur->get();
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
void
|
||||
CDRMonitor::show(FILE *fd, bool destroy)
|
||||
{
|
||||
for(CDRNode *cur=first(); !!cur; cur=cur->next())
|
||||
{
|
||||
cur->show(fd);
|
||||
}
|
||||
if (destroy)
|
||||
CDRMonitor::destroy();
|
||||
}
|
||||
|
||||
void
|
||||
CDRMonitor::show(std::ostream& out, bool destroy) const
|
||||
{
|
||||
for(CDRNode *cur=first(); !!cur; cur=cur->next())
|
||||
{
|
||||
cur->show(out);
|
||||
}
|
||||
if (destroy)
|
||||
CDRMonitor::destroy();
|
||||
}
|
||||
|
||||
void
|
||||
CDRNode::show(FILE *fd)
|
||||
{
|
||||
Lock x(guard);
|
||||
if(!current.cons && !current.dtys && !current.refs)
|
||||
return;
|
||||
fprintf(fd,"%s: totalConstruct %lu totalDestruct %lu",
|
||||
nodeName.c_str(), (unsigned long)current.cons,
|
||||
(unsigned long)current.dtys);
|
||||
ssize_t alive=current.cons;
|
||||
alive-=current.dtys;
|
||||
if(current.refs)
|
||||
fprintf(fd," totalReference %ld", current.refs);
|
||||
if(alive)
|
||||
fprintf(fd," ACTIVE %ld\n", (long)alive);
|
||||
else
|
||||
fprintf(fd,"\n");
|
||||
}
|
||||
|
||||
void
|
||||
CDRNode::show(std::ostream& out) const
|
||||
{
|
||||
Lock x(guard);
|
||||
if(!current.cons && !current.dtys && !current.refs)
|
||||
return;
|
||||
out<<nodeName<<" totalConstruct "<<current.cons
|
||||
<<" totalDestruct "<<current.dtys;
|
||||
ssize_t alive=current.cons;
|
||||
alive-=current.dtys;
|
||||
if(current.refs)
|
||||
out<<" totalReference "<<current.refs;
|
||||
if(alive)
|
||||
out<<" ACTIVE "<<alive;
|
||||
out<<"\n";
|
||||
}
|
||||
|
||||
void
|
||||
onceNode(void* raw)
|
||||
{
|
||||
CDRNodeInstance* inst=static_cast<CDRNodeInstance*>(raw);
|
||||
inst->node=new CDRNode(inst->name);
|
||||
}
|
||||
|
||||
}} // namespace epics::pvData
|
||||
|
||||
std::ostream& operator<<(std::ostream& out,const epics::pvData::CDRMonitor& mon)
|
||||
{
|
||||
mon.show(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& out,const epics::pvData::CDRNode& node)
|
||||
{
|
||||
node.show(out);
|
||||
return out;
|
||||
}
|
||||
@@ -1,140 +0,0 @@
|
||||
/* CDRMonitor.h */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
#ifndef CDRMONITOR_H
|
||||
#define CDRMONITOR_H
|
||||
#include <ostream>
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
|
||||
#include <epicsThread.h>
|
||||
#include <pv/noDefaultMethods.h>
|
||||
#include <pv/lock.h>
|
||||
#include <pv/pvType.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
//! Used to pass around snapshots
|
||||
struct CDRCount { // default copy and assignment are ok
|
||||
size_t cons, dtys;
|
||||
long refs;
|
||||
CDRCount():cons(0),dtys(0),refs(0){}
|
||||
CDRCount& operator+=(const CDRCount& o)
|
||||
{cons+=o.cons; dtys+=o.dtys; refs+=o.refs; return *this;}
|
||||
CDRCount& operator=(size_t count) // reset counters
|
||||
{cons=count; dtys=count; refs=count; return *this;}
|
||||
};
|
||||
|
||||
class CDRNode;
|
||||
|
||||
//! @brief Global registrar for CDRNodes
|
||||
class CDRMonitor : private NoDefaultMethods {
|
||||
public:
|
||||
static CDRMonitor& get();
|
||||
static void destroy();
|
||||
|
||||
CDRNode* addNode(CDRNode& next)
|
||||
{
|
||||
CDRNode *ret=firstNode;
|
||||
firstNode=&next;
|
||||
return ret;
|
||||
}
|
||||
|
||||
CDRCount current(); //!< current global count
|
||||
|
||||
CDRNode* first() const{return firstNode;}
|
||||
|
||||
void show(FILE*, bool destroy = false);
|
||||
void show(std::ostream&, bool destroy = false) const;
|
||||
private:
|
||||
// Private ctor for singleton
|
||||
CDRMonitor();
|
||||
CDRNode *firstNode;
|
||||
|
||||
static CDRMonitor *theone;
|
||||
static void init(void*);
|
||||
};
|
||||
|
||||
//! Counters for Construction, Destruction, and References of one class
|
||||
class CDRNode : private NoDefaultMethods {
|
||||
public:
|
||||
CDRNode(const String& name)
|
||||
:nodeName(name)
|
||||
,current()
|
||||
,guard()
|
||||
,nextNode(CDRMonitor::get().addNode(*this))
|
||||
{}
|
||||
void construct(){Lock x(guard); current.cons++;}
|
||||
void destruct(){Lock x(guard); current.dtys++;}
|
||||
void incRef(){Lock x(guard); current.refs++;}
|
||||
void decRef(){Lock x(guard); current.refs--;}
|
||||
|
||||
CDRNode* next() const{return nextNode;}
|
||||
|
||||
CDRCount get() const{Lock x(guard); return current;}
|
||||
|
||||
void show(FILE*);
|
||||
void show(std::ostream&) const;
|
||||
private:
|
||||
const String nodeName;
|
||||
CDRCount current;
|
||||
mutable Mutex guard;
|
||||
CDRNode * const nextNode;
|
||||
};
|
||||
|
||||
struct CDRNodeInstance
|
||||
{
|
||||
CDRNode *node;
|
||||
epicsThreadOnceId once;
|
||||
const char* const name;
|
||||
};
|
||||
|
||||
void onceNode(void* raw);
|
||||
|
||||
static inline
|
||||
CDRNode*
|
||||
getNode(CDRNodeInstance *inst)
|
||||
{
|
||||
epicsThreadOnce(&inst->once,&onceNode,
|
||||
static_cast<void*>(inst));
|
||||
return inst->node;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
|
||||
#define PVDATA_REFCOUNT_MONITOR_DEFINE(NAME) \
|
||||
static CDRNodeInstance NAME ## _node={0,EPICS_THREAD_ONCE_INIT,#NAME}
|
||||
|
||||
#define PVDATA_REFCOUNT_MONITOR_DESTRUCT(NAME) \
|
||||
getNode(&NAME ## _node)->destruct()
|
||||
|
||||
#define PVDATA_REFCOUNT_MONITOR_CONSTRUCT(NAME) \
|
||||
getNode(&NAME ## _node)->construct()
|
||||
|
||||
#define PVDATA_REFCOUNT_MONITOR_INCREF(NAME) \
|
||||
getNode(&NAME ## _node)->incRef()
|
||||
#define PVDATA_REFCOUNT_MONITOR_DECREF(NAME) \
|
||||
getNode(&NAME ## _node)->decRef()
|
||||
|
||||
|
||||
#else
|
||||
|
||||
#define PVDATA_REFCOUNT_MONITOR_DEFINE(NAME)
|
||||
#define PVDATA_REFCOUNT_MONITOR_DESTRUCT(NAME)
|
||||
#define PVDATA_REFCOUNT_MONITOR_CONSTRUCT(NAME)
|
||||
#define PVDATA_REFCOUNT_MONITOR_INCREF(NAME)
|
||||
#define PVDATA_REFCOUNT_MONITOR_DECREF(NAME)
|
||||
|
||||
#endif
|
||||
|
||||
}}
|
||||
|
||||
std::ostream& operator<<(std::ostream&,const epics::pvData::CDRMonitor&);
|
||||
std::ostream& operator<<(std::ostream&,const epics::pvData::CDRNode&);
|
||||
|
||||
#endif /* CDRMONITOR_H */
|
||||
@@ -1,395 +0,0 @@
|
||||
/* bitSet.cpp */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
#include "string.h"
|
||||
#include "stdio.h"
|
||||
#include <pv/bitSet.h>
|
||||
#include <pv/lock.h>
|
||||
#include <pv/CDRMonitor.h>
|
||||
#include <pv/serializeHelper.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
PVDATA_REFCOUNT_MONITOR_DEFINE(bitSet);
|
||||
|
||||
BitSet::BitSet() : words(0), wordsLength(0), wordsInUse(0) {
|
||||
initWords(BITS_PER_WORD);
|
||||
|
||||
PVDATA_REFCOUNT_MONITOR_CONSTRUCT(bitSet);
|
||||
}
|
||||
|
||||
BitSet::BitSet(uint32 nbits) : words(0), wordsLength(0), wordsInUse(0) {
|
||||
initWords(nbits);
|
||||
|
||||
PVDATA_REFCOUNT_MONITOR_CONSTRUCT(bitSet);
|
||||
}
|
||||
|
||||
BitSet::~BitSet() {
|
||||
delete[] words;
|
||||
|
||||
PVDATA_REFCOUNT_MONITOR_DESTRUCT(bitSet);
|
||||
}
|
||||
|
||||
void BitSet::initWords(uint32 nbits) {
|
||||
uint32 length = (nbits <= 0) ? 1 : wordIndex(nbits-1) + 1;
|
||||
if (words) delete[] words;
|
||||
words = new uint64[length];
|
||||
memset(words, 0, sizeof(uint64)*length);
|
||||
wordsLength = length;
|
||||
}
|
||||
|
||||
void BitSet::recalculateWordsInUse() {
|
||||
// wordsInUse is unsigned
|
||||
if (wordsInUse == 0)
|
||||
return;
|
||||
|
||||
// Traverse the bitset until a used word is found
|
||||
int32 i;
|
||||
for (i = (int32)wordsInUse-1; i >= 0; i--)
|
||||
if (words[i] != 0)
|
||||
break;
|
||||
|
||||
wordsInUse = i+1; // The new logical size
|
||||
}
|
||||
|
||||
void BitSet::ensureCapacity(uint32 wordsRequired) {
|
||||
if (wordsLength < wordsRequired) {
|
||||
|
||||
// create and copy
|
||||
uint64* newwords = new uint64[wordsRequired];
|
||||
memset(newwords, 0, sizeof(uint64)*wordsRequired);
|
||||
memcpy(newwords, words, sizeof(uint64)*wordsLength);
|
||||
if (words) delete[] words;
|
||||
words = newwords;
|
||||
wordsLength = wordsRequired;
|
||||
}
|
||||
}
|
||||
|
||||
void BitSet::expandTo(uint32 wordIndex) {
|
||||
uint32 wordsRequired = wordIndex+1;
|
||||
if (wordsInUse < wordsRequired) {
|
||||
ensureCapacity(wordsRequired);
|
||||
wordsInUse = wordsRequired;
|
||||
}
|
||||
}
|
||||
|
||||
void BitSet::flip(uint32 bitIndex) {
|
||||
|
||||
uint32 wordIdx = wordIndex(bitIndex);
|
||||
expandTo(wordIdx);
|
||||
|
||||
words[wordIdx] ^= (((uint64)1) << (bitIndex % BITS_PER_WORD));
|
||||
|
||||
recalculateWordsInUse();
|
||||
}
|
||||
|
||||
void BitSet::set(uint32 bitIndex) {
|
||||
|
||||
uint32 wordIdx = wordIndex(bitIndex);
|
||||
expandTo(wordIdx);
|
||||
|
||||
words[wordIdx] |= (((uint64)1) << (bitIndex % BITS_PER_WORD));
|
||||
}
|
||||
|
||||
void BitSet::clear(uint32 bitIndex) {
|
||||
|
||||
uint32 wordIdx = wordIndex(bitIndex);
|
||||
if (wordIdx >= wordsInUse)
|
||||
return;
|
||||
|
||||
words[wordIdx] &= ~(((uint64)1) << (bitIndex % BITS_PER_WORD));
|
||||
|
||||
recalculateWordsInUse();
|
||||
}
|
||||
|
||||
void BitSet::set(uint32 bitIndex, bool value) {
|
||||
if (value)
|
||||
set(bitIndex);
|
||||
else
|
||||
clear(bitIndex);
|
||||
}
|
||||
|
||||
bool BitSet::get(uint32 bitIndex) const {
|
||||
uint32 wordIdx = wordIndex(bitIndex);
|
||||
return ((wordIdx < wordsInUse)
|
||||
&& ((words[wordIdx] & (((uint64)1) << (bitIndex % BITS_PER_WORD))) != 0));
|
||||
}
|
||||
|
||||
void BitSet::clear() {
|
||||
while (wordsInUse > 0)
|
||||
words[--wordsInUse] = 0;
|
||||
}
|
||||
|
||||
uint32 BitSet::numberOfTrailingZeros(uint64 i) {
|
||||
// HD, Figure 5-14
|
||||
uint32 x, y;
|
||||
if (i == 0) return 64;
|
||||
uint32 n = 63;
|
||||
y = (uint32)i; if (y != 0) { n = n -32; x = y; } else x = (uint32)(i>>32);
|
||||
y = x <<16; if (y != 0) { n = n -16; x = y; }
|
||||
y = x << 8; if (y != 0) { n = n - 8; x = y; }
|
||||
y = x << 4; if (y != 0) { n = n - 4; x = y; }
|
||||
y = x << 2; if (y != 0) { n = n - 2; x = y; }
|
||||
return n - ((x << 1) >> 31);
|
||||
}
|
||||
|
||||
uint32 BitSet::bitCount(uint64 i) {
|
||||
// HD, Figure 5-14
|
||||
i = i - ((i >> 1) & 0x5555555555555555LL);
|
||||
i = (i & 0x3333333333333333LL) + ((i >> 2) & 0x3333333333333333LL);
|
||||
i = (i + (i >> 4)) & 0x0f0f0f0f0f0f0f0fLL;
|
||||
i = i + (i >> 8);
|
||||
i = i + (i >> 16);
|
||||
i = i + (i >> 32);
|
||||
return (uint32)(i & 0x7f);
|
||||
}
|
||||
|
||||
int32 BitSet::nextSetBit(uint32 fromIndex) const {
|
||||
|
||||
uint32 u = wordIndex(fromIndex);
|
||||
if (u >= wordsInUse)
|
||||
return -1;
|
||||
|
||||
uint64 word = words[u] & (WORD_MASK << (fromIndex % BITS_PER_WORD));
|
||||
|
||||
while (true) {
|
||||
if (word != 0)
|
||||
return (u * BITS_PER_WORD) + numberOfTrailingZeros(word);
|
||||
if (++u == wordsInUse)
|
||||
return -1;
|
||||
word = words[u];
|
||||
}
|
||||
}
|
||||
|
||||
int32 BitSet::nextClearBit(uint32 fromIndex) const {
|
||||
// Neither spec nor implementation handle bitsets of maximal length.
|
||||
|
||||
uint32 u = wordIndex(fromIndex);
|
||||
if (u >= wordsInUse)
|
||||
return fromIndex;
|
||||
|
||||
uint64 word = ~words[u] & (WORD_MASK << (fromIndex % BITS_PER_WORD));
|
||||
|
||||
while (true) {
|
||||
if (word != 0)
|
||||
return (u * BITS_PER_WORD) + numberOfTrailingZeros(word);
|
||||
if (++u == wordsInUse)
|
||||
return wordsInUse * BITS_PER_WORD;
|
||||
word = ~words[u];
|
||||
}
|
||||
}
|
||||
|
||||
bool BitSet::isEmpty() const {
|
||||
return (wordsInUse == 0);
|
||||
}
|
||||
|
||||
uint32 BitSet::cardinality() const {
|
||||
uint32 sum = 0;
|
||||
for (uint32 i = 0; i < wordsInUse; i++)
|
||||
sum += bitCount(words[i]);
|
||||
return sum;
|
||||
}
|
||||
|
||||
BitSet& BitSet::operator&=(const BitSet& set) {
|
||||
|
||||
while (wordsInUse > set.wordsInUse)
|
||||
words[--wordsInUse] = 0;
|
||||
|
||||
// Perform logical AND on words in common
|
||||
for (uint32 i = 0; i < wordsInUse; i++)
|
||||
words[i] &= set.words[i];
|
||||
|
||||
recalculateWordsInUse();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
BitSet& BitSet::operator|=(const BitSet& set) {
|
||||
|
||||
uint32 wordsInCommon;
|
||||
if (wordsInUse < set.wordsInUse) {
|
||||
wordsInCommon = wordsInUse;
|
||||
//ensureCapacity(set.wordsInUse);
|
||||
//wordsInUse = set.wordsInUse;
|
||||
}
|
||||
else
|
||||
wordsInCommon = set.wordsInUse;
|
||||
|
||||
// Perform logical OR on words in common
|
||||
uint32 i = 0;
|
||||
for (; i < wordsInCommon; i++)
|
||||
words[i] |= set.words[i];
|
||||
|
||||
// TODO what to do if BitSets are not the same size !!!
|
||||
|
||||
// recalculateWordsInUse() is not needed
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
BitSet& BitSet::operator^=(const BitSet& set) {
|
||||
|
||||
uint32 wordsInCommon;
|
||||
if (wordsInUse < set.wordsInUse) {
|
||||
wordsInCommon = wordsInUse;
|
||||
//ensureCapacity(set.wordsInUse);
|
||||
//wordsInUse = set.wordsInUse;
|
||||
}
|
||||
else
|
||||
wordsInCommon = set.wordsInUse;
|
||||
|
||||
// Perform logical XOR on words in common
|
||||
uint32 i = 0;
|
||||
for (; i < wordsInCommon; i++)
|
||||
words[i] ^= set.words[i];
|
||||
|
||||
// TODO what to do if BitSets are not the same size !!!
|
||||
|
||||
recalculateWordsInUse();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
BitSet& BitSet::operator-=(const BitSet& set) {
|
||||
|
||||
uint32 wordsInCommon;
|
||||
if (wordsInUse < set.wordsInUse) {
|
||||
wordsInCommon = wordsInUse;
|
||||
//ensureCapacity(set.wordsInUse);
|
||||
//wordsInUse = set.wordsInUse;
|
||||
}
|
||||
else
|
||||
wordsInCommon = set.wordsInUse;
|
||||
|
||||
// Perform logical (a & !b) on words in common
|
||||
uint32 i = 0;
|
||||
for (; i < wordsInCommon; i++)
|
||||
words[i] &= ~set.words[i];
|
||||
|
||||
recalculateWordsInUse();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
BitSet& BitSet::operator=(const BitSet &set) {
|
||||
// Check for self-assignment!
|
||||
if (this == &set)
|
||||
return *this;
|
||||
|
||||
// we ensure that words array size is adequate (and not wordsInUse to ensure capacity to the future)
|
||||
if (wordsLength < set.wordsLength)
|
||||
{
|
||||
if (words) delete[] words;
|
||||
words = new uint64[set.wordsLength];
|
||||
wordsLength = set.wordsLength;
|
||||
}
|
||||
memcpy(words, set.words, sizeof(uint64)*set.wordsInUse);
|
||||
wordsInUse = set.wordsInUse;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void BitSet::or_and(const BitSet& set1, const BitSet& set2) {
|
||||
uint32 inUse = (set1.wordsInUse < set2.wordsInUse) ? set1.wordsInUse : set2.wordsInUse;
|
||||
|
||||
ensureCapacity(inUse);
|
||||
wordsInUse = inUse;
|
||||
|
||||
// Perform logical AND on words in common
|
||||
for (uint32 i = 0; i < inUse; i++)
|
||||
words[i] |= (set1.words[i] & set2.words[i]);
|
||||
|
||||
// recalculateWordsInUse()...
|
||||
}
|
||||
|
||||
bool BitSet::operator==(const BitSet &set) const
|
||||
{
|
||||
if (this == &set)
|
||||
return true;
|
||||
|
||||
if (wordsInUse != set.wordsInUse)
|
||||
return false;
|
||||
|
||||
// Check words in use by both BitSets
|
||||
for (uint32 i = 0; i < wordsInUse; i++)
|
||||
if (words[i] != set.words[i])
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BitSet::operator!=(const BitSet &set) const
|
||||
{
|
||||
return !(*this == set);
|
||||
}
|
||||
|
||||
void BitSet::toString(StringBuilder buffer, int indentLevel) const
|
||||
{
|
||||
*buffer += '{';
|
||||
int32 i = nextSetBit(0);
|
||||
char tmp[30];
|
||||
if (i != -1) {
|
||||
sprintf(tmp,"%d",i); *buffer += tmp;
|
||||
for (i = nextSetBit(i+1); i >= 0; i = nextSetBit(i+1)) {
|
||||
int32 endOfRun = nextClearBit(i);
|
||||
do { *buffer += ", "; sprintf(tmp,"%d",i); *buffer += tmp; } while (++i < endOfRun);
|
||||
}
|
||||
}
|
||||
*buffer += '}';
|
||||
}
|
||||
|
||||
void BitSet::serialize(ByteBuffer* buffer, SerializableControl* flusher) const {
|
||||
|
||||
uint32 n = wordsInUse;
|
||||
if (n == 0) {
|
||||
SerializeHelper::writeSize(0, buffer, flusher);
|
||||
return;
|
||||
}
|
||||
uint32 len = 8 * (n-1);
|
||||
for (uint64 x = words[n - 1]; x != 0; x >>= 8)
|
||||
len++;
|
||||
|
||||
SerializeHelper::writeSize(len, buffer, flusher);
|
||||
flusher->ensureBuffer(len);
|
||||
|
||||
for (uint32 i = 0; i < n - 1; i++)
|
||||
buffer->putLong(words[i]);
|
||||
|
||||
for (uint64 x = words[n - 1]; x != 0; x >>= 8)
|
||||
buffer->putByte((int8) (x & 0xff));
|
||||
}
|
||||
|
||||
void BitSet::deserialize(ByteBuffer* buffer, DeserializableControl* control) {
|
||||
|
||||
uint32 bytes = SerializeHelper::readSize(buffer, control); // in bytes
|
||||
|
||||
wordsInUse = (bytes + 7) / 8;
|
||||
if (wordsInUse > wordsLength)
|
||||
{
|
||||
if (words) delete[] words;
|
||||
words = new uint64[wordsInUse];
|
||||
wordsLength = wordsInUse;
|
||||
}
|
||||
|
||||
if (wordsInUse == 0)
|
||||
return;
|
||||
|
||||
control->ensureData(bytes);
|
||||
|
||||
uint32 i = 0;
|
||||
uint32 longs = bytes / 8;
|
||||
while (i < longs)
|
||||
words[i++] = buffer->getLong();
|
||||
|
||||
for (uint32 j = i; j < wordsInUse; j++)
|
||||
words[j] = 0;
|
||||
|
||||
for (uint32 remaining = (bytes - longs * 8), j = 0; j < remaining; j++)
|
||||
words[i] |= (buffer->getByte() & 0xffL) << (8 * j);
|
||||
|
||||
}
|
||||
|
||||
}};
|
||||
@@ -1,5 +0,0 @@
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
@@ -1,850 +0,0 @@
|
||||
/* byteBuffer.h */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
#ifndef BYTEBUFFER_H
|
||||
#define BYTEBUFFER_H
|
||||
|
||||
#include <string>
|
||||
#include <pv/pvType.h>
|
||||
#include <epicsEndian.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <pv/epicsException.h>
|
||||
|
||||
namespace epics {
|
||||
namespace pvData {
|
||||
|
||||
/*
|
||||
TODO can be used:
|
||||
|
||||
MS Visual C++:
|
||||
|
||||
You include intrin.h and call the following functions:
|
||||
|
||||
For 16 bit numbers:
|
||||
unsigned short _byteswap_ushort(unsigned short value);
|
||||
|
||||
For 32 bit numbers:
|
||||
unsigned long _byteswap_ulong(unsigned long value);
|
||||
|
||||
For 64 bit numbers:
|
||||
unsigned __int64 _byteswap_uint64(unsigned __int64 value);
|
||||
*/
|
||||
|
||||
/*
|
||||
For floats and doubles it's more difficult as with plain integers as these may or not may be in the host machines byte-order.
|
||||
You can get little-endian floats on big-endian machines and vice versa.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#define GCC_VERSION_SINCE(major, minor, patchlevel) \
|
||||
(defined(__GNUC__) && !defined(__INTEL_COMPILER) && \
|
||||
((__GNUC__ > (major)) || \
|
||||
(__GNUC__ == (major) && __GNUC_MINOR__ > (minor)) || \
|
||||
(__GNUC__ == (major) && __GNUC_MINOR__ == (minor) && __GNUC_PATCHLEVEL__ >= (patchlevel))))
|
||||
|
||||
|
||||
#if GCC_VERSION_SINCE(4,3,0)
|
||||
|
||||
#define swap32(x) __builtin_bswap32(x)
|
||||
#define swap64(x) __builtin_bswap64(x)
|
||||
|
||||
#define __byte_swap16(x) \
|
||||
(((x) >> 8) | \
|
||||
((x) << 8))
|
||||
|
||||
static inline uint16_t
|
||||
swap16(uint16_t _x)
|
||||
{
|
||||
return (__byte_swap16(_x));
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
|
||||
#define __byte_swap16(x) \
|
||||
(((x) >> 8) | \
|
||||
((x) << 8))
|
||||
|
||||
#define __byte_swap32(x) \
|
||||
((((x) & 0xff000000) >> 24) | \
|
||||
(((x) & 0x00ff0000) >> 8) | \
|
||||
(((x) & 0x0000ff00) << 8) | \
|
||||
(((x) & 0x000000ff) << 24))
|
||||
|
||||
#define __byte_swap64(x) \
|
||||
(((x) >> 56) | \
|
||||
(((x) >> 40) & 0xff00) | \
|
||||
(((x) >> 24) & 0xff0000) | \
|
||||
(((x) >> 8) & 0xff000000) | \
|
||||
(((x) << 8) & ((uint64_t)0xff << 32)) | \
|
||||
(((x) << 24) & ((uint64_t)0xff << 40)) | \
|
||||
(((x) << 40) & ((uint64_t)0xff << 48)) | \
|
||||
(((x) << 56)))
|
||||
|
||||
static inline uint16_t
|
||||
swap16(uint16_t _x)
|
||||
{
|
||||
return (__byte_swap16(_x));
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
swap32(uint32_t _x)
|
||||
{
|
||||
return (__byte_swap32(_x));
|
||||
}
|
||||
|
||||
static inline uint64_t
|
||||
swap64(uint64_t _x)
|
||||
{
|
||||
return (__byte_swap64(_x));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
template<typename T>
|
||||
inline T swap(T val) { return val; } // not valid
|
||||
|
||||
template<>
|
||||
inline int16 swap(int16 val)
|
||||
{
|
||||
return swap16(val);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline int32 swap(int32 val)
|
||||
{
|
||||
return swap32(val);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline int64 swap(int64 val)
|
||||
{
|
||||
return swap64(val);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline float swap(float val)
|
||||
{
|
||||
union {
|
||||
int32 i;
|
||||
float f;
|
||||
} conv;
|
||||
conv.f = val;
|
||||
conv.i = swap32(conv.i);
|
||||
return conv.f;
|
||||
}
|
||||
|
||||
template<>
|
||||
inline double swap(double val)
|
||||
{
|
||||
union {
|
||||
int64 i;
|
||||
double d;
|
||||
} conv;
|
||||
conv.d = val;
|
||||
conv.i = swap64(conv.i);
|
||||
return conv.d;
|
||||
}
|
||||
|
||||
#define is_aligned(POINTER, BYTE_COUNT) \
|
||||
(((uintptr_t)(const void *)(POINTER)) % (BYTE_COUNT) == 0)
|
||||
|
||||
/*template <bool ENDIANESS_SUPPORT = false,
|
||||
bool UNALIGNED_ACCESS = false,
|
||||
bool ADAPTIVE_ACCESS = true,
|
||||
bool USE_INLINE_MEMCPY = true>*/
|
||||
|
||||
#define ENDIANESS_SUPPORT true
|
||||
#define UNALIGNED_ACCESS true
|
||||
#define ADAPTIVE_ACCESS true
|
||||
#define USE_INLINE_MEMCPY true
|
||||
|
||||
/**
|
||||
* This class implements {@code Bytebuffer} that is like the {@code java.nio.ByteBuffer}.
|
||||
* <p>A {@code BitSet} is not safe for multithreaded use without
|
||||
* external synchronization.
|
||||
*
|
||||
* Based on Java implementation.
|
||||
*/
|
||||
class ByteBuffer
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param size The number of bytes.
|
||||
* @param byteOrder The byte order.
|
||||
* Must be one of EPICS_BYTE_ORDER,EPICS_ENDIAN_LITTLE,EPICS_ENDIAN_BIG,
|
||||
*/
|
||||
ByteBuffer(uintptr_t size, int byteOrder = EPICS_BYTE_ORDER) :
|
||||
_buffer(0), _size(size),
|
||||
_reverseEndianess(byteOrder != EPICS_BYTE_ORDER),
|
||||
_reverseFloatEndianess(byteOrder != EPICS_FLOAT_WORD_ORDER)
|
||||
{
|
||||
_buffer = (char*)malloc(size);
|
||||
clear();
|
||||
}
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~ByteBuffer()
|
||||
{
|
||||
if (_buffer) free(_buffer);
|
||||
}
|
||||
/**
|
||||
* Set the byte order.
|
||||
*
|
||||
* @param byteOrder The byte order.
|
||||
* Must be one of EPICS_BYTE_ORDER,EPICS_ENDIAN_LITTLE,EPICS_ENDIAN_BIG,
|
||||
*/
|
||||
inline void setEndianess(int byteOrder)
|
||||
{
|
||||
_reverseEndianess = (byteOrder != EPICS_BYTE_ORDER);
|
||||
_reverseFloatEndianess = (byteOrder != EPICS_FLOAT_WORD_ORDER);
|
||||
}
|
||||
/**
|
||||
* Get the raw buffer data.
|
||||
* @return the raw buffer data.
|
||||
*/
|
||||
inline const char* getBuffer()
|
||||
{
|
||||
return _buffer;
|
||||
}
|
||||
/**
|
||||
* Makes a buffer ready for a new sequence of channel-read or relative put operations:
|
||||
* It sets the limit to the capacity and the position to zero.
|
||||
*/
|
||||
inline void clear()
|
||||
{
|
||||
_position = _buffer;
|
||||
_limit = _buffer + _size;
|
||||
}
|
||||
/**
|
||||
* Makes a buffer ready for a new sequence of channel-write or relative get operations:
|
||||
* It sets the limit to the current position and then sets the position to zero.
|
||||
*/
|
||||
inline void flip() {
|
||||
_limit = _position;
|
||||
_position = _buffer;
|
||||
}
|
||||
/**
|
||||
* Makes a buffer ready for re-reading the data that it already contains:
|
||||
* It leaves the limit unchanged and sets the position to zero.
|
||||
*/
|
||||
inline void rewind() {
|
||||
_position = _buffer;
|
||||
}
|
||||
/**
|
||||
* Returns the current position.
|
||||
* @return The current position in the raw data.
|
||||
*/
|
||||
inline uintptr_t getPosition()
|
||||
{
|
||||
return (((uintptr_t)(const void *)_position) - ((uintptr_t)(const void *)_buffer));
|
||||
}
|
||||
/**
|
||||
* Sets the buffer position.
|
||||
* If the mark is defined and larger than the new position then it is discarded.
|
||||
*
|
||||
* @param pos The offset into the raw buffer.
|
||||
* The new position value; must be no larger than the current limit
|
||||
*/
|
||||
inline void setPosition(uintptr_t pos)
|
||||
{
|
||||
_position = _buffer + pos;
|
||||
}
|
||||
/**
|
||||
* Returns this buffer's limit.
|
||||
*
|
||||
* @return The offset into the raw buffer.
|
||||
*/
|
||||
inline uintptr_t getLimit()
|
||||
{
|
||||
return (((uintptr_t)(const void *)_limit) - ((uintptr_t)(const void *)_buffer));
|
||||
}
|
||||
/**
|
||||
* Sets this buffer's limit.
|
||||
* If the position is larger than the new limit then it is set to the new limit.s
|
||||
* If the mark is defined and larger than the new limit then it is discarded.
|
||||
*
|
||||
* @param limit The new position value;
|
||||
* must be no larger than the current limit
|
||||
*/
|
||||
inline void setLimit(uintptr_t limit)
|
||||
{
|
||||
_limit = _buffer + limit;
|
||||
}
|
||||
/**
|
||||
* Returns the number of elements between the current position and the limit.
|
||||
*
|
||||
* @return The number of elements remaining in this buffer.
|
||||
*/
|
||||
inline uintptr_t getRemaining()
|
||||
{
|
||||
return (((uintptr_t)(const void *)_limit) - ((uintptr_t)(const void *)_position));
|
||||
}
|
||||
/**
|
||||
* Returns The size, i.e. capacity of the raw data buffer in bytes.
|
||||
*
|
||||
* @return The size of the raw data buffer.
|
||||
*/
|
||||
inline uintptr_t getSize()
|
||||
{
|
||||
return _size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Put the value into the raw buffer as a byte stream in the current byte order.
|
||||
*
|
||||
* @param value The value to be put into the byte buffer.
|
||||
*/
|
||||
template<typename T>
|
||||
inline void put(T value)
|
||||
{
|
||||
// this avoids int8 specialization, compiler will take care if optimization, -O2 or more
|
||||
if (sizeof(T) == 1)
|
||||
{
|
||||
*(_position++) = (int8)value;
|
||||
return;
|
||||
}
|
||||
|
||||
if (ENDIANESS_SUPPORT && reverse<T>())
|
||||
{
|
||||
value = swap<T>(value);
|
||||
}
|
||||
|
||||
if (UNALIGNED_ACCESS)
|
||||
{
|
||||
// NOTE: some CPU handle unaligned access pretty good (e.g. x86)
|
||||
*((T*)_position) = value;
|
||||
_position += sizeof(T);
|
||||
}
|
||||
else
|
||||
{
|
||||
// NOTE: this check and branching does not always payoff
|
||||
if (ADAPTIVE_ACCESS && is_aligned(_position, sizeof(T)))
|
||||
{
|
||||
*((T*)_position) = value;
|
||||
_position += sizeof(T);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (USE_INLINE_MEMCPY)
|
||||
{
|
||||
// NOTE: it turns out that this compiler can optimize this with inline code, e.g. gcc
|
||||
memcpy(_position, &value, sizeof(T));
|
||||
_position += sizeof(T);
|
||||
}
|
||||
else
|
||||
{
|
||||
// NOTE: compiler should optimize this and unroll the loop
|
||||
for (size_t i = 0; i < sizeof(T); i++)
|
||||
_position[i] = ((char*)&value)[i];
|
||||
_position += sizeof(T);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* Put the value into the raw buffer at the specified index as a byte stream in the current byte order.
|
||||
*
|
||||
* @param index Offset in the byte buffer.
|
||||
* @param value The value to be put into the byte buffer.
|
||||
*/
|
||||
template<typename T>
|
||||
inline void put(uintptr_t index, T value)
|
||||
{
|
||||
// this avoids int8 specialization, compiler will take care if optimization, -O2 or more
|
||||
if (sizeof(T) == 1)
|
||||
{
|
||||
*(_buffer + index) = (int8)value;
|
||||
return;
|
||||
}
|
||||
|
||||
if (ENDIANESS_SUPPORT && reverse<T>())
|
||||
{
|
||||
value = swap<T>(value);
|
||||
}
|
||||
|
||||
if (UNALIGNED_ACCESS)
|
||||
{
|
||||
// NOTE: some CPU handle unaligned access preety good (e.g. x86)
|
||||
*((T*)(_buffer + index)) = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
// NOTE: this check and branching does not always payoff
|
||||
if (ADAPTIVE_ACCESS && is_aligned(_position, sizeof(T)))
|
||||
{
|
||||
*((T*)(_buffer + index)) = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (USE_INLINE_MEMCPY)
|
||||
{
|
||||
// NOTE: it turns out that this compiler can optimize this with inline code, e.g. gcc
|
||||
memcpy(_buffer + index, &value, sizeof(T));
|
||||
}
|
||||
else
|
||||
{
|
||||
// NOTE: compiler should optimize this and unroll the loop
|
||||
char *p = _buffer + index;
|
||||
for (size_t i = 0; i < sizeof(T); i++)
|
||||
p[i] = ((char*)&value)[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* Get the new object from the byte buffer. The item MUST have type {@code T}.
|
||||
* The position is adjusted based on the type.
|
||||
*
|
||||
* @return The object.
|
||||
*/
|
||||
template<typename T>
|
||||
inline T get()
|
||||
{
|
||||
// this avoids int8 specialization, compiler will take care if optimization, -O2 or more
|
||||
if (sizeof(T) == 1)
|
||||
{
|
||||
return (int8)(*(_position++));
|
||||
}
|
||||
|
||||
|
||||
T value;
|
||||
|
||||
if (UNALIGNED_ACCESS)
|
||||
{
|
||||
// NOTE: some CPU handle unaligned access preety good (e.g. x86)
|
||||
value = *((T*)_position);
|
||||
_position += sizeof(T);
|
||||
}
|
||||
else
|
||||
{
|
||||
// NOTE: this check and branching does not always payoff
|
||||
if (ADAPTIVE_ACCESS && is_aligned(_position, sizeof(T)))
|
||||
{
|
||||
value = *((T*)_position);
|
||||
_position += sizeof(T);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (USE_INLINE_MEMCPY)
|
||||
{
|
||||
// NOTE: it turns out that this compiler can optimize this with inline code, e.g. gcc
|
||||
memcpy(&value, _position, sizeof(T));
|
||||
_position += sizeof(T);
|
||||
}
|
||||
else
|
||||
{
|
||||
// NOTE: compiler should optimize this and unroll the loop
|
||||
for (size_t i = 0; i < sizeof(T); i++)
|
||||
((char*)&value)[i] = _position[i];
|
||||
_position += sizeof(T);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ENDIANESS_SUPPORT && reverse<T>())
|
||||
{
|
||||
value = swap<T>(value);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the new object from the byte buffer at the specified index.
|
||||
* The item MUST have type {@code T}.
|
||||
* The position is adjusted based on the type.
|
||||
*
|
||||
* @param index The location in the byte buffer.
|
||||
* @return The object.
|
||||
*/
|
||||
template<typename T>
|
||||
inline T get(uintptr_t index)
|
||||
{
|
||||
// this avoids int8 specialization, compiler will take care if optimization, -O2 or more
|
||||
if (sizeof(T) == 1)
|
||||
{
|
||||
return (int8)(*(_buffer + index));
|
||||
}
|
||||
|
||||
|
||||
T value;
|
||||
|
||||
if (UNALIGNED_ACCESS)
|
||||
{
|
||||
// NOTE: some CPU handle unaligned access preety good (e.g. x86)
|
||||
value = *((T*)(_buffer + index));
|
||||
}
|
||||
else
|
||||
{
|
||||
// NOTE: this check and branching does not always payoff
|
||||
if (ADAPTIVE_ACCESS && is_aligned(_position, sizeof(T)))
|
||||
{
|
||||
value = *((T*)(_buffer + index));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (USE_INLINE_MEMCPY)
|
||||
{
|
||||
// NOTE: it turns out that this compiler can optimize this with inline code, e.g. gcc
|
||||
memcpy(&value, _buffer + index, sizeof(T));
|
||||
}
|
||||
else
|
||||
{
|
||||
// NOTE: compiler should optimize this and unroll the loop
|
||||
char* p = _buffer + index;
|
||||
for (size_t i = 0; i < sizeof(T); i++)
|
||||
((char*)&value)[i] = p[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ENDIANESS_SUPPORT && reverse<T>())
|
||||
{
|
||||
value = swap<T>(value);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
/**
|
||||
* Put a sub-array of bytes into the byte buffer.
|
||||
* The position is increased by the count.
|
||||
*
|
||||
* @param src The source array.
|
||||
* @param offset The starting position within src.
|
||||
* @param count The number of bytes to put into the byte buffer,
|
||||
*/
|
||||
inline void put(const char* src, uintptr_t src_offset, uintptr_t count) {
|
||||
//if(count>getRemaining()) THROW_BASE_EXCEPTION("buffer overflow");
|
||||
memcpy(_position, src + src_offset, count);
|
||||
_position += count;
|
||||
}
|
||||
/**
|
||||
* Get a sub-array of bytes from the byte buffer.
|
||||
* The position is increased by the count.
|
||||
*
|
||||
* @param dest The destination array.
|
||||
* @param offset The starting position within src.
|
||||
* @param count The number of bytes to put into the byte buffer,
|
||||
*/
|
||||
inline void get(char* dest, uintptr_t dest_offset, uintptr_t count) {
|
||||
//if(count>getRemaining()) THROW_BASE_EXCEPTION("buffer overflow");
|
||||
memcpy(dest + dest_offset, _position, count);
|
||||
_position += count;
|
||||
}
|
||||
/**
|
||||
* Put an array of type {@code T} into the byte buffer.
|
||||
* The position is adjusted.
|
||||
*
|
||||
* @param values The input array.
|
||||
* @param count The number of elements.
|
||||
*/
|
||||
template<typename T>
|
||||
inline void putArray(T* values, uintptr_t count)
|
||||
{
|
||||
// this avoids int8 specialization, compiler will take care if optimization, -O2 or more
|
||||
if (sizeof(T) == 1)
|
||||
{
|
||||
put((const char*)values, 0, count);
|
||||
return;
|
||||
}
|
||||
|
||||
T* start = (T*)_position;
|
||||
|
||||
size_t n = sizeof(T)*count;
|
||||
// we require aligned arrays...
|
||||
memcpy(_position, values, n);
|
||||
_position += n;
|
||||
|
||||
// ... so that we can be fast changing endianess
|
||||
if (ENDIANESS_SUPPORT && reverse<T>())
|
||||
{
|
||||
for (uintptr_t i = 0; i < count; i++)
|
||||
{
|
||||
*start = swap<T>(*start);
|
||||
start++;
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Get an array of type {@code T} from the byte buffer.
|
||||
* The position is adjusted.
|
||||
*
|
||||
* @param values The destination array.
|
||||
* @param count The number of elements.
|
||||
*/
|
||||
template<typename T>
|
||||
inline void getArray(T* values, uintptr_t count)
|
||||
{
|
||||
// this avoids int8 specialization, compiler will take care if optimization, -O2 or more
|
||||
if (sizeof(T) == 1)
|
||||
{
|
||||
get((char*)values, 0, count);
|
||||
return;
|
||||
}
|
||||
|
||||
T* start = (T*)values;
|
||||
|
||||
size_t n = sizeof(T)*count;
|
||||
// we require aligned arrays...
|
||||
memcpy(values, _position, n);
|
||||
_position += n;
|
||||
|
||||
// ... so that we can be fast changing endianess
|
||||
if (ENDIANESS_SUPPORT && reverse<T>())
|
||||
{
|
||||
for (uintptr_t i = 0; i < count; i++)
|
||||
{
|
||||
*start = swap<T>(*start);
|
||||
start++;
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Is the byte order the EPICS_BYTE_ORDER
|
||||
* @return (false,true) if (is, is not) the EPICS_BYTE_ORDER
|
||||
*/
|
||||
template<typename T>
|
||||
inline bool reverse()
|
||||
{
|
||||
return _reverseEndianess;
|
||||
}
|
||||
/**
|
||||
* Adjust position so that it is aligned to the specified size.
|
||||
* Size MUST be a power of 2.
|
||||
* @param size The alignment requirement.
|
||||
*/
|
||||
inline void align(int size)
|
||||
{
|
||||
const uintptr_t k = size - 1;
|
||||
_position = (char*)((((uintptr_t)(const void *)_position) + k) & ~(k));
|
||||
}
|
||||
/**
|
||||
* Put a boolean value into the byte buffer.
|
||||
*
|
||||
* @param value The value.
|
||||
*/
|
||||
inline void putBoolean( bool value) { put< int8>(value ? 1 : 0); }
|
||||
/**
|
||||
* Put a byte value into the byte buffer.
|
||||
*
|
||||
* @param value The value.
|
||||
*/
|
||||
inline void putByte ( int8 value) { put< int8>(value); }
|
||||
/**
|
||||
* Put a short value into the byte buffer.
|
||||
*
|
||||
* @param value The value.
|
||||
*/
|
||||
inline void putShort ( int16 value) { put< int16>(value); }
|
||||
/**
|
||||
* Put an int value into the byte buffer.
|
||||
*
|
||||
* @param value The value.
|
||||
*/
|
||||
inline void putInt ( int32 value) { put< int32>(value); }
|
||||
/**
|
||||
* Put a long value into the byte buffer.
|
||||
*
|
||||
* @param value The value.
|
||||
*/
|
||||
inline void putLong ( int64 value) { put< int64>(value); }
|
||||
/**
|
||||
* Put a float value into the byte buffer.
|
||||
*
|
||||
* @param value The value.
|
||||
*/
|
||||
inline void putFloat ( float value) { put< float>(value); }
|
||||
/**
|
||||
* Put a double value into the byte buffer.
|
||||
*
|
||||
* @param value The value.
|
||||
*/
|
||||
inline void putDouble (double value) { put<double>(value); }
|
||||
|
||||
/**
|
||||
* Put a boolean value into the byte buffer at the specified index.
|
||||
*
|
||||
* @param index The offset in the byte buffer,
|
||||
* @param value The value.
|
||||
*/
|
||||
inline void putBoolean(uintptr_t index, bool value) { put< int8>(index, value); }
|
||||
/**
|
||||
* Put a byte value into the byte buffer at the specified index.
|
||||
*
|
||||
* @param index The offset in the byte buffer,
|
||||
* @param value The value.
|
||||
*/
|
||||
inline void putByte (uintptr_t index, int8 value) { put< int8>(index, value); }
|
||||
/**
|
||||
* Put a short value into the byte buffer at the specified index.
|
||||
*
|
||||
* @param index The offset in the byte buffer,
|
||||
* @param value The value.
|
||||
*/
|
||||
inline void putShort (uintptr_t index, int16 value) { put< int16>(index, value); }
|
||||
/**
|
||||
* Put an int value into the byte buffer at the specified index.
|
||||
*
|
||||
* @param index The offset in the byte buffer,
|
||||
* @param value The value.
|
||||
*/
|
||||
inline void putInt (uintptr_t index, int32 value) { put< int32>(index, value); }
|
||||
/**
|
||||
* Put a long value into the byte buffer at the specified index.
|
||||
*
|
||||
* @param index The offset in the byte buffer,
|
||||
* @param value The value.
|
||||
*/
|
||||
inline void putLong (uintptr_t index, int64 value) { put< int64>(index, value); }
|
||||
/**
|
||||
* Put a float value into the byte buffer at the specified index.
|
||||
*
|
||||
* @param index The offset in the byte buffer,
|
||||
* @param value The value.
|
||||
*/
|
||||
inline void putFloat (uintptr_t index, float value) { put< float>(index, value); }
|
||||
/**
|
||||
* Put a double value into the byte buffer at the specified index.
|
||||
*
|
||||
* @param index The offset in the byte buffer,
|
||||
* @param value The value.
|
||||
*/
|
||||
inline void putDouble (uintptr_t index,double value) { put<double>(index, value); }
|
||||
|
||||
/**
|
||||
* Get a boolean value from the byte buffer.
|
||||
*
|
||||
* @return The value.
|
||||
*/
|
||||
inline bool getBoolean() { return get< int8>() != 0; }
|
||||
/**
|
||||
* Get a byte value from the byte buffer.
|
||||
*
|
||||
* @return The value.
|
||||
*/
|
||||
inline int8 getByte () { return get< int8>(); }
|
||||
/**
|
||||
* Get a short value from the byte buffer.
|
||||
*
|
||||
* @return The value.
|
||||
*/
|
||||
inline int16 getShort () { return get< int16>(); }
|
||||
/**
|
||||
* Get a int value from the byte buffer.
|
||||
*
|
||||
* @return The value.
|
||||
*/
|
||||
inline int32 getInt () { return get< int32>(); }
|
||||
/**
|
||||
* Get a long value from the byte buffer.
|
||||
*
|
||||
* @return The value.
|
||||
*/
|
||||
inline int64 getLong () { return get< int64>(); }
|
||||
/**
|
||||
* Get a float value from the byte buffer.
|
||||
*
|
||||
* @return The value.
|
||||
*/
|
||||
inline float getFloat () { return get< float>(); }
|
||||
/**
|
||||
* Get a double value from the byte buffer.
|
||||
*
|
||||
* @return The value.
|
||||
*/
|
||||
inline double getDouble () { return get<double>(); }
|
||||
|
||||
/**
|
||||
* Get a boolean value from the byte buffer at the specified index.
|
||||
*
|
||||
* @param index The offset in the byte buffer.
|
||||
* @return The value.
|
||||
*/
|
||||
inline bool getBoolean(uintptr_t index) { return get< int8>(index) != 0; }
|
||||
/**
|
||||
* Get a byte value from the byte buffer at the specified index.
|
||||
*
|
||||
* @param index The offset in the byte buffer.
|
||||
* @return The value.
|
||||
*/
|
||||
inline int8 getByte (uintptr_t index) { return get< int8>(index); }
|
||||
/**
|
||||
* Get a short value from the byte buffer at the specified index.
|
||||
*
|
||||
* @param index The offset in the byte buffer.
|
||||
* @return The value.
|
||||
*/
|
||||
inline int16 getShort (uintptr_t index) { return get< int16>(index); }
|
||||
/**
|
||||
* Get an int value from the byte buffer at the specified index.
|
||||
*
|
||||
* @param index The offset in the byte buffer.
|
||||
* @return The value.
|
||||
*/
|
||||
inline int32 getInt (uintptr_t index) { return get< int32>(index); }
|
||||
/**
|
||||
* Get a long value from the byte buffer at the specified index.
|
||||
*
|
||||
* @param index The offset in the byte buffer.
|
||||
* @return The value.
|
||||
*/
|
||||
inline int64 getLong (uintptr_t index) { return get< int64>(index); }
|
||||
/**
|
||||
* Get a float value from the byte buffer at the specified index.
|
||||
*
|
||||
* @param index The offset in the byte buffer.
|
||||
* @return The value.
|
||||
*/
|
||||
inline float getFloat (uintptr_t index) { return get< float>(index); }
|
||||
/**
|
||||
* Get a boolean value from the byte buffer at the specified index.
|
||||
*
|
||||
* @param double The offset in the byte buffer.
|
||||
* @return The value.
|
||||
*/
|
||||
inline double getDouble (uintptr_t index) { return get<double>(index); }
|
||||
|
||||
// TODO remove
|
||||
inline const char* getArray()
|
||||
{
|
||||
return _buffer;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
char* _buffer;
|
||||
char* _position;
|
||||
char* _limit;
|
||||
uintptr_t _size;
|
||||
bool _reverseEndianess;
|
||||
bool _reverseFloatEndianess;
|
||||
};
|
||||
|
||||
template<>
|
||||
inline bool ByteBuffer::reverse<float>()
|
||||
{
|
||||
return _reverseFloatEndianess;
|
||||
}
|
||||
|
||||
template<>
|
||||
inline bool ByteBuffer::reverse<double>()
|
||||
{
|
||||
return _reverseFloatEndianess;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
#endif /* BYTEBUFFER_H */
|
||||
@@ -1,35 +0,0 @@
|
||||
/* destroyable.h */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
#ifndef DESTROYABLE_H
|
||||
#define DESTROYABLE_H
|
||||
|
||||
#include <pv/sharedPtr.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
|
||||
/**
|
||||
* Instance declaring destroy method.
|
||||
* @author mse
|
||||
*/
|
||||
class Destroyable {
|
||||
public:
|
||||
POINTER_DEFINITIONS(Destroyable);
|
||||
/**
|
||||
* Destroy this instance.
|
||||
*/
|
||||
virtual void destroy() = 0;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Do not allow delete on this instance and derived classes, destroy() must be used instead.
|
||||
*/
|
||||
virtual ~Destroyable() {};
|
||||
};
|
||||
|
||||
}}
|
||||
#endif /* DESTROYABLE_H */
|
||||
@@ -1,30 +0,0 @@
|
||||
/* event.h */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
#ifndef EVENT_H
|
||||
#define EVENT_H
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <epicsEvent.h>
|
||||
#include <pv/noDefaultMethods.h>
|
||||
#include <pv/pvType.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
class Event : private NoDefaultMethods {
|
||||
public:
|
||||
explicit Event(bool = false);
|
||||
~Event();
|
||||
void signal();
|
||||
bool wait (); /* blocks until full */
|
||||
bool wait ( double timeOut ); /* false if empty at time out */
|
||||
bool tryWait (); /* false if empty */
|
||||
private:
|
||||
epicsEventId id;
|
||||
};
|
||||
|
||||
}}
|
||||
#endif /* EVENT_H */
|
||||
@@ -1,162 +0,0 @@
|
||||
/* executor.cpp */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <pv/linkedList.h>
|
||||
#include <pv/lock.h>
|
||||
#include <pv/thread.h>
|
||||
#include <pv/event.h>
|
||||
#include <pv/executor.h>
|
||||
#include <pv/CDRMonitor.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
// special instance to stop the executor thread
|
||||
static
|
||||
class ExecutorShutdown : public Command {
|
||||
virtual void command(){};
|
||||
} executorShutdown;
|
||||
|
||||
static
|
||||
Command *shutdown=&executorShutdown;
|
||||
|
||||
PVDATA_REFCOUNT_MONITOR_DEFINE(executor);
|
||||
|
||||
typedef LinkedListNode<ExecutorNode> ExecutorListNode;
|
||||
typedef LinkedList<ExecutorNode> ExecutorList;
|
||||
|
||||
class ExecutorNode {
|
||||
public:
|
||||
ExecutorNode(Command *command);
|
||||
|
||||
Command *command;
|
||||
ExecutorListNode node;
|
||||
ExecutorListNode runNode;
|
||||
};
|
||||
|
||||
ExecutorNode::ExecutorNode(Command *command)
|
||||
: command(command),
|
||||
node(*this),
|
||||
runNode(*this)
|
||||
{}
|
||||
|
||||
class ExecutorPvt : public Runnable{
|
||||
public:
|
||||
ExecutorPvt(String threadName,ThreadPriority priority);
|
||||
~ExecutorPvt();
|
||||
ExecutorNode * createNode(Command *command);
|
||||
void execute(ExecutorNode *node);
|
||||
virtual void run();
|
||||
private:
|
||||
ExecutorList executorList;
|
||||
ExecutorList runList;
|
||||
Event moreWork;
|
||||
Event stopped;
|
||||
Mutex mutex;
|
||||
Thread thread;
|
||||
};
|
||||
|
||||
ExecutorPvt::ExecutorPvt(String threadName,ThreadPriority priority)
|
||||
: executorList(),
|
||||
runList(),
|
||||
moreWork(),
|
||||
stopped(),
|
||||
mutex(),
|
||||
thread(threadName,priority,this)
|
||||
{}
|
||||
|
||||
ExecutorPvt::~ExecutorPvt()
|
||||
{
|
||||
ExecutorNode shutdownNode(shutdown);
|
||||
|
||||
execute(&shutdownNode);
|
||||
stopped.wait();
|
||||
|
||||
// The thread signals 'stopped' while still holding
|
||||
// the lock. By taking it we wait for the run() function
|
||||
// to actually return
|
||||
Lock xx(mutex);
|
||||
|
||||
ExecutorListNode *node;
|
||||
while((node=executorList.removeHead())!=0) {
|
||||
delete &node->getObject();
|
||||
}
|
||||
}
|
||||
|
||||
void ExecutorPvt::run()
|
||||
{
|
||||
Lock xx(mutex);
|
||||
while(true) {
|
||||
ExecutorListNode * executorListNode = 0;
|
||||
while(runList.isEmpty()) {
|
||||
xx.unlock();
|
||||
moreWork.wait();
|
||||
xx.lock();
|
||||
}
|
||||
executorListNode = runList.removeHead();
|
||||
|
||||
if(!executorListNode) continue;
|
||||
Command *cmd=executorListNode->getObject().command;
|
||||
|
||||
if(cmd==shutdown) break;
|
||||
|
||||
xx.unlock();
|
||||
try {
|
||||
executorListNode->getObject().command->command();
|
||||
}catch(std::exception& e){
|
||||
//TODO: feed into logging mechanism
|
||||
fprintf(stderr, "Executor: Unhandled exception: %s",e.what());
|
||||
}catch(...){
|
||||
fprintf(stderr, "Executor: Unhandled exception");
|
||||
}
|
||||
|
||||
xx.lock();
|
||||
}
|
||||
|
||||
stopped.signal();
|
||||
}
|
||||
|
||||
ExecutorNode * ExecutorPvt::createNode(Command *command)
|
||||
{
|
||||
Lock xx(mutex);
|
||||
ExecutorNode *executorNode = new ExecutorNode(command);
|
||||
executorList.addTail(executorNode->node);
|
||||
return executorNode;
|
||||
}
|
||||
|
||||
void ExecutorPvt::execute(ExecutorNode *node)
|
||||
{
|
||||
Lock xx(mutex);
|
||||
if(node->runNode.isOnList()) return;
|
||||
bool isEmpty = runList.isEmpty();
|
||||
runList.addTail(node->runNode);
|
||||
if(isEmpty) moreWork.signal();
|
||||
}
|
||||
|
||||
Executor::Executor(String threadName,ThreadPriority priority)
|
||||
: pImpl(new ExecutorPvt(threadName,priority))
|
||||
{
|
||||
PVDATA_REFCOUNT_MONITOR_CONSTRUCT(executor);
|
||||
}
|
||||
|
||||
Executor::~Executor() {
|
||||
delete pImpl;
|
||||
PVDATA_REFCOUNT_MONITOR_DESTRUCT(executor);
|
||||
}
|
||||
|
||||
ExecutorNode * Executor::createNode(Command*command)
|
||||
{return pImpl->createNode(command);}
|
||||
|
||||
void Executor::execute(ExecutorNode *node) {pImpl->execute(node);}
|
||||
|
||||
}}
|
||||
@@ -1,37 +0,0 @@
|
||||
/* executor.h */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
#ifndef EXECUTOR_H
|
||||
#define EXECUTOR_H
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <pv/noDefaultMethods.h>
|
||||
#include <pv/pvType.h>
|
||||
#include <pv/thread.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
// This is created by Executor.createNode and passed to Executor.execute
|
||||
class ExecutorNode;
|
||||
|
||||
class Command {
|
||||
public:
|
||||
virtual ~Command(){}
|
||||
virtual void command() = 0;
|
||||
};
|
||||
|
||||
class Executor : private NoDefaultMethods {
|
||||
public:
|
||||
Executor(String threadName,ThreadPriority priority);
|
||||
~Executor();
|
||||
ExecutorNode * createNode(Command *command);
|
||||
void execute(ExecutorNode *node);
|
||||
private:
|
||||
class ExecutorPvt *pImpl;
|
||||
};
|
||||
|
||||
}}
|
||||
#endif /* EXECUTOR_H */
|
||||
@@ -1,84 +0,0 @@
|
||||
/* linkedList.h */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
#ifndef LINKEDLIST_H
|
||||
#define LINKEDLIST_H
|
||||
#include <pv/linkedListVoid.h>
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
template <typename T>
|
||||
class LinkedList;
|
||||
|
||||
template <typename T>
|
||||
class LinkedListNode : private LinkedListVoidNode {
|
||||
public:
|
||||
LinkedListNode(T &object) : LinkedListVoidNode(&object){}
|
||||
~LinkedListNode() {}
|
||||
T &getObject() { return *static_cast<T *>(LinkedListVoidNode::getObject());}
|
||||
bool isOnList() {return LinkedListVoidNode::isOnList();}
|
||||
friend class LinkedList<T>;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class LinkedList : private LinkedListVoid {
|
||||
public:
|
||||
LinkedList() : LinkedListVoid() {}
|
||||
~LinkedList() {}
|
||||
int getLength() {return LinkedListVoid::getLength();}
|
||||
void addTail(LinkedListNode<T> &listNode)
|
||||
{
|
||||
LinkedListVoid::addTail(static_cast<LinkedListVoidNode &>(listNode));
|
||||
}
|
||||
void addHead(LinkedListNode<T> &listNode)
|
||||
{
|
||||
LinkedListVoid::addHead(static_cast<LinkedListVoidNode &>(listNode));
|
||||
}
|
||||
void insertAfter(LinkedListNode<T> &listNode,
|
||||
LinkedListNode<T> &addNode)
|
||||
{
|
||||
LinkedListVoid::insertAfter(
|
||||
static_cast<LinkedListVoidNode &>(listNode),
|
||||
static_cast<LinkedListVoidNode &>(addNode));
|
||||
}
|
||||
void insertBefore(LinkedListNode<T> &listNode,
|
||||
LinkedListNode<T> &addNode)
|
||||
{
|
||||
LinkedListVoid::insertBefore(
|
||||
static_cast<LinkedListVoidNode &>(listNode),
|
||||
static_cast<LinkedListVoidNode &>(addNode));
|
||||
}
|
||||
LinkedListNode<T> *removeTail(){
|
||||
return static_cast<LinkedListNode<T> *>(LinkedListVoid::removeTail());
|
||||
}
|
||||
LinkedListNode<T> *removeHead(){
|
||||
return static_cast<LinkedListNode<T> *>(LinkedListVoid::removeHead());
|
||||
}
|
||||
void remove(LinkedListNode<T> &listNode){
|
||||
LinkedListVoid::remove(static_cast<LinkedListVoidNode &>(listNode));
|
||||
}
|
||||
LinkedListNode<T> *getHead(){
|
||||
return static_cast<LinkedListNode<T> *>(LinkedListVoid::getHead());
|
||||
}
|
||||
LinkedListNode<T> *getTail(){
|
||||
return static_cast<LinkedListNode<T> *>(LinkedListVoid::getTail());
|
||||
}
|
||||
LinkedListNode<T> *getNext(LinkedListNode<T> &listNode){
|
||||
return static_cast<LinkedListNode<T> *>(LinkedListVoid::getNext(
|
||||
static_cast<LinkedListVoidNode &>(listNode)));
|
||||
}
|
||||
LinkedListNode<T> *getPrev(LinkedListNode<T> &listNode){
|
||||
return static_cast<LinkedListNode<T> *>(LinkedListVoid::getPrev(
|
||||
static_cast<LinkedListVoidNode &>(listNode)));
|
||||
}
|
||||
bool isEmpty() { return LinkedListVoid::isEmpty();}
|
||||
};
|
||||
|
||||
|
||||
}}
|
||||
#endif /* LINKEDLIST_H */
|
||||
|
||||
|
||||
|
||||
@@ -1,210 +0,0 @@
|
||||
/* linkedListVoid.cpp */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <pv/lock.h>
|
||||
#include <pv/pvType.h>
|
||||
#include <pv/linkedListVoid.h>
|
||||
#include <pv/CDRMonitor.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
static String alreadyOnList("already on list");
|
||||
|
||||
PVDATA_REFCOUNT_MONITOR_DEFINE(LinkedListNode);
|
||||
PVDATA_REFCOUNT_MONITOR_DEFINE(LinkedList);
|
||||
|
||||
LinkedListVoidNode::LinkedListVoidNode(void *object)
|
||||
: object(object),before(0),after(0),linkedListVoid(0)
|
||||
{
|
||||
PVDATA_REFCOUNT_MONITOR_CONSTRUCT(LinkedListNode);
|
||||
}
|
||||
|
||||
LinkedListVoidNode::LinkedListVoidNode(bool isHead)
|
||||
: object(this),before(this),after(this)
|
||||
{
|
||||
PVDATA_REFCOUNT_MONITOR_CONSTRUCT(LinkedListNode);
|
||||
}
|
||||
|
||||
|
||||
LinkedListVoidNode::~LinkedListVoidNode()
|
||||
{
|
||||
PVDATA_REFCOUNT_MONITOR_DESTRUCT(LinkedListNode);
|
||||
}
|
||||
|
||||
void *LinkedListVoidNode::getObject() {
|
||||
return object;
|
||||
}
|
||||
|
||||
bool LinkedListVoidNode::isOnList()
|
||||
{
|
||||
if(before==0 && after==0) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
LinkedListVoid::LinkedListVoid()
|
||||
: head(new LinkedListVoidNode(true)),length(0)
|
||||
{
|
||||
PVDATA_REFCOUNT_MONITOR_CONSTRUCT(LinkedList);
|
||||
}
|
||||
|
||||
LinkedListVoid::~LinkedListVoid()
|
||||
{
|
||||
delete head;
|
||||
PVDATA_REFCOUNT_MONITOR_DESTRUCT(LinkedList);
|
||||
}
|
||||
|
||||
int LinkedListVoid::getLength()
|
||||
{
|
||||
return length;
|
||||
}
|
||||
|
||||
void LinkedListVoid::addTail(LinkedListVoidNode &node)
|
||||
{
|
||||
if(node.before!=0 || node.after!=0) {
|
||||
throw std::logic_error(alreadyOnList);
|
||||
}
|
||||
node.linkedListVoid = this;
|
||||
node.before = head->before;
|
||||
node.after = head;
|
||||
head->before->after = &node;
|
||||
head->before = &node;
|
||||
++length;
|
||||
}
|
||||
|
||||
void LinkedListVoid::addHead(LinkedListVoidNode &node)
|
||||
{
|
||||
if(node.before!=0 || node.after!=0) {
|
||||
throw std::logic_error(alreadyOnList);
|
||||
}
|
||||
node.linkedListVoid = this;
|
||||
node.after = head->after;
|
||||
node.before = head;
|
||||
head->after->before = &node;
|
||||
head->after = &node;
|
||||
++length;
|
||||
}
|
||||
|
||||
void LinkedListVoid::insertAfter(LinkedListVoidNode &node,
|
||||
LinkedListVoidNode &addNode)
|
||||
{
|
||||
LinkedListVoidNode *existingNode = &node;
|
||||
LinkedListVoidNode *newNode = &addNode;
|
||||
if(existingNode->after==0 || existingNode->before==0) {
|
||||
throw std::logic_error(String("listNode not on list"));
|
||||
}
|
||||
if(newNode->before!=0 || newNode->after!=0) {
|
||||
throw std::logic_error(alreadyOnList);
|
||||
}
|
||||
if(node.linkedListVoid!=this) {
|
||||
throw std::logic_error(String("node not on this list"));
|
||||
}
|
||||
newNode->linkedListVoid = this;
|
||||
newNode->after = existingNode->after;
|
||||
newNode->before = existingNode;
|
||||
existingNode->after->before = newNode;
|
||||
existingNode->after = newNode;
|
||||
++length;
|
||||
}
|
||||
|
||||
void LinkedListVoid::insertBefore(LinkedListVoidNode &node,
|
||||
LinkedListVoidNode &addNode)
|
||||
{
|
||||
LinkedListVoidNode *existingNode = &node;
|
||||
LinkedListVoidNode *newNode = &addNode;
|
||||
if(existingNode->after==0 || existingNode->before==0) {
|
||||
throw std::logic_error(String("listNode not on list"));
|
||||
}
|
||||
if(newNode->before!=0 || newNode->after!=0) {
|
||||
throw std::logic_error(alreadyOnList);
|
||||
}
|
||||
if(node.linkedListVoid!=this) {
|
||||
throw std::logic_error(String("node not on this list"));
|
||||
}
|
||||
newNode->linkedListVoid = this;
|
||||
newNode->after = existingNode;
|
||||
newNode->before = existingNode->before;
|
||||
existingNode->before->after = newNode;
|
||||
existingNode->before = newNode;
|
||||
++length;
|
||||
}
|
||||
|
||||
LinkedListVoidNode *LinkedListVoid::removeTail()
|
||||
{
|
||||
if(head->after==head) return 0;
|
||||
LinkedListVoidNode *node = head->before;
|
||||
remove(*head->before);
|
||||
return node;
|
||||
}
|
||||
|
||||
LinkedListVoidNode *LinkedListVoid::removeHead()
|
||||
{
|
||||
if(head->after==head) return 0;
|
||||
LinkedListVoidNode *node = head->after;
|
||||
remove(*head->after);
|
||||
return node;
|
||||
}
|
||||
|
||||
void LinkedListVoid::remove(LinkedListVoidNode &node)
|
||||
{
|
||||
if(node.before==0 || node.after==0) {
|
||||
throw std::logic_error(String("node not on list"));
|
||||
}
|
||||
if(node.linkedListVoid!=this) {
|
||||
throw std::logic_error(String("node not on this list"));
|
||||
}
|
||||
node.linkedListVoid = 0;
|
||||
LinkedListVoidNode *prev = node.before;
|
||||
LinkedListVoidNode *next = node.after;
|
||||
node.after = node.before = 0;
|
||||
prev->after = next;
|
||||
next->before = prev;
|
||||
length--;
|
||||
}
|
||||
|
||||
LinkedListVoidNode *LinkedListVoid::getHead()
|
||||
{
|
||||
if(head->after==head) return 0;
|
||||
return head->after;
|
||||
}
|
||||
|
||||
LinkedListVoidNode *LinkedListVoid::getTail()
|
||||
{
|
||||
if(head->after==head) return 0;
|
||||
return head->before;
|
||||
}
|
||||
|
||||
LinkedListVoidNode *LinkedListVoid::getNext(LinkedListVoidNode &listNode)
|
||||
{
|
||||
if(listNode.linkedListVoid!=this) {
|
||||
throw std::logic_error(String("node not on this list"));
|
||||
}
|
||||
if(listNode.after==head) return 0;
|
||||
return listNode.after;
|
||||
}
|
||||
|
||||
LinkedListVoidNode *LinkedListVoid::getPrev(LinkedListVoidNode &listNode)
|
||||
{
|
||||
if(listNode.linkedListVoid!=this) {
|
||||
throw std::logic_error(String("node not on this list"));
|
||||
}
|
||||
if(listNode.before==head) return 0;
|
||||
return listNode.before;
|
||||
}
|
||||
|
||||
bool LinkedListVoid::isEmpty()
|
||||
{
|
||||
if(head->after==head) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
}}
|
||||
@@ -1,68 +0,0 @@
|
||||
/* linkedListVoid.h */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
|
||||
#ifndef LINKEDLISTVOID_H
|
||||
#define LINKEDLISTVOID_H
|
||||
#include <pv/pvType.h>
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
class LinkedListVoid;
|
||||
class LinkedListVoidNode;
|
||||
|
||||
class LinkedListVoidNode {
|
||||
public:
|
||||
~LinkedListVoidNode();
|
||||
void *getObject();
|
||||
bool isOnList();
|
||||
protected:
|
||||
LinkedListVoidNode(void *object);
|
||||
private:
|
||||
LinkedListVoidNode(bool isHead);
|
||||
friend class LinkedListVoid;
|
||||
void *object;
|
||||
LinkedListVoidNode *before;
|
||||
LinkedListVoidNode *after;
|
||||
LinkedListVoid *linkedListVoid;
|
||||
// do not implement the following
|
||||
LinkedListVoidNode(const LinkedListVoidNode&);
|
||||
LinkedListVoidNode & operator=(const LinkedListVoidNode&);
|
||||
};
|
||||
|
||||
class LinkedListVoid {
|
||||
public:
|
||||
~LinkedListVoid();
|
||||
int getLength();
|
||||
void addTail(LinkedListVoidNode &listNode);
|
||||
void addHead(LinkedListVoidNode &listNode);
|
||||
void insertAfter(LinkedListVoidNode &listNode,
|
||||
LinkedListVoidNode &addNode);
|
||||
void insertBefore(LinkedListVoidNode &listNode,
|
||||
LinkedListVoidNode &addNode);
|
||||
LinkedListVoidNode *removeTail();
|
||||
LinkedListVoidNode *removeHead();
|
||||
void remove(LinkedListVoidNode &listNode);
|
||||
LinkedListVoidNode *getHead();
|
||||
LinkedListVoidNode *getTail();
|
||||
LinkedListVoidNode *getNext(LinkedListVoidNode &listNode);
|
||||
LinkedListVoidNode *getPrev(LinkedListVoidNode &listNode);
|
||||
bool isEmpty();
|
||||
protected:
|
||||
LinkedListVoid();
|
||||
private:
|
||||
friend class LinkedListVoidNode;
|
||||
LinkedListVoidNode *head;
|
||||
int length;
|
||||
// do not implement the following
|
||||
LinkedListVoid(const LinkedListVoid&);
|
||||
LinkedListVoid & operator=(const LinkedListVoid&);
|
||||
};
|
||||
|
||||
}}
|
||||
#endif /* LINKEDLISTVOID_H */
|
||||
|
||||
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
/* lock.h */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
#ifndef LOCK_H
|
||||
#define LOCK_H
|
||||
#include <stdexcept>
|
||||
#include <epicsMutex.h>
|
||||
#include <pv/noDefaultMethods.h>
|
||||
/* This is based on item 14 of
|
||||
* Effective C++, Third Edition, Scott Meyers
|
||||
*/
|
||||
|
||||
// TODO reference counting lock to allow recursions
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
typedef epicsMutex Mutex;
|
||||
|
||||
class Lock : private NoDefaultMethods {
|
||||
public:
|
||||
explicit Lock(Mutex &m)
|
||||
: mutexPtr(m), locked(true)
|
||||
{ mutexPtr.lock();}
|
||||
~Lock(){unlock();}
|
||||
void lock()
|
||||
{
|
||||
if(!locked)
|
||||
{
|
||||
mutexPtr.lock();
|
||||
locked = true;
|
||||
}
|
||||
}
|
||||
void unlock()
|
||||
{
|
||||
if(locked)
|
||||
{
|
||||
mutexPtr.unlock();
|
||||
locked=false;
|
||||
}
|
||||
}
|
||||
bool ownsLock() const{return locked;}
|
||||
private:
|
||||
Mutex &mutexPtr;
|
||||
bool locked;
|
||||
};
|
||||
|
||||
|
||||
}}
|
||||
#endif /* LOCK_H */
|
||||
@@ -1,136 +0,0 @@
|
||||
/* messageQueue.cpp */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <pv/pvType.h>
|
||||
#include <pv/lock.h>
|
||||
#include <pv/requester.h>
|
||||
#include <pv/noDefaultMethods.h>
|
||||
#include <pv/CDRMonitor.h>
|
||||
#include <pv/queue.h>
|
||||
#include <pv/messageQueue.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
PVDATA_REFCOUNT_MONITOR_DEFINE(messageQueue);
|
||||
|
||||
typedef MessageNode * MessageNodePtr;
|
||||
typedef QueueElement<MessageNode> MessageElement;
|
||||
typedef MessageElement *MessageElementPtr;
|
||||
typedef Queue<MessageNode> MessageNodeQueue;
|
||||
|
||||
|
||||
MessageNode::MessageNode()
|
||||
: message(String()),messageType(infoMessage){}
|
||||
|
||||
MessageNode::~MessageNode() {
|
||||
}
|
||||
|
||||
String MessageNode::getMessage() const { return message;};
|
||||
|
||||
MessageType MessageNode::getMessageType() const { return messageType;}
|
||||
|
||||
void MessageNode::setMessageNull() {message = String();}
|
||||
|
||||
class MessageQueuePvt {
|
||||
public:
|
||||
MessageNodePtr *messageNodeArray;
|
||||
MessageNodeQueue *queue;
|
||||
MessageNodePtr lastPut;
|
||||
MessageElementPtr lastGet;
|
||||
int size;
|
||||
int overrun;
|
||||
};
|
||||
|
||||
MessageQueue::MessageQueue(int size)
|
||||
: pImpl(new MessageQueuePvt)
|
||||
{
|
||||
PVDATA_REFCOUNT_MONITOR_CONSTRUCT(messageQueue);
|
||||
pImpl->size = size;
|
||||
pImpl->overrun = 0;
|
||||
pImpl->lastPut = 0;
|
||||
pImpl->lastGet = 0;
|
||||
pImpl->messageNodeArray = new MessageNodePtr[size];
|
||||
for(int i=0; i<size; i++) {
|
||||
pImpl->messageNodeArray[i] = new MessageNode();
|
||||
}
|
||||
pImpl->queue = new MessageNodeQueue(pImpl->messageNodeArray,size);
|
||||
}
|
||||
|
||||
MessageQueue::~MessageQueue()
|
||||
{
|
||||
delete pImpl->queue;
|
||||
for(int i=0; i< pImpl->size; i++) {
|
||||
delete pImpl->messageNodeArray[i];
|
||||
}
|
||||
delete[] pImpl->messageNodeArray;
|
||||
PVDATA_REFCOUNT_MONITOR_DESTRUCT(messageQueue);
|
||||
}
|
||||
|
||||
MessageNode *MessageQueue::get() {
|
||||
if(pImpl->lastGet!=0) {
|
||||
throw std::logic_error(
|
||||
String("MessageQueue::get() but did not release last"));
|
||||
}
|
||||
MessageElementPtr element = pImpl->queue->getUsed();
|
||||
if(element==0) return 0;
|
||||
pImpl->lastGet = element;
|
||||
return element->getObject();
|
||||
}
|
||||
|
||||
void MessageQueue::release() {
|
||||
if(pImpl->lastGet==0) return;
|
||||
pImpl->queue->releaseUsed(pImpl->lastGet);
|
||||
pImpl->lastGet = 0;
|
||||
}
|
||||
|
||||
bool MessageQueue::put(String message,MessageType messageType,bool replaceLast)
|
||||
{
|
||||
MessageElementPtr element = pImpl->queue->getFree();
|
||||
if(element!=0) {
|
||||
MessageNodePtr node = element->getObject();
|
||||
node->message = message;
|
||||
node->messageType = messageType;
|
||||
pImpl->lastPut = node;
|
||||
pImpl->queue->setUsed(element);
|
||||
return true;
|
||||
}
|
||||
pImpl->overrun++;
|
||||
if(replaceLast) {
|
||||
MessageNodePtr node = pImpl->lastPut;
|
||||
node->message = message;
|
||||
node->messageType = messageType;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MessageQueue::isEmpty() const
|
||||
{
|
||||
int free = pImpl->queue->getNumberFree();
|
||||
if(free==pImpl->size) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MessageQueue::isFull() const
|
||||
{
|
||||
if(pImpl->queue->getNumberFree()==0) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
int MessageQueue::getClearOverrun()
|
||||
{
|
||||
int num = pImpl->overrun;
|
||||
pImpl->overrun = 0;
|
||||
return num;
|
||||
}
|
||||
|
||||
}}
|
||||
@@ -1,48 +0,0 @@
|
||||
/* messageQueue.h */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
#ifndef MESSAGEQUEUE_H
|
||||
#define MESSAGEQUEUE_H
|
||||
#include <pv/pvType.h>
|
||||
#include <pv/requester.h>
|
||||
#include <pv/noDefaultMethods.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
class MessageNode {
|
||||
public:
|
||||
String getMessage() const;
|
||||
MessageType getMessageType() const;
|
||||
void setMessageNull();
|
||||
private:
|
||||
MessageNode();
|
||||
~MessageNode();
|
||||
friend class MessageQueue;
|
||||
String message;
|
||||
MessageType messageType;
|
||||
};
|
||||
|
||||
class MessageQueue : private NoDefaultMethods {
|
||||
public:
|
||||
MessageQueue(int size);
|
||||
~MessageQueue();
|
||||
MessageNode *get();
|
||||
// must call release before next get
|
||||
void release();
|
||||
// return (false,true) if message (was not, was) put into queue
|
||||
bool put(String message,MessageType messageType,bool replaceLast);
|
||||
bool isEmpty() const;
|
||||
bool isFull() const;
|
||||
int getClearOverrun();
|
||||
private:
|
||||
class MessageQueuePvt *pImpl;
|
||||
};
|
||||
|
||||
}}
|
||||
#endif /* MESSAGEQUEUE_H */
|
||||
|
||||
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
/* noDefaultMethods.h */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
#ifndef NO_DEFAULT_METHODS_H
|
||||
#define NO_DEFAULT_METHODS_H
|
||||
namespace epics { namespace pvData {
|
||||
/* This is based on Item 6 of
|
||||
* Effective C++, Third Edition, Scott Meyers
|
||||
*/
|
||||
|
||||
|
||||
class NoDefaultMethods {
|
||||
protected:
|
||||
// allow by derived objects
|
||||
NoDefaultMethods(){};
|
||||
~NoDefaultMethods(){}
|
||||
private:
|
||||
// do not implment
|
||||
NoDefaultMethods(const NoDefaultMethods&);
|
||||
NoDefaultMethods & operator=(const NoDefaultMethods &);
|
||||
};
|
||||
|
||||
}}
|
||||
#endif /* NO_DEFAULT_METHODS_H */
|
||||
@@ -1,54 +0,0 @@
|
||||
/* queue.h */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
#ifndef QUEUE_H
|
||||
#define QUEUE_H
|
||||
#include <pv/queueVoid.h>
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
template <typename T>
|
||||
class Queue;
|
||||
|
||||
template <typename T>
|
||||
class QueueElement;
|
||||
|
||||
template <typename T>
|
||||
class QueueElement : private QueueElementVoid {
|
||||
public:
|
||||
T *getObject() { return static_cast<T *>(QueueElementVoid::getObject());}
|
||||
protected:
|
||||
QueueElement(T *object) : QueueElementVoid(static_cast<void *>(object)){}
|
||||
~QueueElement() {}
|
||||
friend class Queue<T>;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class Queue : private QueueVoid {
|
||||
public:
|
||||
Queue(T *array[],int number)
|
||||
: QueueVoid((ObjectPtr*)array,number)
|
||||
//: QueueVoid(static_cast<ObjectPtr*>(array),number)
|
||||
{}
|
||||
~Queue() {}
|
||||
void clear() {QueueVoid::clear();}
|
||||
int getNumberFree() {return QueueVoid::getNumberFree();}
|
||||
int capacity() {return QueueVoid::capacity();}
|
||||
QueueElement<T> *getFree() {
|
||||
return static_cast<QueueElement<T> *>(QueueVoid::getFree());}
|
||||
void setUsed(QueueElement<T> *queueElement) {
|
||||
QueueVoid::setUsed(static_cast<QueueElementVoid *>(queueElement));}
|
||||
QueueElement<T> *getUsed() {
|
||||
return static_cast<QueueElement<T> *>(QueueVoid::getUsed());}
|
||||
void releaseUsed(QueueElement<T> *queueElement) {
|
||||
QueueVoid::releaseUsed(static_cast<QueueElementVoid *>(queueElement));}
|
||||
};
|
||||
|
||||
|
||||
}}
|
||||
#endif /* QUEUE_H */
|
||||
|
||||
|
||||
|
||||
@@ -1,120 +0,0 @@
|
||||
/* queueVoid.cpp */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <pv/lock.h>
|
||||
#include <pv/pvType.h>
|
||||
#include <pv/queueVoid.h>
|
||||
#include <pv/CDRMonitor.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
PVDATA_REFCOUNT_MONITOR_DEFINE(queueElement);
|
||||
PVDATA_REFCOUNT_MONITOR_DEFINE(queue);
|
||||
|
||||
QueueElementVoid::QueueElementVoid(ObjectPtr object)
|
||||
: object(object)
|
||||
{
|
||||
PVDATA_REFCOUNT_MONITOR_CONSTRUCT(queueElement);
|
||||
}
|
||||
|
||||
|
||||
QueueElementVoid::~QueueElementVoid()
|
||||
{
|
||||
PVDATA_REFCOUNT_MONITOR_DESTRUCT(queueElement);
|
||||
}
|
||||
|
||||
ObjectPtr QueueElementVoid::getObject() {
|
||||
return object;
|
||||
}
|
||||
|
||||
|
||||
|
||||
QueueVoid::QueueVoid(ObjectPtr object[],int number)
|
||||
: array(new QueueElementVoidPtr[number]),number(number),
|
||||
numberFree(number),numberUsed(0),
|
||||
nextGetFree(0),nextSetUsed(),
|
||||
nextGetUsed(0),nextReleaseUsed(0)
|
||||
{
|
||||
for(int i=0; i<number; i++) {
|
||||
array[i] = new QueueElementVoid(object[i]);
|
||||
}
|
||||
PVDATA_REFCOUNT_MONITOR_CONSTRUCT(queue);
|
||||
}
|
||||
|
||||
QueueVoid::~QueueVoid()
|
||||
{
|
||||
for(int i=0; i<number; i++) {
|
||||
delete array[i];
|
||||
}
|
||||
delete[]array;
|
||||
PVDATA_REFCOUNT_MONITOR_DESTRUCT(queue);
|
||||
}
|
||||
|
||||
void QueueVoid::clear()
|
||||
{
|
||||
numberFree = number;
|
||||
numberUsed = 0;
|
||||
nextGetFree = 0;
|
||||
nextSetUsed = 0;
|
||||
nextGetUsed = 0;
|
||||
nextReleaseUsed = 0;
|
||||
}
|
||||
|
||||
int QueueVoid::getNumberFree()
|
||||
{
|
||||
return numberFree;
|
||||
}
|
||||
|
||||
int QueueVoid::capacity()
|
||||
{
|
||||
return number;
|
||||
}
|
||||
|
||||
QueueElementVoid * QueueVoid::getFree()
|
||||
{
|
||||
if(numberFree==0) return 0;
|
||||
numberFree--;
|
||||
QueueElementVoid *queueElement = array[nextGetFree++];
|
||||
if(nextGetFree>=number) nextGetFree = 0;
|
||||
return queueElement;
|
||||
}
|
||||
|
||||
void QueueVoid::setUsed(QueueElementVoid *queueElement)
|
||||
{
|
||||
if(queueElement!=array[nextSetUsed++]) {
|
||||
throw std::logic_error(String("not correct queueElement"));
|
||||
}
|
||||
numberUsed++;
|
||||
if(nextSetUsed>=number) nextSetUsed = 0;
|
||||
}
|
||||
|
||||
QueueElementVoid * QueueVoid::getUsed()
|
||||
{
|
||||
if(numberUsed==0) return 0;
|
||||
QueueElementVoid *queueElement = array[nextGetUsed++];
|
||||
if(nextGetUsed>=number) nextGetUsed = 0;
|
||||
return queueElement;
|
||||
}
|
||||
|
||||
void QueueVoid::releaseUsed(QueueElementVoid *queueElement)
|
||||
{
|
||||
if(queueElement!=array[nextReleaseUsed++]) {
|
||||
throw std::logic_error(String(
|
||||
"not queueElement returned by last call to getUsed"));
|
||||
}
|
||||
if(nextReleaseUsed>=number) nextReleaseUsed = 0;
|
||||
numberUsed--;
|
||||
numberFree++;
|
||||
}
|
||||
|
||||
}}
|
||||
@@ -1,56 +0,0 @@
|
||||
/* queueVoid.h */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
#ifndef QUEUEVOID_H
|
||||
#define QUEUEVOID_H
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
class QueueVoid;
|
||||
class QueueElementVoid;
|
||||
|
||||
typedef void * ObjectPtr;
|
||||
typedef QueueElementVoid * QueueElementVoidPtr;
|
||||
typedef QueueElementVoidPtr * QueueElementVoidPtrArray;
|
||||
|
||||
class QueueElementVoid {
|
||||
protected:
|
||||
ObjectPtr getObject();
|
||||
QueueElementVoid(ObjectPtr object);
|
||||
~QueueElementVoid();
|
||||
ObjectPtr object;
|
||||
friend class QueueVoid;
|
||||
};
|
||||
|
||||
|
||||
class QueueVoid {
|
||||
protected:
|
||||
QueueVoid(ObjectPtr array[],int number);
|
||||
~QueueVoid();
|
||||
void clear();
|
||||
int getNumberFree();
|
||||
int capacity();
|
||||
QueueElementVoidPtr getFree();
|
||||
void setUsed(QueueElementVoid *queueElement);
|
||||
QueueElementVoid *getUsed();
|
||||
void releaseUsed(QueueElementVoid *queueElement);
|
||||
private:
|
||||
friend class QueueElementVoid;
|
||||
QueueElementVoidPtrArray array;
|
||||
int number;
|
||||
int numberFree;
|
||||
int numberUsed;
|
||||
int nextGetFree;
|
||||
int nextSetUsed;
|
||||
int nextGetUsed;
|
||||
int nextReleaseUsed;
|
||||
};
|
||||
|
||||
|
||||
}}
|
||||
#endif /* QUEUEVOID_H */
|
||||
|
||||
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
/* requester.cpp */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
#include <string>
|
||||
#include <pv/requester.h>
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
const size_t messageTypeCount = 4;
|
||||
static std::string typeName[messageTypeCount] = {
|
||||
String("info"),
|
||||
String("warning"),
|
||||
String("error"),
|
||||
String("fatalError")
|
||||
};
|
||||
|
||||
StringArray messageTypeName = typeName;
|
||||
}}
|
||||
@@ -1,33 +0,0 @@
|
||||
/* requester.h */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
#ifndef REQUESTER_H
|
||||
#define REQUESTER_H
|
||||
#include <string>
|
||||
#include <pv/pvType.h>
|
||||
#include <pv/sharedPtr.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
class Requester;
|
||||
|
||||
enum MessageType {
|
||||
infoMessage,warningMessage,errorMessage,fatalErrorMessage
|
||||
};
|
||||
|
||||
extern StringArray messageTypeName;
|
||||
extern const size_t messageTypeCount;
|
||||
class Requester {
|
||||
public:
|
||||
POINTER_DEFINITIONS(Requester);
|
||||
|
||||
virtual ~Requester(){}
|
||||
virtual String getRequesterName() = 0;
|
||||
virtual void message(String message,MessageType messageType) = 0;
|
||||
};
|
||||
|
||||
}}
|
||||
#endif /* REQUESTER_H */
|
||||
@@ -1,61 +0,0 @@
|
||||
/* serialize.h */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
#ifndef SERIALIZE_H
|
||||
#define SERIALIZE_H
|
||||
#include <pv/byteBuffer.h>
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
class SerializableControl;
|
||||
class DeserializableControl;
|
||||
class Serializable;
|
||||
class BitSetSerializable;
|
||||
class SerializableArray;
|
||||
class BitSet;
|
||||
|
||||
class SerializableControl {
|
||||
public:
|
||||
virtual ~SerializableControl(){}
|
||||
virtual void flushSerializeBuffer() =0;
|
||||
virtual void ensureBuffer(int size) =0;
|
||||
virtual void alignBuffer(int alignment) =0;
|
||||
};
|
||||
|
||||
class DeserializableControl {
|
||||
public:
|
||||
virtual ~DeserializableControl(){}
|
||||
virtual void ensureData(int size) =0;
|
||||
virtual void alignData(int alignment) =0;
|
||||
};
|
||||
|
||||
class Serializable {
|
||||
public:
|
||||
virtual ~Serializable(){}
|
||||
virtual void serialize(ByteBuffer *buffer,
|
||||
SerializableControl *flusher) const = 0;
|
||||
virtual void deserialize(ByteBuffer *buffer,
|
||||
DeserializableControl *flusher) = 0;
|
||||
};
|
||||
|
||||
class BitSetSerializable {
|
||||
public:
|
||||
virtual ~BitSetSerializable(){}
|
||||
virtual void serialize(ByteBuffer *buffer,
|
||||
SerializableControl *flusher,BitSet *bitSet) const = 0;
|
||||
virtual void deserialize(ByteBuffer *buffer,
|
||||
DeserializableControl *flusher,BitSet *bitSet) = 0;
|
||||
};
|
||||
|
||||
|
||||
class SerializableArray : virtual public Serializable {
|
||||
public:
|
||||
virtual ~SerializableArray(){}
|
||||
virtual void serialize(ByteBuffer *buffer,
|
||||
SerializableControl *flusher, int offset, int count) const = 0;
|
||||
};
|
||||
|
||||
}}
|
||||
#endif /* SERIALIZE_H */
|
||||
@@ -1,144 +0,0 @@
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/*
|
||||
* serializeHelper.cpp
|
||||
*
|
||||
* Created on: Oct 22, 2010
|
||||
* Author: Miha vitorovic
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <pv/pvType.h>
|
||||
|
||||
#include <pv/epicsException.h>
|
||||
#include <pv/byteBuffer.h>
|
||||
#include <pv/serializeHelper.h>
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace epics {
|
||||
namespace pvData {
|
||||
|
||||
void SerializeHelper::writeSize(int s, ByteBuffer* buffer,
|
||||
SerializableControl* flusher) {
|
||||
flusher->ensureBuffer(sizeof(int64)+1);
|
||||
SerializeHelper::writeSize(s, buffer);
|
||||
}
|
||||
|
||||
void SerializeHelper::writeSize(int s, ByteBuffer* buffer) {
|
||||
if(s==-1) // null
|
||||
buffer->putByte(-1);
|
||||
else if(s<254)
|
||||
buffer->putByte(s);
|
||||
else
|
||||
{
|
||||
buffer->putByte(-2);
|
||||
buffer->putInt(s); // (byte)-2 + size
|
||||
}
|
||||
}
|
||||
|
||||
int SerializeHelper::readSize(ByteBuffer* buffer,
|
||||
DeserializableControl* control) {
|
||||
control->ensureData(1);
|
||||
int8 b = buffer->getByte();
|
||||
if(b==-1)
|
||||
return -1;
|
||||
else if(b==-2) {
|
||||
control->ensureData(sizeof(int32));
|
||||
int32 s = buffer->getInt();
|
||||
if(s<0) THROW_BASE_EXCEPTION("negative size");
|
||||
return s;
|
||||
}
|
||||
else
|
||||
return (int)(b<0 ? b+256 : b);
|
||||
}
|
||||
|
||||
void SerializeHelper::serializeString(const String& value,
|
||||
ByteBuffer* buffer, SerializableControl* flusher) {
|
||||
int len = value.length();
|
||||
SerializeHelper::writeSize(len, buffer, flusher);
|
||||
if (len<=0) return;
|
||||
int i = 0;
|
||||
while(true) {
|
||||
int maxToWrite = min(len-i, (int)buffer->getRemaining());
|
||||
buffer->put(value.data(), i, maxToWrite); // ASCII
|
||||
i += maxToWrite;
|
||||
if(i<len)
|
||||
flusher->flushSerializeBuffer();
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void SerializeHelper::serializeSubstring(const String& value,
|
||||
int offset, int count, ByteBuffer* buffer,
|
||||
SerializableControl* flusher) {
|
||||
if(offset<0)
|
||||
offset = 0;
|
||||
else if(offset>(int)value.length()) offset = value.length();
|
||||
|
||||
if(offset+count>(int)value.length()) count = value.length()-offset;
|
||||
|
||||
SerializeHelper::writeSize(count, buffer, flusher);
|
||||
if (count<=0) return;
|
||||
int i = 0;
|
||||
while(true) {
|
||||
int maxToWrite = min(count-i, (int)buffer->getRemaining());
|
||||
buffer->put(value.data(), offset+i, maxToWrite); // ASCII
|
||||
i += maxToWrite;
|
||||
if(i<count)
|
||||
flusher->flushSerializeBuffer();
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static String emptyString;
|
||||
|
||||
String SerializeHelper::deserializeString(ByteBuffer* buffer,
|
||||
DeserializableControl* control) {
|
||||
|
||||
int size = SerializeHelper::readSize(buffer, control);
|
||||
if(size>0)
|
||||
{
|
||||
if ((int)buffer->getRemaining()>=size)
|
||||
{
|
||||
// entire string is in buffer, simply create a string out of it (copy)
|
||||
int pos = buffer->getPosition();
|
||||
String str(buffer->getArray()+pos, size);
|
||||
buffer->setPosition(pos+size);
|
||||
return str;
|
||||
}
|
||||
else
|
||||
{
|
||||
String str;
|
||||
str.reserve(size);
|
||||
try {
|
||||
int i = 0;
|
||||
while(true) {
|
||||
int toRead = min(size-i, (int)buffer->getRemaining());
|
||||
int pos = buffer->getPosition();
|
||||
str.append(buffer->getArray()+pos, toRead);
|
||||
buffer->setPosition(pos+toRead);
|
||||
i += toRead;
|
||||
if(i<size)
|
||||
control->ensureData(1); // at least one
|
||||
else
|
||||
break;
|
||||
}
|
||||
return str;
|
||||
} catch(...) {
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
return emptyString;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
|
||||
#ifndef SHAREDPTR_H
|
||||
#define SHAREDPTR_H
|
||||
|
||||
/*
|
||||
* Pulls in the std::tr1 namespace with the following names
|
||||
*
|
||||
* class shared_ptr
|
||||
* class weak_ptr
|
||||
* class bad_weak_ptr
|
||||
* function static_pointer_cast;
|
||||
* function dynamic_pointer_cast
|
||||
* function const_pointer_cast
|
||||
* function swap
|
||||
* function get_deleter
|
||||
* function enable_shared_from_this
|
||||
*/
|
||||
|
||||
// where should we look?
|
||||
|
||||
#if defined(__GNUC__) && __GNUC__>=4
|
||||
// GCC >=4.0.0
|
||||
# define SHARED_FROM_TR1
|
||||
|
||||
#elif defined(_MSC_VER) && (_MSC_VER>1500 || defined(_HAS_TR1))
|
||||
// MSVC > 2008, or 2008 w/ SP1
|
||||
# define SHARED_FROM_TR1
|
||||
|
||||
#else
|
||||
# define SHARED_FROM_BOOST
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER>=1600)
|
||||
// MSVC 2010 has it in <memory>
|
||||
# undef SHARED_FROM_BOOST
|
||||
# undef SHARED_FROM_TR1
|
||||
#endif
|
||||
|
||||
// go and get it
|
||||
|
||||
#if defined(SHARED_FROM_TR1)
|
||||
# include <tr1/memory>
|
||||
|
||||
#elif defined(SHARED_FROM_BOOST)
|
||||
# include <boost/tr1/memory.hpp>
|
||||
|
||||
#else
|
||||
// eventually...
|
||||
# include <memory>
|
||||
#endif
|
||||
|
||||
// cleanup
|
||||
|
||||
#ifdef SHARED_FROM_TR1
|
||||
# undef SHARED_FROM_TR1
|
||||
#endif
|
||||
|
||||
#ifdef SHARED_FROM_BOOST
|
||||
# undef SHARED_FROM_BOOST
|
||||
#endif
|
||||
|
||||
#define POINTER_DEFINITIONS(clazz) \
|
||||
typedef std::tr1::shared_ptr<clazz> shared_pointer; \
|
||||
typedef std::tr1::shared_ptr<const clazz> const_shared_pointer; \
|
||||
typedef std::tr1::weak_ptr<clazz> weak_pointer; \
|
||||
typedef std::tr1::weak_ptr<const clazz> const_weak_pointer;
|
||||
|
||||
#endif // SHAREDPTR_H
|
||||
@@ -1,135 +0,0 @@
|
||||
/*pvData.cpp*/
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
#include <pv/status.h>
|
||||
#include <pv/epicsException.h>
|
||||
#include <pv/serializeHelper.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
const char* Status::StatusTypeName[] = { "OK", "WARNING", "ERROR", "FATAL" };
|
||||
epics::pvData::String Status::m_emptyString;
|
||||
|
||||
Status Status::OK;
|
||||
|
||||
//PVDATA_REFCOUNT_MONITOR_DEFINE(status);
|
||||
|
||||
Status::Status() :
|
||||
m_type(STATUSTYPE_OK)
|
||||
{
|
||||
}
|
||||
|
||||
Status::Status(StatusType type, String message) :
|
||||
m_type(type), m_message(message)
|
||||
{
|
||||
if (type == STATUSTYPE_OK)
|
||||
throw std::invalid_argument("type == STATUSTYPE_OK");
|
||||
|
||||
//PVDATA_REFCOUNT_MONITOR_CONSTRUCT(status);
|
||||
}
|
||||
|
||||
Status::Status(StatusType type, String message, String stackDump) :
|
||||
m_type(type), m_message(message), m_stackDump(stackDump)
|
||||
{
|
||||
if (type == STATUSTYPE_OK)
|
||||
throw std::invalid_argument("type == STATUSTYPE_OK");
|
||||
|
||||
//PVDATA_REFCOUNT_MONITOR_CONSTRUCT(status);
|
||||
}
|
||||
|
||||
Status::~Status() {
|
||||
//PVDATA_REFCOUNT_MONITOR_DESTRUCT(status);
|
||||
}
|
||||
|
||||
Status::StatusType Status::getType() const
|
||||
{
|
||||
return m_type;
|
||||
}
|
||||
|
||||
|
||||
epics::pvData::String Status::getMessage() const
|
||||
{
|
||||
return m_message;
|
||||
}
|
||||
|
||||
epics::pvData::String Status::getStackDump() const
|
||||
{
|
||||
return m_stackDump;
|
||||
}
|
||||
|
||||
bool Status::isOK() const
|
||||
{
|
||||
return (m_type == STATUSTYPE_OK);
|
||||
}
|
||||
|
||||
bool Status::isSuccess() const
|
||||
{
|
||||
return (m_type == STATUSTYPE_OK || m_type == STATUSTYPE_WARNING);
|
||||
}
|
||||
|
||||
void Status::serialize(ByteBuffer *buffer, SerializableControl *flusher) const
|
||||
{
|
||||
flusher->ensureBuffer(1);
|
||||
if (m_type == STATUSTYPE_OK)
|
||||
{
|
||||
// special code for okStatus (optimization)
|
||||
buffer->putByte((int8)-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer->putByte((int8)m_type);
|
||||
SerializeHelper::serializeString(m_message, buffer, flusher);
|
||||
SerializeHelper::serializeString(m_stackDump, buffer, flusher);
|
||||
}
|
||||
}
|
||||
|
||||
void Status::deserialize(ByteBuffer *buffer, DeserializableControl *flusher)
|
||||
{
|
||||
flusher->ensureData(1);
|
||||
int8 typeCode = buffer->getByte();
|
||||
if (typeCode == (int8)-1)
|
||||
{
|
||||
// in most of the cases status will be OK, we statistically optimize
|
||||
if (m_type != STATUSTYPE_OK)
|
||||
{
|
||||
m_type = STATUSTYPE_OK;
|
||||
m_message = m_stackDump = m_emptyString;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_type = (StatusType)typeCode;
|
||||
m_message = SerializeHelper::deserializeString(buffer, flusher);
|
||||
m_stackDump = SerializeHelper::deserializeString(buffer, flusher);
|
||||
}
|
||||
}
|
||||
|
||||
String Status::toString() const
|
||||
{
|
||||
String str;
|
||||
toString(&str, 0);
|
||||
return str;
|
||||
}
|
||||
|
||||
void Status::toString(StringBuilder buffer, int indentLevel) const
|
||||
{
|
||||
*buffer += "Status [type=";
|
||||
*buffer += StatusTypeName[m_type];
|
||||
if (!m_message.empty())
|
||||
{
|
||||
*buffer += ", message=";
|
||||
*buffer += m_message;
|
||||
}
|
||||
if (!m_stackDump.empty())
|
||||
{
|
||||
*buffer += ", stackDump=";
|
||||
*buffer += '\n';
|
||||
*buffer += m_stackDump;
|
||||
}
|
||||
*buffer += ']';
|
||||
}
|
||||
|
||||
}}
|
||||
@@ -1,107 +0,0 @@
|
||||
/* status.h */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
#ifndef STATUS_H
|
||||
#define STATUS_H
|
||||
|
||||
#include <pv/serialize.h>
|
||||
#include <pv/byteBuffer.h>
|
||||
#include <pv/sharedPtr.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
/**
|
||||
* Status.
|
||||
* @author mse
|
||||
*/
|
||||
class Status : public epics::pvData::Serializable {
|
||||
public:
|
||||
POINTER_DEFINITIONS(Status);
|
||||
/**
|
||||
* Status type enum.
|
||||
*/
|
||||
enum StatusType {
|
||||
/** Operation completed successfully. */
|
||||
STATUSTYPE_OK,
|
||||
/** Operation completed successfully, but there is a warning message. */
|
||||
STATUSTYPE_WARNING,
|
||||
/** Operation failed due to an error. */
|
||||
STATUSTYPE_ERROR,
|
||||
/** Operation failed due to an unexpected error. */
|
||||
STATUSTYPE_FATAL
|
||||
};
|
||||
|
||||
static const char* StatusTypeName[];
|
||||
|
||||
static Status OK;
|
||||
|
||||
/**
|
||||
* Creates OK status; STATUSTYPE_OK, empty message and stackDump.
|
||||
*/
|
||||
Status();
|
||||
|
||||
/**
|
||||
* Create non-OK status.
|
||||
*/
|
||||
Status(StatusType type, epics::pvData::String message);
|
||||
|
||||
/**
|
||||
* Create non-OK status.
|
||||
*/
|
||||
Status(StatusType type, epics::pvData::String message, epics::pvData::String stackDump);
|
||||
|
||||
~Status();
|
||||
|
||||
/**
|
||||
* Get status type.
|
||||
* @return status type, non-<code>null</code>.
|
||||
*/
|
||||
StatusType getType() const;
|
||||
|
||||
/**
|
||||
* Get error message describing an error. Required if error status.
|
||||
* @return error message.
|
||||
*/
|
||||
epics::pvData::String getMessage() const;
|
||||
|
||||
/**
|
||||
* Get stack dump where error (exception) happened. Optional.
|
||||
* @return stack dump.
|
||||
*/
|
||||
epics::pvData::String getStackDump() const;
|
||||
|
||||
/**
|
||||
* Convenient OK test. Same as <code>(getType() == StatusType.OK)</code>.
|
||||
* NOTE: this will return <code>false</code> on WARNING message although operation succeeded.
|
||||
* To check if operation succeeded, use <code>isSuccess</code>.
|
||||
* @return OK status.
|
||||
* @see #isSuccess()
|
||||
*/
|
||||
bool isOK() const;
|
||||
|
||||
/**
|
||||
* Check if operation succeeded.
|
||||
* @return operation success status.
|
||||
*/
|
||||
bool isSuccess() const;
|
||||
|
||||
String toString() const;
|
||||
void toString(StringBuilder buffer, int indentLevel = 0) const;
|
||||
|
||||
void serialize(ByteBuffer *buffer, SerializableControl *flusher) const;
|
||||
void deserialize(ByteBuffer *buffer, DeserializableControl *flusher);
|
||||
|
||||
private:
|
||||
|
||||
static epics::pvData::String m_emptyString;
|
||||
|
||||
StatusType m_type;
|
||||
String m_message;
|
||||
String m_stackDump;
|
||||
};
|
||||
|
||||
}}
|
||||
#endif /* STATUS_H */
|
||||
@@ -1,63 +0,0 @@
|
||||
/* thread.h */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
#ifndef THREAD_H
|
||||
#define THREAD_H
|
||||
#include <memory>
|
||||
#include <pv/noDefaultMethods.h>
|
||||
#include <pv/pvType.h>
|
||||
|
||||
#include <epicsThread.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
enum ThreadPriority {
|
||||
lowestPriority =epicsThreadPriorityLow,
|
||||
lowerPriority =epicsThreadPriorityLow + 15,
|
||||
lowPriority =epicsThreadPriorityMedium - 15,
|
||||
middlePriority =epicsThreadPriorityMedium,
|
||||
highPriority =epicsThreadPriorityMedium + 15,
|
||||
higherPriority =epicsThreadPriorityHigh - 15,
|
||||
highestPriority =epicsThreadPriorityHigh
|
||||
};
|
||||
|
||||
typedef epicsThreadRunable Runnable;
|
||||
|
||||
class Thread : public epicsThread, private NoDefaultMethods {
|
||||
public:
|
||||
|
||||
Thread(String name,
|
||||
ThreadPriority priority,
|
||||
Runnable *runnable,
|
||||
epicsThreadStackSizeClass stkcls=epicsThreadStackSmall)
|
||||
:epicsThread(*runnable,
|
||||
name.c_str(),
|
||||
epicsThreadGetStackSize(stkcls),
|
||||
priority)
|
||||
{
|
||||
this->start();
|
||||
}
|
||||
|
||||
Thread(Runnable &runnable,
|
||||
String name,
|
||||
unsigned int stksize,
|
||||
unsigned int priority=lowestPriority)
|
||||
:epicsThread(runnable,
|
||||
name.c_str(),
|
||||
stksize,
|
||||
priority)
|
||||
{
|
||||
this->start();
|
||||
}
|
||||
|
||||
~Thread()
|
||||
{
|
||||
this->exitWait();
|
||||
}
|
||||
};
|
||||
|
||||
}}
|
||||
#endif /* THREAD_H */
|
||||
@@ -1,41 +0,0 @@
|
||||
/* timeFunction.cpp */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
#include <pv/noDefaultMethods.h>
|
||||
#include <pv/pvType.h>
|
||||
#include <pv/timeStamp.h>
|
||||
#include <pv/timeFunction.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
TimeFunction::TimeFunction(TimeFunctionRequester *requester)
|
||||
: requester(requester) {}
|
||||
|
||||
|
||||
TimeFunction::~TimeFunction() {}
|
||||
|
||||
double TimeFunction::timeCall()
|
||||
{
|
||||
TimeStamp startTime;
|
||||
TimeStamp endTime;
|
||||
double perCall = 0.0;
|
||||
long ntimes = 1;
|
||||
while(true) {
|
||||
startTime.getCurrent();
|
||||
for(long i=0; i<ntimes; i++) requester->function();
|
||||
endTime.getCurrent();
|
||||
double diff = TimeStamp::diff(endTime,startTime);
|
||||
if(diff>=1.0) {
|
||||
perCall = diff/(double)ntimes;
|
||||
break;
|
||||
}
|
||||
ntimes *= 2;
|
||||
}
|
||||
return perCall;
|
||||
|
||||
}
|
||||
|
||||
}}
|
||||
@@ -1,31 +0,0 @@
|
||||
/* timeFunction.h */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
#ifndef TIMEFUNCTION_H
|
||||
#define TIMEFUNCTION_H
|
||||
#include <pv/noDefaultMethods.h>
|
||||
#include <pv/pvType.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
class TimeFunctionRequester {
|
||||
public:
|
||||
virtual ~TimeFunctionRequester(){}
|
||||
virtual void function() = 0;
|
||||
};
|
||||
|
||||
class TimeFunction : private NoDefaultMethods {
|
||||
public:
|
||||
TimeFunction(TimeFunctionRequester *requester);
|
||||
~TimeFunction();
|
||||
double timeCall();
|
||||
private:
|
||||
TimeFunctionRequester *requester;
|
||||
};
|
||||
|
||||
|
||||
}}
|
||||
#endif /* TIMEFUNCTION_H */
|
||||
@@ -1,234 +0,0 @@
|
||||
/* timer.cpp */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <pv/pvType.h>
|
||||
#include <pv/lock.h>
|
||||
#include <pv/noDefaultMethods.h>
|
||||
#include <pv/CDRMonitor.h>
|
||||
#include <pv/linkedList.h>
|
||||
#include <pv/thread.h>
|
||||
#include <pv/timeStamp.h>
|
||||
#include <pv/timer.h>
|
||||
#include <pv/event.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
PVDATA_REFCOUNT_MONITOR_DEFINE(timerNode);
|
||||
PVDATA_REFCOUNT_MONITOR_DEFINE(timer);
|
||||
|
||||
typedef LinkedListNode<TimerNode::Pvt> TimerListNode;
|
||||
typedef LinkedList<TimerNode::Pvt> TimerList;
|
||||
|
||||
class TimerNode::Pvt {
|
||||
public:
|
||||
TimerNode *timerNode;
|
||||
TimerCallback *callback;
|
||||
TimerListNode timerListNode;
|
||||
TimeStamp timeToRun;
|
||||
Timer::Pvt *timerPvt;
|
||||
double period;
|
||||
Pvt(TimerNode &timerNode,TimerCallback &callback);
|
||||
~Pvt(){}
|
||||
private:
|
||||
};
|
||||
|
||||
TimerNode::Pvt::Pvt(TimerNode &timerNode,TimerCallback &callback)
|
||||
: timerNode(&timerNode),callback(&callback),
|
||||
timerListNode(*this),timeToRun(),
|
||||
timerPvt(0), period(0.0)
|
||||
{}
|
||||
|
||||
struct Timer::Pvt : public Runnable{
|
||||
public:
|
||||
Pvt(String threadName,ThreadPriority priority);
|
||||
virtual void run();
|
||||
public: // only used by this source module
|
||||
TimerList timerList;
|
||||
Mutex mutex;
|
||||
Event waitForWork;
|
||||
Event waitForDone;
|
||||
bool alive;
|
||||
Thread thread;
|
||||
void addElement(TimerNode::Pvt &node);
|
||||
};
|
||||
|
||||
Timer::Pvt::Pvt(String threadName,ThreadPriority priority)
|
||||
: timerList(),
|
||||
mutex(),
|
||||
waitForWork(false),
|
||||
waitForDone(false),
|
||||
alive(true),
|
||||
thread(threadName,priority,this)
|
||||
{}
|
||||
|
||||
void Timer::Pvt::addElement(TimerNode::Pvt &node)
|
||||
{
|
||||
TimerListNode *nextNode = timerList.getHead();
|
||||
if(nextNode==0) {
|
||||
timerList.addTail(node.timerListNode);
|
||||
return;
|
||||
}
|
||||
while(true) {
|
||||
TimerNode::Pvt &timerListNode = nextNode->getObject();
|
||||
if((node.timeToRun)<(timerListNode.timeToRun)) {
|
||||
timerList.insertBefore(timerListNode.timerListNode,node.timerListNode);
|
||||
return;
|
||||
}
|
||||
nextNode = timerList.getNext(timerListNode.timerListNode);
|
||||
if(nextNode==0) {
|
||||
timerList.addTail(node.timerListNode);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TimerNode::TimerNode(TimerCallback &callback)
|
||||
: pImpl(new Pvt(*this,callback))
|
||||
{
|
||||
PVDATA_REFCOUNT_MONITOR_CONSTRUCT(timerNode);
|
||||
}
|
||||
|
||||
|
||||
TimerNode::~TimerNode()
|
||||
{
|
||||
cancel();
|
||||
PVDATA_REFCOUNT_MONITOR_DESTRUCT(timerNode);
|
||||
}
|
||||
|
||||
void TimerNode::cancel()
|
||||
{
|
||||
Timer::Pvt *timerPvt = pImpl->timerPvt;
|
||||
if(timerPvt==0) return;
|
||||
Lock xx(timerPvt->mutex);
|
||||
if(pImpl->timerPvt==0) return;
|
||||
pImpl->timerPvt->timerList.remove(pImpl->timerListNode);
|
||||
pImpl->timerPvt = 0;
|
||||
}
|
||||
|
||||
bool TimerNode::isScheduled()
|
||||
{
|
||||
Timer::Pvt *pvt = pImpl->timerPvt;
|
||||
if(pvt==0) return false;
|
||||
Lock xx(pvt->mutex);
|
||||
return pImpl->timerListNode.isOnList();
|
||||
}
|
||||
|
||||
|
||||
void Timer::Pvt::run()
|
||||
{
|
||||
TimeStamp currentTime;
|
||||
while(true) {
|
||||
currentTime.getCurrent();
|
||||
TimeStamp *timeToRun = 0;
|
||||
double period = 0.0;
|
||||
TimerNode::Pvt *nodeToCall = 0;
|
||||
{
|
||||
Lock xx(mutex);
|
||||
if (!alive) break;
|
||||
TimerListNode *timerListNode = timerList.getHead();
|
||||
if(timerListNode!=0) {
|
||||
TimerNode::Pvt *timerNodePvt = &timerListNode->getObject();
|
||||
timeToRun = &timerNodePvt->timeToRun;
|
||||
double diff = TimeStamp::diff(
|
||||
*timeToRun,currentTime);
|
||||
if(diff<=0.0) {
|
||||
nodeToCall = timerNodePvt;
|
||||
timerList.removeHead();
|
||||
period = timerNodePvt->period;
|
||||
if(period>0.0) {
|
||||
timerNodePvt->timeToRun += period;
|
||||
addElement(*timerNodePvt);
|
||||
} else {
|
||||
timerNodePvt->timerPvt = 0;
|
||||
}
|
||||
timerListNode = timerList.getHead();
|
||||
if(timerListNode!=0) {
|
||||
timerNodePvt = &timerListNode->getObject();
|
||||
timeToRun = &timerNodePvt->timeToRun;
|
||||
} else {
|
||||
timeToRun = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(nodeToCall!=0) {
|
||||
nodeToCall->callback->callback();
|
||||
}
|
||||
{
|
||||
Lock xx(mutex);
|
||||
if(!alive) break;
|
||||
}
|
||||
if(timeToRun==0) {
|
||||
waitForWork.wait();
|
||||
} else {
|
||||
double delay = TimeStamp::diff(*timeToRun,currentTime);
|
||||
waitForWork.wait(delay);
|
||||
}
|
||||
}
|
||||
waitForDone.signal();
|
||||
}
|
||||
|
||||
Timer::Timer(String threadName, ThreadPriority priority)
|
||||
: pImpl(new Pvt(threadName,priority))
|
||||
{
|
||||
PVDATA_REFCOUNT_MONITOR_CONSTRUCT(timer);
|
||||
}
|
||||
|
||||
Timer::~Timer() {
|
||||
{
|
||||
Lock xx(pImpl->mutex);
|
||||
pImpl->alive = false;
|
||||
}
|
||||
pImpl->waitForWork.signal();
|
||||
pImpl->waitForDone.wait();
|
||||
TimerListNode *node = 0;
|
||||
while((node = pImpl->timerList.removeHead())!=0) {
|
||||
node->getObject().callback->timerStopped();
|
||||
}
|
||||
PVDATA_REFCOUNT_MONITOR_DESTRUCT(timer);
|
||||
}
|
||||
|
||||
void Timer::scheduleAfterDelay(TimerNode &timerNode,double delay)
|
||||
{
|
||||
schedulePeriodic(timerNode,delay,0.0);
|
||||
}
|
||||
void Timer::schedulePeriodic(TimerNode &timerNode,double delay,double period)
|
||||
{
|
||||
TimerNode::Pvt *timerNodePvt = timerNode.pImpl.get();
|
||||
if(timerNodePvt->timerListNode.isOnList()) {
|
||||
throw std::logic_error(String("already queued"));
|
||||
}
|
||||
{
|
||||
Lock xx(pImpl->mutex);
|
||||
if(!pImpl->alive) {
|
||||
timerNodePvt->callback->timerStopped();
|
||||
return;
|
||||
}
|
||||
}
|
||||
TimeStamp *timeStamp = &timerNodePvt->timeToRun;
|
||||
timeStamp->getCurrent();
|
||||
*timeStamp += delay;
|
||||
timerNodePvt->period = period;
|
||||
bool isFirst = false;
|
||||
{
|
||||
Lock xx(pImpl->mutex);
|
||||
timerNodePvt->timerPvt = pImpl.get();
|
||||
pImpl->addElement(*timerNodePvt);
|
||||
TimerNode::Pvt *first = &pImpl->timerList.getHead()->getObject();
|
||||
if(first==timerNodePvt) isFirst = true;
|
||||
}
|
||||
if(isFirst) pImpl->waitForWork.signal();
|
||||
}
|
||||
|
||||
}}
|
||||
@@ -1,59 +0,0 @@
|
||||
/* timer.h */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
#ifndef TIMER_H
|
||||
#define TIMER_H
|
||||
#include <memory>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <pv/pvType.h>
|
||||
#include <pv/thread.h>
|
||||
#include <pv/noDefaultMethods.h>
|
||||
#include <pv/sharedPtr.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
class Timer;
|
||||
|
||||
class TimerCallback {
|
||||
public:
|
||||
virtual ~TimerCallback(){}
|
||||
virtual void callback() = 0;
|
||||
virtual void timerStopped() = 0;
|
||||
};
|
||||
|
||||
class TimerNode {
|
||||
public:
|
||||
TimerNode(TimerCallback &timerCallback);
|
||||
~TimerNode();
|
||||
void cancel();
|
||||
bool isScheduled();
|
||||
class Pvt;
|
||||
private:
|
||||
std::auto_ptr<Pvt> pImpl;
|
||||
friend class Timer;
|
||||
};
|
||||
|
||||
class Timer : private NoDefaultMethods {
|
||||
public:
|
||||
POINTER_DEFINITIONS(Timer);
|
||||
|
||||
Timer(String threadName, ThreadPriority priority);
|
||||
~Timer();
|
||||
void scheduleAfterDelay(TimerNode &timerNode,double delay);
|
||||
void schedulePeriodic(TimerNode &timerNode,double delay,double period);
|
||||
|
||||
class Pvt;
|
||||
private:
|
||||
std::auto_ptr<Pvt> pImpl;
|
||||
};
|
||||
|
||||
}}
|
||||
#endif /* TIMER_H */
|
||||
@@ -1,106 +0,0 @@
|
||||
/* monitor.h */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
#ifndef MONITOR_H
|
||||
#define MONITOR_H
|
||||
|
||||
#include <pv/status.h>
|
||||
#include <pv/destroyable.h>
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/sharedPtr.h>
|
||||
#include <pv/bitSet.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
/**
|
||||
* Class instance representing monitor element.
|
||||
* @author mrk
|
||||
*/
|
||||
class MonitorElement {
|
||||
public:
|
||||
POINTER_DEFINITIONS(MonitorElement);
|
||||
virtual ~MonitorElement(){}
|
||||
/**
|
||||
* Get the PVStructure.
|
||||
* @return The PVStructure.
|
||||
*/
|
||||
virtual PVStructure::shared_pointer const & getPVStructure() = 0;
|
||||
/**
|
||||
* Get the bitSet showing which fields have changed.
|
||||
* @return The bitSet.
|
||||
*/
|
||||
virtual BitSet::shared_pointer const & getChangedBitSet() = 0;
|
||||
/**
|
||||
* Get the bitSet showing which fields have been changed more than once.
|
||||
* @return The bitSet.
|
||||
*/
|
||||
virtual BitSet::shared_pointer const & getOverrunBitSet() = 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Interface for Monitor.
|
||||
* @author mrk
|
||||
*/
|
||||
class Monitor : public Destroyable, private NoDefaultMethods {
|
||||
public:
|
||||
POINTER_DEFINITIONS(Monitor);
|
||||
virtual ~Monitor(){}
|
||||
/**
|
||||
* Start monitoring.
|
||||
* @return completion status.
|
||||
*/
|
||||
virtual Status start() = 0;
|
||||
/**
|
||||
* Stop Monitoring.
|
||||
* @return completion status.
|
||||
*/
|
||||
virtual Status stop() = 0;
|
||||
/**
|
||||
* If monitor has occurred return data.
|
||||
* @return monitorElement for modified data.
|
||||
* Must call get to determine if data is available.
|
||||
*/
|
||||
virtual MonitorElement::shared_pointer const & poll() = 0;
|
||||
/**
|
||||
* Release a MonitorElement that was returned by poll.
|
||||
* @param monitorElement
|
||||
*/
|
||||
virtual void release(MonitorElement::shared_pointer const & monitorElement) = 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Requester for ChannelMonitor.
|
||||
* @author mrk
|
||||
*/
|
||||
class MonitorRequester : public virtual Requester {
|
||||
public:
|
||||
POINTER_DEFINITIONS(MonitorRequester);
|
||||
virtual ~MonitorRequester(){}
|
||||
/**
|
||||
* The client and server have both completed the createMonitor request.
|
||||
* @param status Completion status.
|
||||
* @param monitor The monitor
|
||||
* @param structure The structure defining the data.
|
||||
*/
|
||||
virtual void monitorConnect(Status const &status,
|
||||
Monitor::shared_pointer const & monitor, StructureConstPtr const & structure) = 0;
|
||||
/**
|
||||
* A monitor event has occurred.
|
||||
* The requester must call Monitor.poll to get data.
|
||||
* @param monitor The monitor.
|
||||
*/
|
||||
virtual void monitorEvent(Monitor::shared_pointer const &monitor) = 0;
|
||||
/**
|
||||
* The data source is no longer available.
|
||||
* @param monitor The monitor.
|
||||
*/
|
||||
virtual void unlisten(Monitor::shared_pointer const &monitor) = 0;
|
||||
};
|
||||
|
||||
}}
|
||||
#endif /* MONITOR_H */
|
||||
@@ -1,160 +0,0 @@
|
||||
/* monitorQueue.cpp */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/* Marty Kraimer 2011.03 */
|
||||
#include <pv/bitSet.h>
|
||||
|
||||
#include <pv/monitorQueue.h>
|
||||
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
typedef QueueElement<MonitorElement::shared_pointer> MonitorQueueElement;
|
||||
|
||||
class MonitorElementImpl : public MonitorElement {
|
||||
public:
|
||||
MonitorElementImpl(PVStructure::shared_pointer pvStructure);
|
||||
~MonitorElementImpl(){}
|
||||
virtual PVStructure::shared_pointer const & getPVStructure();
|
||||
virtual BitSet::shared_pointer const & getChangedBitSet();
|
||||
virtual BitSet::shared_pointer const & getOverrunBitSet();
|
||||
void setQueueElement(MonitorQueueElement *queueElement);
|
||||
MonitorQueueElement *getQueueElement();
|
||||
private:
|
||||
PVStructure::shared_pointer pvStructure;
|
||||
BitSet::shared_pointer changedBitSet;
|
||||
BitSet::shared_pointer overrunBitSet;
|
||||
MonitorQueueElement *queueElement;
|
||||
};
|
||||
|
||||
MonitorElementImpl::MonitorElementImpl(PVStructure::shared_pointer pvStructure)
|
||||
: pvStructure(pvStructure),
|
||||
changedBitSet(BitSet::shared_pointer(
|
||||
new BitSet(pvStructure->getNumberFields()))),
|
||||
overrunBitSet(BitSet::shared_pointer(
|
||||
new BitSet(pvStructure->getNumberFields()))),
|
||||
queueElement(0)
|
||||
{}
|
||||
|
||||
PVStructure::shared_pointer const & MonitorElementImpl::getPVStructure()
|
||||
{
|
||||
return pvStructure;
|
||||
}
|
||||
|
||||
BitSet::shared_pointer const & MonitorElementImpl::getChangedBitSet()
|
||||
{
|
||||
return changedBitSet;
|
||||
}
|
||||
|
||||
BitSet::shared_pointer const & MonitorElementImpl::getOverrunBitSet()
|
||||
{
|
||||
return overrunBitSet;
|
||||
}
|
||||
|
||||
void MonitorElementImpl::setQueueElement(MonitorQueueElement *queueElement)
|
||||
{
|
||||
this->queueElement = queueElement;
|
||||
}
|
||||
|
||||
MonitorQueueElement *MonitorElementImpl::getQueueElement()
|
||||
{
|
||||
return queueElement;
|
||||
}
|
||||
|
||||
MonitorQueue::MonitorQueue(PVStructureSharedPointerPtrArray structures,int number)
|
||||
: number(number),
|
||||
structures(structures),
|
||||
queue(0),
|
||||
queueElements(new MonitorElement::shared_pointer*[number]),
|
||||
nullElement(MonitorElement::shared_pointer())
|
||||
{
|
||||
if(number<2) {
|
||||
throw std::logic_error(String("queueSize must be >=2"));
|
||||
}
|
||||
|
||||
for(int i=0; i<number; i++) {
|
||||
queueElements[i] = new MonitorElement::shared_pointer(
|
||||
new MonitorElementImpl(*structures[i]));
|
||||
}
|
||||
queue = new Queue<MonitorElement::shared_pointer>(queueElements,number);
|
||||
MonitorQueueElement *queueElement;
|
||||
for(int i=0; i<number;i++) {
|
||||
queueElement = queue->getFree();
|
||||
MonitorElementImpl * element = static_cast<MonitorElementImpl *>(
|
||||
queueElement->getObject()->get());
|
||||
element->setQueueElement(queueElement);
|
||||
queue->setUsed(queueElement);
|
||||
queue->releaseUsed(queueElement);
|
||||
}
|
||||
}
|
||||
|
||||
MonitorQueue::~MonitorQueue()
|
||||
{
|
||||
delete queue;
|
||||
for(int i=0; i<number; i++) {
|
||||
delete queueElements[i];
|
||||
}
|
||||
delete[] queueElements;
|
||||
for(int i=0; i<number; i++) delete structures[i];
|
||||
delete[] structures;
|
||||
}
|
||||
|
||||
PVStructureSharedPointerPtrArray MonitorQueue::createStructures(
|
||||
PVStructurePtrArray array,int number)
|
||||
{
|
||||
PVStructureSharedPointerPtrArray elements =
|
||||
new PVStructureSharedPointerPtr[number];
|
||||
for(int i=0; i<number; i++){
|
||||
elements[i] = new PVStructure::shared_pointer(array[i]);
|
||||
}
|
||||
delete[] array;
|
||||
return elements;
|
||||
}
|
||||
|
||||
void MonitorQueue::clear()
|
||||
{
|
||||
queue->clear();
|
||||
}
|
||||
|
||||
int MonitorQueue::getNumberFree()
|
||||
{
|
||||
return queue->getNumberFree();
|
||||
}
|
||||
|
||||
int MonitorQueue::capacity()
|
||||
{
|
||||
return number;
|
||||
}
|
||||
|
||||
MonitorElement::shared_pointer const & MonitorQueue::getFree()
|
||||
{
|
||||
MonitorQueueElement *queueElement = queue->getFree();
|
||||
if(queueElement==0) return nullElement;
|
||||
return *queueElement->getObject();
|
||||
}
|
||||
|
||||
void MonitorQueue::setUsed(MonitorElement::shared_pointer const & element)
|
||||
{
|
||||
MonitorElementImpl *impl = static_cast<MonitorElementImpl *>(element.get());
|
||||
queue->setUsed(impl->getQueueElement());
|
||||
}
|
||||
|
||||
MonitorElement::shared_pointer const & MonitorQueue::getUsed()
|
||||
{
|
||||
MonitorQueueElement *queueElement = queue->getUsed();
|
||||
if(queueElement==0) return nullElement;
|
||||
return *queueElement->getObject();
|
||||
}
|
||||
|
||||
void MonitorQueue::releaseUsed(MonitorElement::shared_pointer const & element)
|
||||
{
|
||||
MonitorElementImpl *impl = static_cast<MonitorElementImpl *>(element.get());
|
||||
queue->releaseUsed(impl->getQueueElement());
|
||||
}
|
||||
|
||||
|
||||
}}
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
/* monitorQueue.h */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/* Marty Kraimer 2011.03 */
|
||||
#ifndef MONITORQUEUE_H
|
||||
#define MONITORQUEUE_H
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/monitor.h>
|
||||
#include <pv/queue.h>
|
||||
#include <pv/sharedPtr.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
typedef PVStructure::shared_pointer* PVStructureSharedPointerPtr;
|
||||
typedef PVStructureSharedPointerPtr* PVStructureSharedPointerPtrArray;
|
||||
|
||||
class MonitorQueue {
|
||||
public:
|
||||
MonitorQueue(PVStructureSharedPointerPtrArray structures,int number);
|
||||
~MonitorQueue();
|
||||
static PVStructureSharedPointerPtrArray createStructures(
|
||||
PVStructurePtrArray array,int number);
|
||||
void clear();
|
||||
int getNumberFree();
|
||||
int capacity();
|
||||
MonitorElement::shared_pointer const & getFree();
|
||||
void setUsed(MonitorElement::shared_pointer const & element);
|
||||
MonitorElement::shared_pointer const & getUsed();
|
||||
void releaseUsed(MonitorElement::shared_pointer const & element);
|
||||
private:
|
||||
int number;
|
||||
PVStructureSharedPointerPtrArray structures;
|
||||
Queue<MonitorElement::shared_pointer> *queue;
|
||||
MonitorElement::shared_pointer **queueElements;
|
||||
MonitorElement::shared_pointer nullElement;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif /* MONITORQUEUE_H */
|
||||
@@ -1,108 +0,0 @@
|
||||
/* alarm.cpp */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <pv/pvType.h>
|
||||
#include <pv/pvIntrospect.h>
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/alarm.h>
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
const size_t severityCount = 5;
|
||||
static String severityNames[severityCount] =
|
||||
{
|
||||
String("NONE"),
|
||||
String("MINOR"),
|
||||
String("MAJOR"),
|
||||
String("INVALID"),
|
||||
String("UNDEFINED")
|
||||
};
|
||||
|
||||
AlarmSeverity AlarmSeverityFunc::getSeverity(int value)
|
||||
{
|
||||
if(value<0 || value>4) {
|
||||
throw std::logic_error(String("getSeverity value is illegal"));
|
||||
}
|
||||
switch (value) {
|
||||
case 0: return noAlarm;
|
||||
case 1: return minorAlarm;
|
||||
case 2: return majorAlarm;
|
||||
case 3: return invalidAlarm;
|
||||
case 4: return undefinedAlarm;
|
||||
}
|
||||
throw std::logic_error(String("should never get here"));
|
||||
}
|
||||
|
||||
StringArray AlarmSeverityFunc::getSeverityNames()
|
||||
{
|
||||
return severityNames;
|
||||
}
|
||||
|
||||
AlarmSeverity Alarm::getSeverity() const
|
||||
{
|
||||
switch(severity) {
|
||||
case 0: return noAlarm;
|
||||
case 1: return minorAlarm;
|
||||
case 2: return majorAlarm;
|
||||
case 3: return invalidAlarm;
|
||||
case 4: return undefinedAlarm;
|
||||
}
|
||||
throw std::logic_error(String("should never get here"));
|
||||
}
|
||||
|
||||
const size_t statusCount = 8;
|
||||
static String statusNames[statusCount] =
|
||||
{
|
||||
String("NONE"),
|
||||
String("DEVICE"),
|
||||
String("DRIVER"),
|
||||
String("RECORD"),
|
||||
String("DB"),
|
||||
String("CONF"),
|
||||
String("UNDEFINED"),
|
||||
String("CLIENT")
|
||||
};
|
||||
|
||||
AlarmStatus AlarmStatusFunc::getStatus(int value)
|
||||
{
|
||||
if(value<0 || value>7) {
|
||||
throw std::logic_error(String("getStatus value is illegal"));
|
||||
}
|
||||
switch (value) {
|
||||
case 0: return noStatus;
|
||||
case 1: return deviceStatus;
|
||||
case 2: return driverStatus;
|
||||
case 3: return recordStatus;
|
||||
case 4: return dbStatus;
|
||||
case 5: return confStatus;
|
||||
case 6: return undefinedStatus;
|
||||
case 7: return clientStatus;
|
||||
}
|
||||
throw std::logic_error(String("should never get here"));
|
||||
}
|
||||
|
||||
StringArray AlarmStatusFunc::getStatusNames()
|
||||
{
|
||||
return statusNames;
|
||||
}
|
||||
|
||||
AlarmStatus Alarm::getStatus() const
|
||||
{
|
||||
switch(status) {
|
||||
case 0: return noStatus;
|
||||
case 1: return deviceStatus;
|
||||
case 2: return driverStatus;
|
||||
case 3: return recordStatus;
|
||||
case 4: return dbStatus;
|
||||
case 5: return confStatus;
|
||||
case 6: return undefinedStatus;
|
||||
case 7: return clientStatus;
|
||||
}
|
||||
throw std::logic_error(String("should never get here"));
|
||||
}
|
||||
|
||||
}}
|
||||
@@ -1,54 +0,0 @@
|
||||
/* alarm.h */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
#include <string>
|
||||
#include <pv/pvType.h>
|
||||
#ifndef ALARM_H
|
||||
#define ALARM_H
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
enum AlarmSeverity {
|
||||
noAlarm,minorAlarm,majorAlarm,invalidAlarm,undefinedAlarm
|
||||
};
|
||||
|
||||
enum AlarmStatus {
|
||||
noStatus,deviceStatus,driverStatus,recordStatus,
|
||||
dbStatus,confStatus,undefinedStatus,clientStatus
|
||||
};
|
||||
|
||||
|
||||
extern const size_t severityCount;
|
||||
class AlarmSeverityFunc {
|
||||
public:
|
||||
static AlarmSeverity getSeverity(int value);
|
||||
static StringArray getSeverityNames();
|
||||
};
|
||||
|
||||
extern const size_t statusCount;
|
||||
class AlarmStatusFunc {
|
||||
public:
|
||||
static AlarmStatus getStatus(int value);
|
||||
static StringArray getStatusNames();
|
||||
};
|
||||
|
||||
class Alarm {
|
||||
public:
|
||||
Alarm() : severity(0),status(0), message(String("")) {}
|
||||
//default constructors and destructor are OK
|
||||
String getMessage() const {return message;}
|
||||
void setMessage(String value) {message = value;}
|
||||
AlarmSeverity getSeverity() const;
|
||||
void setSeverity(AlarmSeverity value) {severity = value;}
|
||||
AlarmStatus getStatus() const;
|
||||
void setStatus(AlarmStatus value) { status = value;}
|
||||
private:
|
||||
int32 severity;
|
||||
int32 status;
|
||||
String message;
|
||||
};
|
||||
|
||||
}}
|
||||
#endif /* ALARM_H */
|
||||
@@ -1,25 +0,0 @@
|
||||
/* control.h */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
#ifndef CONTROL_H
|
||||
#define CONTROL_H
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
class Control {
|
||||
public:
|
||||
Control() : low(0.0), high(0.0) {}
|
||||
//default constructors and destructor are OK
|
||||
double getLow() const {return low;}
|
||||
double getHigh() const {return high;}
|
||||
void setLow(double value) {low = value;}
|
||||
void setHigh(double value) {high = value;}
|
||||
private:
|
||||
double low;
|
||||
double high;
|
||||
};
|
||||
|
||||
}}
|
||||
#endif /* CONTROL_H */
|
||||
@@ -1,39 +0,0 @@
|
||||
/* display.h */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
#include <string>
|
||||
#include <pv/pvType.h>
|
||||
#include <pv/pvData.h>
|
||||
#ifndef DISPLAY_H
|
||||
#define DISPLAY_H
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
class Display {
|
||||
public:
|
||||
Display()
|
||||
: description(String("")),format(String("")),units(String("")),
|
||||
low(0.0),high(0.0) {}
|
||||
//default constructors and destructor are OK
|
||||
double getLow() const {return low;}
|
||||
double getHigh() const{ return high;}
|
||||
void setLow(double value){low = value;}
|
||||
void setHigh(double value){high = value;}
|
||||
String getDescription() const {return description;}
|
||||
void setDescription(String value) {description = value;}
|
||||
String getFormat() const {return format;}
|
||||
void setFormat(String value) {format = value;}
|
||||
String getUnits() const {return units;}
|
||||
void setUnits(String value) {units = value;}
|
||||
private:
|
||||
String description;
|
||||
String format;
|
||||
String units;
|
||||
double low;
|
||||
double high;
|
||||
};
|
||||
|
||||
}}
|
||||
#endif /* DISPLAY_H */
|
||||
@@ -1,99 +0,0 @@
|
||||
/* pvAlarm.cpp */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <pv/pvType.h>
|
||||
#include <pv/pvIntrospect.h>
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/pvAlarm.h>
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
static String noAlarmFound("No alarm structure found");
|
||||
static String notAttached("Not attached to an alarm structure");
|
||||
|
||||
bool PVAlarm::attach(PVField *pvField)
|
||||
{
|
||||
PVStructure *pvStructure = 0;
|
||||
if(pvField->getField()->getFieldName().compare("alarm")!=0) {
|
||||
if(pvField->getField()->getFieldName().compare("value")!=0) {
|
||||
pvField->message(noAlarmFound,errorMessage);
|
||||
return false;
|
||||
}
|
||||
PVStructure *pvParent = pvField->getParent();
|
||||
if(pvParent==0) {
|
||||
pvField->message(noAlarmFound,errorMessage);
|
||||
return false;
|
||||
}
|
||||
pvStructure = pvParent->getStructureField(String("alarm"));
|
||||
if(pvStructure==0) {
|
||||
pvField->message(noAlarmFound,errorMessage);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if(pvField->getField()->getType()!=structure) {
|
||||
pvField->message(noAlarmFound,errorMessage);
|
||||
return false;
|
||||
}
|
||||
pvStructure = static_cast<PVStructure*>(pvField);
|
||||
}
|
||||
PVInt *pvInt = pvStructure->getIntField(String("severity"));
|
||||
if(pvInt==0) {
|
||||
pvField->message(noAlarmFound,errorMessage);
|
||||
return false;
|
||||
}
|
||||
pvSeverity = pvInt;
|
||||
pvInt = pvStructure->getIntField(String("status"));
|
||||
if(pvInt==0) {
|
||||
pvField->message(noAlarmFound,errorMessage);
|
||||
return false;
|
||||
}
|
||||
pvStatus = pvInt;
|
||||
PVString *pvString = pvStructure->getStringField(String("message"));
|
||||
if(pvInt==0) {
|
||||
pvField->message(noAlarmFound,errorMessage);
|
||||
return false;
|
||||
}
|
||||
pvMessage = pvString;
|
||||
return true;
|
||||
}
|
||||
|
||||
void PVAlarm::detach()
|
||||
{
|
||||
pvSeverity = 0;
|
||||
pvStatus = 0;
|
||||
pvMessage = 0;
|
||||
}
|
||||
|
||||
bool PVAlarm::isAttached()
|
||||
{
|
||||
if(pvSeverity==0 || pvMessage==0) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void PVAlarm::get(Alarm & alarm) const
|
||||
{
|
||||
if(pvSeverity==0 || pvMessage==0) {
|
||||
throw std::logic_error(notAttached);
|
||||
}
|
||||
alarm.setSeverity(AlarmSeverityFunc::getSeverity(pvSeverity->get()));
|
||||
alarm.setStatus(AlarmStatusFunc::getStatus(pvStatus->get()));
|
||||
alarm.setMessage(pvMessage->get());
|
||||
}
|
||||
|
||||
bool PVAlarm::set(Alarm const & alarm)
|
||||
{
|
||||
if(pvSeverity==0 || pvMessage==0) {
|
||||
throw std::logic_error(notAttached);
|
||||
}
|
||||
if(pvSeverity->isImmutable() || pvMessage->isImmutable()) return false;
|
||||
pvSeverity->put(alarm.getSeverity());
|
||||
pvStatus->put(alarm.getStatus());
|
||||
pvMessage->put(alarm.getMessage());
|
||||
return true;
|
||||
}
|
||||
|
||||
}}
|
||||
@@ -1,36 +0,0 @@
|
||||
/* pvAlarm.h */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
#ifndef PVALARM_H
|
||||
#define PVALARM_H
|
||||
#include <string>
|
||||
#include <pv/pvType.h>
|
||||
#include <pv/alarm.h>
|
||||
#include <pv/pvData.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
class PVAlarm {
|
||||
public:
|
||||
PVAlarm() : pvSeverity(0),pvStatus(0),pvMessage(0) {}
|
||||
//default constructors and destructor are OK
|
||||
//returns (false,true) if pvField(isNot, is valid enumerated structure
|
||||
//An automatic detach is issued if already attached.
|
||||
bool attach(PVField *pvField);
|
||||
void detach();
|
||||
bool isAttached();
|
||||
// each of the following throws logic_error is not attached to PVField
|
||||
// set returns false if field is immutable
|
||||
void get(Alarm & alarm) const;
|
||||
bool set(Alarm const & alarm);
|
||||
private:
|
||||
PVInt *pvSeverity;
|
||||
PVInt *pvStatus;
|
||||
PVString *pvMessage;
|
||||
};
|
||||
|
||||
}}
|
||||
#endif /* PVALARM_H */
|
||||
@@ -1,90 +0,0 @@
|
||||
/* pvControl.cpp */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <pv/pvType.h>
|
||||
#include <pv/pvIntrospect.h>
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/pvControl.h>
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
static String noControlFound("No control structure found");
|
||||
static String notAttached("Not attached to an control structure");
|
||||
|
||||
bool PVControl::attach(PVField *pvField)
|
||||
{
|
||||
PVStructure *pvStructure = 0;
|
||||
if(pvField->getField()->getFieldName().compare("control")!=0) {
|
||||
if(pvField->getField()->getFieldName().compare("value")!=0) {
|
||||
pvField->message(noControlFound,errorMessage);
|
||||
return false;
|
||||
}
|
||||
PVStructure *pvParent = pvField->getParent();
|
||||
if(pvParent==0) {
|
||||
pvField->message(noControlFound,errorMessage);
|
||||
return false;
|
||||
}
|
||||
pvStructure = pvParent->getStructureField(String("control"));
|
||||
if(pvStructure==0) {
|
||||
pvField->message(noControlFound,errorMessage);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if(pvField->getField()->getType()!=structure) {
|
||||
pvField->message(noControlFound,errorMessage);
|
||||
return false;
|
||||
}
|
||||
pvStructure = static_cast<PVStructure*>(pvField);
|
||||
}
|
||||
PVDouble *pvDouble = pvStructure->getDoubleField(String("limit.low"));
|
||||
if(pvDouble==0) {
|
||||
pvField->message(noControlFound,errorMessage);
|
||||
return false;
|
||||
}
|
||||
pvLow = pvDouble;
|
||||
pvDouble = pvStructure->getDoubleField(String("limit.high"));
|
||||
if(pvDouble==0) {
|
||||
pvLow = 0;
|
||||
pvField->message(noControlFound,errorMessage);
|
||||
return false;
|
||||
}
|
||||
pvHigh = pvDouble;
|
||||
return true;
|
||||
}
|
||||
|
||||
void PVControl::detach()
|
||||
{
|
||||
pvLow = 0;
|
||||
pvHigh = 0;
|
||||
}
|
||||
|
||||
bool PVControl::isAttached(){
|
||||
if(pvLow==0 || pvHigh==0) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void PVControl::get(Control &control) const
|
||||
{
|
||||
if(pvLow==0 || pvHigh==0) {
|
||||
throw std::logic_error(notAttached);
|
||||
}
|
||||
control.setLow(pvLow->get());
|
||||
control.setHigh(pvHigh->get());
|
||||
}
|
||||
|
||||
bool PVControl::set(Control const & control)
|
||||
{
|
||||
if(pvLow==0 || pvHigh==0) {
|
||||
throw std::logic_error(notAttached);
|
||||
}
|
||||
if(pvLow->isImmutable() || pvHigh->isImmutable()) return false;
|
||||
pvLow->put(control.getLow());
|
||||
pvHigh->put(control.getHigh());
|
||||
return true;
|
||||
}
|
||||
|
||||
}}
|
||||
@@ -1,32 +0,0 @@
|
||||
/* pvControl.h */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
#include <pv/control.h>
|
||||
#include <pv/pvData.h>
|
||||
#ifndef PVCONTROL_H
|
||||
#define PVCONTROL_H
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
class PVControl {
|
||||
public:
|
||||
PVControl() : pvLow(0),pvHigh(0) {}
|
||||
//default constructors and destructor are OK
|
||||
//returns (false,true) if pvField(isNot, is valid enumerated structure
|
||||
//An automatic detach is issued if already attached.
|
||||
bool attach(PVField *pvField);
|
||||
void detach();
|
||||
bool isAttached();
|
||||
// each of the following throws logic_error is not attached to PVField
|
||||
// set returns false if field is immutable
|
||||
void get(Control &) const;
|
||||
bool set(Control const & control);
|
||||
private:
|
||||
PVDouble *pvLow;
|
||||
PVDouble *pvHigh;
|
||||
};
|
||||
|
||||
}}
|
||||
#endif /* PVCONTROL_H */
|
||||
@@ -1,119 +0,0 @@
|
||||
/* pvDisplay.cpp */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <pv/pvType.h>
|
||||
#include <pv/pvIntrospect.h>
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/pvDisplay.h>
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
static String noDisplayFound("No display structure found");
|
||||
static String notAttached("Not attached to an display structure");
|
||||
|
||||
bool PVDisplay::attach(PVField *pvField)
|
||||
{
|
||||
PVStructure *pvStructure = 0;
|
||||
if(pvField->getField()->getFieldName().compare("display")!=0) {
|
||||
if(pvField->getField()->getFieldName().compare("value")!=0) {
|
||||
pvField->message(noDisplayFound,errorMessage);
|
||||
return false;
|
||||
}
|
||||
PVStructure *pvParent = pvField->getParent();
|
||||
if(pvParent==0) {
|
||||
pvField->message(noDisplayFound,errorMessage);
|
||||
return false;
|
||||
}
|
||||
pvStructure = pvParent->getStructureField(String("display"));
|
||||
if(pvStructure==0) {
|
||||
pvField->message(noDisplayFound,errorMessage);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if(pvField->getField()->getType()!=structure) {
|
||||
pvField->message(noDisplayFound,errorMessage);
|
||||
return false;
|
||||
}
|
||||
pvStructure = static_cast<PVStructure*>(pvField);
|
||||
}
|
||||
pvDescription = pvStructure->getStringField(String("description"));
|
||||
if(pvDescription==0) {
|
||||
pvField->message(noDisplayFound,errorMessage);
|
||||
return false;
|
||||
}
|
||||
pvFormat = pvStructure->getStringField(String("format"));
|
||||
if(pvFormat==0) {
|
||||
pvField->message(noDisplayFound,errorMessage);
|
||||
detach();
|
||||
return false;
|
||||
}
|
||||
pvUnits = pvStructure->getStringField(String("units"));
|
||||
if(pvUnits==0) {
|
||||
pvField->message(noDisplayFound,errorMessage);
|
||||
detach();
|
||||
return false;
|
||||
}
|
||||
pvLow = pvStructure->getDoubleField(String("limit.low"));
|
||||
if(pvLow==0) {
|
||||
pvField->message(noDisplayFound,errorMessage);
|
||||
detach();
|
||||
return false;
|
||||
}
|
||||
pvHigh = pvStructure->getDoubleField(String("limit.high"));
|
||||
if(pvHigh==0) {
|
||||
pvField->message(noDisplayFound,errorMessage);
|
||||
detach();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void PVDisplay::detach()
|
||||
{
|
||||
pvDescription = 0;
|
||||
pvFormat = 0;
|
||||
pvUnits = 0;
|
||||
pvLow = 0;
|
||||
pvHigh = 0;
|
||||
}
|
||||
|
||||
bool PVDisplay::isAttached() {
|
||||
if(pvDescription==0 || pvFormat==0 || pvUnits==0 || pvLow==0 || pvHigh==0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void PVDisplay::get(Display & display) const
|
||||
{
|
||||
if(pvDescription==0 || pvFormat==0 || pvUnits==0 || pvLow==0 || pvHigh==0) {
|
||||
throw std::logic_error(notAttached);
|
||||
}
|
||||
display.setDescription(pvDescription->get());
|
||||
display.setFormat(pvFormat->get());
|
||||
display.setUnits(pvUnits->get());
|
||||
display.setLow(pvLow->get());
|
||||
display.setHigh(pvHigh->get());
|
||||
}
|
||||
|
||||
bool PVDisplay::set(Display const & display)
|
||||
{
|
||||
if(pvDescription==0 || pvFormat==0 || pvUnits==0 || pvLow==0 || pvHigh==0) {
|
||||
throw std::logic_error(notAttached);
|
||||
}
|
||||
if(pvDescription->isImmutable() || pvFormat->isImmutable()) return false;
|
||||
if(pvUnits->isImmutable() || pvLow->isImmutable() || pvHigh->isImmutable())
|
||||
return false;
|
||||
|
||||
pvDescription->put(display.getDescription());
|
||||
pvFormat->put(display.getFormat());
|
||||
pvUnits->put(display.getUnits());
|
||||
pvLow->put(display.getLow());
|
||||
pvHigh->put(display.getHigh());
|
||||
return true;
|
||||
}
|
||||
|
||||
}}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user