Compare commits
358 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7fc3f50ae9 | ||
|
|
05d41f81e4 | ||
|
|
d400e8eaf5 | ||
|
|
fdc289d888 | ||
|
|
0a2243e033 | ||
|
|
9d877d764f | ||
|
|
f5df29cf34 | ||
|
|
8008823ea5 | ||
|
|
6515de4bc0 | ||
|
|
8c5f535b79 | ||
|
|
de2fac122c | ||
|
|
7707da0b45 | ||
|
|
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 | ||
|
|
ec6b67ffad | ||
|
|
3de28e3cef | ||
|
|
23d5aab1e8 | ||
|
|
cf8c6718dd | ||
|
|
b0c8249562 | ||
|
|
8cb0b1a7d6 | ||
|
|
7f9745c8d1 | ||
|
|
4e749cc8be | ||
|
|
70c9a7c18f | ||
|
|
11e2ee19ea | ||
|
|
a4cfab1242 | ||
|
|
be4738f59c | ||
|
|
b63c3da565 | ||
|
|
0b89f08d09 | ||
|
|
ac53153bea | ||
|
|
bc3187a3f6 | ||
|
|
4294710d9e | ||
|
|
82a33460cf | ||
|
|
3b6268a4fc | ||
|
|
41425b3fa1 | ||
|
|
57804494ef | ||
|
|
9039a10c9a | ||
|
|
9e865bc37d | ||
|
|
54ee8bf7a0 | ||
|
|
629c8346d2 | ||
|
|
1bf2ff430a | ||
|
|
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 |
15
.gitignore
vendored
Normal file
15
.gitignore
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
bin/
|
||||
lib/
|
||||
doc/
|
||||
include/
|
||||
db/
|
||||
dbd/
|
||||
documentation/html
|
||||
documentation/*.tag
|
||||
envPaths
|
||||
configure/*.local
|
||||
configure/RELEASE.*
|
||||
configure/CONFIG_SITE.*
|
||||
!configure/ExampleRELEASE.local
|
||||
**/O.*
|
||||
QtC-*
|
||||
11
.hgignore
11
.hgignore
@@ -1,11 +0,0 @@
|
||||
^QtC-
|
||||
^bin/
|
||||
^lib/
|
||||
^doc/
|
||||
^include/
|
||||
^db/
|
||||
^dbd/
|
||||
^documentation/html
|
||||
envPaths
|
||||
configure/.*\.local
|
||||
/O\..*
|
||||
7
.hgtags
7
.hgtags
@@ -1,7 +0,0 @@
|
||||
459f10877e5628241704f31437b4cbd342df0798 test1
|
||||
6e8a22d01e824702088195c08bf50bfb6f293de5 1.0-BETA
|
||||
d29d84f4c3f389f2accd497185b106c8541f95c9 1.1-SNAPSHOT
|
||||
a29729ca0ecd60b66f2d997031d97911377e44a7 marchtest
|
||||
9c59737f56e71aef641b70d0f72aa768fd7f8414 1.0.1-BETA
|
||||
4559c3de0cb4e3420e26272817f58bab005063ec 1.1-BETA
|
||||
d70c5ad29163306f50979a95b5aebbe9a93cfe76 2.0-BETA
|
||||
35
COPYRIGHT
35
COPYRIGHT
@@ -1,12 +1,31 @@
|
||||
/****************************************************
|
||||
Copyright (c) 2008 All rights reserved
|
||||
Copyright (c) 2008 Martin R. Kraimer
|
||||
Copyright (c) 2006 The University of Chicago, as Operator of Argonne
|
||||
National Laboratory.
|
||||
This software is in part copyrighted by the various organizations and
|
||||
individuals listed below. Permission to use it is set out in the file
|
||||
LICENSE that accompanies the software.
|
||||
|
||||
In no event shall any copyright holder 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 they have been advised of the possibility of such
|
||||
damage.
|
||||
|
||||
The copyright holders 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 the copyright holders have no
|
||||
obligation either collectively or individually to provide maintenance,
|
||||
support, updates, enhancements, or modifications.
|
||||
|
||||
Copyright (c) 2006 - 2015 All rights reserved
|
||||
|
||||
Martin R. Kraimer
|
||||
The University of Chicago, as Operator of Argonne National Laboratory.
|
||||
Deutsches Elektronen-Synchroton, Member of the Helmholtz Association,
|
||||
(DESY), HAMBURG, GERMANY,
|
||||
BERLINER SPEICHERRING GESELLSCHAFT FUER SYNCHROTRONSTRAHLUNG M.B.H.
|
||||
(BESSY), BERLIN, GERMANY.
|
||||
COSYLAB (Control System Laboratory)
|
||||
(Cosylab) Ljubljana Slovenia
|
||||
*************************************************** */
|
||||
COSYLAB (Control System Laboratory), Ljubljana, Slovenia.
|
||||
Brookhaven Science Associates, as Operator of Brookhaven
|
||||
National Laboratory.
|
||||
Diamond Light Source Ltd., Didcot, United Kingdom.
|
||||
|
||||
|
||||
|
||||
44
LICENSE
44
LICENSE
@@ -1,12 +1,15 @@
|
||||
|
||||
Copyright (c) 2008 Martin R. Kraimer
|
||||
Copyright (c) 2006-2015 Martin R. Kraimer
|
||||
Copyright (c) 2006 The University of Chicago, as Operator of Argonne
|
||||
National Laboratory.
|
||||
Copyright (c) 2006 Deutsches Elektronen-Synchroton,
|
||||
Copyright (c) 2006 Deutsches Elektronen-Synchrotron,
|
||||
Member of the Helmholtz Association, (DESY), HAMBURG, GERMANY.
|
||||
Copyright (c) 2007 Control System Laboratory,
|
||||
Copyright (c) 2007-2015 Control System Laboratory,
|
||||
(COSYLAB) Ljubljana Slovenia
|
||||
|
||||
Copyright (c) 2010-2015 Brookhaven Science Associates, as Operator of Brookhaven
|
||||
National Laboratory
|
||||
Copyright (c) 2011-2015 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
|
||||
@@ -75,4 +78,37 @@ to, the implied warranties of merchantability, fitness for a particular
|
||||
purpose, and non-infringement. This software is provided on an "as is"
|
||||
basis, and DESY has no obligation to provide maintenance, support,
|
||||
updates, enhancements, or modifications.
|
||||
|
||||
______________________________________________________________________
|
||||
|
||||
This software is in part copyrighted by the Brookhaven
|
||||
National Laboratory (BNL).
|
||||
|
||||
In no event shall BNL 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
|
||||
BNL has been advised of the possibility of such damage.
|
||||
|
||||
BNL specifically disclaims 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 BNL has no obligation to provide maintenance, support,
|
||||
updates, enhancements, or modifications.
|
||||
|
||||
________________________________________________________________________
|
||||
|
||||
This software is in part copyrighted by Diamond Light Source Limited (DLS)
|
||||
|
||||
In no event shall DLS 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
|
||||
DLS has been advised of the possibility of such damage.
|
||||
|
||||
DLS specifically disclaims 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 DLS has no obligation to provide maintenance, support,
|
||||
updates, enhancements, or modifications.
|
||||
|
||||
________________________________________________________________________
|
||||
|
||||
|
||||
14
Makefile
14
Makefile
@@ -1,12 +1,14 @@
|
||||
#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
|
||||
|
||||
include $(TOP)/configure/RULES_TOP
|
||||
|
||||
|
||||
|
||||
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>
|
||||
57
README.md
Normal file
57
README.md
Normal file
@@ -0,0 +1,57 @@
|
||||
pvaDataCPP
|
||||
==========
|
||||
|
||||
pvDataCPP is a set of data types and utilities that form part of the EPICS V4 project.
|
||||
|
||||
|
||||
Further Info
|
||||
------------
|
||||
|
||||
Consult the documents in the documentation directory, in particular
|
||||
|
||||
* pvDataCPP.html
|
||||
* RELEASE_NOTES.md
|
||||
|
||||
Also see the [EPICS Version 4 website](http://epics-pvdata.sourceforge.net)
|
||||
|
||||
Prerequisites
|
||||
-------------
|
||||
|
||||
The pvDataCPP requires recent versions of the following software:
|
||||
|
||||
1. EPICS Base (v3.14.12.3 or later)
|
||||
2. EPICS4 pvCommonCPP (4.1.0 or later)
|
||||
|
||||
(pvCommonCPP may not be needed depending on host/compiler.)
|
||||
|
||||
|
||||
Building
|
||||
--------
|
||||
|
||||
Building uses the make utility and the EPICS base build system.
|
||||
|
||||
The build system needs the location of the prerequisites, e.g. by placing the
|
||||
lines of the form
|
||||
|
||||
PVCOMMON = /home/install/epicsV4/pvCommonCPP
|
||||
EPICS_BASE = /home/install/epics/base
|
||||
|
||||
pointing to the locations in a file called RELEASE.local
|
||||
in the configure directory or the parent directory of pvDataCPP.
|
||||
|
||||
With this in place, to build type make
|
||||
|
||||
make
|
||||
|
||||
To perform a clean build type
|
||||
|
||||
make clean uninstall
|
||||
|
||||
To run the unit tests type
|
||||
|
||||
make runtests
|
||||
|
||||
For more information on the EPICS build system consult the
|
||||
[Application Development guide](http://www.aps.anl.gov/epics/base/R3-14/12-docs/AppDevGuide.pdf).
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -1,36 +1,30 @@
|
||||
# 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>
|
||||
-include $(TOP)/../CONFIG_SITE.local
|
||||
-include $(TOP)/configure/CONFIG_SITE.local
|
||||
|
||||
ifeq ($(EPICS_TEST_COVERAGE),1)
|
||||
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
|
||||
-include $(TOP)/../CONFIG.local
|
||||
|
||||
@@ -2,14 +2,6 @@ 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
|
||||
|
||||
TARGETS = $(CONFIG_TARGETS)
|
||||
CONFIGS += $(subst ../,,$(wildcard $(CONFIG_INSTALLS)))
|
||||
|
||||
|
||||
@@ -16,10 +16,10 @@
|
||||
|
||||
# EPICS V4 Developers: Do not edit the locations in this file!
|
||||
#
|
||||
# Create a file RELEASE.local pointing to your EPICS_BASE
|
||||
# and PVCOMMON build directories, e.g.
|
||||
# EPICS_BASE = /home/install/epics/base
|
||||
# Create a file RELEASE.local pointing to your PVCOMMON
|
||||
# and EPICS_BASE build directories, e.g.
|
||||
# PVCOMMON = /home/install/epicsV4/pvCommonCPP
|
||||
# EPICS_BASE = /home/install/epics/base
|
||||
|
||||
-include $(TOP)/configure/RELEASE.local
|
||||
-include $(TOP)/../RELEASE.local
|
||||
-include $(TOP)/configure/RELEASE.local
|
||||
|
||||
1621
documentation/Doxyfile
Normal file
1621
documentation/Doxyfile
Normal file
File diff suppressed because it is too large
Load Diff
218
documentation/RELEASE_NOTES.html
Normal file
218
documentation/RELEASE_NOTES.html
Normal file
@@ -0,0 +1,218 @@
|
||||
<h1>Release 5.0</h1>
|
||||
|
||||
<p>The main changes since release 4.0 are:</p>
|
||||
|
||||
<ul>
|
||||
<li>Deprecated getXXXField() methods have been removed from PVStructure</li>
|
||||
<li>Convert copy methods and equals operators (re)moved</li>
|
||||
<li>Convert::copyUnion now always copies between subfields.</li>
|
||||
<li>New method getSubFieldT, like getSubField except it throws an exception</li>
|
||||
<li>findSubField method removed from PVStructure</li>
|
||||
<li>New stream operators for Field and PVField are provided</li>
|
||||
<li>New template versions of Structure::getField</li>
|
||||
<li>Fixes for static initialisation order issues</li>
|
||||
<li>CreateRequest prevents a possible SEGFAULT</li>
|
||||
</ul>
|
||||
|
||||
<h2>Deprecated getXXXField methods have been removed from PVStructure</h2>
|
||||
|
||||
<p>The following methods have been removed from PVStructure</p>
|
||||
|
||||
<ul>
|
||||
<li>getBooleanField</li>
|
||||
<li>getByteField, getShortField, getIntField, getLongField</li>
|
||||
<li>getUByteField, getUShortField, getUIntField, getULongField</li>
|
||||
<li>getStringField</li>
|
||||
<li>getStructureField, getUnionField</li>
|
||||
<li>getScalarArrayField, getStructureArrayField, getUnionArrayField</li>
|
||||
</ul>
|
||||
|
||||
<p>Use template getSubField instead, e.g. use</p>
|
||||
|
||||
<pre><code>getSubField< PVInt >(fieldName)
|
||||
</code></pre>
|
||||
|
||||
<p>in place of</p>
|
||||
|
||||
<pre><code>getIntField(fieldName)
|
||||
</code></pre>
|
||||
|
||||
<h2>Convert copy methods and equals operators</h2>
|
||||
|
||||
<p>Convert copy methods where moved and replaced with methods
|
||||
on PVField classes, i.e.</p>
|
||||
|
||||
<pre><code>PVField::copy(const PVField& from)
|
||||
</code></pre>
|
||||
|
||||
<p>Methods</p>
|
||||
|
||||
<pre><code>PVField::copyUnchecked(const PVField& from)
|
||||
</code></pre>
|
||||
|
||||
<p>were added to allow unchecked copies, to gain performance
|
||||
where checked are not needed (anymore).</p>
|
||||
|
||||
<p>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</p>
|
||||
|
||||
<h2>Convert::copyUnion</h2>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<h2>New method getSubFieldT, like getSubField except it throws an exception</h2>
|
||||
|
||||
<p>PVStructure has a new template member</p>
|
||||
|
||||
<pre><code>getSubFieldT(std::string const &fieldName)
|
||||
</code></pre>
|
||||
|
||||
<p>that is like <b>getSubField</b> except that it throws a runtime_error
|
||||
instead of returning null.</p>
|
||||
|
||||
<h2>findSubField method removed from PVStructure</h2>
|
||||
|
||||
<p>This was mainly used in the implementation of getSubField. With a change to
|
||||
the latter, findSubField was removed.</p>
|
||||
|
||||
<h2>New stream operators</h2>
|
||||
|
||||
<p>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:</p>
|
||||
|
||||
<pre><code> void print(StructureConstPtr struc, PVStructurePtr pv)
|
||||
{
|
||||
if(struc) {
|
||||
cout << *struc << endl;
|
||||
} else {
|
||||
cout << "nullptr\n"
|
||||
}
|
||||
if(pv) {
|
||||
cout << *.struc << endl;
|
||||
} else {
|
||||
cout << "nullptr\n"
|
||||
}
|
||||
}
|
||||
</code></pre>
|
||||
|
||||
<p>Now it can be done as follows:</p>
|
||||
|
||||
<pre><code> void print(StructureConstPtr struc, PVStructurePtr pv)
|
||||
{
|
||||
cout << struc << endl;
|
||||
cout << pv << endl;
|
||||
}
|
||||
</code></pre>
|
||||
|
||||
<h2>New template version of Structure::getField</h2>
|
||||
|
||||
<p>A new template getField method has been added to Structure</p>
|
||||
|
||||
<p>template<typename FT >
|
||||
std::tr1::shared_ptr< const FT > getField(std::string const &fieldName) const </p>
|
||||
|
||||
<p>Can be used, for example, as follows:</p>
|
||||
|
||||
<pre><code>StructurePtr tsStruc = struc->getField<Structure>("timeStamp");
|
||||
</code></pre>
|
||||
|
||||
<h2>Fixes for static initialisation order issues</h2>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<h2>CreateRequest change</h2>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<h1>Release 4.0</h1>
|
||||
|
||||
<p>The main changes since release 3.0.2 are:</p>
|
||||
|
||||
<ul>
|
||||
<li>array semantics now enforce Copy On Write.</li>
|
||||
<li>String no longer defined.</li>
|
||||
<li>timeStamp and valueAlarm name changes</li>
|
||||
<li>toString replaced by stream I/O </li>
|
||||
<li>union is new type.</li>
|
||||
<li>copy is new.</li>
|
||||
<li>monitorPlugin is new.</li>
|
||||
</ul>
|
||||
|
||||
<h2>New Semantics for Arrays</h2>
|
||||
|
||||
<p>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<em>vector facility.
|
||||
This allows multiple instances of array data to use the shared raw data.
|
||||
COW is implemented via shared</em>vectors of const data, i. e. data that can not be modified.</p>
|
||||
|
||||
<h2>String no longer defined</h2>
|
||||
|
||||
<p>This is replaced by std::string.</p>
|
||||
|
||||
<h2>timeStamp and valueAlarm name changes</h2>
|
||||
|
||||
<p>In timeStamp nanoSeconds is changed to nanoseconds.</p>
|
||||
|
||||
<p>In valueAlarm hysteresis is changed to hysteresis</p>
|
||||
|
||||
<h2>toString replaced by stream I/O</h2>
|
||||
|
||||
<p>pvData.h and pvIntrospect no longer defines toString
|
||||
Instead they have stream support.
|
||||
pvIntrospect uses method dump and pvData uses dumpValue.
|
||||
For example:</p>
|
||||
|
||||
<pre><code> PVDoublePtr pvValue;
|
||||
String buffer;
|
||||
pvValue->toString(&buffer);
|
||||
cout << buffer << endl;
|
||||
buffer.clear();
|
||||
pvValue->getField()->toString(&buffer);
|
||||
cout << buffer << evdl;
|
||||
</code></pre>
|
||||
|
||||
<p>is replaced by</p>
|
||||
|
||||
<pre><code> PVDoublePtr pvValue;
|
||||
cout << *pvValue << endl
|
||||
cout << *pvValue->getField() << endl;
|
||||
</code></pre>
|
||||
|
||||
<h2>union is a new basic type.</h2>
|
||||
|
||||
<p>There are two new basic types: union_t and unionArray.</p>
|
||||
|
||||
<p>A union is like a structure that has a single subfield.
|
||||
There are two flavors:</p>
|
||||
|
||||
<ul>
|
||||
<li><b>variant union</b> The field can have any type.</li>
|
||||
<li><b>union</b> The field can any of specified set of types.</li>
|
||||
</ul>
|
||||
|
||||
<p>The field type can be dynamically changed.</p>
|
||||
|
||||
<h2>copy </h2>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<h2>monitorPlugin</h2>
|
||||
|
||||
<p>This is for is for use by code that implements pvAccess monitors.
|
||||
This is prototype and is subject to debate.</p>
|
||||
|
||||
<h1>Release 3.0.2</h1>
|
||||
|
||||
<p>This was the starting point for RELEASE_NOTES</p>
|
||||
232
documentation/RELEASE_NOTES.md
Normal file
232
documentation/RELEASE_NOTES.md
Normal file
@@ -0,0 +1,232 @@
|
||||
Release 5.0
|
||||
===========
|
||||
|
||||
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 <b>getSubField</b> 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
|
||||
===========
|
||||
|
||||
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:
|
||||
|
||||
* <b>variant union</b> The field can have any type.
|
||||
* <b>union</b> 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
|
||||
20
documentation/TODO.md
Normal file
20
documentation/TODO.md
Normal file
@@ -0,0 +1,20 @@
|
||||
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.
|
||||
|
||||
monitorPlugin
|
||||
-------------
|
||||
|
||||
A debate is on-going about what semantics should be.
|
||||
|
||||
679
documentation/copyandmonitor.html
Normal file
679
documentation/copyandmonitor.html
Normal file
@@ -0,0 +1,679 @@
|
||||
<?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 pvDataCPP: copy and monitor</title>
|
||||
<link rel="stylesheet" type="text/css"
|
||||
href="http://epics-pvdata.sourceforge.net/base.css" />
|
||||
<link rel="stylesheet" type="text/css"
|
||||
href="http://epics-pvdata.sourceforge.net/epicsv4.css" />
|
||||
<style type="text/css">
|
||||
/*<![CDATA[*/
|
||||
.about { margin-left: 3em; margin-right: 3em; font-size: .83em}
|
||||
table { margin-left: auto; margin-right: auto }
|
||||
.diagram { text-align: center; margin: 2.5em 0 }
|
||||
span.opt { color: grey }
|
||||
span.nterm { font-style:italic }
|
||||
span.term { font-family:courier }
|
||||
span.user { font-family:courier }
|
||||
span.user:before { content:"<" }
|
||||
span.user:after { content:">" }
|
||||
.nonnorm { font-style:italic }
|
||||
p.ed { color: #AA0000 }
|
||||
span.ed { color: #AA0000 }
|
||||
p.ed.priv { display: inline; }
|
||||
span.ed.priv { display: inline; }
|
||||
/*]]>*/</style>
|
||||
<!-- Script that generates the Table of Contents -->
|
||||
<script type="text/javascript"
|
||||
src="http://epics-pvdata.sourceforge.net/script/tocgen.js">
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
||||
<div id="toc">
|
||||
<h2 class="nocount" style="page-break-before: always">Table of Contents</h2>
|
||||
</div>
|
||||
<div id="contents" class="contents">
|
||||
|
||||
<h2>support for copy and monitor</h2>
|
||||
<p><b>copy</b> and <b>monitor</b> are not used in this project.
|
||||
They are intended for use by pvAccess and by pvAccess servers.
|
||||
They are provided with this project because the code depends only on
|
||||
pvData itself.
|
||||
</p>
|
||||
<p>This document describes C++ specific code.
|
||||
<a href="http://epics-pvdata.sourceforge.net/informative/pvRequest.html">
|
||||
pvRequest.html</a>
|
||||
provides a language independent overview of <b>copy</b> and <b>monitor</b>.
|
||||
</p>
|
||||
<p>
|
||||
<b>NOTE:pvRequest.html</b> must be updated since it is based on an earlier version of pvCopy that
|
||||
had knowledge of PVRecord. The C++ version was implemented in pvDatabaseCPP
|
||||
and the Java version on pvIOCJava.
|
||||
At present only the C++ version of the new API for pvCopy is implemented.
|
||||
</p>
|
||||
<p>Copy provides:
|
||||
<dl>
|
||||
<dt>createRequest</dt>
|
||||
<dd>
|
||||
The Channel create methods in pvAccess all have an argument
|
||||
<b>PVStructure pvRequest</b>.<br />
|
||||
Given an ascii string createRequest creates a PVStructure that provides
|
||||
a pvData representation of the information from the ascii string.
|
||||
It is this structure that can be passed to the channel create methods.<br />
|
||||
The information in a pvRequest selects an arbitrary subset of the
|
||||
fields in a top level structure that resides in the server.
|
||||
In addition options can be specified. Both global and field specific
|
||||
options can be specified.
|
||||
</dd>
|
||||
<dt>pvCopy</dt>
|
||||
<dd>This is a facility used by channel providers.
|
||||
It provides client specific code that manages a copy of an arbitrary
|
||||
subset of the fields in a top level structure that resides in the
|
||||
provider. It also allows provider access to options specified
|
||||
by the client.
|
||||
</dd>
|
||||
</dl>
|
||||
Monitor provides:
|
||||
<dl>
|
||||
<dt>monitor</dt>
|
||||
<dd>This is support code for channel providers that implement channel
|
||||
monitor. It, together with the queue facility, provides support for
|
||||
monitor queues.
|
||||
</dd>
|
||||
<dt>monitorPlugin</dt>
|
||||
<dd>This is support for implementing monitor plugins.
|
||||
A monitor plugin can be developed that has no knowledge
|
||||
of pvAccess but only pvData.
|
||||
</dd>
|
||||
</dl>
|
||||
</p>
|
||||
|
||||
<h2>support for copy</h2>
|
||||
<p><b>copy</b> provides the ability to create a structure that has
|
||||
a copy of an arbitrary subset of the fields in an existing top level
|
||||
structure. In addition it allows global options and field specific options.
|
||||
It has two main components: <b>createRequest</b> and <b>pvCopy</b>.
|
||||
Given a string createRequest creates a pvRequest, which is a PVStructure
|
||||
that has the format expected by <b>pvCopy</b>.
|
||||
</p>
|
||||
|
||||
<h3>createRequest</h3>
|
||||
<p>This is mainly used by pvAccess clients. Given a request string it creates
|
||||
a pvRequest structure that can be passed to the pvAccess create methods.
|
||||
In turn pvAccess passes the pvRequest to a local channel provider which
|
||||
then passes it to pvCopy.
|
||||
</p>
|
||||
<p>The definition of the public members is:</p>
|
||||
<pre>
|
||||
class CreateRequest {
|
||||
...
|
||||
static CreateRequestPtr create();
|
||||
virtual PVStructurePtr createRequest(std::string const &request);
|
||||
std::string getMessage();
|
||||
};
|
||||
</pre>
|
||||
<p>An example of how it is used is:</p>
|
||||
<pre>
|
||||
CreateRequestPtr createRequest = CreateRequest::create();
|
||||
PVStructurePtr pvRequest = createRequest->createRequest(request);
|
||||
if(pvRequest==NULL) {
|
||||
std::string error = createRequest->getMessage();
|
||||
// take some action
|
||||
} else {
|
||||
//success do something
|
||||
}
|
||||
</pre>
|
||||
<h3>pvCopy</h3>
|
||||
<p>The definition of the public members is:</p>
|
||||
<pre>
|
||||
class epicsShareClass PVCopyTraverseMasterCallback
|
||||
{
|
||||
...
|
||||
virtual void nextMasterPVField(PVFieldPtr const &pvField);
|
||||
};
|
||||
|
||||
class class epicsShareClass PVCopy
|
||||
{
|
||||
...
|
||||
static PVCopyPtr create(
|
||||
PVStructurePtr const &pvMaster,
|
||||
PVStructurePtr const &pvRequest,
|
||||
std::string const & structureName);
|
||||
PVStructurePtr getPVMaster();
|
||||
void traverseMaster(PVCopyTraverseMasterCallbackPtr const & callback);
|
||||
StructureConstPtr getStructure();
|
||||
PVStructurePtr createPVStructure();
|
||||
size_t getCopyOffset(PVFieldPtr const &masterPVField);
|
||||
size_t getCopyOffset(
|
||||
PVStructurePtr const &masterPVStructure,
|
||||
PVFieldPtr const &masterPVField);
|
||||
PVFieldPtr getMasterPVField(std::size_t structureOffset);
|
||||
void initCopy(
|
||||
PVStructurePtr const &copyPVStructure,
|
||||
BitSetPtr const &bitSet);
|
||||
void updateCopySetBitSet(
|
||||
PVStructurePtr const &copyPVStructure,
|
||||
BitSetPtr const &bitSet);
|
||||
void updateCopyFromBitSet(
|
||||
PVStructurePtr const &copyPVStructure,
|
||||
BitSetPtr const &bitSet);
|
||||
void updateMaster(
|
||||
PVStructurePtr const &copyPVStructure,
|
||||
BitSetPtr const &bitSet);
|
||||
PVStructurePtr getOptions(std::size_t fieldOffset);
|
||||
...
|
||||
};
|
||||
</pre>
|
||||
where
|
||||
<dl>
|
||||
<dt>PVCopyTraverseMasterCallback::nextMasterPVField</dt>
|
||||
<dd>
|
||||
<b>PVCopyTraverseMasterCallback</b> is a callback which must
|
||||
be implemented by the code that uses pvCopy, normally
|
||||
the channel provider. It has the single method <b>nextMasterPVField</b>
|
||||
<br />
|
||||
<b>nextMasterPVField</b> is called for each field in the master
|
||||
as a result of a call to <b>traverseMaster</b>.
|
||||
</dd>
|
||||
<dt>create</dt>
|
||||
<dd>
|
||||
This is the method for creating a PVCopy instance.<br/>
|
||||
<dl>
|
||||
<dt>pvMaster</dt>
|
||||
<dd>the top level structure managed by the server.</dd>
|
||||
<dt>pvRequest</dt>
|
||||
<dd>selects the set of subfields desired
|
||||
and options for each field.</dd>
|
||||
<dt>structureName</dt>
|
||||
<dd>the name for the top level of any PVStructure created.
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt>getPVMaster</dt>
|
||||
<dd>
|
||||
Gets the top level structure from pvMaster.
|
||||
</dd>
|
||||
<dt>traverseMaster</dt>
|
||||
<dd>
|
||||
Traverse all fields of the top level structure of pvMaster.
|
||||
For each field the callback is called.
|
||||
</dd>
|
||||
<dt>getStructure</dt>
|
||||
<dd>
|
||||
Get the introspection interface for a PVStructure for e copy.
|
||||
</dd>
|
||||
<dt>createPVStructure</dt>
|
||||
<dd>Create a copy instance.
|
||||
Monitors keep a queue of monitor elements.
|
||||
Since each element needs a PVStructure, multiple top level structures
|
||||
will be created.
|
||||
</dd>
|
||||
<dt>getCopyOffset</dt>
|
||||
<dd>Given a field in pvMaster.
|
||||
return the offset in copy for the same field.
|
||||
A value of std::string::npos means that the copy does not have this field.
|
||||
Two overloaded methods are provided. The first is called if
|
||||
the field of master is not a structure. The second is for
|
||||
subfields of a structure.
|
||||
</dd>
|
||||
<dt>getMasterPVField</dt>
|
||||
<dd>
|
||||
Given a offset in the copy get the corresponding field in pvMaster.
|
||||
</dd>
|
||||
<dt>initCopy</dt>
|
||||
<dd>
|
||||
Initialize the fields in copyPVStructure
|
||||
by giving each field the value from the corresponding field in pvMaster.
|
||||
bitSet will be set to show that all fields are changed.
|
||||
This means that bit set will have the value <b>{0}</b>.
|
||||
</dd>
|
||||
<dt>updateCopySetBitSet</dt>
|
||||
<dd>
|
||||
Set all fields in copyPVStructure to the value of the corresponding field
|
||||
in pvMaster. Each field that is changed has it's corresponding
|
||||
bit set in bitSet.
|
||||
</dd>
|
||||
<dt>updateCopyFromBitSet</dt>
|
||||
<dd>
|
||||
For each set bit in bitSet set the field in copyPVStructure to the value
|
||||
of the corresponding field in pvMaster.
|
||||
</dd>
|
||||
<dt>updateMaster</dt>
|
||||
<dd>
|
||||
For each set bit in bitSet set the field in pvMaster to the value
|
||||
of the corresponding field in copyPVStructure.
|
||||
|
||||
</dd>
|
||||
<dt>getOptions</dt>
|
||||
<dd>
|
||||
Get the options for the field at the specified offset.
|
||||
A NULL is returned if no options were specified for the field.
|
||||
If options were specified,PVStructurePtr is
|
||||
a structure with a set of PVString subfields that specify name,value
|
||||
pairs. name is the subField name and value is the subField value.
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
<h2>support for monitor</h2>
|
||||
<p>This consists of two components:
|
||||
<dl>
|
||||
<dt>monitor</dt>
|
||||
<dd>Used by code that implements pvAccess monitors.</dd>
|
||||
<dt>monitorPlugin</dt>
|
||||
<dd>Code that provides special semantics for monitors.</dd>
|
||||
</dl>
|
||||
</p>
|
||||
<h3>monitor</h3>
|
||||
<pre>
|
||||
class MonitorElement {
|
||||
MonitorElement(PVStructurePtr const & pvStructurePtr);
|
||||
PVStructurePtr pvStructurePtr;
|
||||
BitSetPtr changedBitSet;
|
||||
BitSetPtr overrunBitSet;
|
||||
};
|
||||
|
||||
class Monitor {
|
||||
virtual Status start() = 0;
|
||||
virtual Status stop() = 0;
|
||||
virtual MonitorElementPtr poll() = 0;
|
||||
virtual void release(MonitorElementPtr const & monitorElement) = 0;
|
||||
};
|
||||
|
||||
class MonitorRequester : public virtual Requester {
|
||||
virtual void monitorConnect(Status const & status,
|
||||
MonitorPtr const & monitor, StructureConstPtr const & structure) = 0;
|
||||
virtual void monitorEvent(MonitorPtr const & monitor) = 0;
|
||||
virtual void unlisten(MonitorPtr const & monitor) = 0;
|
||||
};
|
||||
</pre>
|
||||
<h4>monitorElement</h4>
|
||||
<p><b>MonitorElement</b> holds the data for one element of a monitor queue.
|
||||
It has the fields:
|
||||
<dl>
|
||||
<dt>pvStructurePtr</dt>
|
||||
<dd>A top level structure with data values at the time the monitors occurs.</dd>
|
||||
<dt>changedBitSet</dt>
|
||||
<dd>Shows which fields have changed since the previous monitor.</dd>
|
||||
<dt>overrunBitSet</dt>
|
||||
<dd>Shows which fields have changed more han once since the previous monitor.</dd>
|
||||
</dl>
|
||||
</p>
|
||||
<h4>monitorElement queue</h4>
|
||||
<p>
|
||||
A queue of monitor elements must be implemented by any channel provider that implements
|
||||
<b>Channel::createMonitor</b>.
|
||||
For an example implementation look at pvDatabaseCPP.
|
||||
It has the following:
|
||||
<pre>
|
||||
typedef Queue<MonitorElement> MonitorElementQueue;
|
||||
typedef std::tr1::shared_ptr<MonitorElementQueue> MonitorElementQueuePtr;
|
||||
|
||||
class MultipleElementQueue :
|
||||
public ElementQueue
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(MultipleElementQueue);
|
||||
virtual ~MultipleElementQueue(){}
|
||||
MultipleElementQueue(
|
||||
MonitorLocalPtr const &monitorLocal,
|
||||
MonitorElementQueuePtr const &queue,
|
||||
size_t nfields);
|
||||
virtual void destroy(){}
|
||||
virtual Status start();
|
||||
virtual Status stop();
|
||||
virtual bool dataChanged();
|
||||
virtual MonitorElementPtr poll();
|
||||
virtual void release(MonitorElementPtr const &monitorElement);
|
||||
...
|
||||
};
|
||||
</pre>
|
||||
<h4>Monitor</h4>
|
||||
<p><b>Monitor</b> must be implemented by any channel provider that implements
|
||||
<b>Channel::createMonitor</b>.
|
||||
Remote PVAccess also implements Monitor on the client side.
|
||||
Note that each client has it's own queue that is not shared with other client.
|
||||
</p>
|
||||
<p>Monitor has the following methods:</p>
|
||||
<dl>
|
||||
<dt>start</dt>
|
||||
<dd>
|
||||
Start monitoring.
|
||||
This will result in a an initial monitor that has the current value
|
||||
of all fields.
|
||||
</dd>
|
||||
<dt>stop</dt>
|
||||
<dd>
|
||||
Stop monitoring.
|
||||
</dd>
|
||||
<dt>poll</dt>
|
||||
<dd>
|
||||
Called to get a monitor element.
|
||||
If no new elements are available then a null pointer is returned.
|
||||
</dd>
|
||||
<dt>release</dt>
|
||||
<dd>
|
||||
Release the monitor element.
|
||||
The caller owns the monitor element between the calls to poll and release.
|
||||
</dd>
|
||||
<dl>
|
||||
</dl>
|
||||
<h4>MonitorRequester</h4>
|
||||
<p>This must be implemented by a pvAccess client.
|
||||
It has the methods:</p>
|
||||
<dl>
|
||||
<dt>monitorConnect</dt>
|
||||
<dd>
|
||||
A monitor has either connected of disconnected.
|
||||
</dd>
|
||||
<dt>monitorEvent</dt>
|
||||
<dd>
|
||||
A new monitor element is available.
|
||||
</dd>
|
||||
<dt>unlisten</dt>
|
||||
<dd>
|
||||
The channel is going away. The client cam no longer access the monitor.
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<h3>monitorPlugin</h3>
|
||||
<pre>
|
||||
class MonitorPlugin
|
||||
{
|
||||
virtual std::string const & getName() = 0;
|
||||
virtual bool causeMonitor(
|
||||
PVFieldPtr const &pvField,
|
||||
PVStructurePtr const &pvTop,
|
||||
MonitorElementPtr const &monitorElement) = 0;
|
||||
virtual void monitorDone(
|
||||
MonitorElementPtr const &monitorElement);
|
||||
virtual void startMonitoring();
|
||||
virtual void stopMonitoring();
|
||||
virtual void beginGroupPut();
|
||||
virtual void endGroupPut();
|
||||
};
|
||||
|
||||
class MonitorPluginCreator
|
||||
{
|
||||
virtual MonitorPluginPtr create(
|
||||
FieldConstPtr const &field,
|
||||
StructureConstPtr const &top,
|
||||
PVStructurePtr const &pvFieldOptions) = 0;
|
||||
virtual std::string const & getName() = 0;
|
||||
}
|
||||
|
||||
class MonitorPluginManager
|
||||
{
|
||||
static MonitorPluginManagerPtr get();
|
||||
bool addPlugin(
|
||||
std::string const &pluginName,
|
||||
MonitorPluginCreatorPtr const &creator);
|
||||
MonitorPluginCreatorPtr findPlugin(std::string const &pluginName);
|
||||
void showNames();
|
||||
};
|
||||
|
||||
</pre>
|
||||
<h4>MonitorPlugin</h4>
|
||||
<p><b>MonitorPlugin</b> must be implemented by the plugin implementation.
|
||||
It has methods:</p>
|
||||
<dl>
|
||||
<dt>getName</dt>
|
||||
<dd>Get the name of the plugin.</dd>
|
||||
<dt>causeMonitor</dt>
|
||||
<dd>
|
||||
Should the value of pvField cause a monitor to be raised.
|
||||
pvField and pvTop are fields in the top level structure
|
||||
being monitored. monitorElement has the top level structure
|
||||
for the copy</b>.
|
||||
The implementation should <b>not</b> modify the fields in the structure
|
||||
being monitored.
|
||||
Called with pvTop locked.
|
||||
</dd>
|
||||
<dt>monitorDone</dt>
|
||||
<dd>
|
||||
Called just before monitorElement will be given to client.
|
||||
The plugin can change the data values and bitSets in monitorElement.
|
||||
Called with pvTop unlocked.
|
||||
</dd>
|
||||
<dt>startMonitoring</dt>
|
||||
<dd>
|
||||
Monitoring is starting.
|
||||
</dd>
|
||||
<dt>stopMonitoring</dt>
|
||||
<dd>
|
||||
Monitoring is being stopped.
|
||||
</dd>
|
||||
<dt>beginGroupPut</dt>
|
||||
<dd>
|
||||
A set of puts is starting.
|
||||
Called with pvTop locked.
|
||||
</dd>
|
||||
<dt>endGroupPut</dt>
|
||||
<dd>
|
||||
The set of puts is complete.
|
||||
Called with pvTop locked.
|
||||
</dd>
|
||||
</dl>
|
||||
<h4>MonitorPluginCreator</h4>
|
||||
<p><b>MonitorPluginCreator</b> must also be implemented by the plugin implementation.
|
||||
It is called for each field instance that has options of the from
|
||||
<b>[plugin=name...]</b> where <b>name</b> is the name of the plugin.
|
||||
Note that a plugin instance will belong to a single client.
|
||||
It has methods:</p>
|
||||
<dl>
|
||||
<dt>getName</dt>
|
||||
<dd>Get the name of the plugin.</dd>
|
||||
<dt>create</dt>
|
||||
<dd>
|
||||
Create a new plugin instance.
|
||||
If the arguments are not compatible with the plugin a NULL shared pointer is
|
||||
returned.<br/>
|
||||
pvFieldOptions is
|
||||
a structure with a set of PVString subfields that specify <b>name,value</b>
|
||||
pairs. name is the subField name and value is the subField value.<br/>
|
||||
Note that a plugin will below to a single client.
|
||||
</dd>
|
||||
<dl>
|
||||
<h4>MonitorPluginManager</h4>
|
||||
<p><b>MonitorPluginManager</b> has the methods:</p>
|
||||
<dl>
|
||||
<dt>get</dt>
|
||||
<dd>
|
||||
MonitorPluginManager is a singleton.
|
||||
The first call to get will create the single instance.
|
||||
Further calls will return the single instance.
|
||||
</dd>
|
||||
<dt>addPlugin</dt>
|
||||
<dd>
|
||||
Add a new plugin.
|
||||
</dd>
|
||||
<dt>findPlugin</dt>
|
||||
<dd>
|
||||
Find a plugin. A NULL shared pointer is returned if it has not been added.
|
||||
</dd>
|
||||
<dt>showNames</dt>
|
||||
<dd>
|
||||
Show the names of all plugins that have been added.
|
||||
</dd>
|
||||
</dl>
|
||||
<p><b>NOTE:</b>
|
||||
Should the method <b>causeMonitor</b>
|
||||
have arguments <b>pvField</b> and <b>pvTop</b>
|
||||
be defined so that they can not be modified.
|
||||
This would be possible if the following was defined:
|
||||
<pre>
|
||||
typedef std::tr1::shared_ptr<const PVField> PVFieldConstPtr;
|
||||
typedef std::tr1::shared_ptr<const PVStructure> PVStructureConstPtr;
|
||||
</pre>
|
||||
then the definition for causeMonitor could be:
|
||||
<pre>
|
||||
virtual bool causeMonitor(
|
||||
PVFieldConstPtr const &pvField,
|
||||
PVStructureConstPtr const &pvTop,
|
||||
MonitorElementPtr const &monitorElement) = 0;
|
||||
</pre>
|
||||
But just adding these definitions is not sufficient.
|
||||
In addition all methods defined in pvDataCPP must be checked.
|
||||
In particular many of the methods in <b>Convert</b> must have
|
||||
their arguments modified.
|
||||
Big job.
|
||||
</p>
|
||||
<h2>monitorPlugin example</h2>
|
||||
<h3>Example Plugin Overview</h3>
|
||||
<p>This section describes an example plugin that:</p>
|
||||
<ul>
|
||||
<li>Only raises monitors when a field changes value.<br />
|
||||
If no plugin is provided
|
||||
the default is to raise a monitor when a put is issued to a field.</li>
|
||||
<li>Optionally a change will not raise a monitor.<br />
|
||||
The change will, however,
|
||||
appear if a put to another field raise a monitor.</li>
|
||||
</ul>
|
||||
<p>As an example assume that a channel provided by pvAccess has a top level structure
|
||||
that represents a power supply.</p>
|
||||
<pre>
|
||||
structure powerSupply
|
||||
structure alarm
|
||||
structure timeStamp
|
||||
structure power
|
||||
double value
|
||||
structure alarm
|
||||
structure display
|
||||
structure voltage
|
||||
double value
|
||||
structure alarm
|
||||
structure display
|
||||
structure current
|
||||
double value
|
||||
structure alarm
|
||||
structure display
|
||||
</pre>
|
||||
<p>A pvAccess client wants to create a monitor on the powerSupply as follows:
|
||||
The client wants a top level structure that looks like:
|
||||
<pre>
|
||||
structure powerSupply
|
||||
structure alarm
|
||||
structure timeStamp
|
||||
structure power
|
||||
double value
|
||||
structure voltage
|
||||
double value
|
||||
structure current
|
||||
double value
|
||||
</pre>
|
||||
In addition the client wants monitors to occur only when one of the monitored
|
||||
fields changes value but not just because a put occured.
|
||||
Also if only the timeStamp changes value then that should not cause a monitor.
|
||||
</p>
|
||||
<p>The example monitor plugin implements the semantics the
|
||||
client wants. It can be attached to any field via the following options:
|
||||
<pre>
|
||||
[plugin=onChange,raiseMonitor=value]
|
||||
</pre>
|
||||
This plugin will trigger a monitor for the field only if the field changes
|
||||
value. In addition <b>value</b> equals <b>false</b> means do not raise a monitor
|
||||
for changes to this field.
|
||||
But if a change to another field does cause a monitor the change to this field
|
||||
will be passed to the client.
|
||||
</p>
|
||||
<p>
|
||||
Assume that the client has already connected to the channel.
|
||||
The client can then issue the commands:</p>
|
||||
<pre>
|
||||
std::string request("field(alarm[plugin=onChange]");
|
||||
request += ",timeStamp[plugin=onChange,raiseMonitor=false]";
|
||||
request += ",power.value[plugin=onChange";
|
||||
request += ",voltage.value[plugin=onChange";
|
||||
request += ",current.value[plugin=onChange";
|
||||
|
||||
PVStructurePtr pvRequest = createRequest->createRequest(request);
|
||||
|
||||
MonitorPtr monitor = channel->createMonitor(monitorRequester,pvRequest);
|
||||
</pre>
|
||||
<h3>Example Plugin Code</h3>
|
||||
<p>The header file to create the example has the definition:</p>
|
||||
<pre>
|
||||
class ExampleMonitorPlugin{
|
||||
public:
|
||||
static void create();
|
||||
};
|
||||
</pre>
|
||||
<p>The implementation is:</p>
|
||||
<pre>
|
||||
class OnChangePlugin : public MonitorPlugin
|
||||
{
|
||||
public:
|
||||
virtual ~OnChangePlugin(){}
|
||||
OnChangePlugin() {}
|
||||
bool init(
|
||||
FieldConstPtr const &field,
|
||||
StructureConstPtr const &top,
|
||||
PVStructurePtr const &pvFieldOptions)
|
||||
{
|
||||
pvField = getPVDataCreate()->createPVField(field);
|
||||
raiseMonitor = true;
|
||||
if(pvFieldOptions!=NULL) {
|
||||
PVStringPtr pvString =
|
||||
pvFieldOptions->getSubField<PVString>("raiseMonitor");
|
||||
if(pvString!=NULL) {
|
||||
std::string value = pvString->get();
|
||||
if(value.compare("false")==0) raiseMonitor = false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
virtual std::string &getName(){return pluginName;}
|
||||
virtual bool causeMonitor(
|
||||
PVFieldPtr const &pvNew,
|
||||
PVStructurePtr const &pvTop,
|
||||
MonitorElementPtr const &monitorElement)
|
||||
{
|
||||
bool isSame = convert->equals(pvNew,pvField);
|
||||
if(isSame) return false;
|
||||
convert->copy(pvNew,pvField);
|
||||
return raiseMonitor;
|
||||
}
|
||||
private:
|
||||
PVFieldPtr pvField;
|
||||
bool raiseMonitor;
|
||||
};
|
||||
class OnChangePluginCreator : public MonitorPluginCreator
|
||||
{
|
||||
public:
|
||||
virtual std::string &getName(){return pluginName;}
|
||||
virtual MonitorPluginPtr create(
|
||||
FieldConstPtr const &field,
|
||||
StructureConstPtr const &top,
|
||||
PVStructurePtr const &pvFieldOptions)
|
||||
{
|
||||
OnChangePluginPtr plugin(new OnChangePlugin());
|
||||
bool result = plugin->init(field,top,pvFieldOptions);
|
||||
if(!result) return MonitorPluginPtr();
|
||||
return plugin;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
void ExampleMonitorPlugin::create()
|
||||
{
|
||||
static OnChangePluginCreatorPtr plugin;
|
||||
static Mutex mutex;
|
||||
Lock xx(mutex);
|
||||
if(plugin==NULL) {
|
||||
plugin = OnChangePluginCreatorPtr(new OnChangePluginCreator());
|
||||
MonitorPluginManager::get()->addPlugin(pluginName,plugin);
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
BIN
documentation/examples.zip
Normal file
BIN
documentation/examples.zip
Normal file
Binary file not shown.
File diff suppressed because it is too large
Load Diff
179
documentation/pvDataCPPCookbook.txt
Normal file
179
documentation/pvDataCPPCookbook.txt
Normal file
@@ -0,0 +1,179 @@
|
||||
pvDataCPP cookbook
|
||||
------------------
|
||||
|
||||
|
||||
Creating introspection data interfaces
|
||||
|
||||
// create a scalar
|
||||
getFieldCreate()->createScalar(pvDouble);
|
||||
|
||||
// create a scalar array
|
||||
getFieldCreate()->createScalarArray(pvDouble);
|
||||
|
||||
// create a structure
|
||||
getFieldCreate()->createFieldBuilder()->
|
||||
setId("enum_t")->
|
||||
add("index", pvDouble)->
|
||||
addArray("choices", pvString)->
|
||||
createStructure();
|
||||
|
||||
// create a structure (cntd.)
|
||||
StructureConstPtr enum_t =
|
||||
getFieldCreate()->createFieldBuilder()->
|
||||
setId("enum_t")->
|
||||
add("index", pvInt)->
|
||||
addArray("choices", pvString)->
|
||||
createStructure();
|
||||
|
||||
// create a structure (cntd.)
|
||||
StructureConstPtr ntEnum =
|
||||
getFieldCreate()->createFieldBuilder()->
|
||||
setId("epics:nt/NTEnum:1.0")->
|
||||
add("value", enum_t)->
|
||||
addNestedStructure("timeStamp")->
|
||||
setId("time_t")->
|
||||
add("secondsPastEpoch", pvLong)->
|
||||
add("nanoseconds", pvInt)->
|
||||
add("userTag", pvInt)->
|
||||
endNested()->
|
||||
createStructure();
|
||||
|
||||
// create an union == same as structure
|
||||
|
||||
---
|
||||
|
||||
Creating data containers
|
||||
|
||||
// create a scalar
|
||||
PVDouble::shared_pointer doubleValue = getPVDataCreate()->createPVScalar<PVDouble>();
|
||||
|
||||
// create a scalar array
|
||||
PVDoubleArray::shared_pointer doubleArrayValue = getPVDataCreate()->createPVScalarArray<PVDouble>();
|
||||
|
||||
// create a structure
|
||||
PVStructure::shared_pointer struct = getPVDataCreate()->createPVStructure(ntEnum);
|
||||
|
||||
// create an union
|
||||
PVUnion::shared_pointer pvUnion = getPVDataCreate()->createPVUnion(unionIF);
|
||||
|
||||
// create a structure array
|
||||
PVStructureArray::shared_pointer structArray = getPVDataCreate()->createPVStructureArray(ntEnum);
|
||||
|
||||
|
||||
// scalar usage
|
||||
PVInt::shared_pointer index = struct->getSubField<PVInt>("value.index");
|
||||
int32 ix = index->get();
|
||||
index->put(3);
|
||||
std::cout << *index << std::endl;
|
||||
|
||||
|
||||
// using <<=, >>= operators to get/set
|
||||
*doubleValue <<= 12.3;
|
||||
|
||||
double val;
|
||||
*doubleValue >>= val;
|
||||
|
||||
|
||||
|
||||
// array usage
|
||||
PVStringArray::shared_pointer choices = struct->getSubField<PVStringArray>("value.choices");
|
||||
|
||||
// use view() to access read-only data
|
||||
PVStringArray::const_svector data(choices->view());
|
||||
for (std::size_t i = 0; i < data.size(); i++)
|
||||
std::cout << data[i] << std::endl;
|
||||
|
||||
// use replace() to put new data
|
||||
PVStringArray::svector newdata;
|
||||
newdata.push_back("zero");
|
||||
newdata.push_back("one");
|
||||
newdata.push_back("two");
|
||||
choices->replace(freeze(newdata));
|
||||
|
||||
// (add more use-cases) here
|
||||
|
||||
// print entire array
|
||||
std::cout << *choices << std::endl;
|
||||
|
||||
// print elmenet at index == 1
|
||||
std::cout << format::array_at(1) << *choices << std::endl;
|
||||
|
||||
----
|
||||
|
||||
Union handling
|
||||
|
||||
|
||||
Union::const_shared_pointer punion =
|
||||
getFieldCreate()->createFieldBuilder()->
|
||||
add("doubleValue", pvDouble)->
|
||||
add("intValue", pvInt)->
|
||||
createUnion();
|
||||
|
||||
PVUnion::shared_pointer u = getPVDataCreate()->createPVUnion(punion);
|
||||
|
||||
// select and put
|
||||
// this create a new instance of PVDouble (everytime select() is called)
|
||||
PVDouble::shared_pointer doubleValue = u->select<PVDouble>("doubleValue");
|
||||
doubeValue->put(12);
|
||||
// select using index (and direct put)
|
||||
u->select<PVDouble>(0)->put(12);
|
||||
// select using existing PVField (PVUnion stores by-reference)
|
||||
u->set("doubleValue", doubleValue);
|
||||
|
||||
// get selected field name or index
|
||||
std::string selectedFN = u->getSelectedFieldName();
|
||||
int32 selectedIndex = u->getSelectedIndex();
|
||||
|
||||
// get currently selected (knowing it's PVDouble)
|
||||
PVDouble value = u->get<PVDouble>();
|
||||
|
||||
|
||||
|
||||
Variant Union handling
|
||||
|
||||
|
||||
PVUnion::shared_pointer any = getPVDataCreate()->createPVVariantUnion();
|
||||
|
||||
PVDouble::shared_pointer doubleValue = getPVDataCreate()->createPVScalar<PVDouble>();
|
||||
doubleValue->put(12.8);
|
||||
any->set(doubleValue);
|
||||
|
||||
PVDouble::shared_pointer doubleValue2 = any->get<PVDouble>();
|
||||
|
||||
// variant union work by-reference (pointers match also)
|
||||
// doubleValue.get() == doubleValue2.get()
|
||||
|
||||
|
||||
|
||||
------
|
||||
|
||||
Convert
|
||||
|
||||
|
||||
// convert to int
|
||||
int32 i = doubleValue->getAs<int32>();
|
||||
|
||||
// from int
|
||||
doubleValue->putFrom<int32>(i);
|
||||
|
||||
// from string
|
||||
doubleValue->putFrom<std::string>("12.3");
|
||||
|
||||
// from scalar field
|
||||
doubleValue->assign(pvScalar);
|
||||
|
||||
|
||||
|
||||
// convert to int array
|
||||
PVIntArray::const_svector intData;
|
||||
doubleArrayValue->getAs<int32>(intData);
|
||||
|
||||
// from string array
|
||||
PVStringArray::svector labels;
|
||||
labels.push_back("zero");
|
||||
labels.push_back("one");
|
||||
labels.push_back("two");
|
||||
doubleArrayValue->putFrom<std::string>(labels);
|
||||
|
||||
// from scalar array
|
||||
doubleArrayValue->assign(pvScalarArray);
|
||||
@@ -42,11 +42,11 @@
|
||||
<dl>
|
||||
<dt>Latest version:</dt>
|
||||
<dd><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvDataCPP/raw-file/tip/documentation/pvDataCPP.html">pvDataCPP.html</a>
|
||||
href="pvDataCPP.html">pvDataCPP.html</a>
|
||||
</dd>
|
||||
<dt>This version:</dt>
|
||||
<dd><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvDataCPP/raw-file/tip/documentation/pvDataCPP_20120927.html">pvDataCPP_20120927.html</a>
|
||||
href="pvDataCPP_20120927.html">pvDataCPP_20120927.html</a>
|
||||
</dd>
|
||||
<dt>Previous version:</dt>
|
||||
<dd>None.</dd>
|
||||
@@ -65,33 +65,9 @@ license.</a></p>
|
||||
<p>pvDataCPP is a computer software package for the efficient
|
||||
storage, access, and communication, of structured data. It is specifically the
|
||||
C++ implementation of pvData, which is one part of the set of related products in the EPICS
|
||||
V4 control system programming environment:</p>
|
||||
<dl>
|
||||
<dt><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvDataCPP/raw-file/tip/documentation/pvDataCPP.html">pvData</a></dt>
|
||||
<dd>pvData (Process Variable Data) defines and implements an efficent way
|
||||
to store, access, and communicate memory resident structured data</dd>
|
||||
<dt><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvAccessCPP/raw-file/tip/documentation/pvAccessCPP.html">pvAccess</a></dt>
|
||||
<dd>pvAccess is a software library for high speed controls network communications,
|
||||
optimized for pvData</dd>
|
||||
<dt><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvIOCCPP/raw-file/tip/documentation/pvIOCCPP.html">pvIOC</a></dt>
|
||||
<dd>pvIOC is a software framework for building network accessable "smart" real time
|
||||
databases, suitable for interfacing devices in a distributed control system,
|
||||
that can exchange pvData over pvAccess.
|
||||
</dd>
|
||||
<dt><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvServiceCPP/raw-file/tip/documentation/pvAccessCPP.html">pvService</a></dt>
|
||||
<dd>A middle layer for implementing efficient data services.</dd>
|
||||
</dl>
|
||||
|
||||
<p>Each of these products has a Java and a C++ implementation.</p>
|
||||
|
||||
<p>The products are all part of the <a
|
||||
href="http://epics-pvdata.sourceforge.net/">V4</a> implementation of <a
|
||||
href="http://www.aps.anl.gov/epics/">Experimental Physics and Industrial
|
||||
Control System (EPICS).</a></p>
|
||||
V4 control system programming environment:<br />
|
||||
<a href="http://epics-pvdata.sourceforge.net/relatedDocumentsV4.html">relatedDocumentsV4.html</a>
|
||||
</p>
|
||||
|
||||
<h2 class="nocount">Status of this Document</h2>
|
||||
|
||||
|
||||
@@ -42,15 +42,15 @@
|
||||
<dl>
|
||||
<dt>Latest version:</dt>
|
||||
<dd><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvDataCPP/raw-file/tip/documentation/pvDataCPP.html">pvDataCPP.html</a>
|
||||
href="pvDataCPP.html">pvDataCPP.html</a>
|
||||
</dd>
|
||||
<dt>This version:</dt>
|
||||
<dd><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvDataCPP/raw-file/tip/documentation/pvDataCPP_20121001.html">pvDataCPP_20121001.html</a>
|
||||
href="pvDataCPP_20121001.html">pvDataCPP_20121001.html</a>
|
||||
</dd>
|
||||
<dt>Previous version:</dt>
|
||||
<dd><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvDataCPP/raw-file/tip/documentation/pvDataCPP_20120927.html">pvDataCPP_20120927.html</a>
|
||||
href="pvDataCPP_20120927.html">pvDataCPP_20120927.html</a>
|
||||
</dd>
|
||||
<dt>Editors:</dt>
|
||||
<dd>Marty Kraimer, BNL</dd>
|
||||
@@ -67,33 +67,9 @@ license.</a></p>
|
||||
<p>pvDataCPP is a computer software package for the efficient
|
||||
storage, access, and communication, of structured data. It is specifically the
|
||||
C++ implementation of pvData, which is one part of the set of related products in the EPICS
|
||||
V4 control system programming environment:</p>
|
||||
<dl>
|
||||
<dt><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvDataCPP/raw-file/tip/documentation/pvDataCPP.html">pvData</a></dt>
|
||||
<dd>pvData (Process Variable Data) defines and implements an efficent way
|
||||
to store, access, and communicate memory resident structured data</dd>
|
||||
<dt><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvAccessCPP/raw-file/tip/documentation/pvAccessCPP.html">pvAccess</a></dt>
|
||||
<dd>pvAccess is a software library for high speed controls network communications,
|
||||
optimized for pvData</dd>
|
||||
<dt><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvIOCCPP/raw-file/tip/documentation/pvIOCCPP.html">pvIOC</a></dt>
|
||||
<dd>pvIOC is a software framework for building network accessable "smart" real time
|
||||
databases, suitable for interfacing devices in a distributed control system,
|
||||
that can exchange pvData over pvAccess.
|
||||
</dd>
|
||||
<dt><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvServiceCPP/raw-file/tip/documentation/pvAccessCPP.html">pvService</a></dt>
|
||||
<dd>A middle layer for implementing efficient data services.</dd>
|
||||
</dl>
|
||||
|
||||
<p>Each of these products has a Java and a C++ implementation.</p>
|
||||
|
||||
<p>The products are all part of the <a
|
||||
href="http://epics-pvdata.sourceforge.net/">V4</a> implementation of <a
|
||||
href="http://www.aps.anl.gov/epics/">Experimental Physics and Industrial
|
||||
Control System (EPICS).</a></p>
|
||||
V4 control system programming environment:<br />
|
||||
<a href="http://epics-pvdata.sourceforge.net/relatedDocumentsV4.html">relatedDocumentsV4.html</a>
|
||||
</p>
|
||||
|
||||
<h2 class="nocount">Status of this Document</h2>
|
||||
|
||||
|
||||
@@ -42,15 +42,15 @@
|
||||
<dl>
|
||||
<dt>Latest version:</dt>
|
||||
<dd><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvDataCPP/raw-file/tip/documentation/pvDataCPP.html">pvDataCPP.html</a>
|
||||
href="pvDataCPP.html">pvDataCPP.html</a>
|
||||
</dd>
|
||||
<dt>This version:</dt>
|
||||
<dd><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvDataCPP/raw-file/tip/documentation/pvDataCPP_20121026html">pvDataCPP_20121026html</a>
|
||||
href="pvDataCPP_20121026html">pvDataCPP_20121026html</a>
|
||||
</dd>
|
||||
<dt>Previous version:</dt>
|
||||
<dd><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvDataCPP/raw-file/tip/documentation/pvDataCPP_20121001.html">pvDataCPP_20121001.html</a>
|
||||
href="pvDataCPP_20121001.html">pvDataCPP_20121001.html</a>
|
||||
</dd>
|
||||
<dt>Editors:</dt>
|
||||
<dd>Marty Kraimer, BNL</dd>
|
||||
@@ -67,33 +67,9 @@ license.</a></p>
|
||||
<p>pvDataCPP is a computer software package for the efficient
|
||||
storage, access, and communication, of structured data. It is specifically the
|
||||
C++ implementation of pvData, which is one part of the set of related products in the EPICS
|
||||
V4 control system programming environment:</p>
|
||||
<dl>
|
||||
<dt><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvDataCPP/raw-file/tip/documentation/pvDataCPP.html">pvData</a></dt>
|
||||
<dd>pvData (Process Variable Data) defines and implements an efficent way
|
||||
to store, access, and communicate memory resident structured data</dd>
|
||||
<dt><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvAccessCPP/raw-file/tip/documentation/pvAccessCPP.html">pvAccess</a></dt>
|
||||
<dd>pvAccess is a software library for high speed controls network communications,
|
||||
optimized for pvData</dd>
|
||||
<dt><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvIOCCPP/raw-file/tip/documentation/pvIOCCPP.html">pvIOC</a></dt>
|
||||
<dd>pvIOC is a software framework for building network accessable "smart" real time
|
||||
databases, suitable for interfacing devices in a distributed control system,
|
||||
that can exchange pvData over pvAccess.
|
||||
</dd>
|
||||
<dt><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvServiceCPP/raw-file/tip/documentation/pvAccessCPP.html">pvService</a></dt>
|
||||
<dd>A middle layer for implementing efficient data services.</dd>
|
||||
</dl>
|
||||
|
||||
<p>Each of these products has a Java and a C++ implementation.</p>
|
||||
|
||||
<p>The products are all part of the <a
|
||||
href="http://epics-pvdata.sourceforge.net/">V4</a> implementation of <a
|
||||
href="http://www.aps.anl.gov/epics/">Experimental Physics and Industrial
|
||||
Control System (EPICS).</a></p>
|
||||
V4 control system programming environment:<br />
|
||||
<a href="http://epics-pvdata.sourceforge.net/relatedDocumentsV4.html">relatedDocumentsV4.html</a>
|
||||
</p>
|
||||
|
||||
<h2 class="nocount">Status of this Document</h2>
|
||||
|
||||
|
||||
@@ -42,15 +42,15 @@
|
||||
<dl>
|
||||
<dt>Latest version:</dt>
|
||||
<dd><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvDataCPP/raw-file/tip/documentation/pvDataCPP.html">pvDataCPP.html</a>
|
||||
href="pvDataCPP.html">pvDataCPP.html</a>
|
||||
</dd>
|
||||
<dt>This version:</dt>
|
||||
<dd><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvDataCPP/raw-file/tip/documentation/pvDataCPP_20121212html">pvDataCPP_20121212html</a>
|
||||
href="pvDataCPP_20121212.html">pvDataCPP_20121212.html</a>
|
||||
</dd>
|
||||
<dt>Previous version:</dt>
|
||||
<dd><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvDataCPP/raw-file/tip/documentation/pvDataCPP_20121026html">pvDataCPP_20121026html</a>
|
||||
href="pvDataCPP_20121026.html">pvDataCPP_20121026.html</a>
|
||||
</dd>
|
||||
<dt>Editors:</dt>
|
||||
<dd>Marty Kraimer, BNL</dd>
|
||||
@@ -67,33 +67,9 @@ license.</a></p>
|
||||
<p>pvDataCPP is a computer software package for the efficient
|
||||
storage, access, and communication, of structured data. It is specifically the
|
||||
C++ implementation of pvData, which is one part of the set of related products in the EPICS
|
||||
V4 control system programming environment:</p>
|
||||
<dl>
|
||||
<dt><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvDataCPP/raw-file/tip/documentation/pvDataCPP.html">pvData</a></dt>
|
||||
<dd>pvData (Process Variable Data) defines and implements an efficent way
|
||||
to store, access, and communicate memory resident structured data</dd>
|
||||
<dt><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvAccessCPP/raw-file/tip/documentation/pvAccessCPP.html">pvAccess</a></dt>
|
||||
<dd>pvAccess is a software library for high speed controls network communications,
|
||||
optimized for pvData</dd>
|
||||
<dt><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvIOCCPP/raw-file/tip/documentation/pvIOCCPP.html">pvIOC</a></dt>
|
||||
<dd>pvIOC is a software framework for building network accessable "smart" real time
|
||||
databases, suitable for interfacing devices in a distributed control system,
|
||||
that can exchange pvData over pvAccess.
|
||||
</dd>
|
||||
<dt><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvServiceCPP/raw-file/tip/documentation/pvAccessCPP.html">pvService</a></dt>
|
||||
<dd>A middle layer for implementing efficient data services.</dd>
|
||||
</dl>
|
||||
|
||||
<p>Each of these products has a Java and a C++ implementation.</p>
|
||||
|
||||
<p>The products are all part of the <a
|
||||
href="http://epics-pvdata.sourceforge.net/">V4</a> implementation of <a
|
||||
href="http://www.aps.anl.gov/epics/">Experimental Physics and Industrial
|
||||
Control System (EPICS).</a></p>
|
||||
V4 control system programming environment:<br />
|
||||
<a href="http://epics-pvdata.sourceforge.net/relatedDocumentsV4.html">relatedDocumentsV4.html</a>
|
||||
</p>
|
||||
|
||||
<h2 class="nocount">Status of this Document</h2>
|
||||
|
||||
|
||||
@@ -42,15 +42,15 @@
|
||||
<dl>
|
||||
<dt>Latest version:</dt>
|
||||
<dd><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvDataCPP/raw-file/tip/documentation/pvDataCPP.html">pvDataCPP.html</a>
|
||||
href="pvDataCPP.html">pvDataCPP.html</a>
|
||||
</dd>
|
||||
<dt>This version:</dt>
|
||||
<dd><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvDataCPP/raw-file/tip/documentation/pvDataCPP_20130516.html">pvDataCPP_20130516.html</a>
|
||||
href="pvDataCPP_20130516.html">pvDataCPP_20130516.html</a>
|
||||
</dd>
|
||||
<dt>Previous version:</dt>
|
||||
<dd><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvDataCPP/raw-file/tip/documentation/pvDataCPP_20121212.html">pvDataCPP_20121212.html</a>
|
||||
href="pvDataCPP_20121212.html">pvDataCPP_20121212.html</a>
|
||||
</dd>
|
||||
<dt>Editors:</dt>
|
||||
<dd>Marty Kraimer, BNL</dd>
|
||||
@@ -67,33 +67,10 @@ license.</a></p>
|
||||
<p>pvDataCPP is a computer software package for the efficient
|
||||
storage, access, and communication, of structured data. It is specifically the
|
||||
C++ implementation of pvData, which is one part of the set of related products in the EPICS
|
||||
V4 control system programming environment:</p>
|
||||
<dl>
|
||||
<dt><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvDataCPP/raw-file/tip/documentation/pvDataCPP.html">pvData</a></dt>
|
||||
<dd>pvData (Process Variable Data) defines and implements an efficent way
|
||||
to store, access, and communicate memory resident structured data</dd>
|
||||
<dt><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvAccessCPP/raw-file/tip/documentation/pvAccessCPP.html">pvAccess</a></dt>
|
||||
<dd>pvAccess is a software library for high speed controls network communications,
|
||||
optimized for pvData</dd>
|
||||
<dt><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvIOCCPP/raw-file/tip/documentation/pvIOCCPP.html">pvIOC</a></dt>
|
||||
<dd>pvIOC is a software framework for building network accessable "smart" real time
|
||||
databases, suitable for interfacing devices in a distributed control system,
|
||||
that can exchange pvData over pvAccess.
|
||||
</dd>
|
||||
<dt><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvServiceCPP/raw-file/tip/documentation/pvAccessCPP.html">pvService</a></dt>
|
||||
<dd>A middle layer for implementing efficient data services.</dd>
|
||||
</dl>
|
||||
V4 control system programming environment:<br />
|
||||
<a href="http://epics-pvdata.sourceforge.net/relatedDocumentsV4.html">relatedDocumentsV4.html</a>
|
||||
</p>
|
||||
|
||||
<p>Each of these products has a Java and a C++ implementation.</p>
|
||||
|
||||
<p>The products are all part of the <a
|
||||
href="http://epics-pvdata.sourceforge.net/">V4</a> implementation of <a
|
||||
href="http://www.aps.anl.gov/epics/">Experimental Physics and Industrial
|
||||
Control System (EPICS).</a></p>
|
||||
|
||||
<h2 class="nocount">Status of this Document</h2>
|
||||
|
||||
|
||||
5537
documentation/pvDataCPP_20140501.html
Normal file
5537
documentation/pvDataCPP_20140501.html
Normal file
File diff suppressed because it is too large
Load Diff
5380
documentation/pvDataCPP_20140708.html
Normal file
5380
documentation/pvDataCPP_20140708.html
Normal file
File diff suppressed because it is too large
Load Diff
5392
documentation/pvDataCPP_20140723.html
Normal file
5392
documentation/pvDataCPP_20140723.html
Normal file
File diff suppressed because it is too large
Load Diff
5478
documentation/pvDataCPP_20141110.html
Normal file
5478
documentation/pvDataCPP_20141110.html
Normal file
File diff suppressed because it is too large
Load Diff
5480
documentation/pvDataCPP_20150623.html
Normal file
5480
documentation/pvDataCPP_20150623.html
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,29 +0,0 @@
|
||||
# pvData C++ implementation
|
||||
# Jenkins @ APS 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> and Andrew Johnson <anj@aps.anl.gov>
|
||||
# Copyright (C) 2013 Helmholtz-Zentrum Berlin für Materialien und Energie GmbH
|
||||
# All rights reserved. Use is subject to license terms.
|
||||
|
||||
###########################################
|
||||
# Build
|
||||
|
||||
export EPICS_BASE=${HOME}/jobs/epics-base-3.14/workspace
|
||||
export EPICS_HOST_ARCH=$(${EPICS_BASE}/startup/EpicsHostArch)
|
||||
|
||||
cat > configure/RELEASE.local << EOF
|
||||
PVCOMMON=${HOME}/jobs/epics-pvCommon/workspace
|
||||
EPICS_BASE=${EPICS_BASE}
|
||||
EOF
|
||||
|
||||
make distclean all
|
||||
|
||||
###########################################
|
||||
# Test
|
||||
|
||||
for t in bin/linux-x86_64/test*; do
|
||||
$t
|
||||
done
|
||||
@@ -4,10 +4,19 @@
|
||||
# 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>
|
||||
# Author: Ralph Lange <ralph.lange@gmx.de>
|
||||
# Copyright (C) 2013 Helmholtz-Zentrum Berlin für Materialien und Energie GmbH
|
||||
# Copyright (C) 2014-2015 ITER Organization.
|
||||
# All rights reserved. Use is subject to license terms.
|
||||
|
||||
###########################################
|
||||
# Determine EPICS Base version
|
||||
|
||||
DEFAULT_BASE=3.14.12.5
|
||||
|
||||
BASE=${1:-${DEFAULT_BASE}}
|
||||
USE_MB=${2:-"MB_NO"}
|
||||
|
||||
###########################################
|
||||
# Fetch and unpack dependencies
|
||||
|
||||
@@ -17,10 +26,8 @@ rm -fr ${STUFF}
|
||||
mkdir -p ${STUFF}
|
||||
cd ${STUFF}
|
||||
|
||||
wget -nv https://openepics.ci.cloudbees.com/job/Base-3.14.12.3_Build/lastSuccessfulBuild/artifact/baseR3.14.12.3.CB-dist.tar.gz
|
||||
wget -nv https://openepics.ci.cloudbees.com/job/Doxygen-1.8.3_Build/lastSuccessfulBuild/artifact/doxygen-1.8.3.CB-dist.tar.gz
|
||||
tar -xzf baseR3.14.12.3.CB-dist.tar.gz
|
||||
tar -xzf doxygen-1.8.3.CB-dist.tar.gz
|
||||
wget -nv https://openepics.ci.cloudbees.com/job/Base-${BASE}_Build/lastSuccessfulBuild/artifact/base-${BASE}.CB-dist.tar.gz
|
||||
tar -xzf base-${BASE}.CB-dist.tar.gz
|
||||
|
||||
###########################################
|
||||
# Build
|
||||
@@ -37,21 +44,13 @@ EPICS_BASE=${EPICS_BASE}
|
||||
EOF
|
||||
|
||||
make distclean all
|
||||
doxygen
|
||||
|
||||
###########################################
|
||||
# Test
|
||||
|
||||
for t in bin/linux-x86_64/test*; do
|
||||
$t
|
||||
done
|
||||
make runtests
|
||||
|
||||
###########################################
|
||||
# Create distribution
|
||||
|
||||
tar czf pvData.CB-dist.tar.gz lib include COPYRIGHT LICENSE
|
||||
|
||||
###########################################
|
||||
# Publish documentation
|
||||
|
||||
rsync -aP --delete -e ssh documentation epics-jenkins@web.sourceforge.net:/home/project-web/epics-pvdata/htdocs/docbuild/pvDataCPP/tip
|
||||
|
||||
51
jenkins/cloudbees_doc
Normal file
51
jenkins/cloudbees_doc
Normal file
@@ -0,0 +1,51 @@
|
||||
# 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-2015 ITER Organization.
|
||||
# All rights reserved. Use is subject to license terms.
|
||||
|
||||
###########################################
|
||||
# Set EPICS Base version and upload target
|
||||
|
||||
BASE=3.15.2
|
||||
PUBLISH=${1:-DONT}
|
||||
|
||||
###########################################
|
||||
# Fetch and unpack dependencies
|
||||
|
||||
export STUFF=/tmp/stuff
|
||||
|
||||
rm -fr ${STUFF}
|
||||
mkdir -p ${STUFF}
|
||||
cd ${STUFF}
|
||||
|
||||
wget -nv https://openepics.ci.cloudbees.com/job/Doxygen-1.8.3_Build/lastSuccessfulBuild/artifact/doxygen-1.8.3.CB-dist.tar.gz
|
||||
tar -xzf doxygen-1.8.3.CB-dist.tar.gz
|
||||
|
||||
###########################################
|
||||
# Generate
|
||||
|
||||
cd ${WORKSPACE}
|
||||
|
||||
wget -nv https://openepics.ci.cloudbees.com/job/pvDataCPP_Build/BASE=${BASE},USE_MB=MB_NO/lastSuccessfulBuild/artifact/pvData.CB-dist.tar.gz
|
||||
tar -xzf pvData.CB-dist.tar.gz
|
||||
|
||||
export PATH=${STUFF}/bin:${PATH}
|
||||
|
||||
doxygen
|
||||
|
||||
###########################################
|
||||
# Publish
|
||||
|
||||
if [ "${PUBLISH}" != "DONT" ]; 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,20 +0,0 @@
|
||||
# pvData C++ implementation
|
||||
# Jenkins @ Cloudbees hgweb sync 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
|
||||
# All rights reserved. Use is subject to license terms.
|
||||
|
||||
###########################################
|
||||
# Fetch complete repo
|
||||
|
||||
rm -fr hgweb
|
||||
hg clone -U http://hg.code.sf.net/p/epics-pvdata/pvDataCPP hgweb
|
||||
|
||||
###########################################
|
||||
# Sync into SF webspace
|
||||
|
||||
rsync -aqP --delete --exclude=\.hg/hgrc -e ssh hgweb/.hg epics-jenkins@web.sourceforge.net:/home/project-web/epics-pvdata/repos/pvDataCPP
|
||||
@@ -1,99 +0,0 @@
|
||||
TOP = ..
|
||||
include $(TOP)/configure/CONFIG
|
||||
|
||||
PVDATA = $(TOP)/pvDataApp/
|
||||
|
||||
SRC_DIRS += $(PVDATA)/misc
|
||||
|
||||
INC += noDefaultMethods.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 += timeFunction.h
|
||||
INC += timer.h
|
||||
INC += queue.h
|
||||
INC += messageQueue.h
|
||||
INC += destroyable.h
|
||||
INC += status.h
|
||||
INC += sharedPtr.h
|
||||
INC += localStaticLock.h
|
||||
|
||||
LIBSRCS += byteBuffer.cpp
|
||||
LIBSRCS += bitSet.cpp
|
||||
LIBSRCS += epicsException.cpp
|
||||
LIBSRCS += requester.cpp
|
||||
LIBSRCS += serializeHelper.cpp
|
||||
LIBSRCS += event.cpp
|
||||
LIBSRCS += executor.cpp
|
||||
LIBSRCS += timeFunction.cpp
|
||||
LIBSRCS += timer.cpp
|
||||
LIBSRCS += status.cpp
|
||||
LIBSRCS += messageQueue.cpp
|
||||
LIBSRCS += localStaticLock.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 += FieldCreateFactory.cpp
|
||||
LIBSRCS += PVAuxInfoImpl.cpp
|
||||
LIBSRCS += PVField.cpp
|
||||
LIBSRCS += PVScalar.cpp
|
||||
LIBSRCS += PVArray.cpp
|
||||
LIBSRCS += PVScalarArray.cpp
|
||||
LIBSRCS += PVStructure.cpp
|
||||
LIBSRCS += PVStructureArray.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
|
||||
|
||||
LIBRARY = pvData
|
||||
pvData_LIBS += Com
|
||||
|
||||
include $(TOP)/configure/RULES
|
||||
|
||||
@@ -1,108 +0,0 @@
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mes
|
||||
*/
|
||||
|
||||
#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();
|
||||
}
|
||||
|
||||
bool operator==(const ScalarArray& a, const ScalarArray& b)
|
||||
{
|
||||
if(&a==&b)
|
||||
return true;
|
||||
return a.getElementType()==b.getElementType();
|
||||
}
|
||||
|
||||
bool operator==(const Structure& a, const Structure& b)
|
||||
{
|
||||
if(&a==&b)
|
||||
return true;
|
||||
if (a.getID()!=b.getID())
|
||||
return false;
|
||||
size_t nflds=a.getNumberFields();
|
||||
if (b.getNumberFields()!=nflds)
|
||||
return false;
|
||||
|
||||
// std::equals does not work, since FieldConstPtrArray is an array of shared_pointers
|
||||
FieldConstPtrArray af = a.getFields();
|
||||
FieldConstPtrArray bf = b.getFields();
|
||||
for (size_t i = 0; i < nflds; i++)
|
||||
if (*(af[i].get()) != *(bf[i].get()))
|
||||
return false;
|
||||
|
||||
StringArray an = a.getFieldNames();
|
||||
StringArray bn = b.getFieldNames();
|
||||
return std::equal( an.begin(), an.end(), bn.begin() );
|
||||
}
|
||||
|
||||
bool operator==(const StructureArray& a, const StructureArray& b)
|
||||
{
|
||||
return *(a.getStructure().get())==*(b.getStructure().get());
|
||||
}
|
||||
|
||||
namespace nconvert {
|
||||
|
||||
} // namespace nconvert
|
||||
|
||||
}} // namespace epics::pvData
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,563 +0,0 @@
|
||||
/*FieldCreateFactory.cpp*/
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
*/
|
||||
#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/serializeHelper.h>
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using std::size_t;
|
||||
|
||||
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 += " ";
|
||||
}
|
||||
|
||||
Field::Field(Type type)
|
||||
: m_fieldType(type)
|
||||
{
|
||||
}
|
||||
|
||||
Field::~Field() {
|
||||
}
|
||||
|
||||
|
||||
void Field::toString(StringBuilder /*buffer*/,int /*indentLevel*/) const{
|
||||
}
|
||||
|
||||
|
||||
// TODO move all these to a header file
|
||||
|
||||
struct ScalarHashFunction {
|
||||
size_t operator() (const Scalar& scalar) const { return scalar.getScalarType(); }
|
||||
};
|
||||
|
||||
struct ScalarArrayHashFunction {
|
||||
size_t operator() (const ScalarArray& scalarArray) const { return 0x10 | scalarArray.getElementType(); }
|
||||
};
|
||||
|
||||
struct StructureHashFunction {
|
||||
size_t operator() (const Structure& /*structure*/) const { return 0; }
|
||||
// TODO
|
||||
// final int PRIME = 31;
|
||||
// return PRIME * Arrays.hashCode(fieldNames) + Arrays.hashCode(fields);
|
||||
};
|
||||
|
||||
struct StructureArrayHashFunction {
|
||||
size_t operator() (const StructureArray& structureArray) const { StructureHashFunction shf; return (0x10 | shf(*(structureArray.getStructure()))); }
|
||||
};
|
||||
|
||||
|
||||
Scalar::Scalar(ScalarType scalarType)
|
||||
: Field(scalar),scalarType(scalarType){}
|
||||
|
||||
Scalar::~Scalar(){}
|
||||
|
||||
void Scalar::toString(StringBuilder buffer,int /*indentLevel*/) const{
|
||||
*buffer += getID();
|
||||
}
|
||||
|
||||
|
||||
String Scalar::getID() const
|
||||
{
|
||||
static const String idScalarLUT[] = {
|
||||
"boolean", // pvBoolean
|
||||
"byte", // pvByte
|
||||
"short", // pvShort
|
||||
"int", // pvInt
|
||||
"long", // pvLong
|
||||
"ubyte", // pvUByte
|
||||
"ushort", // pvUShort
|
||||
"uint", // pvUInt
|
||||
"ulong", // pvULong
|
||||
"float", // pvFloat
|
||||
"double", // pvDouble
|
||||
"string" // pvString
|
||||
};
|
||||
return idScalarLUT[scalarType];
|
||||
}
|
||||
|
||||
int8 Scalar::getTypeCodeLUT() const
|
||||
{
|
||||
static const int8 typeCodeLUT[] = {
|
||||
0x00, // pvBoolean
|
||||
0x20, // pvByte
|
||||
0x21, // pvShort
|
||||
0x22, // pvInt
|
||||
0x23, // pvLong
|
||||
0x28, // pvUByte
|
||||
0x29, // pvUShort
|
||||
0x2A, // pvUInt
|
||||
0x2B, // pvULong
|
||||
0x42, // pvFloat
|
||||
0x43, // pvDouble
|
||||
0x60 // pvString
|
||||
};
|
||||
return typeCodeLUT[scalarType];
|
||||
}
|
||||
|
||||
|
||||
void Scalar::serialize(ByteBuffer *buffer, SerializableControl *control) const {
|
||||
control->ensureBuffer(1);
|
||||
buffer->putByte(getTypeCodeLUT());
|
||||
}
|
||||
|
||||
void Scalar::deserialize(ByteBuffer */*buffer*/, DeserializableControl */*control*/) {
|
||||
// must be done via FieldCreate
|
||||
throw std::runtime_error("not valid operation, use FieldCreate::deserialize instead");
|
||||
}
|
||||
|
||||
static String emptyString;
|
||||
|
||||
static void serializeStructureField(const Structure* structure, ByteBuffer* buffer, SerializableControl* control)
|
||||
{
|
||||
// to optimize default (non-empty) IDs optimization
|
||||
// empty IDs are not allowed
|
||||
String id = structure->getID();
|
||||
if (id == Structure::DEFAULT_ID) // TODO slow comparison
|
||||
SerializeHelper::serializeString(emptyString, buffer, control);
|
||||
else
|
||||
SerializeHelper::serializeString(id, buffer, control);
|
||||
|
||||
FieldConstPtrArray const & fields = structure->getFields();
|
||||
StringArray const & fieldNames = structure->getFieldNames();
|
||||
std::size_t len = fields.size();
|
||||
SerializeHelper::writeSize(len, buffer, control);
|
||||
for (std::size_t i = 0; i < len; i++)
|
||||
{
|
||||
SerializeHelper::serializeString(fieldNames[i], buffer, control);
|
||||
control->cachedSerialize(fields[i], buffer);
|
||||
}
|
||||
}
|
||||
|
||||
static StructureConstPtr deserializeStructureField(const FieldCreate* fieldCreate, ByteBuffer* buffer, DeserializableControl* control)
|
||||
{
|
||||
String id = SerializeHelper::deserializeString(buffer, control);
|
||||
const std::size_t size = SerializeHelper::readSize(buffer, control);
|
||||
FieldConstPtrArray fields; fields.reserve(size);
|
||||
StringArray fieldNames; fieldNames.reserve(size);
|
||||
for (std::size_t i = 0; i < size; i++)
|
||||
{
|
||||
fieldNames.push_back(SerializeHelper::deserializeString(buffer, control));
|
||||
fields.push_back(control->cachedDeserialize(buffer));
|
||||
}
|
||||
|
||||
if (id.empty())
|
||||
return fieldCreate->createStructure(fieldNames, fields);
|
||||
else
|
||||
return fieldCreate->createStructure(id, fieldNames, fields);
|
||||
}
|
||||
|
||||
ScalarArray::ScalarArray(ScalarType elementType)
|
||||
: Field(scalarArray),elementType(elementType){}
|
||||
|
||||
ScalarArray::~ScalarArray() {}
|
||||
|
||||
int8 ScalarArray::getTypeCodeLUT() const
|
||||
{
|
||||
static const int8 typeCodeLUT[] = {
|
||||
0x00, // pvBoolean
|
||||
0x20, // pvByte
|
||||
0x21, // pvShort
|
||||
0x22, // pvInt
|
||||
0x23, // pvLong
|
||||
0x28, // pvUByte
|
||||
0x29, // pvUShort
|
||||
0x2A, // pvUInt
|
||||
0x2B, // pvULong
|
||||
0x42, // pvFloat
|
||||
0x43, // pvDouble
|
||||
0x60 // pvString
|
||||
};
|
||||
return typeCodeLUT[elementType];
|
||||
}
|
||||
|
||||
const String ScalarArray::getIDScalarArrayLUT() const
|
||||
{
|
||||
static const String idScalarArrayLUT[] = {
|
||||
"boolean[]", // pvBoolean
|
||||
"byte[]", // pvByte
|
||||
"short[]", // pvShort
|
||||
"int[]", // pvInt
|
||||
"long[]", // pvLong
|
||||
"ubyte[]", // pvUByte
|
||||
"ushort[]", // pvUShort
|
||||
"uint[]", // pvUInt
|
||||
"ulong[]", // pvULong
|
||||
"float[]", // pvFloat
|
||||
"double[]", // pvDouble
|
||||
"string[]" // pvString
|
||||
};
|
||||
return idScalarArrayLUT[elementType];
|
||||
}
|
||||
|
||||
String ScalarArray::getID() const
|
||||
{
|
||||
return getIDScalarArrayLUT();
|
||||
}
|
||||
|
||||
void ScalarArray::toString(StringBuilder buffer,int /*indentLevel*/) const{
|
||||
*buffer += getID();
|
||||
}
|
||||
|
||||
void ScalarArray::serialize(ByteBuffer *buffer, SerializableControl *control) const {
|
||||
control->ensureBuffer(1);
|
||||
buffer->putByte(0x10 | getTypeCodeLUT());
|
||||
}
|
||||
|
||||
void ScalarArray::deserialize(ByteBuffer */*buffer*/, DeserializableControl */*control*/) {
|
||||
throw std::runtime_error("not valid operation, use FieldCreate::deserialize instead");
|
||||
}
|
||||
|
||||
StructureArray::StructureArray(StructureConstPtr const & structure)
|
||||
: Field(structureArray),pstructure(structure)
|
||||
{
|
||||
}
|
||||
|
||||
StructureArray::~StructureArray() {
|
||||
if(debugLevel==highDebug) printf("~StructureArray\n");
|
||||
}
|
||||
|
||||
String StructureArray::getID() const
|
||||
{
|
||||
return pstructure->getID() + "[]";
|
||||
}
|
||||
|
||||
void StructureArray::toString(StringBuilder buffer,int indentLevel) const {
|
||||
*buffer += getID();
|
||||
newLine(buffer,indentLevel + 1);
|
||||
pstructure->toString(buffer,indentLevel + 1);
|
||||
}
|
||||
|
||||
void StructureArray::serialize(ByteBuffer *buffer, SerializableControl *control) const {
|
||||
control->ensureBuffer(1);
|
||||
buffer->putByte(0x90);
|
||||
control->cachedSerialize(pstructure, buffer);
|
||||
}
|
||||
|
||||
void StructureArray::deserialize(ByteBuffer */*buffer*/, DeserializableControl */*control*/) {
|
||||
throw std::runtime_error("not valid operation, use FieldCreate::deserialize instead");
|
||||
}
|
||||
|
||||
String Structure::DEFAULT_ID = "structure";
|
||||
|
||||
Structure::Structure (
|
||||
StringArray const & fieldNames,
|
||||
FieldConstPtrArray const & infields,
|
||||
String const & inid)
|
||||
: Field(structure),
|
||||
fieldNames(fieldNames),
|
||||
fields(infields),
|
||||
id(inid)
|
||||
{
|
||||
if(inid.empty()) {
|
||||
throw std::invalid_argument("id is empty");
|
||||
}
|
||||
if(fieldNames.size()!=fields.size()) {
|
||||
throw std::invalid_argument("fieldNames.size()!=fields.size()");
|
||||
}
|
||||
size_t number = fields.size();
|
||||
for(size_t i=0; i<number; i++) {
|
||||
String name = fieldNames[i];
|
||||
if(name.size()<1) {
|
||||
throw std::invalid_argument("fieldNames has a zero length string");
|
||||
}
|
||||
// look for duplicates
|
||||
for(size_t j=i+1; j<number; j++) {
|
||||
String otherName = fieldNames[j];
|
||||
int result = name.compare(otherName);
|
||||
if(result==0) {
|
||||
String message("duplicate fieldName ");
|
||||
message += name;
|
||||
throw std::invalid_argument(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Structure::~Structure() { }
|
||||
|
||||
|
||||
String Structure::getID() const
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
FieldConstPtr Structure::getField(String const & fieldName) const {
|
||||
size_t numberFields = fields.size();
|
||||
for(size_t i=0; i<numberFields; i++) {
|
||||
FieldConstPtr pfield = fields[i];
|
||||
int result = fieldName.compare(fieldNames[i]);
|
||||
if(result==0) return pfield;
|
||||
}
|
||||
return FieldConstPtr();
|
||||
}
|
||||
|
||||
size_t Structure::getFieldIndex(String const &fieldName) const {
|
||||
size_t numberFields = fields.size();
|
||||
for(size_t i=0; i<numberFields; i++) {
|
||||
FieldConstPtr pfield = fields[i];
|
||||
int result = fieldName.compare(fieldNames[i]);
|
||||
if(result==0) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void Structure::toString(StringBuilder buffer,int indentLevel) const{
|
||||
*buffer += getID();
|
||||
toStringCommon(buffer,indentLevel+1);
|
||||
}
|
||||
|
||||
void Structure::toStringCommon(StringBuilder buffer,int indentLevel) const{
|
||||
newLine(buffer,indentLevel);
|
||||
size_t numberFields = fields.size();
|
||||
for(size_t i=0; i<numberFields; i++) {
|
||||
FieldConstPtr pfield = fields[i];
|
||||
*buffer += pfield->getID() + " " + fieldNames[i];
|
||||
switch(pfield->getType()) {
|
||||
case scalar:
|
||||
case scalarArray:
|
||||
break;
|
||||
case structure:
|
||||
{
|
||||
Field const *xxx = pfield.get();
|
||||
Structure const *pstruct = static_cast<Structure const*>(xxx);
|
||||
pstruct->toStringCommon(buffer,indentLevel + 1);
|
||||
break;
|
||||
}
|
||||
case structureArray:
|
||||
newLine(buffer,indentLevel +1);
|
||||
pfield->toString(buffer,indentLevel +1);
|
||||
break;
|
||||
}
|
||||
if(i<numberFields-1) newLine(buffer,indentLevel);
|
||||
}
|
||||
}
|
||||
|
||||
void Structure::serialize(ByteBuffer *buffer, SerializableControl *control) const {
|
||||
control->ensureBuffer(1);
|
||||
buffer->putByte(0x80);
|
||||
serializeStructureField(this, buffer, control);
|
||||
}
|
||||
|
||||
void Structure::deserialize(ByteBuffer */*buffer*/, DeserializableControl */*control*/) {
|
||||
throw std::runtime_error("not valid operation, use FieldCreate::deserialize instead");
|
||||
}
|
||||
|
||||
ScalarConstPtr FieldCreate::createScalar(ScalarType scalarType) const
|
||||
{
|
||||
// TODO use singleton instance
|
||||
ScalarConstPtr scalar(new Scalar(scalarType), Field::Deleter());
|
||||
return scalar;
|
||||
}
|
||||
|
||||
ScalarArrayConstPtr FieldCreate::createScalarArray(ScalarType elementType) const
|
||||
{
|
||||
// TODO use singleton instance
|
||||
ScalarArrayConstPtr scalarArray(new ScalarArray(elementType), Field::Deleter());
|
||||
return scalarArray;
|
||||
}
|
||||
|
||||
StructureConstPtr FieldCreate::createStructure (
|
||||
StringArray const & fieldNames,FieldConstPtrArray const & fields) const
|
||||
{
|
||||
StructureConstPtr structure(
|
||||
new Structure(fieldNames,fields), Field::Deleter());
|
||||
return structure;
|
||||
}
|
||||
|
||||
StructureConstPtr FieldCreate::createStructure (
|
||||
String const & id,
|
||||
StringArray const & fieldNames,
|
||||
FieldConstPtrArray const & fields) const
|
||||
{
|
||||
StructureConstPtr structure(
|
||||
new Structure(fieldNames,fields,id), Field::Deleter());
|
||||
return structure;
|
||||
}
|
||||
|
||||
StructureArrayConstPtr FieldCreate::createStructureArray(
|
||||
StructureConstPtr const & structure) const
|
||||
{
|
||||
StructureArrayConstPtr structureArray(
|
||||
new StructureArray(structure), Field::Deleter());
|
||||
return structureArray;
|
||||
}
|
||||
|
||||
StructureConstPtr FieldCreate::appendField(
|
||||
StructureConstPtr const & structure,
|
||||
String const & fieldName,
|
||||
FieldConstPtr const & field) const
|
||||
{
|
||||
StringArray oldNames = structure->getFieldNames();
|
||||
FieldConstPtrArray oldFields = structure->getFields();
|
||||
size_t oldLen = oldNames.size();
|
||||
StringArray newNames(oldLen+1);
|
||||
FieldConstPtrArray newFields(oldLen+1);
|
||||
for(size_t i = 0; i<oldLen; i++) {
|
||||
newNames[i] = oldNames[i];
|
||||
newFields[i] = oldFields[i];
|
||||
}
|
||||
newNames[oldLen] = fieldName;
|
||||
newFields[oldLen] = field;
|
||||
return createStructure(structure->getID(),newNames,newFields);
|
||||
}
|
||||
|
||||
StructureConstPtr FieldCreate::appendFields(
|
||||
StructureConstPtr const & structure,
|
||||
StringArray const & fieldNames,
|
||||
FieldConstPtrArray const & fields) const
|
||||
{
|
||||
StringArray oldNames = structure->getFieldNames();
|
||||
FieldConstPtrArray oldFields = structure->getFields();
|
||||
size_t oldLen = oldNames.size();
|
||||
size_t extra = fieldNames.size();
|
||||
StringArray newNames(oldLen+extra);
|
||||
FieldConstPtrArray newFields(oldLen+extra);
|
||||
for(size_t i = 0; i<oldLen; i++) {
|
||||
newNames[i] = oldNames[i];
|
||||
newFields[i] = oldFields[i];
|
||||
}
|
||||
for(size_t i = 0; i<extra; i++) {
|
||||
newNames[oldLen +i] = fieldNames[i];
|
||||
newFields[oldLen +i] = fields[i];
|
||||
}
|
||||
return createStructure(structure->getID(),newNames,newFields);
|
||||
}
|
||||
|
||||
|
||||
static int decodeScalar(int8 code)
|
||||
{
|
||||
static const int integerLUT[] =
|
||||
{
|
||||
pvByte, // 8-bits
|
||||
pvShort, // 16-bits
|
||||
pvInt, // 32-bits
|
||||
pvLong, // 64-bits
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
pvUByte, // unsigned 8-bits
|
||||
pvUShort, // unsigned 16-bits
|
||||
pvUInt, // unsigned 32-bits
|
||||
pvULong, // unsigned 64-bits
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1
|
||||
};
|
||||
|
||||
static const int floatLUT[] =
|
||||
{
|
||||
-1, // reserved
|
||||
-1, // 16-bits
|
||||
pvFloat, // 32-bits
|
||||
pvDouble, // 64-bits
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1
|
||||
};
|
||||
// bits 7-5
|
||||
switch (code >> 5)
|
||||
{
|
||||
case 0: return pvBoolean;
|
||||
case 1: return integerLUT[code & 0x0F];
|
||||
case 2: return floatLUT[code & 0x0F];
|
||||
case 3: return pvString;
|
||||
default: return -1;
|
||||
}
|
||||
}
|
||||
|
||||
FieldConstPtr FieldCreate::deserialize(ByteBuffer* buffer, DeserializableControl* control) const
|
||||
{
|
||||
control->ensureData(1);
|
||||
int8 code = buffer->getByte();
|
||||
if (code == -1)
|
||||
return FieldConstPtr();
|
||||
|
||||
int typeCode = code & 0xE0;
|
||||
bool notArray = ((code & 0x10) == 0);
|
||||
if (notArray)
|
||||
{
|
||||
if (typeCode < 0x80)
|
||||
{
|
||||
// Type type = Type.scalar;
|
||||
int scalarType = decodeScalar(code);
|
||||
if (scalarType == -1)
|
||||
throw std::invalid_argument("invalid scalar type encoding");
|
||||
return FieldConstPtr(new Scalar(static_cast<ScalarType>(scalarType)), Field::Deleter());
|
||||
}
|
||||
else if (typeCode == 0x80)
|
||||
{
|
||||
// Type type = Type.structure;
|
||||
return deserializeStructureField(this, buffer, control);
|
||||
}
|
||||
else
|
||||
throw std::invalid_argument("invalid type encoding");
|
||||
}
|
||||
else // array
|
||||
{
|
||||
if (typeCode < 0x80)
|
||||
{
|
||||
// Type type = Type.scalarArray;
|
||||
int scalarType = decodeScalar(code);
|
||||
if (scalarType == -1)
|
||||
throw std::invalid_argument("invalid scalarArray type encoding");
|
||||
return FieldConstPtr(new ScalarArray(static_cast<ScalarType>(scalarType)), Field::Deleter());
|
||||
}
|
||||
else if (typeCode == 0x80)
|
||||
{
|
||||
// Type type = Type.structureArray;
|
||||
StructureConstPtr elementStructure = std::tr1::static_pointer_cast<const Structure>(control->cachedDeserialize(buffer));
|
||||
return FieldConstPtr(new StructureArray(elementStructure), Field::Deleter());
|
||||
}
|
||||
else
|
||||
throw std::invalid_argument("invalid type encoding");
|
||||
}
|
||||
}
|
||||
|
||||
FieldCreatePtr FieldCreate::getFieldCreate()
|
||||
{
|
||||
LOCAL_STATIC_LOCK;
|
||||
static FieldCreatePtr fieldCreate;
|
||||
static Mutex mutex;
|
||||
|
||||
Lock xx(mutex);
|
||||
if(fieldCreate.get()==0) fieldCreate = FieldCreatePtr(new FieldCreate());
|
||||
return fieldCreate;
|
||||
}
|
||||
|
||||
FieldCreate::FieldCreate(){}
|
||||
|
||||
FieldCreatePtr getFieldCreate() {
|
||||
return FieldCreate::getFieldCreate();
|
||||
}
|
||||
|
||||
}}
|
||||
@@ -1,105 +0,0 @@
|
||||
/*PVArray.cpp*/
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
*/
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/factory.h>
|
||||
|
||||
using std::size_t;
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
class PVArrayPvt {
|
||||
public:
|
||||
PVArrayPvt() : length(0),capacity(0),capacityMutable(true)
|
||||
{}
|
||||
size_t length;
|
||||
size_t capacity;
|
||||
bool capacityMutable;
|
||||
};
|
||||
|
||||
PVArray::PVArray(FieldConstPtr const & field)
|
||||
: PVField(field),pImpl(new PVArrayPvt())
|
||||
{ }
|
||||
|
||||
PVArray::~PVArray()
|
||||
{
|
||||
delete pImpl;
|
||||
}
|
||||
|
||||
void PVArray::setImmutable()
|
||||
{
|
||||
pImpl->capacityMutable = false;
|
||||
PVField::setImmutable();
|
||||
}
|
||||
|
||||
size_t PVArray::getLength() const {return pImpl->length;}
|
||||
|
||||
size_t PVArray::getCapacity() const {return pImpl->capacity;}
|
||||
|
||||
static String fieldImmutable("field is immutable");
|
||||
|
||||
void PVArray::setLength(size_t 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(size_t capacity,size_t length) {
|
||||
pImpl->capacity = capacity;
|
||||
pImpl->length = length;
|
||||
}
|
||||
|
||||
|
||||
bool PVArray::isCapacityMutable() const
|
||||
{
|
||||
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(size_t capacity) {
|
||||
if(PVField::isImmutable()) {
|
||||
PVField::message(fieldImmutable,errorMessage);
|
||||
return;
|
||||
}
|
||||
if(pImpl->capacityMutable==false) {
|
||||
PVField::message(capacityImmutable,errorMessage);
|
||||
return;
|
||||
}
|
||||
pImpl->capacity = capacity;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(format::array_at_internal const& manip, const PVArray& array)
|
||||
{
|
||||
return array.dumpValue(manip.stream, manip.index);
|
||||
}
|
||||
|
||||
}}
|
||||
@@ -1,84 +0,0 @@
|
||||
/*PVAuxInfo.cpp*/
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
*/
|
||||
#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>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
|
||||
PVAuxInfo::PVAuxInfo(PVField * pvField)
|
||||
: pvField(pvField),
|
||||
pvInfos(std::map<String,std::tr1::shared_ptr<PVScalar> > ())
|
||||
{
|
||||
}
|
||||
|
||||
PVAuxInfo::~PVAuxInfo()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
PVField * PVAuxInfo::getPVField() {
|
||||
return pvField;
|
||||
}
|
||||
|
||||
|
||||
PVScalarPtr PVAuxInfo::createInfo(String const & key,ScalarType scalarType)
|
||||
{
|
||||
PVInfoIter iter = pvInfos.find(key);
|
||||
if(iter!=pvInfos.end()) {
|
||||
String message = key.c_str();
|
||||
message += " already exists ";
|
||||
pvField->message(message,errorMessage);
|
||||
return nullPVScalar;
|
||||
}
|
||||
PVScalarPtr pvScalar = getPVDataCreate()->createPVScalar(scalarType);
|
||||
pvInfos.insert(PVInfoPair(key,pvScalar));
|
||||
return pvScalar;
|
||||
}
|
||||
|
||||
PVScalarPtr PVAuxInfo::getInfo(String const & key)
|
||||
{
|
||||
PVInfoIter iter;
|
||||
iter = pvInfos.find(key);
|
||||
if(iter==pvInfos.end()) return nullPVScalar;
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
PVAuxInfo::PVInfoMap & PVAuxInfo::getInfoMap()
|
||||
{
|
||||
return pvInfos;
|
||||
}
|
||||
|
||||
|
||||
void PVAuxInfo::toString(StringBuilder buf)
|
||||
{
|
||||
PVAuxInfo::toString(buf,0);
|
||||
}
|
||||
|
||||
void PVAuxInfo::toString(StringBuilder buf,int indentLevel)
|
||||
{
|
||||
if(pvInfos.size()<=0) return;
|
||||
ConvertPtr convert = getConvert();
|
||||
convert->newLine(buf,indentLevel);
|
||||
*buf += "auxInfo";
|
||||
for(PVInfoIter iter = pvInfos.begin(); iter!= pvInfos.end(); ++iter) {
|
||||
convert->newLine(buf,indentLevel+1);
|
||||
PVFieldPtr value = iter->second;
|
||||
value->toString(buf,indentLevel + 1);
|
||||
}
|
||||
}
|
||||
}}
|
||||
@@ -1,296 +0,0 @@
|
||||
/*PVField.cpp*/
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
*/
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <pv/lock.h>
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/factory.h>
|
||||
#include <pv/convert.h>
|
||||
|
||||
using std::tr1::const_pointer_cast;
|
||||
using std::size_t;
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
|
||||
PVField::PVField(FieldConstPtr field)
|
||||
: notImplemented("not implemented"),
|
||||
parent(NULL),field(field),
|
||||
fieldOffset(0), nextFieldOffset(0),
|
||||
immutable(false),
|
||||
convert(getConvert())
|
||||
{
|
||||
}
|
||||
|
||||
PVField::~PVField()
|
||||
{ }
|
||||
|
||||
void PVField::message(
|
||||
String message,
|
||||
MessageType messageType,
|
||||
String fullFieldName)
|
||||
{
|
||||
if(parent!=NULL) {
|
||||
if(fullFieldName.length()>0) {
|
||||
fullFieldName = fieldName + '.' + fullFieldName;
|
||||
} else {
|
||||
fullFieldName = fieldName;
|
||||
}
|
||||
parent->message(message,messageType,fullFieldName);
|
||||
return;
|
||||
}
|
||||
message = fullFieldName + " " + message;
|
||||
if(requester) {
|
||||
requester->message(message,messageType);
|
||||
} else {
|
||||
printf("%s %s %s\n",
|
||||
getMessageTypeName(messageType).c_str(),
|
||||
fieldName.c_str(),
|
||||
message.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void PVField::message(String message,MessageType messageType)
|
||||
{
|
||||
PVField::message(message,messageType,"");
|
||||
}
|
||||
|
||||
String PVField::getFieldName() const
|
||||
{
|
||||
return fieldName;
|
||||
}
|
||||
|
||||
void PVField::setRequester(RequesterPtr const &req)
|
||||
{
|
||||
if(parent!=NULL) {
|
||||
throw std::logic_error(
|
||||
"PVField::setRequester only legal for top level structure");
|
||||
}
|
||||
if(requester.get()!=NULL) {
|
||||
if(requester.get()==req.get()) return;
|
||||
throw std::logic_error(
|
||||
"PVField::setRequester requester is already present");
|
||||
}
|
||||
requester = req;
|
||||
}
|
||||
|
||||
size_t PVField::getFieldOffset() const
|
||||
{
|
||||
if(nextFieldOffset==0) computeOffset(this);
|
||||
return fieldOffset;
|
||||
}
|
||||
|
||||
size_t PVField::getNextFieldOffset() const
|
||||
{
|
||||
if(nextFieldOffset==0) computeOffset(this);
|
||||
return nextFieldOffset;
|
||||
}
|
||||
|
||||
size_t PVField::getNumberFields() const
|
||||
{
|
||||
if(nextFieldOffset==0) computeOffset(this);
|
||||
return (nextFieldOffset - fieldOffset);
|
||||
}
|
||||
|
||||
PVAuxInfoPtr & PVField::getPVAuxInfo(){
|
||||
if(pvAuxInfo.get()==NULL) {
|
||||
pvAuxInfo = PVAuxInfoPtr(new PVAuxInfo(this));
|
||||
}
|
||||
return pvAuxInfo;
|
||||
}
|
||||
|
||||
bool PVField::isImmutable() const {return immutable;}
|
||||
|
||||
void PVField::setImmutable() {immutable = true;}
|
||||
|
||||
const FieldConstPtr & PVField::getField() const {return field;}
|
||||
|
||||
PVStructure *PVField::getParent() const {return parent;}
|
||||
|
||||
void PVField::replacePVField(const PVFieldPtr & newPVField)
|
||||
{
|
||||
if(parent==NULL) {
|
||||
throw std::logic_error("no parent");
|
||||
}
|
||||
PVFieldPtrArray pvFields = parent->getPVFields();
|
||||
StructureConstPtr structure = parent->getStructure();
|
||||
StringArray fieldNames = structure->getFieldNames();
|
||||
for(size_t i=0; i<fieldNames.size(); i++) {
|
||||
if(newPVField->getFieldName().compare(fieldNames[i]) == 0) {
|
||||
pvFields[i] = newPVField;
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw std::logic_error("Did not find field in parent");
|
||||
}
|
||||
|
||||
void PVField::replaceField(FieldConstPtr &xxx)
|
||||
{
|
||||
field = xxx;
|
||||
}
|
||||
|
||||
void PVField::renameField(String const & newName)
|
||||
{
|
||||
if(parent==NULL) {
|
||||
throw std::logic_error("no parent");
|
||||
}
|
||||
std::tr1::shared_ptr<Structure> parentStructure = const_pointer_cast<Structure>(
|
||||
parent->getStructure());
|
||||
PVFieldPtrArray pvFields = parent->getPVFields();
|
||||
for(size_t i=0; i<pvFields.size(); i++) {
|
||||
if(pvFields[i].get()==this) {
|
||||
parentStructure->renameField(i,newName);
|
||||
fieldName = newName;
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw std::logic_error("Did not find field in parent");
|
||||
}
|
||||
|
||||
void PVField::postPut()
|
||||
{
|
||||
if(postHandler.get()!=NULL) postHandler->postPut();
|
||||
}
|
||||
|
||||
void PVField::setPostHandler(PostHandlerPtr const &handler)
|
||||
{
|
||||
if(postHandler.get()!=NULL) {
|
||||
if(postHandler.get()==handler.get()) return;
|
||||
throw std::logic_error(
|
||||
"PVField::setPostHandler a postHandler is already registered");
|
||||
|
||||
}
|
||||
postHandler = handler;
|
||||
}
|
||||
|
||||
void PVField::setParentAndName(PVStructure * xxx,String const & name)
|
||||
{
|
||||
parent = xxx;
|
||||
fieldName = name;
|
||||
}
|
||||
|
||||
bool PVField::equals(PVField &pv)
|
||||
{
|
||||
return convert->equals(*this,pv);
|
||||
}
|
||||
|
||||
void PVField::toString(StringBuilder buf)
|
||||
{
|
||||
toString(buf,0);
|
||||
}
|
||||
|
||||
void PVField::toString(StringBuilder buf,int indentLevel)
|
||||
{
|
||||
convert->getString(buf,this,indentLevel);
|
||||
if(pvAuxInfo.get()!=NULL) pvAuxInfo->toString(buf,indentLevel);
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& o, const PVField& f)
|
||||
{
|
||||
std::ostream& ro = f.dumpValue(o);
|
||||
// TODO I do not want to call getPVAuxInfo() since it lazily creates a new instance of it
|
||||
//if (f.pvAuxInfo.get()!=NULL) ro << *(f.pvAuxInfo.get());
|
||||
return ro;
|
||||
};
|
||||
|
||||
namespace format
|
||||
{
|
||||
std::ostream& operator<<(std::ostream& os, indent_level const& indent)
|
||||
{
|
||||
indent_value(os) = indent.level;
|
||||
return os;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, indent const&)
|
||||
{
|
||||
long il = indent_value(os);
|
||||
std::size_t spaces = static_cast<std::size_t>(il) * 4;
|
||||
return os << std::string(spaces, ' ');
|
||||
}
|
||||
|
||||
array_at_internal operator<<(std::ostream& str, array_at const& manip)
|
||||
{
|
||||
return array_at_internal(manip.index, str);
|
||||
}
|
||||
};
|
||||
|
||||
void PVField::computeOffset(const PVField * pvField) {
|
||||
const PVStructure * pvTop = pvField->getParent();
|
||||
if(pvTop==NULL) {
|
||||
if(pvField->getField()->getType()!=structure) {
|
||||
PVField *xxx = const_cast<PVField *>(pvField);
|
||||
xxx->fieldOffset = 0;
|
||||
xxx->nextFieldOffset = 1;
|
||||
return;
|
||||
}
|
||||
pvTop = static_cast<const PVStructure *>(pvField);
|
||||
} else {
|
||||
while(pvTop->getParent()!=NULL) pvTop = pvTop->getParent();
|
||||
}
|
||||
int offset = 0;
|
||||
int nextOffset = 1;
|
||||
PVFieldPtrArray pvFields = pvTop->getPVFields();
|
||||
for(size_t i=0; i < pvTop->getStructure()->getNumberFields(); i++) {
|
||||
offset = nextOffset;
|
||||
PVField *pvField = pvFields[i].get();
|
||||
FieldConstPtr field = pvField->getField();
|
||||
switch(field->getType()) {
|
||||
case scalar:
|
||||
case scalarArray:
|
||||
case structureArray:{
|
||||
nextOffset++;
|
||||
pvField->fieldOffset = offset;
|
||||
pvField->nextFieldOffset = nextOffset;
|
||||
break;
|
||||
}
|
||||
case structure: {
|
||||
pvField->computeOffset(pvField,offset);
|
||||
nextOffset = pvField->getNextFieldOffset();
|
||||
}
|
||||
}
|
||||
}
|
||||
PVField *top = (PVField *)pvTop;
|
||||
PVField *xxx = const_cast<PVField *>(top);
|
||||
xxx->fieldOffset = 0;
|
||||
xxx->nextFieldOffset = nextOffset;
|
||||
}
|
||||
|
||||
void PVField::computeOffset(const PVField * pvField,size_t offset) {
|
||||
int beginOffset = offset;
|
||||
int nextOffset = offset + 1;
|
||||
const PVStructure *pvStructure = static_cast<const PVStructure *>(pvField);
|
||||
const PVFieldPtrArray pvFields = pvStructure->getPVFields();
|
||||
for(size_t i=0; i < pvStructure->getStructure()->getNumberFields(); i++) {
|
||||
offset = nextOffset;
|
||||
PVField *pvSubField = pvFields[i].get();
|
||||
FieldConstPtr field = pvSubField->getField();
|
||||
switch(field->getType()) {
|
||||
case scalar:
|
||||
case scalarArray:
|
||||
case structureArray: {
|
||||
nextOffset++;
|
||||
pvSubField->fieldOffset = offset;
|
||||
pvSubField->nextFieldOffset = nextOffset;
|
||||
break;
|
||||
}
|
||||
case structure: {
|
||||
pvSubField->computeOffset(pvSubField,offset);
|
||||
nextOffset = pvSubField->getNextFieldOffset();
|
||||
}
|
||||
}
|
||||
}
|
||||
PVField *xxx = const_cast<PVField *>(pvField);
|
||||
xxx->fieldOffset = beginOffset;
|
||||
xxx->nextFieldOffset = nextOffset;
|
||||
}
|
||||
|
||||
}}
|
||||
@@ -1,732 +0,0 @@
|
||||
/*PVStructure.cpp*/
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
*/
|
||||
#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::size_t;
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
PVFieldPtr PVStructure::nullPVField;
|
||||
PVBooleanPtr PVStructure::nullPVBoolean;
|
||||
PVBytePtr PVStructure::nullPVByte;
|
||||
PVShortPtr PVStructure::nullPVShort;
|
||||
PVIntPtr PVStructure::nullPVInt;
|
||||
PVLongPtr PVStructure::nullPVLong;
|
||||
PVUBytePtr PVStructure::nullPVUByte;
|
||||
PVUShortPtr PVStructure::nullPVUShort;
|
||||
PVUIntPtr PVStructure::nullPVUInt;
|
||||
PVULongPtr PVStructure::nullPVULong;
|
||||
PVFloatPtr PVStructure::nullPVFloat;
|
||||
PVDoublePtr PVStructure::nullPVDouble;
|
||||
PVStringPtr PVStructure::nullPVString;
|
||||
PVStructurePtr PVStructure::nullPVStructure;
|
||||
PVStructureArrayPtr PVStructure::nullPVStructureArray;
|
||||
PVScalarArrayPtr PVStructure::nullPVScalarArray;
|
||||
|
||||
static PVFieldPtr findSubField(
|
||||
String const &fieldName,
|
||||
const PVStructure *pvStructure);
|
||||
|
||||
PVStructure::PVStructure(StructureConstPtr const & structurePtr)
|
||||
: PVField(structurePtr),
|
||||
structurePtr(structurePtr),
|
||||
extendsStructureName("")
|
||||
{
|
||||
size_t numberFields = structurePtr->getNumberFields();
|
||||
FieldConstPtrArray fields = structurePtr->getFields();
|
||||
StringArray fieldNames = structurePtr->getFieldNames();
|
||||
// PVFieldPtrArray * xxx = const_cast<PVFieldPtrArray *>(&pvFields);
|
||||
pvFields.reserve(numberFields);
|
||||
PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
||||
for(size_t i=0; i<numberFields; i++) {
|
||||
pvFields.push_back(pvDataCreate->createPVField(fields[i]));
|
||||
}
|
||||
for(size_t i=0; i<numberFields; i++) {
|
||||
pvFields[i]->setParentAndName(this,fieldNames[i]);
|
||||
}
|
||||
}
|
||||
|
||||
PVStructure::PVStructure(StructureConstPtr const & structurePtr,
|
||||
PVFieldPtrArray const & pvs
|
||||
)
|
||||
: PVField(structurePtr),
|
||||
structurePtr(structurePtr),
|
||||
extendsStructureName("")
|
||||
{
|
||||
size_t numberFields = structurePtr->getNumberFields();
|
||||
StringArray fieldNames = structurePtr->getFieldNames();
|
||||
pvFields.reserve(numberFields);
|
||||
for(size_t i=0; i<numberFields; i++) {
|
||||
pvFields.push_back(pvs[i]);
|
||||
}
|
||||
for(size_t i=0; i<numberFields; i++) {
|
||||
pvFields[i]->setParentAndName(this,fieldNames[i]);
|
||||
}
|
||||
}
|
||||
|
||||
PVStructure::~PVStructure()
|
||||
{
|
||||
}
|
||||
|
||||
void PVStructure::setImmutable()
|
||||
{
|
||||
size_t numFields = pvFields.size();
|
||||
for(size_t i=0; i<numFields; i++) {
|
||||
PVFieldPtr pvField = pvFields[i];
|
||||
pvField->setImmutable();
|
||||
}
|
||||
PVField::setImmutable();
|
||||
}
|
||||
|
||||
StructureConstPtr PVStructure::getStructure() const
|
||||
{
|
||||
return structurePtr;
|
||||
}
|
||||
|
||||
const PVFieldPtrArray & PVStructure::getPVFields() const
|
||||
{
|
||||
return pvFields;
|
||||
}
|
||||
|
||||
PVFieldPtr PVStructure::getSubField(String const &fieldName) const
|
||||
{
|
||||
return findSubField(fieldName,this);
|
||||
}
|
||||
|
||||
|
||||
PVFieldPtr PVStructure::getSubField(size_t fieldOffset) const
|
||||
{
|
||||
if(fieldOffset<=getFieldOffset()) {
|
||||
return nullPVField;
|
||||
}
|
||||
if(fieldOffset>getNextFieldOffset()) return nullPVField;
|
||||
size_t numFields = pvFields.size();
|
||||
for(size_t i=0; i<numFields; i++) {
|
||||
PVFieldPtr pvField = pvFields[i];
|
||||
if(pvField->getFieldOffset()==fieldOffset) return pvFields[i];
|
||||
if(pvField->getNextFieldOffset()<=fieldOffset) continue;
|
||||
if(pvField->getField()->getType()==structure) {
|
||||
PVStructure *pvStructure = static_cast<PVStructure *>(pvField.get());
|
||||
return pvStructure->getSubField(fieldOffset);
|
||||
}
|
||||
}
|
||||
throw std::logic_error("PVStructure.getSubField: Logic error");
|
||||
}
|
||||
|
||||
void PVStructure::fixParentStructure()
|
||||
{
|
||||
PVStructure *parent = getParent();
|
||||
if(parent==NULL) return;
|
||||
StructureConstPtr parentStructure = parent->structurePtr;
|
||||
String fieldName = getFieldName();
|
||||
size_t index = parentStructure->getFieldIndex(fieldName);
|
||||
StringArray const &fieldNames = parentStructure->getFieldNames();
|
||||
size_t num = fieldNames.size();
|
||||
FieldConstPtrArray fields(num);
|
||||
FieldConstPtrArray const & oldFields = parentStructure->getFields();
|
||||
for(size_t i=0; i< num; i++) {
|
||||
if(i==index) {
|
||||
fields[i] = structurePtr;
|
||||
} else {
|
||||
fields[i] = oldFields[i];
|
||||
}
|
||||
}
|
||||
FieldConstPtr field = getFieldCreate()->createStructure(
|
||||
parentStructure->getID(),fieldNames,fields);
|
||||
parent->replaceField(field);
|
||||
parent->fixParentStructure();
|
||||
}
|
||||
|
||||
void PVStructure::appendPVField(
|
||||
String const &fieldName,
|
||||
PVFieldPtr const & pvField)
|
||||
{
|
||||
size_t origLength = pvFields.size();
|
||||
size_t newLength = origLength+1;
|
||||
PVFieldPtrArray * xxx = const_cast<PVFieldPtrArray *>(&pvFields);
|
||||
xxx->push_back(pvField);
|
||||
FieldConstPtr field = getFieldCreate()->appendField(
|
||||
structurePtr,fieldName,pvField->getField());
|
||||
replaceField(field);
|
||||
structurePtr = static_pointer_cast<const Structure>(field);
|
||||
StringArray fieldNames = structurePtr->getFieldNames();
|
||||
for(size_t i=0; i<newLength; i++) {
|
||||
pvFields[i]->setParentAndName(this,fieldNames[i]);
|
||||
}
|
||||
fixParentStructure();
|
||||
}
|
||||
|
||||
void PVStructure::appendPVFields(
|
||||
StringArray const & fieldNames,
|
||||
PVFieldPtrArray const & pvFields)
|
||||
{
|
||||
size_t origLength = this->pvFields.size();
|
||||
size_t extra = fieldNames.size();
|
||||
if(extra==0) return;
|
||||
size_t newLength = origLength + extra;
|
||||
PVFieldPtrArray * xxx = const_cast<PVFieldPtrArray *>(&this->pvFields);
|
||||
xxx->reserve(newLength);
|
||||
for(size_t i=0; i<extra; i++) {
|
||||
xxx->push_back(pvFields[i]);
|
||||
}
|
||||
FieldConstPtrArray fields;
|
||||
fields.reserve(extra);
|
||||
for(size_t i=0; i<extra; i++) fields.push_back(pvFields[i]->getField());
|
||||
FieldConstPtr field = getFieldCreate()->appendFields(
|
||||
structurePtr,fieldNames,fields);
|
||||
replaceField(field);
|
||||
structurePtr = static_pointer_cast<const Structure>(field);
|
||||
StringArray names = structurePtr->getFieldNames();
|
||||
for(size_t i=0; i<newLength; i++) {
|
||||
(*xxx)[i]->setParentAndName(this,names[i]);
|
||||
}
|
||||
fixParentStructure();
|
||||
}
|
||||
|
||||
void PVStructure::removePVField(String const &fieldName)
|
||||
{
|
||||
PVFieldPtr pvField = getSubField(fieldName);
|
||||
if(pvField.get()==NULL) {
|
||||
String message("removePVField ");
|
||||
message += fieldName + " does not exist";
|
||||
this->message(message, errorMessage);
|
||||
return;
|
||||
}
|
||||
size_t origLength = pvFields.size();
|
||||
size_t newLength = origLength - 1;
|
||||
PVFieldPtrArray const & origPVFields = pvFields;
|
||||
FieldConstPtrArray origFields = structurePtr->getFields();
|
||||
PVFieldPtrArray newPVFields;
|
||||
newPVFields.reserve(newLength);
|
||||
StringArray newFieldNames;
|
||||
newFieldNames.reserve(newLength);
|
||||
FieldConstPtrArray fields;
|
||||
fields.reserve(newLength);
|
||||
for(size_t i=0; i<origLength; i++) {
|
||||
if(origPVFields[i]!=pvField) {
|
||||
newFieldNames.push_back(origPVFields[i]->getFieldName());
|
||||
newPVFields.push_back(origPVFields[i]);
|
||||
fields.push_back(origFields[i]);
|
||||
}
|
||||
}
|
||||
PVFieldPtrArray * xxx = const_cast<PVFieldPtrArray *>(&pvFields);
|
||||
xxx->swap(newPVFields);
|
||||
FieldConstPtr field = getFieldCreate()->createStructure(
|
||||
structurePtr->getID(),newFieldNames,fields);
|
||||
replaceField(field);
|
||||
structurePtr = static_pointer_cast<const Structure>(field);
|
||||
StringArray fieldNames = structurePtr->getFieldNames();
|
||||
for(size_t i=0; i<newLength; i++) {
|
||||
pvFields[i]->setParentAndName(this,fieldNames[i]);
|
||||
}
|
||||
}
|
||||
|
||||
PVBooleanPtr PVStructure::getBooleanField(String const &fieldName)
|
||||
{
|
||||
PVFieldPtr pvField = findSubField(fieldName,this);
|
||||
if(pvField.get()==NULL) {
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not exist";
|
||||
this->message(message, errorMessage);
|
||||
return nullPVBoolean;
|
||||
}
|
||||
if(pvField->getField()->getType()==scalar) {
|
||||
ScalarConstPtr pscalar = static_pointer_cast<const Scalar>(
|
||||
pvField->getField());
|
||||
if(pscalar->getScalarType()==pvBoolean) {
|
||||
return std::tr1::static_pointer_cast<PVBoolean>(pvField);
|
||||
}
|
||||
}
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not have type boolean ";
|
||||
this->message(message, errorMessage);
|
||||
return nullPVBoolean;
|
||||
}
|
||||
|
||||
PVBytePtr PVStructure::getByteField(String const &fieldName)
|
||||
{
|
||||
PVFieldPtr pvField = findSubField(fieldName,this);
|
||||
if(pvField.get()==NULL) {
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not exist";
|
||||
this->message(message, errorMessage);
|
||||
return nullPVByte;
|
||||
}
|
||||
if(pvField->getField()->getType()==scalar) {
|
||||
ScalarConstPtr pscalar = static_pointer_cast<const Scalar>(
|
||||
pvField->getField());
|
||||
if(pscalar->getScalarType()==pvByte) {
|
||||
return std::tr1::static_pointer_cast<PVByte>(pvField);
|
||||
}
|
||||
}
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not have type byte ";
|
||||
this->message(message, errorMessage);
|
||||
return nullPVByte;
|
||||
}
|
||||
|
||||
PVShortPtr PVStructure::getShortField(String const &fieldName)
|
||||
{
|
||||
PVFieldPtr pvField = findSubField(fieldName,this);
|
||||
if(pvField.get()==NULL) {
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not exist";
|
||||
this->message(message, errorMessage);
|
||||
return nullPVShort;
|
||||
}
|
||||
if(pvField->getField()->getType()==scalar) {
|
||||
ScalarConstPtr pscalar = static_pointer_cast<const Scalar>(
|
||||
pvField->getField());
|
||||
if(pscalar->getScalarType()==pvShort) {
|
||||
return std::tr1::static_pointer_cast<PVShort>(pvField);
|
||||
}
|
||||
}
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not have type short ";
|
||||
this->message(message, errorMessage);
|
||||
return nullPVShort;
|
||||
}
|
||||
|
||||
PVIntPtr PVStructure::getIntField(String const &fieldName)
|
||||
{
|
||||
PVFieldPtr pvField = findSubField(fieldName,this);
|
||||
if(pvField.get()==NULL) {
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not exist";
|
||||
this->message(message, errorMessage);
|
||||
return nullPVInt;
|
||||
}
|
||||
if(pvField->getField()->getType()==scalar) {
|
||||
ScalarConstPtr pscalar = static_pointer_cast<const Scalar>(
|
||||
pvField->getField());
|
||||
if(pscalar->getScalarType()==pvInt) {
|
||||
return std::tr1::static_pointer_cast<PVInt>(pvField);
|
||||
}
|
||||
}
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not have type int ";
|
||||
this->message(message, errorMessage);
|
||||
return nullPVInt;
|
||||
}
|
||||
|
||||
PVLongPtr PVStructure::getLongField(String const &fieldName)
|
||||
{
|
||||
PVFieldPtr pvField = findSubField(fieldName,this);
|
||||
if(pvField.get()==NULL) {
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not exist";
|
||||
this->message(message, errorMessage);
|
||||
return nullPVLong;
|
||||
}
|
||||
if(pvField->getField()->getType()==scalar) {
|
||||
ScalarConstPtr pscalar = static_pointer_cast<const Scalar>(
|
||||
pvField->getField());
|
||||
if(pscalar->getScalarType()==pvLong) {
|
||||
return std::tr1::static_pointer_cast<PVLong>(pvField);
|
||||
}
|
||||
}
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not have type long ";
|
||||
this->message(message, errorMessage);
|
||||
return nullPVLong;
|
||||
}
|
||||
|
||||
PVUBytePtr PVStructure::getUByteField(String const &fieldName)
|
||||
{
|
||||
PVFieldPtr pvField = findSubField(fieldName,this);
|
||||
if(pvField.get()==NULL) {
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not exist";
|
||||
this->message(message, errorMessage);
|
||||
return nullPVUByte;
|
||||
}
|
||||
if(pvField->getField()->getType()==scalar) {
|
||||
ScalarConstPtr pscalar = static_pointer_cast<const Scalar>(
|
||||
pvField->getField());
|
||||
if(pscalar->getScalarType()==pvUByte) {
|
||||
return std::tr1::static_pointer_cast<PVUByte>(pvField);
|
||||
}
|
||||
}
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not have type byte ";
|
||||
this->message(message, errorMessage);
|
||||
return nullPVUByte;
|
||||
}
|
||||
|
||||
PVUShortPtr PVStructure::getUShortField(String const &fieldName)
|
||||
{
|
||||
PVFieldPtr pvField = findSubField(fieldName,this);
|
||||
if(pvField.get()==NULL) {
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not exist";
|
||||
this->message(message, errorMessage);
|
||||
return nullPVUShort;
|
||||
}
|
||||
if(pvField->getField()->getType()==scalar) {
|
||||
ScalarConstPtr pscalar = static_pointer_cast<const Scalar>(
|
||||
pvField->getField());
|
||||
if(pscalar->getScalarType()==pvUShort) {
|
||||
return std::tr1::static_pointer_cast<PVUShort>(pvField);
|
||||
}
|
||||
}
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not have type short ";
|
||||
this->message(message, errorMessage);
|
||||
return nullPVUShort;
|
||||
}
|
||||
|
||||
PVUIntPtr PVStructure::getUIntField(String const &fieldName)
|
||||
{
|
||||
PVFieldPtr pvField = findSubField(fieldName,this);
|
||||
if(pvField.get()==NULL) {
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not exist";
|
||||
this->message(message, errorMessage);
|
||||
return nullPVUInt;
|
||||
}
|
||||
if(pvField->getField()->getType()==scalar) {
|
||||
ScalarConstPtr pscalar = static_pointer_cast<const Scalar>(
|
||||
pvField->getField());
|
||||
if(pscalar->getScalarType()==pvUInt) {
|
||||
return std::tr1::static_pointer_cast<PVUInt>(pvField);
|
||||
}
|
||||
}
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not have type int ";
|
||||
this->message(message, errorMessage);
|
||||
return nullPVUInt;
|
||||
}
|
||||
|
||||
PVULongPtr PVStructure::getULongField(String const &fieldName)
|
||||
{
|
||||
PVFieldPtr pvField = findSubField(fieldName,this);
|
||||
if(pvField.get()==NULL) {
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not exist";
|
||||
this->message(message, errorMessage);
|
||||
return nullPVULong;
|
||||
}
|
||||
if(pvField->getField()->getType()==scalar) {
|
||||
ScalarConstPtr pscalar = static_pointer_cast<const Scalar>(
|
||||
pvField->getField());
|
||||
if(pscalar->getScalarType()==pvULong) {
|
||||
return std::tr1::static_pointer_cast<PVULong>(pvField);
|
||||
}
|
||||
}
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not have type long ";
|
||||
this->message(message, errorMessage);
|
||||
return nullPVULong;
|
||||
}
|
||||
|
||||
PVFloatPtr PVStructure::getFloatField(String const &fieldName)
|
||||
{
|
||||
PVFieldPtr pvField = findSubField(fieldName,this);
|
||||
if(pvField.get()==NULL) {
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not exist";
|
||||
this->message(message, errorMessage);
|
||||
return nullPVFloat;
|
||||
}
|
||||
if(pvField->getField()->getType()==scalar) {
|
||||
ScalarConstPtr pscalar = static_pointer_cast<const Scalar>(
|
||||
pvField->getField());
|
||||
if(pscalar->getScalarType()==pvFloat) {
|
||||
return std::tr1::static_pointer_cast<PVFloat>(pvField);
|
||||
}
|
||||
}
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not have type float ";
|
||||
this->message(message, errorMessage);
|
||||
return nullPVFloat;
|
||||
}
|
||||
|
||||
PVDoublePtr PVStructure::getDoubleField(String const &fieldName)
|
||||
{
|
||||
PVFieldPtr pvField = findSubField(fieldName,this);
|
||||
if(pvField.get()==NULL) {
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not exist";
|
||||
this->message(message, errorMessage);
|
||||
return nullPVDouble;
|
||||
}
|
||||
if(pvField->getField()->getType()==scalar) {
|
||||
ScalarConstPtr pscalar = static_pointer_cast<const Scalar>(
|
||||
pvField->getField());
|
||||
if(pscalar->getScalarType()==pvDouble) {
|
||||
return std::tr1::static_pointer_cast<PVDouble>(pvField);
|
||||
}
|
||||
}
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not have type double ";
|
||||
this->message(message, errorMessage);
|
||||
return nullPVDouble;
|
||||
}
|
||||
|
||||
PVStringPtr PVStructure::getStringField(String const &fieldName)
|
||||
{
|
||||
PVFieldPtr pvField = findSubField(fieldName,this);
|
||||
if(pvField.get()==NULL) {
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not exist";
|
||||
this->message(message, errorMessage);
|
||||
return nullPVString;
|
||||
}
|
||||
if(pvField->getField()->getType()==scalar) {
|
||||
ScalarConstPtr pscalar = static_pointer_cast<const Scalar>(
|
||||
pvField->getField());
|
||||
if(pscalar->getScalarType()==pvString) {
|
||||
return std::tr1::static_pointer_cast<PVString>(pvField);
|
||||
}
|
||||
}
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not have type string ";
|
||||
this->message(message, errorMessage);
|
||||
return nullPVString;
|
||||
}
|
||||
|
||||
PVStructurePtr PVStructure::getStructureField(String const &fieldName)
|
||||
{
|
||||
PVFieldPtr pvField = findSubField(fieldName,this);
|
||||
if(pvField.get()==NULL) {
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not exist";
|
||||
this->message(message, errorMessage);
|
||||
return nullPVStructure;
|
||||
}
|
||||
if(pvField->getField()->getType()==structure) {
|
||||
return std::tr1::static_pointer_cast<PVStructure>(pvField);
|
||||
}
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not have type structure ";
|
||||
this->message(message, errorMessage);
|
||||
return nullPVStructure;
|
||||
}
|
||||
|
||||
PVScalarArrayPtr PVStructure::getScalarArrayField(
|
||||
String const &fieldName,ScalarType elementType)
|
||||
{
|
||||
PVFieldPtr pvField = findSubField(fieldName,this);
|
||||
if(pvField.get()==NULL) {
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not exist";
|
||||
this->message(message, errorMessage);
|
||||
return nullPVScalarArray;
|
||||
}
|
||||
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 nullPVScalarArray;
|
||||
}
|
||||
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 nullPVScalarArray;
|
||||
}
|
||||
return std::tr1::static_pointer_cast<PVScalarArray>(pvField);
|
||||
}
|
||||
|
||||
PVStructureArrayPtr PVStructure::getStructureArrayField(
|
||||
String const &fieldName)
|
||||
{
|
||||
PVFieldPtr pvField = findSubField(fieldName,this);
|
||||
if(pvField.get()==NULL) {
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not exist";
|
||||
this->message(message, errorMessage);
|
||||
return nullPVStructureArray;
|
||||
}
|
||||
if(pvField->getField()->getType()==structureArray) {
|
||||
return std::tr1::static_pointer_cast<PVStructureArray>(pvField);
|
||||
}
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not have type structureArray ";
|
||||
this->message(message, errorMessage);
|
||||
return nullPVStructureArray;
|
||||
}
|
||||
|
||||
String PVStructure::getExtendsStructureName() const
|
||||
{
|
||||
return extendsStructureName;
|
||||
}
|
||||
|
||||
bool PVStructure::putExtendsStructureName(
|
||||
String const &xxx)
|
||||
{
|
||||
if(extendsStructureName.length()!=0) return false;
|
||||
extendsStructureName = xxx;
|
||||
return true;
|
||||
}
|
||||
|
||||
void PVStructure::serialize(ByteBuffer *pbuffer,
|
||||
SerializableControl *pflusher) const {
|
||||
size_t fieldsSize = pvFields.size();
|
||||
for(size_t i = 0; i<fieldsSize; i++)
|
||||
pvFields[i]->serialize(pbuffer, pflusher);
|
||||
}
|
||||
|
||||
void PVStructure::deserialize(ByteBuffer *pbuffer,
|
||||
DeserializableControl *pcontrol) {
|
||||
size_t fieldsSize = pvFields.size();
|
||||
for(size_t i = 0; i<fieldsSize; i++)
|
||||
pvFields[i]->deserialize(pbuffer, pcontrol);
|
||||
|
||||
}
|
||||
|
||||
void PVStructure::serialize(ByteBuffer *pbuffer,
|
||||
SerializableControl *pflusher, BitSet *pbitSet) const {
|
||||
PVStructure* nonConstThis = const_cast<PVStructure*>(this);
|
||||
size_t numberFields = nonConstThis->getNumberFields();
|
||||
size_t offset = nonConstThis->getFieldOffset();
|
||||
int32 next = pbitSet->nextSetBit(offset);
|
||||
|
||||
// no more changes or no changes in this structure
|
||||
if(next<0||next>=static_cast<int32>(offset+numberFields)) return;
|
||||
|
||||
// entire structure
|
||||
if(static_cast<int32>(offset)==next) {
|
||||
serialize(pbuffer, pflusher);
|
||||
return;
|
||||
}
|
||||
|
||||
size_t fieldsSize = pvFields.size();
|
||||
for(size_t i = 0; i<fieldsSize; i++) {
|
||||
PVFieldPtr pvField = pvFields[i];
|
||||
offset = pvField->getFieldOffset();
|
||||
int32 inumberFields = pvField->getNumberFields();
|
||||
next = pbitSet->nextSetBit(offset);
|
||||
|
||||
// no more changes
|
||||
if(next<0) return;
|
||||
// no change in this pvField
|
||||
if(next>=static_cast<int32>(offset+inumberFields)) continue;
|
||||
|
||||
// serialize field or fields
|
||||
if(inumberFields==1) {
|
||||
pvField->serialize(pbuffer, pflusher);
|
||||
} else {
|
||||
PVStructurePtr pvStructure = std::tr1::static_pointer_cast<PVStructure>(pvField);
|
||||
pvStructure->serialize(pbuffer, pflusher, pbitSet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PVStructure::deserialize(ByteBuffer *pbuffer,
|
||||
DeserializableControl *pcontrol, BitSet *pbitSet) {
|
||||
size_t offset = getFieldOffset();
|
||||
size_t numberFields = getNumberFields();
|
||||
int32 next = pbitSet->nextSetBit(offset);
|
||||
|
||||
// no more changes or no changes in this structure
|
||||
if(next<0||next>=static_cast<int32>(offset+numberFields)) return;
|
||||
|
||||
// entire structure
|
||||
if(static_cast<int32>(offset)==next) {
|
||||
deserialize(pbuffer, pcontrol);
|
||||
return;
|
||||
}
|
||||
|
||||
size_t fieldsSize = pvFields.size();
|
||||
for(size_t i = 0; i<fieldsSize; i++) {
|
||||
PVFieldPtr pvField = pvFields[i];
|
||||
offset = pvField->getFieldOffset();
|
||||
int32 inumberFields = pvField->getNumberFields();
|
||||
next = pbitSet->nextSetBit(offset);
|
||||
// no more changes
|
||||
if(next<0) return;
|
||||
// no change in this pvField
|
||||
if(next>=static_cast<int32>(offset+inumberFields)) continue;
|
||||
|
||||
// deserialize field or fields
|
||||
if(inumberFields==1) {
|
||||
pvField->deserialize(pbuffer, pcontrol);
|
||||
} else {
|
||||
PVStructurePtr pvStructure = std::tr1::static_pointer_cast<PVStructure>(pvField);
|
||||
pvStructure->deserialize(pbuffer, pcontrol, pbitSet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static PVFieldPtr findSubField(
|
||||
String const & fieldName,
|
||||
PVStructure const *pvStructure)
|
||||
{
|
||||
if( fieldName.length()<1) return PVFieldPtr();
|
||||
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();
|
||||
PVFieldPtr pvField;
|
||||
size_t numFields = pvStructure->getStructure()->getNumberFields();
|
||||
for(size_t i=0; i<numFields; i++) {
|
||||
pvField = pvFields[i];
|
||||
size_t result = pvField->getFieldName().compare(name);
|
||||
if(result==0) {
|
||||
if(restOfName.length()==0) return pvFields[i];
|
||||
if(pvField->getField()->getType()!=structure) return PVFieldPtr();
|
||||
PVStructurePtr pvStructure =
|
||||
std::tr1::static_pointer_cast<PVStructure>(pvField);
|
||||
return findSubField(restOfName,pvStructure.get());
|
||||
}
|
||||
}
|
||||
return PVFieldPtr();
|
||||
}
|
||||
|
||||
std::ostream& PVStructure::dumpValue(std::ostream& o) const
|
||||
{
|
||||
o << format::indent() << getStructure()->getID() << ' ' << getFieldName();
|
||||
String extendsName = getExtendsStructureName();
|
||||
if(extendsName.length()>0) {
|
||||
o << " extends " << extendsName;
|
||||
}
|
||||
o << std::endl;
|
||||
{
|
||||
format::indent_scope s(o);
|
||||
|
||||
PVFieldPtrArray const & fieldsData = getPVFields();
|
||||
if (fieldsData.size() != 0) {
|
||||
size_t length = getStructure()->getNumberFields();
|
||||
for(size_t i=0; i<length; i++) {
|
||||
PVFieldPtr fieldField = fieldsData[i];
|
||||
Type type = fieldField->getField()->getType();
|
||||
if (type == scalar || type == scalarArray)
|
||||
o << format::indent() << fieldField->getField()->getID() << ' ' << fieldField->getFieldName() << ' ' << *(fieldField.get()) << std::endl;
|
||||
else
|
||||
o << *(fieldField.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
}}
|
||||
@@ -1,276 +0,0 @@
|
||||
/*PVStructureArray.cpp*/
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
*/
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/convert.h>
|
||||
#include <pv/factory.h>
|
||||
#include <pv/serializeHelper.h>
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using std::size_t;
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
PVStructureArray::PVStructureArray(StructureArrayConstPtr const & structureArray)
|
||||
: PVArray(structureArray),
|
||||
structureArray(structureArray),
|
||||
value(std::tr1::shared_ptr<PVStructurePtrArray>(new PVStructurePtrArray()))
|
||||
{
|
||||
}
|
||||
|
||||
size_t PVStructureArray::append(size_t number)
|
||||
{
|
||||
size_t currentLength = getLength();
|
||||
size_t newLength = currentLength + number;
|
||||
setCapacity(newLength);
|
||||
setLength(newLength);
|
||||
StructureConstPtr structure = structureArray->getStructure();
|
||||
PVStructurePtrArray *to = value.get();
|
||||
for(size_t i=currentLength; i<newLength; i++) {
|
||||
(*to)[i] =getPVDataCreate()->createPVStructure(structure);
|
||||
}
|
||||
return newLength;
|
||||
}
|
||||
|
||||
bool PVStructureArray::remove(size_t offset,size_t number)
|
||||
{
|
||||
size_t length = getLength();
|
||||
if(offset+number>length) return false;
|
||||
PVStructurePtrArray vec = *value.get();
|
||||
for(size_t i = offset; i+number < length; i++) {
|
||||
vec[i] = vec[i + number];
|
||||
}
|
||||
size_t newLength = length - number;
|
||||
setCapacityLength(newLength,newLength);
|
||||
return true;
|
||||
}
|
||||
|
||||
void PVStructureArray::compress() {
|
||||
size_t length = getCapacity();
|
||||
size_t newLength = 0;
|
||||
PVStructurePtrArray vec = *value.get();
|
||||
for(size_t i=0; i<length; i++) {
|
||||
if(vec[i].get()!=NULL) {
|
||||
newLength++;
|
||||
continue;
|
||||
}
|
||||
// find first non 0
|
||||
size_t notNull = 0;
|
||||
for(size_t j=i+1;j<length;j++) {
|
||||
if(vec[j].get()!=NULL) {
|
||||
notNull = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(notNull!=0) {
|
||||
vec[i] = vec[notNull];
|
||||
vec[notNull].reset();
|
||||
newLength++;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
setCapacityLength(newLength,newLength);
|
||||
}
|
||||
|
||||
void PVStructureArray::setCapacity(size_t capacity) {
|
||||
if(getCapacity()==capacity) return;
|
||||
if(!isCapacityMutable()) {
|
||||
std::string message("not capacityMutable");
|
||||
PVField::message(message, errorMessage);
|
||||
return;
|
||||
}
|
||||
size_t length = getLength();
|
||||
if(length>capacity) length = capacity;
|
||||
size_t oldCapacity = getCapacity();
|
||||
if(oldCapacity>capacity) {
|
||||
PVStructurePtrArray array;
|
||||
array.reserve(capacity);
|
||||
array.resize(length);
|
||||
PVStructurePtr * from = get();
|
||||
for (size_t i=0; i<length; i++) array[i] = from[i];
|
||||
value->swap(array);
|
||||
} else {
|
||||
value->reserve(capacity);
|
||||
}
|
||||
setCapacityLength(capacity,length);
|
||||
}
|
||||
|
||||
void PVStructureArray::setLength(size_t length) {
|
||||
if(PVArray::getLength()==length) return;
|
||||
size_t capacity = PVArray::getCapacity();
|
||||
if(length>capacity) {
|
||||
if(!PVArray::isCapacityMutable()) {
|
||||
std::string message("not capacityMutable");
|
||||
PVField::message(message, errorMessage);
|
||||
return;
|
||||
}
|
||||
setCapacity(length);
|
||||
}
|
||||
value->resize(length);
|
||||
PVArray::setCapacityLength(capacity,length);
|
||||
}
|
||||
|
||||
StructureArrayConstPtr PVStructureArray::getStructureArray() const
|
||||
{
|
||||
return structureArray;
|
||||
}
|
||||
|
||||
size_t PVStructureArray::get(
|
||||
size_t offset, size_t len, StructureArrayData &data)
|
||||
{
|
||||
size_t n = len;
|
||||
size_t length = getLength();
|
||||
if(offset+len > length) {
|
||||
n = length - offset;
|
||||
//if(n<0) n = 0;
|
||||
}
|
||||
data.data = *value.get();
|
||||
data.offset = offset;
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t PVStructureArray::put(size_t offset,size_t len,
|
||||
const_vector const & from, size_t fromOffset)
|
||||
{
|
||||
if(isImmutable()) {
|
||||
message(String("field is immutable"), errorMessage);
|
||||
return 0;
|
||||
}
|
||||
if(&from==value.get()) return 0;
|
||||
if(len<1) return 0;
|
||||
size_t length = getLength();
|
||||
size_t capacity = getCapacity();
|
||||
if(offset+len > length) {
|
||||
size_t newlength = offset + len;
|
||||
if(newlength>capacity) {
|
||||
setCapacity(newlength);
|
||||
capacity = getCapacity();
|
||||
newlength = capacity;
|
||||
len = newlength - offset;
|
||||
if(len<=0) return 0;
|
||||
}
|
||||
length = newlength;
|
||||
setLength(length);
|
||||
}
|
||||
PVStructurePtrArray *to = value.get();
|
||||
StructureConstPtr structure = structureArray->getStructure();
|
||||
for(size_t i=0; i<len; i++) {
|
||||
PVStructurePtr frompv = from[i+fromOffset];
|
||||
if(frompv.get()!=NULL) {
|
||||
if(frompv->getStructure()!=structure) {
|
||||
throw std::invalid_argument(String(
|
||||
"Element is not a compatible structure"));
|
||||
}
|
||||
}
|
||||
(*to)[i+offset] = frompv;
|
||||
}
|
||||
postPut();
|
||||
setLength(length);
|
||||
return len;
|
||||
}
|
||||
|
||||
void PVStructureArray::shareData(
|
||||
std::tr1::shared_ptr<std::vector<PVStructurePtr> > const & sharedValue,
|
||||
std::size_t capacity,
|
||||
std::size_t length)
|
||||
{
|
||||
value = sharedValue;
|
||||
setCapacityLength(capacity,length);
|
||||
}
|
||||
|
||||
void PVStructureArray::serialize(ByteBuffer *pbuffer,
|
||||
SerializableControl *pflusher) const {
|
||||
serialize(pbuffer, pflusher, 0, getLength());
|
||||
}
|
||||
|
||||
void PVStructureArray::deserialize(ByteBuffer *pbuffer,
|
||||
DeserializableControl *pcontrol) {
|
||||
size_t size = SerializeHelper::readSize(pbuffer, pcontrol);
|
||||
//if(size>=0) {
|
||||
// prepare array, if necessary
|
||||
if(size>getCapacity()) setCapacity(size);
|
||||
setLength(size);
|
||||
PVStructurePtrArray *pvArray = value.get();
|
||||
for(size_t i = 0; i<size; i++) {
|
||||
pcontrol->ensureData(1);
|
||||
size_t temp = pbuffer->getByte();
|
||||
if(temp==0) {
|
||||
(*pvArray)[i].reset();
|
||||
}
|
||||
else {
|
||||
if((*pvArray)[i].get()==NULL) {
|
||||
StructureConstPtr structure = structureArray->getStructure();
|
||||
(*pvArray)[i] = getPVDataCreate()->createPVStructure(structure);
|
||||
}
|
||||
(*pvArray)[i]->deserialize(pbuffer, pcontrol);
|
||||
}
|
||||
}
|
||||
postPut();
|
||||
//}
|
||||
}
|
||||
|
||||
void PVStructureArray::serialize(ByteBuffer *pbuffer,
|
||||
SerializableControl *pflusher, size_t offset, size_t count) const {
|
||||
// cache
|
||||
size_t length = getLength();
|
||||
|
||||
// check bounds
|
||||
/*if(offset<0)
|
||||
offset = 0;
|
||||
else*/ if(offset>length) offset = length;
|
||||
//if(count<0) count = length;
|
||||
|
||||
size_t maxCount = length-offset;
|
||||
if(count>maxCount) count = maxCount;
|
||||
|
||||
PVStructurePtrArray pvArray = *value.get();
|
||||
// write
|
||||
SerializeHelper::writeSize(count, pbuffer, pflusher);
|
||||
for(size_t i = 0; i<count; i++) {
|
||||
if(pbuffer->getRemaining()<1) pflusher->flushSerializeBuffer();
|
||||
PVStructurePtr pvStructure = pvArray[i+offset];
|
||||
if(pvStructure.get()==NULL) {
|
||||
pbuffer->putByte(0);
|
||||
}
|
||||
else {
|
||||
pbuffer->putByte(1);
|
||||
pvStructure->serialize(pbuffer, pflusher);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::ostream& PVStructureArray::dumpValue(std::ostream& o) const
|
||||
{
|
||||
o << format::indent() << getStructureArray()->getID() << ' ' << getFieldName() << std::endl;
|
||||
size_t length = getLength();
|
||||
if (length > 0)
|
||||
{
|
||||
format::indent_scope s(o);
|
||||
|
||||
for (size_t i = 0; i < length; i++)
|
||||
dumpValue(o, i);
|
||||
}
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
std::ostream& PVStructureArray::dumpValue(std::ostream& o, std::size_t index) const
|
||||
{
|
||||
PVStructurePtrArray pvArray = *value.get();
|
||||
PVStructurePtr pvStructure = pvArray[index];
|
||||
return o << *(pvStructure.get());
|
||||
return o;
|
||||
}
|
||||
|
||||
}}
|
||||
@@ -1,38 +0,0 @@
|
||||
/* event.h */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
*/
|
||||
#ifndef EVENT_H
|
||||
#define EVENT_H
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <epicsEvent.h>
|
||||
#include <pv/pvType.h>
|
||||
#include <pv/sharedPtr.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
class Event;
|
||||
typedef std::tr1::shared_ptr<Event> EventPtr;
|
||||
|
||||
class Event {
|
||||
public:
|
||||
POINTER_DEFINITIONS(Event);
|
||||
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;
|
||||
String alreadyOn;
|
||||
};
|
||||
|
||||
}}
|
||||
#endif /* EVENT_H */
|
||||
@@ -1,65 +0,0 @@
|
||||
/* messageQueue.h */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
*/
|
||||
#ifndef MESSAGEQUEUE_H
|
||||
#define MESSAGEQUEUE_H
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <cstddef>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <pv/pvType.h>
|
||||
#include <pv/requester.h>
|
||||
#include <pv/queue.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
class MessageNode;
|
||||
class MessageQueue;
|
||||
typedef std::tr1::shared_ptr<MessageNode> MessageNodePtr;
|
||||
typedef std::vector<MessageNodePtr> MessageNodePtrArray;
|
||||
typedef std::tr1::shared_ptr<MessageQueue> MessageQueuePtr;
|
||||
|
||||
class MessageNode {
|
||||
public:
|
||||
MessageNode();
|
||||
String getMessage() const;
|
||||
MessageType getMessageType() const;
|
||||
private:
|
||||
String message;
|
||||
MessageType messageType;
|
||||
friend class MessageQueue;
|
||||
};
|
||||
|
||||
class MessageQueue : public Queue<MessageNode> {
|
||||
public:
|
||||
POINTER_DEFINITIONS(MessageQueue);
|
||||
static MessageQueuePtr create(int size);
|
||||
MessageQueue(MessageNodePtrArray &nodeArray);
|
||||
virtual ~MessageQueue();
|
||||
MessageNodePtr &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() ;
|
||||
bool isFull() ;
|
||||
int getClearOverrun();
|
||||
private:
|
||||
MessageNodePtr nullNode;
|
||||
MessageNodePtr lastGet;
|
||||
MessageNodePtr lastPut;
|
||||
uint32 overrun;
|
||||
};
|
||||
|
||||
}}
|
||||
#endif /* MESSAGEQUEUE_H */
|
||||
|
||||
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
/* requester.h */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
*/
|
||||
#ifndef REQUESTER_H
|
||||
#define REQUESTER_H
|
||||
#include <string>
|
||||
#include <pv/pvType.h>
|
||||
#include <pv/sharedPtr.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
class Requester;
|
||||
typedef std::tr1::shared_ptr<Requester> RequesterPtr;
|
||||
|
||||
enum MessageType {
|
||||
infoMessage,warningMessage,errorMessage,fatalErrorMessage
|
||||
};
|
||||
|
||||
extern String getMessageTypeName(MessageType messageType);
|
||||
extern const size_t messageTypeCount;
|
||||
class Requester {
|
||||
public:
|
||||
POINTER_DEFINITIONS(Requester);
|
||||
virtual ~Requester(){}
|
||||
virtual String getRequesterName() = 0;
|
||||
virtual void message(String const & message,MessageType messageType) = 0;
|
||||
};
|
||||
|
||||
}}
|
||||
#endif /* REQUESTER_H */
|
||||
@@ -1,72 +0,0 @@
|
||||
/* serialize.h */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
*/
|
||||
#ifndef SERIALIZE_H
|
||||
#define SERIALIZE_H
|
||||
#include <pv/byteBuffer.h>
|
||||
#include <pv/sharedPtr.h>
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
class SerializableControl;
|
||||
class DeserializableControl;
|
||||
class Serializable;
|
||||
class BitSetSerializable;
|
||||
class SerializableArray;
|
||||
class BitSet;
|
||||
class Field;
|
||||
|
||||
class SerializableControl {
|
||||
public:
|
||||
virtual ~SerializableControl(){}
|
||||
virtual void flushSerializeBuffer() =0;
|
||||
virtual void ensureBuffer(std::size_t size) =0;
|
||||
virtual void alignBuffer(std::size_t alignment) =0;
|
||||
virtual bool directSerialize(ByteBuffer *existingBuffer, const char* toSerialize,
|
||||
std::size_t elementCount, std::size_t elementSize) = 0;
|
||||
virtual void cachedSerialize(std::tr1::shared_ptr<const Field> const & field, ByteBuffer* buffer) = 0;
|
||||
};
|
||||
|
||||
class DeserializableControl {
|
||||
public:
|
||||
virtual ~DeserializableControl(){}
|
||||
virtual void ensureData(std::size_t size) =0;
|
||||
virtual void alignData(std::size_t alignment) =0;
|
||||
virtual bool directDeserialize(ByteBuffer *existingBuffer, char* deserializeTo,
|
||||
std::size_t elementCount, std::size_t elementSize) = 0;
|
||||
virtual std::tr1::shared_ptr<const Field> cachedDeserialize(ByteBuffer* buffer) = 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, std::size_t offset, std::size_t count) const = 0;
|
||||
};
|
||||
|
||||
}}
|
||||
#endif /* SERIALIZE_H */
|
||||
@@ -1,57 +0,0 @@
|
||||
/* alarm.h */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
*/
|
||||
#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 StringArrayPtr getSeverityNames();
|
||||
};
|
||||
|
||||
extern const size_t statusCount;
|
||||
class AlarmStatusFunc {
|
||||
public:
|
||||
static AlarmStatus getStatus(int value);
|
||||
static StringArrayPtr 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 const &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,31 +0,0 @@
|
||||
/* control.h */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
*/
|
||||
#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;}
|
||||
double getMinStep() const {return minStep;}
|
||||
void setLow(double value) {low = value;}
|
||||
void setHigh(double value) {high = value;}
|
||||
void setMinStep(double value) {minStep = value;}
|
||||
private:
|
||||
double low;
|
||||
double high;
|
||||
double minStep;
|
||||
};
|
||||
|
||||
}}
|
||||
#endif /* CONTROL_H */
|
||||
@@ -1,42 +0,0 @@
|
||||
/* display.h */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
*/
|
||||
#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 const & value) {description = value;}
|
||||
String getFormat() const {return format;}
|
||||
void setFormat(String const & value) {format = value;}
|
||||
String getUnits() const {return units;}
|
||||
void setUnits(String const & value) {units = value;}
|
||||
private:
|
||||
String description;
|
||||
String format;
|
||||
String units;
|
||||
double low;
|
||||
double high;
|
||||
};
|
||||
|
||||
}}
|
||||
#endif /* DISPLAY_H */
|
||||
@@ -1,41 +0,0 @@
|
||||
/* pvAlarm.h */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
*/
|
||||
#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() {}
|
||||
//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(PVFieldPtr const & 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:
|
||||
PVIntPtr pvSeverity;
|
||||
PVIntPtr pvStatus;
|
||||
PVStringPtr pvMessage;
|
||||
static String noAlarmFound;
|
||||
static String notAttached;
|
||||
};
|
||||
|
||||
}}
|
||||
#endif /* PVALARM_H */
|
||||
@@ -1,37 +0,0 @@
|
||||
/* pvControl.h */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
*/
|
||||
#include <pv/control.h>
|
||||
#include <pv/pvData.h>
|
||||
#ifndef PVCONTROL_H
|
||||
#define PVCONTROL_H
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
class PVControl {
|
||||
public:
|
||||
PVControl(){}
|
||||
//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(PVFieldPtr const & 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:
|
||||
PVDoublePtr pvLow;
|
||||
PVDoublePtr pvHigh;
|
||||
static String noControlFound;
|
||||
static String notAttached;
|
||||
};
|
||||
|
||||
}}
|
||||
#endif /* PVCONTROL_H */
|
||||
@@ -1,41 +0,0 @@
|
||||
/* pvDisplay.h */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
*/
|
||||
#include <string>
|
||||
#include <pv/pvType.h>
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/display.h>
|
||||
#ifndef PVDISPLAY_H
|
||||
#define PVDISPLAY_H
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
class PVDisplay {
|
||||
public:
|
||||
PVDisplay() {}
|
||||
//default constructors and destructor are OK
|
||||
//An automatic detach is issued if already attached.
|
||||
bool attach(PVFieldPtr const & pvField);
|
||||
void detach();
|
||||
bool isAttached();
|
||||
// each of the following throws logic_error is not attached to PVField
|
||||
// a set returns false if field is immutable
|
||||
void get(Display &) const;
|
||||
bool set(Display const & display);
|
||||
private:
|
||||
static String noDisplayFound;
|
||||
static String notAttached;
|
||||
PVStringPtr pvDescription;
|
||||
PVStringPtr pvFormat;
|
||||
PVStringPtr pvUnits;
|
||||
PVDoublePtr pvLow;
|
||||
PVDoublePtr pvHigh;
|
||||
};
|
||||
|
||||
}}
|
||||
#endif /* PVDISPLAY_H */
|
||||
@@ -1,44 +0,0 @@
|
||||
/* pvEnumerated.h */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
*/
|
||||
#include <string>
|
||||
#include <pv/pvType.h>
|
||||
#include <pv/pvData.h>
|
||||
#ifndef PVENUMERATED_H
|
||||
#define PVENUMERATED_H
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
class PVEnumerated {
|
||||
public:
|
||||
PVEnumerated() {}
|
||||
//default constructors and destructor are OK
|
||||
//This class should not be extended
|
||||
//returns (false,true) if pvField(isNot, is valid enumerated structure
|
||||
//An automatic detach is issued if already attached.
|
||||
bool attach(PVFieldPtr const & pvField);
|
||||
void detach();
|
||||
bool isAttached();
|
||||
// each of the following throws logic_error is not attached to PVField
|
||||
// a set returns false if field is immutable
|
||||
bool setIndex(int32 index);
|
||||
int32 getIndex();
|
||||
String getChoice();
|
||||
bool choicesMutable();
|
||||
StringArrayPtr const & getChoices();
|
||||
int32 getNumberChoices();
|
||||
bool setChoices(StringArray & choices);
|
||||
private:
|
||||
static String notFound;
|
||||
static String notAttached;
|
||||
PVIntPtr pvIndex;
|
||||
PVStringArrayPtr pvChoices;
|
||||
};
|
||||
|
||||
}}
|
||||
#endif /* PVENUMERATED_H */
|
||||
@@ -1,42 +0,0 @@
|
||||
/* pvTimeStamp.h */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
*/
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <pv/pvType.h>
|
||||
#include <pv/timeStamp.h>
|
||||
#include <pv/pvData.h>
|
||||
#ifndef PVTIMESTAMP_H
|
||||
#define PVTIMESTAMP_H
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
class PVTimeStamp {
|
||||
public:
|
||||
PVTimeStamp(){}
|
||||
//default constructors and destructor are OK
|
||||
//This class should not be extended
|
||||
|
||||
//returns (false,true) if pvField(isNot, is valid timeStamp structure
|
||||
bool attach(PVFieldPtr const & pvField);
|
||||
void detach();
|
||||
bool isAttached();
|
||||
// following throw logic_error is not attached to PVField
|
||||
// a set returns false if field is immutable
|
||||
void get(TimeStamp &) const;
|
||||
bool set(TimeStamp const & timeStamp);
|
||||
private:
|
||||
static String noTimeStamp;
|
||||
static String notAttached;
|
||||
PVLongPtr pvSecs;
|
||||
PVIntPtr pvUserTag;
|
||||
PVIntPtr pvNano;
|
||||
};
|
||||
|
||||
}}
|
||||
#endif /* PVTIMESTAMP_H */
|
||||
@@ -1,69 +0,0 @@
|
||||
/* timeStamp.h */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
*/
|
||||
#ifndef TIMESTAMP_H
|
||||
#define TIMESTAMP_H
|
||||
#include <ctime>
|
||||
#include "epicsTime.h"
|
||||
#include <pv/pvType.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
extern int32 milliSecPerSec;
|
||||
extern int32 microSecPerSec;
|
||||
extern int32 nanoSecPerSec;
|
||||
extern int64 posixEpochAtEpicsEpoch;
|
||||
|
||||
class TimeStamp {
|
||||
public:
|
||||
TimeStamp()
|
||||
:secondsPastEpoch(0), nanoSeconds(0), userTag(0) {}
|
||||
TimeStamp(int64 secondsPastEpoch,int32 nanoSeconds = 0,int32 userTag = 0);
|
||||
//default constructors and destructor are OK
|
||||
//This class should not be extended
|
||||
void normalize();
|
||||
void fromTime_t(const time_t &);
|
||||
void toTime_t(time_t &) const;
|
||||
int64 getSecondsPastEpoch() const {return secondsPastEpoch;}
|
||||
int64 getEpicsSecondsPastEpoch() const {
|
||||
return secondsPastEpoch - posixEpochAtEpicsEpoch;
|
||||
}
|
||||
int32 getNanoSeconds() const {return nanoSeconds;}
|
||||
int32 getUserTag() const {return userTag;}
|
||||
void setUserTag(int userTag) {this->userTag = userTag;}
|
||||
void put(int64 secondsPastEpoch,int32 nanoSeconds = 0) {
|
||||
this->secondsPastEpoch = secondsPastEpoch;
|
||||
this->nanoSeconds = nanoSeconds;
|
||||
normalize();
|
||||
}
|
||||
void put(int64 milliseconds);
|
||||
void getCurrent();
|
||||
double toSeconds() const ;
|
||||
bool operator==(TimeStamp const &) const;
|
||||
bool operator!=(TimeStamp const &) const;
|
||||
bool operator<=(TimeStamp const &) const;
|
||||
bool operator< (TimeStamp const &) const;
|
||||
bool operator>=(TimeStamp const &) const;
|
||||
bool operator> (TimeStamp const &) const;
|
||||
static double diff(TimeStamp const & a,TimeStamp const & b);
|
||||
TimeStamp & operator+=(int64 seconds);
|
||||
TimeStamp & operator-=(int64 seconds);
|
||||
TimeStamp & operator+=(double seconds);
|
||||
TimeStamp & operator-=(double seconds);
|
||||
int64 getMilliseconds(); // milliseconds since epoch
|
||||
private:
|
||||
static int64 diffInt(TimeStamp const &left,TimeStamp const &right );
|
||||
int64 secondsPastEpoch;
|
||||
int32 nanoSeconds;
|
||||
int32 userTag;
|
||||
};
|
||||
|
||||
|
||||
}}
|
||||
#endif /* TIMESTAMP_H */
|
||||
@@ -1,768 +0,0 @@
|
||||
/* convert.h */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
* Author - Marty Kraimer
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
*/
|
||||
#ifndef CONVERT_H
|
||||
#define CONVERT_H
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <pv/pvIntrospect.h>
|
||||
#include <pv/pvData.h>
|
||||
#include <vector>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
bool operator==(PVField&, PVField&);
|
||||
|
||||
static inline bool operator!=(PVField& a, PVField& b)
|
||||
{return !(a==b);}
|
||||
|
||||
|
||||
bool operator==(const Field&, const Field&);
|
||||
bool operator==(const Scalar&, const Scalar&);
|
||||
bool operator==(const ScalarArray&, const ScalarArray&);
|
||||
bool operator==(const Structure&, const Structure&);
|
||||
bool operator==(const StructureArray&, const StructureArray&);
|
||||
|
||||
static inline bool operator!=(const Field& a, const Field& b)
|
||||
{return !(a==b);}
|
||||
static inline bool operator!=(const Scalar& a, const Scalar& b)
|
||||
{return !(a==b);}
|
||||
static inline bool operator!=(const ScalarArray& a, const ScalarArray& b)
|
||||
{return !(a==b);}
|
||||
static inline bool operator!=(const Structure& a, const Structure& b)
|
||||
{return !(a==b);}
|
||||
static inline bool operator!=(const StructureArray& a, const StructureArray& b)
|
||||
{return !(a==b);}
|
||||
|
||||
|
||||
/**
|
||||
* Convert between numeric types, convert any field to a string,
|
||||
* or convert from a string to a scalar field.
|
||||
* <p>Numeric conversions are between scalar numeric types or between arrays of
|
||||
* numeric types. It is not possible to convert between a scalar
|
||||
* and an array.
|
||||
* Numeric conversions are between types:
|
||||
* pvByte, pvShort, pvInt, pvLong,
|
||||
* pvUByte, pvUShort, pvUInt, pvULong,
|
||||
* pvFloat, or pvDouble.</p>
|
||||
*
|
||||
* <p>getString converts any supported type to a String.
|
||||
* Code that implements a PVField interface should implement
|
||||
* method toString by calling this method.</p>
|
||||
*
|
||||
* <p>fromString converts a String to a scalar.
|
||||
* fromStringArray converts an array of Strings
|
||||
* to a pvArray, which must have a scaler element type.
|
||||
* A scalar field is a numeric field or pvBoolean or pvString.</p>
|
||||
* <p>All from methods put data into a PVField, e.g. from means where the PVField gets it's data.</p>
|
||||
*/
|
||||
|
||||
class Convert;
|
||||
typedef std::tr1::shared_ptr<Convert> ConvertPtr;
|
||||
|
||||
class Convert {
|
||||
public:
|
||||
static ConvertPtr getConvert();
|
||||
~Convert();
|
||||
/**
|
||||
* Get the full fieldName for the pvField.
|
||||
* @param builder The builder that will have the result.
|
||||
* @param pvField The pvField.
|
||||
*/
|
||||
void getFullName(StringBuilder buf,PVFieldPtr const & pvField);
|
||||
/**
|
||||
* Do fields have the same definition.
|
||||
*
|
||||
* @param First field
|
||||
* @param Second field
|
||||
* @return (false, true) if the fields (are not, are) the same.
|
||||
*/
|
||||
bool equals(PVFieldPtr const &a,PVFieldPtr const &b);
|
||||
/**
|
||||
* Do fields have the same definition.
|
||||
*
|
||||
* @param First field
|
||||
* @param Second field
|
||||
* @return (false, true) if the fields (are not, are) the same.
|
||||
*/
|
||||
bool equals(PVField &a,PVField &b);
|
||||
/**
|
||||
* Convert a PVField to a string.
|
||||
* @param buf buffer for the result
|
||||
* @param pv a PVField to convert to a string.
|
||||
* If a PVField is a structure or array be prepared for a very long string.
|
||||
* @param indentLevel indentation level
|
||||
*/
|
||||
void getString(StringBuilder buf,PVFieldPtr const & pvField,int indentLevel);
|
||||
/**
|
||||
* Convert a PVField to a string.
|
||||
* param buf buffer for the result
|
||||
* @param pv The PVField to convert to a string.
|
||||
* If the PVField is a structure or array be prepared for a very long string.
|
||||
*/
|
||||
void getString(StringBuilder buf,PVFieldPtr const & pvField);
|
||||
/**
|
||||
* Convert a PVField to a string.
|
||||
* @param buf buffer for the result
|
||||
* @param pv a PVField to convert to a string.
|
||||
* If a PVField is a structure or array be prepared for a very long string.
|
||||
* @param indentLevel indentation level
|
||||
*/
|
||||
void getString(StringBuilder buf,PVField const * pvField,int indentLevel);
|
||||
/**
|
||||
* Convert a PVField to a string.
|
||||
* param buf buffer for the result
|
||||
* @param pv The PVField to convert to a string.
|
||||
* If the PVField is a structure or array be prepared for a very long string.
|
||||
*/
|
||||
void getString(StringBuilder buf,PVField const * pvField);
|
||||
/**
|
||||
* Convert from an array of String to a PVScalar
|
||||
* @param pv The PV.
|
||||
* @param from The array of String value to convert and put into a PV.
|
||||
* @param fromStartIndex The first element if the array of strings.
|
||||
* @throws std::logic_error if the array of String does not have a valid values.
|
||||
*/
|
||||
std::size_t fromString(
|
||||
PVStructurePtr const &pv,
|
||||
StringArray const & from,
|
||||
std::size_t fromStartIndex = 0);
|
||||
/**
|
||||
* Convert from a String to a PVScalar
|
||||
* @param pv The PV.
|
||||
* @param from The String value to convert and put into a PV.
|
||||
* @throws std::logic_error if the String does not have a valid value.
|
||||
*/
|
||||
void fromString(PVScalarPtr const & pv, String const & from);
|
||||
/**
|
||||
* Convert from a String to a PVScalarArray.
|
||||
* The String must be a comma separated set of values optionally enclosed in []
|
||||
* @param pv The PV.
|
||||
* @param from The String value to convert and put into a PV.
|
||||
* @return The number of elements converted.
|
||||
* @throws std::invalid_argument if the element Type is not a scalar.
|
||||
* @throws std::logic_error if the String does not have a valid array values.
|
||||
*/
|
||||
std::size_t fromString(PVScalarArrayPtr const & pv, String from);
|
||||
/**
|
||||
* Convert a PVScalarArray from a String array.
|
||||
* The array element type must be a scalar.
|
||||
* @param pv The PV.
|
||||
* @param offset Starting element in a PV.
|
||||
* @param length The number of elements to transfer.
|
||||
* @param from The array of values to put into the PV.
|
||||
* @param fromOffset Starting element in the source array.
|
||||
* @return The number of elements converted.
|
||||
* @throws std::invalid_argument if the element Type is not a scalar.
|
||||
* @throws std::logic_error if the String does not have a valid value.
|
||||
*/
|
||||
std::size_t fromStringArray(
|
||||
PVScalarArrayPtr const & pv,
|
||||
std::size_t offset, std::size_t length,
|
||||
StringArray const & from,
|
||||
std::size_t fromOffset);
|
||||
/**
|
||||
* Convert a PVScalarArray to a String array.
|
||||
* @param pv The PV.
|
||||
* @param offset Starting element in the PV array.
|
||||
* @param length Number of elements to convert to the string array.
|
||||
* @param to String array to receive the converted PV data.
|
||||
* @param toOffset Starting element in the string array.
|
||||
* @return Number of elements converted.
|
||||
*/
|
||||
std::size_t toStringArray(PVScalarArrayPtr const & pv,
|
||||
std::size_t offset,
|
||||
std::size_t length,
|
||||
StringArray & to,
|
||||
std::size_t toOffset);
|
||||
/**
|
||||
* Are from and to valid arguments to copy.
|
||||
* This first checks of both arguments have the same Type.
|
||||
* Then calls one of isCopyScalarCompatible,
|
||||
* isCopyArrayCompatible, or isCopyStructureCompatible.
|
||||
* @param from The source.
|
||||
* @param to The destination.
|
||||
* @return (false,true) is the arguments (are not, are) compatible.
|
||||
*/
|
||||
bool isCopyCompatible(FieldConstPtr const & from, FieldConstPtr const & to);
|
||||
/**
|
||||
* Copy from a PVField to another PVField.
|
||||
* This calls one on copyScalar, copyArray, copyStructure.
|
||||
* The two arguments must be compatible.
|
||||
* @param from The source.
|
||||
* @param to The destination
|
||||
* @throws std::invalid_argument if the arguments are not compatible.
|
||||
*/
|
||||
void copy(PVFieldPtr const & from, PVFieldPtr const & to);
|
||||
/**
|
||||
* Are from and to valid arguments to copyScalar.
|
||||
* false will be returned if either argument is not a scalar as defined by Type.isScalar().
|
||||
* If both are scalars the return value is true if any of the following are true.
|
||||
* <ul>
|
||||
* <li>Both arguments are numeric.</li>
|
||||
* <li>Both arguments have the same type.</li>
|
||||
* <li>Either argument is a string.</li>
|
||||
* </ul>
|
||||
* @param from The introspection interface for the from data.
|
||||
* @param to The introspection interface for the to data..
|
||||
* @return (false,true) If the arguments (are not, are) compatible.
|
||||
*/
|
||||
bool isCopyScalarCompatible(
|
||||
ScalarConstPtr const & from,
|
||||
ScalarConstPtr const & to);
|
||||
/**
|
||||
* Copy from a scalar pv to another scalar pv.
|
||||
* @param from the source.
|
||||
* @param to the destination.
|
||||
* @throws std::invalid_argument if the arguments are not compatible.
|
||||
*/
|
||||
void copyScalar(PVScalarPtr const & from, PVScalarPtr const & to);
|
||||
/**
|
||||
* Are from and to valid arguments to copyArray.
|
||||
* The results are like isCopyScalarCompatible except that the tests are made on the elementType.
|
||||
* @param from The from array.
|
||||
* @param to The to array.
|
||||
* @return (false,true) If the arguments (are not, are) compatible.
|
||||
*/
|
||||
bool isCopyScalarArrayCompatible(
|
||||
ScalarArrayConstPtr const & from,
|
||||
ScalarArrayConstPtr const & to);
|
||||
/**
|
||||
* Convert from a source PV array to a destination PV array.
|
||||
* @param from The source array.
|
||||
* @param offset Starting element in the source.
|
||||
* @param to The destination array.
|
||||
* @param toOffset Starting element in the array.
|
||||
* @param length Number of elements to transfer.
|
||||
* @return Number of elements converted.
|
||||
* @throws std::invalid_argument if the arguments are not compatible.
|
||||
*/
|
||||
std::size_t copyScalarArray(
|
||||
PVScalarArrayPtr const & from,
|
||||
std::size_t offset,
|
||||
PVScalarArrayPtr const & to,
|
||||
std::size_t toOffset,
|
||||
std::size_t length);
|
||||
/**
|
||||
* Are from and to valid arguments for copyStructure.
|
||||
* They are only compatible if they have the same Structure description.
|
||||
* @param from from structure.
|
||||
* @param to structure.
|
||||
* @return (false,true) If the arguments (are not, are) compatible.
|
||||
*/
|
||||
bool isCopyStructureCompatible(
|
||||
StructureConstPtr const & from, StructureConstPtr const & to);
|
||||
/**
|
||||
* Copy from a structure pv to another structure pv.
|
||||
* NOTE: Only compatible nodes are copied. This means:
|
||||
* <ul>
|
||||
* <li>For scalar nodes this means that isCopyScalarCompatible is true.</li>
|
||||
* <li>For array nodes this means that isCopyArrayCompatible is true.</li>
|
||||
* <li>For structure nodes this means that isCopyStructureCompatible is true.</li>
|
||||
* <li>Link nodes are not copied.</li>
|
||||
* </ul>
|
||||
* @param from The source.
|
||||
* @param to The destination.
|
||||
* @throws std::invalid_argument if the arguments are not compatible.
|
||||
*/
|
||||
void copyStructure(PVStructurePtr const & from, PVStructurePtr const & to);
|
||||
/**
|
||||
* Are from and to valid for copyStructureArray.
|
||||
* @param from The from StructureArray.
|
||||
* @param to The to StructureArray.
|
||||
* @return (false,true) If the arguments (are not, are) compatible.
|
||||
*/
|
||||
bool isCopyStructureArrayCompatible(
|
||||
StructureArrayConstPtr const & from, StructureArrayConstPtr const & to);
|
||||
/**
|
||||
* Copy from a structure array to another structure array.
|
||||
* @param from The source array.
|
||||
* @param to The destination array.
|
||||
*/
|
||||
void copyStructureArray(
|
||||
PVStructureArrayPtr const & from, PVStructureArrayPtr const & to);
|
||||
/**
|
||||
* Convert a PV to a <byte>.
|
||||
* @param pv a PV
|
||||
* @return converted value
|
||||
*/
|
||||
int8 toByte(PVScalarPtr const & pv);
|
||||
/**
|
||||
* Convert a PV to a short.
|
||||
* @param pv a PV
|
||||
* @return converted value
|
||||
* @throws std::invalid_argument if the Type is not a numeric scalar
|
||||
*/
|
||||
int16 toShort(PVScalarPtr const & pv);
|
||||
/**
|
||||
* Convert a PV to a int.
|
||||
* @param pv a PV
|
||||
* @return converted value
|
||||
* @throws std::invalid_argument if the Type is not a numeric scalar
|
||||
*/
|
||||
int32 toInt(PVScalarPtr const & pv);
|
||||
/**
|
||||
* Convert a PV to an long
|
||||
* @param pv a PV
|
||||
* @return converted value
|
||||
* @throws std::invalid_argument if the Type is not a numeric scalar
|
||||
*/
|
||||
int64 toLong(PVScalarPtr const & pv);
|
||||
/**
|
||||
* Convert a PV to a ubyte.
|
||||
* @param pv a PV
|
||||
* @return converted value
|
||||
*/
|
||||
uint8 toUByte(PVScalarPtr const & pv);
|
||||
/**
|
||||
* Convert a PV to a ushort.
|
||||
* @param pv a PV
|
||||
* @return converted value
|
||||
* @throws std::invalid_argument if the Type is not a numeric scalar
|
||||
*/
|
||||
uint16 toUShort(PVScalarPtr const & pv);
|
||||
/**
|
||||
* Convert a PV to a uint.
|
||||
* @param pv a PV
|
||||
* @return converted value
|
||||
* @throws std::invalid_argument if the Type is not a numeric scalar
|
||||
*/
|
||||
uint32 toUInt(PVScalarPtr const & pv);
|
||||
/**
|
||||
* Convert a PV to an ulong
|
||||
* @param pv a PV
|
||||
* @return converted value
|
||||
* @throws std::invalid_argument if the Type is not a numeric scalar
|
||||
*/
|
||||
uint64 toULong(PVScalarPtr const & pv);
|
||||
/**
|
||||
* Convert a PV to a float
|
||||
* @param pv a PV
|
||||
* @return converted value
|
||||
* @throws std::invalid_argument if the Type is not a numeric scalar
|
||||
*/
|
||||
float toFloat(PVScalarPtr const & pv);
|
||||
/**
|
||||
* Convert a PV to a double
|
||||
* @param pv a PV
|
||||
* @return converted value
|
||||
* @throws std::invalid_argument if the Type is not a numeric scalar
|
||||
*/
|
||||
double toDouble(PVScalarPtr const & pv);
|
||||
/**
|
||||
* Convert a PV to a String
|
||||
* @param pv a PV
|
||||
* @return converted value
|
||||
*/
|
||||
String toString(PVScalarPtr const & pv);
|
||||
/**
|
||||
* Convert a PV from a byte
|
||||
* @param pv a PV
|
||||
* @param from value to put into PV
|
||||
* @throws std::invalid_argument if the Type is not a numeric scalar
|
||||
*/
|
||||
void fromByte(PVScalarPtr const & pv,int8 from);
|
||||
/**
|
||||
* Convert a PV from a short
|
||||
* @param pv a PV
|
||||
* @param from value to put into PV
|
||||
* @throws std::invalid_argument if the Type is not a numeric scalar
|
||||
*/
|
||||
void fromShort(PVScalarPtr const & pv,int16 from);
|
||||
/**
|
||||
* Convert a PV from an int
|
||||
* @param pv a PV
|
||||
* @param from value to put into PV
|
||||
* @throws std::invalid_argument if the Type is not a numeric scalar
|
||||
*/
|
||||
void fromInt(PVScalarPtr const & pv, int32 from);
|
||||
/**
|
||||
* Convert a PV from a long
|
||||
* @param pv a PV
|
||||
* @param from value to put into PV
|
||||
* @throws std::invalid_argument if the Type is not a numeric scalar
|
||||
*/
|
||||
void fromLong(PVScalarPtr const & pv, int64 from);
|
||||
/**
|
||||
* Convert a PV from a ubyte
|
||||
* @param pv a PV
|
||||
* @param from value to put into PV
|
||||
* @throws std::invalid_argument if the Type is not a numeric scalar
|
||||
*/
|
||||
void fromUByte(PVScalarPtr const & pv,uint8 from);
|
||||
/**
|
||||
* Convert a PV from a ushort
|
||||
* @param pv a PV
|
||||
* @param from value to put into PV
|
||||
* @throws std::invalid_argument if the Type is not a numeric scalar
|
||||
*/
|
||||
void fromUShort(PVScalarPtr const & pv,uint16 from);
|
||||
/**
|
||||
* Convert a PV from an uint
|
||||
* @param pv a PV
|
||||
* @param from value to put into PV
|
||||
* @throws std::invalid_argument if the Type is not a numeric scalar
|
||||
*/
|
||||
void fromUInt(PVScalarPtr const & pv, uint32 from);
|
||||
/**
|
||||
* Convert a PV from a ulong
|
||||
* @param pv a PV
|
||||
* @param from value to put into PV
|
||||
* @throws std::invalid_argument if the Type is not a numeric scalar
|
||||
*/
|
||||
void fromULong(PVScalarPtr const & pv, uint64 from);
|
||||
/**
|
||||
* Convert a PV from a float
|
||||
* @param pv a PV
|
||||
* @param from value to put into PV
|
||||
* @throws std::invalid_argument if the Type is not a numeric scalar
|
||||
*/
|
||||
void fromFloat(PVScalarPtr const & pv, float from);
|
||||
/**
|
||||
* Convert a PV from a double
|
||||
* @param pv a PV
|
||||
* @param from value to put into PV
|
||||
* @throws std::invalid_argument if the Type is not a numeric scalar
|
||||
*/
|
||||
void fromDouble(PVScalarPtr const & pv, double from);
|
||||
/**
|
||||
* Convert a PV array to a byte array.
|
||||
* @param pv a PV
|
||||
* @param offset starting element in a PV
|
||||
* @param length number of elements to transfer
|
||||
* @param to where to put the PV data
|
||||
* @param toOffset starting element in the array
|
||||
* @return number of elements converted
|
||||
* @throws std::invalid_argument if the element type is not numeric
|
||||
*/
|
||||
std::size_t toByteArray(PVScalarArrayPtr const & pv,
|
||||
std::size_t offset,
|
||||
std::size_t length,
|
||||
int8* to,
|
||||
std::size_t toOffset);
|
||||
/**
|
||||
* Convert a PV array to a short array.
|
||||
* @param pv a PV
|
||||
* @param offset starting element in a PV
|
||||
* @param length number of elements to transfer
|
||||
* @param to where to put the PV data
|
||||
* @param toOffset starting element in the array
|
||||
* @return number of elements converted
|
||||
* @throws std::invalid_argument if the element type is not numeric
|
||||
*/
|
||||
std::size_t toShortArray(PVScalarArrayPtr const & pv,
|
||||
std::size_t offset,
|
||||
std::size_t length,
|
||||
int16* to,
|
||||
std::size_t toOffset);
|
||||
/**
|
||||
* Convert a PV array to an int array.
|
||||
* @param pv a PV
|
||||
* @param offset starting element in a PV
|
||||
* @param length number of elements to transfer
|
||||
* @param to where to put the PV data
|
||||
* @param toOffset starting element in the array
|
||||
* @return number of elements converted
|
||||
* @throws std::invalid_argument if the element type is not numeric
|
||||
*/
|
||||
std::size_t toIntArray(PVScalarArrayPtr const & pv,
|
||||
std::size_t offset,
|
||||
std::size_t length,
|
||||
int32* to,
|
||||
std::size_t toOffset);
|
||||
/**
|
||||
* Convert a PV array to a long array.
|
||||
* @param pv a PV
|
||||
* @param offset starting element in a PV
|
||||
* @param length number of elements to transfer
|
||||
* @param to where to put the PV data
|
||||
* @param toOffset starting element in the array
|
||||
* @return number of elements converted
|
||||
* @throws std::invalid_argument if the element type is not numeric
|
||||
*/
|
||||
std::size_t toLongArray(PVScalarArrayPtr const & pv,
|
||||
std::size_t offset,
|
||||
std::size_t length,
|
||||
int64* to,
|
||||
std::size_t toOffset);
|
||||
/**
|
||||
* Convert a PV array to a ubyte array.
|
||||
* @param pv a PV
|
||||
* @param offset starting element in a PV
|
||||
* @param length number of elements to transfer
|
||||
* @param to where to put the PV data
|
||||
* @param toOffset starting element in the array
|
||||
* @return number of elements converted
|
||||
* @throws std::invalid_argument if the element type is not numeric
|
||||
*/
|
||||
std::size_t toUByteArray(PVScalarArrayPtr const & pv,
|
||||
std::size_t offset,
|
||||
std::size_t length,
|
||||
uint8* to,
|
||||
std::size_t toOffset);
|
||||
/**
|
||||
* Convert a PV array to a ushort array.
|
||||
* @param pv a PV
|
||||
* @param offset starting element in a PV
|
||||
* @param length number of elements to transfer
|
||||
* @param to where to put the PV data
|
||||
* @param toOffset starting element in the array
|
||||
* @return number of elements converted
|
||||
* @throws std::invalid_argument if the element type is not numeric
|
||||
*/
|
||||
std::size_t toUShortArray(PVScalarArrayPtr const & pv,
|
||||
std::size_t offset,
|
||||
std::size_t length,
|
||||
uint16* to,
|
||||
std::size_t toOffset);
|
||||
/**
|
||||
* Convert a PV array to an uint array.
|
||||
* @param pv a PV
|
||||
* @param offset starting element in a PV
|
||||
* @param length number of elements to transfer
|
||||
* @param to where to put the PV data
|
||||
* @param toOffset starting element in the array
|
||||
* @return number of elements converted
|
||||
* @throws std::invalid_argument if the element type is not numeric
|
||||
*/
|
||||
std::size_t toUIntArray(
|
||||
PVScalarArrayPtr const & pv,
|
||||
std::size_t offset,
|
||||
std::size_t length,
|
||||
uint32* to,
|
||||
std::size_t toOffset);
|
||||
/**
|
||||
* Convert a PV array to a ulong array.
|
||||
* @param pv a PV
|
||||
* @param offset starting element in a PV
|
||||
* @param length number of elements to transfer
|
||||
* @param to where to put the PV data
|
||||
* @param toOffset starting element in the array
|
||||
* @return number of elements converted
|
||||
* @throws std::invalid_argument if the element type is not numeric
|
||||
*/
|
||||
std::size_t toULongArray(
|
||||
PVScalarArrayPtr const & pv,
|
||||
std::size_t offset,
|
||||
std::size_t length,
|
||||
uint64* to,
|
||||
std::size_t toOffset);
|
||||
/**
|
||||
* Convert a PV array to a float array.
|
||||
* @param pv a PV
|
||||
* @param offset starting element in a PV
|
||||
* @param length number of elements to transfer
|
||||
* @param to where to put the PV data
|
||||
* @param toOffset starting element in the array
|
||||
* @return number of elements converted
|
||||
* @throws std::invalid_argument if the element type is not numeric
|
||||
*/
|
||||
std::size_t toFloatArray(
|
||||
PVScalarArrayPtr const & pv,
|
||||
std::size_t offset,
|
||||
std::size_t length,
|
||||
float* to,
|
||||
std::size_t toOffset);
|
||||
/**
|
||||
* Convert a PV array to a double array.
|
||||
* @param pv a PV
|
||||
* @param offset starting element in a PV
|
||||
* @param length number of elements to transfer
|
||||
* @param to where to put the PV data
|
||||
* @param toOffset starting element in the array
|
||||
* @return number of elements converted
|
||||
* @throws std::invalid_argument if the element type is not numeric
|
||||
*/
|
||||
std::size_t toDoubleArray(
|
||||
PVScalarArrayPtr const & pv,
|
||||
std::size_t offset,
|
||||
std::size_t length,
|
||||
double* to, std::size_t
|
||||
toOffset);
|
||||
/**
|
||||
* Convert a PV array from a byte array.
|
||||
* @param pv a PV
|
||||
* @param offset starting element in a PV
|
||||
* @param length number of elements to transfer
|
||||
* @param from value to put into PV
|
||||
* @param fromOffset
|
||||
* @return number of elements converted
|
||||
* @throws std::invalid_argument if the element type is not numeric
|
||||
*/
|
||||
std::size_t fromByteArray(
|
||||
PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
|
||||
const int8* from, std::size_t fromOffset);
|
||||
std::size_t fromByteArray(
|
||||
PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
|
||||
const ByteArray & from, std::size_t fromOffset);
|
||||
/**
|
||||
* Convert a PV array from a short array.
|
||||
* @param pv a PV
|
||||
* @param offset starting element in a PV
|
||||
* @param length number of elements to transfer
|
||||
* @param from value to put into PV
|
||||
* @param fromOffset starting element in the source array
|
||||
* @return number of elements converted
|
||||
* @throws std::invalid_argument if the element type is not numeric
|
||||
*/
|
||||
std::size_t fromShortArray(
|
||||
PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
|
||||
const int16* from, std::size_t fromOffset);
|
||||
std::size_t fromShortArray(
|
||||
PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
|
||||
const ShortArray & from, std::size_t fromOffset);
|
||||
/**
|
||||
* Convert a PV array from an int array.
|
||||
* @param pv a PV
|
||||
* @param offset starting element in a PV
|
||||
* @param length number of elements to transfer
|
||||
* @param from value to put into PV
|
||||
* @param fromOffset starting element in the source array
|
||||
* @return number of elements converted
|
||||
* @throws std::invalid_argument if the element type is not numeric
|
||||
*/
|
||||
std::size_t fromIntArray(
|
||||
PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
|
||||
const int32* from, std::size_t fromOffset);
|
||||
std::size_t fromIntArray(
|
||||
PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
|
||||
const IntArray & from, std::size_t fromOffset);
|
||||
/**
|
||||
* Convert a PV array from a long array.
|
||||
* @param pv a PV
|
||||
* @param offset starting element in a PV
|
||||
* @param length number of elements to transfer
|
||||
* @param from value to put into PV
|
||||
* @param fromOffset starting element in the source array
|
||||
* @return number of elements converted
|
||||
* @throws std::invalid_argument if the element type is not numeric
|
||||
*/
|
||||
std::size_t fromLongArray(
|
||||
PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
|
||||
const int64* from, std::size_t fromOffset);
|
||||
std::size_t fromLongArray(
|
||||
PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
|
||||
const LongArray & from, std::size_t fromOffset);
|
||||
/**
|
||||
* Convert a PV array from a ubyte array.
|
||||
* @param pv a PV
|
||||
* @param offset starting element in a PV
|
||||
* @param length number of elements to transfer
|
||||
* @param from value to put into PV
|
||||
* @param fromOffset
|
||||
* @return number of elements converted
|
||||
* @throws std::invalid_argument if the element type is not numeric
|
||||
*/
|
||||
std::size_t fromUByteArray(
|
||||
PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
|
||||
const uint8* from, std::size_t fromOffset);
|
||||
std::size_t fromUByteArray(
|
||||
PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
|
||||
const UByteArray & from, std::size_t fromOffset);
|
||||
/**
|
||||
* Convert a PV array from a ushort array.
|
||||
* @param pv a PV
|
||||
* @param offset starting element in a PV
|
||||
* @param length number of elements to transfer
|
||||
* @param from value to put into PV
|
||||
* @param fromOffset starting element in the source array
|
||||
* @return number of elements converted
|
||||
* @throws std::invalid_argument if the element type is not numeric
|
||||
*/
|
||||
std::size_t fromUShortArray(
|
||||
PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
|
||||
const uint16* from, std::size_t fromOffset);
|
||||
std::size_t fromUShortArray(
|
||||
PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
|
||||
const UShortArray & from, std::size_t fromOffset);
|
||||
/**
|
||||
* Convert a PV array from an uint array.
|
||||
* @param pv a PV
|
||||
* @param offset starting element in a PV
|
||||
* @param length number of elements to transfer
|
||||
* @param from value to put into PV
|
||||
* @param fromOffset starting element in the source array
|
||||
* @return number of elements converted
|
||||
* @throws std::invalid_argument if the element type is not numeric
|
||||
*/
|
||||
std::size_t fromUIntArray(
|
||||
PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
|
||||
const uint32* from, std::size_t fromOffset);
|
||||
std::size_t fromUIntArray(
|
||||
PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
|
||||
const UIntArray & from, std::size_t fromOffset);
|
||||
/**
|
||||
* Convert a PV array from a ulong array.
|
||||
* @param pv a PV
|
||||
* @param offset starting element in a PV
|
||||
* @param length number of elements to transfer
|
||||
* @param from value to put into PV
|
||||
* @param fromOffset starting element in the source array
|
||||
* @return number of elements converted
|
||||
* @throws std::invalid_argument if the element type is not numeric
|
||||
*/
|
||||
std::size_t fromULongArray(
|
||||
PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
|
||||
const uint64* from, std::size_t fromOffset);
|
||||
std::size_t fromULongArray(
|
||||
PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
|
||||
const ULongArray & from, std::size_t fromOffset);
|
||||
/**
|
||||
* Convert a PV array from a float array.
|
||||
* @param pv a PV
|
||||
* @param offset starting element in a PV
|
||||
* @param length number of elements to transfer
|
||||
* @param from value to put into PV
|
||||
* @param fromOffset starting element in the source array
|
||||
* @return number of elements converted
|
||||
* @throws std::invalid_argument if the element type is not numeric
|
||||
*/
|
||||
std::size_t fromFloatArray(
|
||||
PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
|
||||
const float* from, std::size_t fromOffset);
|
||||
std::size_t fromFloatArray(
|
||||
PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
|
||||
const FloatArray & from, std::size_t fromOffset);
|
||||
/**
|
||||
* Convert a PV array from a double array.
|
||||
* @param pv a PV
|
||||
* @param offset starting element in a PV
|
||||
* @param length number of elements to transfer
|
||||
* @param from value to put into PV
|
||||
* @param fromOffset starting element in the source array
|
||||
* @return number of elements converted
|
||||
* @throws std::invalid_argument if the element type is not numeric
|
||||
*/
|
||||
std::size_t fromDoubleArray(
|
||||
PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
|
||||
const double* from, std::size_t fromOffset);
|
||||
std::size_t fromDoubleArray(
|
||||
PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
|
||||
const DoubleArray & from, std::size_t fromOffset);
|
||||
/**
|
||||
* Convenience method for implementing toString.
|
||||
* It generates a newline and inserts blanks at the beginning of the newline.
|
||||
* @param builder The StringBuilder being constructed.
|
||||
* @param indentLevel Indent level, Each level is four spaces.
|
||||
*/
|
||||
void newLine(StringBuilder buf, int indentLevel);
|
||||
private:
|
||||
Convert();
|
||||
PVDataCreatePtr pvDataCreate;
|
||||
String trueString;
|
||||
String falseString;
|
||||
String illegalScalarType;
|
||||
};
|
||||
|
||||
extern ConvertPtr getConvert();
|
||||
|
||||
}}
|
||||
#endif /* CONVERT_H */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,559 +0,0 @@
|
||||
/* pvIntrospect.h */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mrk and Michael Davidsaver
|
||||
*/
|
||||
#ifndef PVINTROSPECT_H
|
||||
#define PVINTROSPECT_H
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <pv/noDefaultMethods.h>
|
||||
#include <pv/pvType.h>
|
||||
#include <pv/byteBuffer.h>
|
||||
#include <pv/serialize.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
class Field;
|
||||
class Scalar;
|
||||
class ScalarArray;
|
||||
class Structure;
|
||||
class StructureArray;
|
||||
|
||||
/**
|
||||
* typedef for a shared pointer to an immutable Field.
|
||||
*/
|
||||
typedef std::tr1::shared_ptr<const Field> FieldConstPtr;
|
||||
/**
|
||||
* typedef for an array of shared pointer to an immutable Field.
|
||||
*/
|
||||
typedef std::vector<FieldConstPtr> FieldConstPtrArray;
|
||||
/**
|
||||
* typedef for a shared pointer to an immutable Scalar.
|
||||
*/
|
||||
typedef std::tr1::shared_ptr<const Scalar> ScalarConstPtr;
|
||||
/**
|
||||
* typedef for a shared pointer to an immutable ScalarArray.
|
||||
*/
|
||||
typedef std::tr1::shared_ptr<const ScalarArray> ScalarArrayConstPtr;
|
||||
/**
|
||||
* typedef for a shared pointer to an immutable Structure.
|
||||
*/
|
||||
typedef std::tr1::shared_ptr<const Structure> StructureConstPtr;
|
||||
/**
|
||||
* typedef for a shared pointer to an immutable StructureArray.
|
||||
*/
|
||||
typedef std::tr1::shared_ptr<const StructureArray> StructureArrayConstPtr;
|
||||
|
||||
/**
|
||||
* Definition of support field types.
|
||||
*/
|
||||
enum Type {
|
||||
/**
|
||||
* The type is scalar. It has a scalarType
|
||||
*/
|
||||
scalar,
|
||||
/**
|
||||
* The type is scalarArray. Each element is a scalar of the same scalarType.
|
||||
*/
|
||||
scalarArray,
|
||||
/**
|
||||
* The type is structure.
|
||||
*/
|
||||
structure,
|
||||
/**
|
||||
* The type is structureArray. Each element is a structure.
|
||||
*/
|
||||
structureArray
|
||||
};
|
||||
|
||||
/**
|
||||
* Convenience functions for Type.
|
||||
*/
|
||||
namespace TypeFunc {
|
||||
/**
|
||||
* Get a name for the type.
|
||||
* @param type The type.
|
||||
* @return The name for the type.
|
||||
*/
|
||||
const char* name(Type type);
|
||||
/**
|
||||
* Convert the type to a string and add it to builder.
|
||||
* @param builder The string builder.
|
||||
* @param type The type.
|
||||
*/
|
||||
void toString(StringBuilder builder,const Type type);
|
||||
};
|
||||
|
||||
/**
|
||||
* Definition of support scalar types.
|
||||
*/
|
||||
enum ScalarType {
|
||||
/**
|
||||
* The type is boolean, i. e. value can be {@code false} or {@code true}
|
||||
*/
|
||||
pvBoolean,
|
||||
/**
|
||||
* The type is byte, i. e. a 8 bit signed integer.
|
||||
*/
|
||||
pvByte,
|
||||
/**
|
||||
* The type is short, i. e. a 16 bit signed integer.
|
||||
*/
|
||||
pvShort,
|
||||
/**
|
||||
* The type is int, i. e. a 32 bit signed integer.
|
||||
*/
|
||||
pvInt,
|
||||
/**
|
||||
* The type is long, i. e. a 64 bit signed integer.
|
||||
*/
|
||||
pvLong,
|
||||
/**
|
||||
* The type is unsigned byte, i. e. a 8 bit unsigned integer.
|
||||
*/
|
||||
pvUByte,
|
||||
/**
|
||||
* The type is unsigned short, i. e. a 16 bit unsigned integer.
|
||||
*/
|
||||
pvUShort,
|
||||
/**
|
||||
* The type is unsigned int, i. e. a 32 bit unsigned integer.
|
||||
*/
|
||||
pvUInt,
|
||||
/**
|
||||
* The type is unsigned long, i. e. a 64 bit unsigned integer.
|
||||
*/
|
||||
pvULong,
|
||||
/**
|
||||
* The type is float, i. e. 32 bit IEEE floating point,
|
||||
*/
|
||||
pvFloat,
|
||||
/**
|
||||
* The type is float, i. e. 64 bit IEEE floating point,
|
||||
*/
|
||||
pvDouble,
|
||||
/**
|
||||
* The type is string, i. e. a UTF8 character string.
|
||||
*/
|
||||
pvString
|
||||
};
|
||||
|
||||
/**
|
||||
* Convenience functions for ScalarType.
|
||||
*/
|
||||
namespace ScalarTypeFunc {
|
||||
/**
|
||||
* Is the type an integer, i. e. is it one of byte,...ulong
|
||||
* @param scalarType The type.
|
||||
* @return (false,true) if the scalarType is an integer.
|
||||
*/
|
||||
bool isInteger(ScalarType scalarType);
|
||||
/**
|
||||
* Is the type an unsigned integer, i. e. is it one of ubyte,...ulong
|
||||
* @param scalarType The type.
|
||||
* @return (false,true) if the scalarType is an integer.
|
||||
*/
|
||||
bool isUInteger(ScalarType scalarType);
|
||||
/**
|
||||
* Is the type numeric, i. e. is it one of byte,...,double
|
||||
* @param scalarType The type.
|
||||
* @return (false,true) if the scalarType is a numeric
|
||||
*/
|
||||
bool isNumeric(ScalarType scalarType);
|
||||
/**
|
||||
* Is the type primitive, i. e. not string
|
||||
* @param scalarType The type.
|
||||
* @return (false,true) if the scalarType is primitive.
|
||||
*/
|
||||
bool isPrimitive(ScalarType scalarType);
|
||||
/**
|
||||
* Get the scalarType for value.
|
||||
* @param value The name of the scalar type.
|
||||
* @return The scalarType.
|
||||
* An exception is thrown if the name is not the name of a scalar type.
|
||||
*/
|
||||
ScalarType getScalarType(String const &value);
|
||||
/**
|
||||
* Get a name for the scalarType.
|
||||
* @param scalarType The type.
|
||||
* @return The name for the scalarType.
|
||||
*/
|
||||
const char* name(ScalarType scalarType);
|
||||
/**
|
||||
* Convert the scalarType to a string and add it to builder.
|
||||
* @param builder The string builder.
|
||||
* @param scalarType The type.
|
||||
*/
|
||||
void toString(StringBuilder builder,ScalarType scalarType);
|
||||
};
|
||||
|
||||
/**
|
||||
* This class implements introspection object for field.
|
||||
*/
|
||||
class Field :
|
||||
virtual public Serializable,
|
||||
public std::tr1::enable_shared_from_this<Field> {
|
||||
public:
|
||||
POINTER_DEFINITIONS(Field);
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
virtual ~Field();
|
||||
/**
|
||||
* Get the field type.
|
||||
* @return The type.
|
||||
*/
|
||||
Type getType() const{return m_fieldType;}
|
||||
/**
|
||||
* Get the identification string.
|
||||
* @return The identification string, can be empty.
|
||||
*/
|
||||
virtual String getID() const = 0;
|
||||
/**
|
||||
* Convert the scalarType to a string and add it to builder.
|
||||
* @param builder The string builder.
|
||||
*/
|
||||
virtual void toString(StringBuilder builder) const{toString(builder,0);}
|
||||
/**
|
||||
* Convert the scalarType to a string and add it to builder.
|
||||
* @param builder The string builder.
|
||||
* @param indentLevel The number of blanks at the beginning of new lines.
|
||||
*/
|
||||
virtual void toString(StringBuilder builder,int indentLevel) const;
|
||||
protected:
|
||||
/**
|
||||
* Constructor
|
||||
* @param fieldName The field type.
|
||||
*/
|
||||
Field(Type type);
|
||||
private:
|
||||
Type m_fieldType;
|
||||
|
||||
friend class StructureArray;
|
||||
friend class Structure;
|
||||
friend class PVFieldPvt;
|
||||
friend class StandardField;
|
||||
friend class BasePVStructureArray;
|
||||
friend class FieldCreate;
|
||||
|
||||
struct Deleter{void operator()(Field *p){delete p;}};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* This class implements introspection object for Scalar.
|
||||
*/
|
||||
class Scalar : public Field{
|
||||
public:
|
||||
POINTER_DEFINITIONS(Scalar);
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
virtual ~Scalar();
|
||||
typedef Scalar& reference;
|
||||
typedef const Scalar& const_reference;
|
||||
/**
|
||||
* Get the scalarType
|
||||
* @return the scalarType
|
||||
*/
|
||||
ScalarType getScalarType() const {return scalarType;}
|
||||
/**
|
||||
* Convert the scalar to a string and add it to builder.
|
||||
* @param builder The string builder.
|
||||
*/
|
||||
virtual void toString(StringBuilder buf) const{toString(buf,0);}
|
||||
/**
|
||||
* Convert the scalar to a string and add it to builder.
|
||||
* @param builder The string builder.
|
||||
* @param indentLevel The number of blanks at the beginning of new lines.
|
||||
*/
|
||||
virtual void toString(StringBuilder buf,int indentLevel) const;
|
||||
|
||||
virtual String getID() const;
|
||||
|
||||
virtual void serialize(ByteBuffer *buffer, SerializableControl *control) const;
|
||||
virtual void deserialize(ByteBuffer *buffer, DeserializableControl *control);
|
||||
|
||||
protected:
|
||||
Scalar(ScalarType scalarType);
|
||||
private:
|
||||
int8 getTypeCodeLUT() const;
|
||||
ScalarType scalarType;
|
||||
friend class FieldCreate;
|
||||
};
|
||||
|
||||
/**
|
||||
* This class implements introspection object for field.
|
||||
*/
|
||||
class ScalarArray : public Field{
|
||||
public:
|
||||
POINTER_DEFINITIONS(ScalarArray);
|
||||
typedef ScalarArray& reference;
|
||||
typedef const ScalarArray& const_reference;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param scalarType The scalarType for the field.
|
||||
*/
|
||||
ScalarArray(ScalarType scalarType);
|
||||
/**
|
||||
* Get the scalarType for the elements.
|
||||
* @return the scalarType
|
||||
*/
|
||||
ScalarType getElementType() const {return elementType;}
|
||||
/**
|
||||
* Convert the scalarType to a string and add it to builder.
|
||||
* @param builder The string builder.
|
||||
*/
|
||||
virtual void toString(StringBuilder buf) const{toString(buf,0);}
|
||||
/**
|
||||
* Convert the scalarType to a string and add it to builder.
|
||||
* @param builder The string builder.
|
||||
* @param indentLevel The number of blanks at the beginning of new lines.
|
||||
*/
|
||||
virtual void toString(StringBuilder buf,int indentLevel) const;
|
||||
|
||||
virtual String getID() const;
|
||||
|
||||
virtual void serialize(ByteBuffer *buffer, SerializableControl *control) const;
|
||||
virtual void deserialize(ByteBuffer *buffer, DeserializableControl *control);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
virtual ~ScalarArray();
|
||||
private:
|
||||
int8 getTypeCodeLUT() const;
|
||||
const String getIDScalarArrayLUT() const;
|
||||
ScalarType elementType;
|
||||
friend class FieldCreate;
|
||||
};
|
||||
|
||||
/**
|
||||
* This class implements introspection object for a structureArray
|
||||
*/
|
||||
class StructureArray : public Field{
|
||||
public:
|
||||
POINTER_DEFINITIONS(StructureArray);
|
||||
typedef StructureArray& reference;
|
||||
typedef const StructureArray& const_reference;
|
||||
|
||||
/**
|
||||
* Get the introspection interface for the array elements.
|
||||
* @return The introspection interface.
|
||||
*/
|
||||
StructureConstPtr getStructure() const {return pstructure;}
|
||||
|
||||
/**
|
||||
* Convert the scalarType to a string and add it to builder.
|
||||
* @param builder The string builder.
|
||||
* @param indentLevel The number of blanks at the beginning of new lines.
|
||||
*/
|
||||
virtual void toString(StringBuilder buf,int indentLevel=0) const;
|
||||
|
||||
virtual String getID() const;
|
||||
|
||||
virtual void serialize(ByteBuffer *buffer, SerializableControl *control) const;
|
||||
virtual void deserialize(ByteBuffer *buffer, DeserializableControl *control);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Constructor.
|
||||
* @param structure The introspection interface for the elements.
|
||||
*/
|
||||
StructureArray(StructureConstPtr const & structure);
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
virtual ~StructureArray();
|
||||
private:
|
||||
StructureConstPtr pstructure;
|
||||
friend class FieldCreate;
|
||||
};
|
||||
|
||||
/**
|
||||
* This class implements introspection object for a structure.
|
||||
*/
|
||||
class Structure : public Field {
|
||||
public:
|
||||
POINTER_DEFINITIONS(Structure);
|
||||
|
||||
/**
|
||||
* Default structure ID.
|
||||
*/
|
||||
static epics::pvData::String DEFAULT_ID;
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
virtual ~Structure();
|
||||
typedef Structure& reference;
|
||||
typedef const Structure& const_reference;
|
||||
|
||||
/**
|
||||
* Get the number of immediate subfields in the structure/
|
||||
* @return The number of fields.
|
||||
*/
|
||||
std::size_t getNumberFields() const {return fieldNames.size();}
|
||||
/**
|
||||
* Get the field for the specified fieldName.
|
||||
* @param fieldName The name of the field to get;
|
||||
* @return The introspection interface.
|
||||
* This will hold a null pointer if the field is not in the structure.
|
||||
*/
|
||||
FieldConstPtr getField(String const &fieldName) const;
|
||||
/**
|
||||
* Get the field for the specified fieldName.
|
||||
* @param fieldName The index of the field to get;
|
||||
* @return The introspection interface.
|
||||
* This will hold a null pointer if the field is not in the structure.
|
||||
*/
|
||||
FieldConstPtr getField(std::size_t index) const {return fields[index];}
|
||||
/**
|
||||
* Get the field index for the specified fieldName.
|
||||
* @return The introspection interface.
|
||||
* This will be -1 if the field is not in the structure.
|
||||
*/
|
||||
std::size_t getFieldIndex(String const &fieldName) const;
|
||||
/**
|
||||
* Get the fields in the structure.
|
||||
* @return The array of fields.
|
||||
*/
|
||||
FieldConstPtrArray const & getFields() const {return fields;}
|
||||
/**
|
||||
* Get the names of the fields in the structure.
|
||||
* @return The array of fieldNames.
|
||||
*/
|
||||
StringArray const & getFieldNames() const {return fieldNames;}
|
||||
void renameField(std::size_t fieldIndex,String const & newName)
|
||||
{fieldNames[fieldIndex] = newName;}
|
||||
/**
|
||||
* Get the name of the field with the specified index;
|
||||
* @param fieldIndex The index of the desired field.
|
||||
* @return The fieldName.
|
||||
*/
|
||||
String getFieldName(std::size_t fieldIndex){return fieldNames[fieldIndex];}
|
||||
/**
|
||||
* Convert the structure to a string and add it to builder.
|
||||
* @param builder The string builder.
|
||||
*/
|
||||
virtual void toString(StringBuilder buf) const{toString(buf,0);}
|
||||
/**
|
||||
* Convert the structure to a string and add it to builder.
|
||||
* @param builder The string builder.
|
||||
* @param indentLevel The number of blanks at the beginning of new lines.
|
||||
*/
|
||||
virtual void toString(StringBuilder buf,int indentLevel) const;
|
||||
|
||||
virtual String getID() const;
|
||||
|
||||
virtual void serialize(ByteBuffer *buffer, SerializableControl *control) const;
|
||||
virtual void deserialize(ByteBuffer *buffer, DeserializableControl *control);
|
||||
|
||||
protected:
|
||||
Structure(StringArray const & fieldNames, FieldConstPtrArray const & fields, String const & id = DEFAULT_ID);
|
||||
private:
|
||||
void toStringCommon(StringBuilder buf,int indentLevel) const;
|
||||
StringArray fieldNames;
|
||||
FieldConstPtrArray fields;
|
||||
String id;
|
||||
friend class FieldCreate;
|
||||
};
|
||||
|
||||
/**
|
||||
* This is a singlton class for creating introspection interfaces.
|
||||
*/
|
||||
class FieldCreate;
|
||||
typedef std::tr1::shared_ptr<FieldCreate> FieldCreatePtr;
|
||||
|
||||
class FieldCreate {
|
||||
public:
|
||||
static FieldCreatePtr getFieldCreate();
|
||||
/**
|
||||
* Create a {@code ScalarField}.
|
||||
* @param scalarType The scalar type.
|
||||
* @return a {@code Scalar} interface for the newly created object.
|
||||
* @throws An {@code IllegalArgumentException} if an illegal type is specified.
|
||||
*/
|
||||
ScalarConstPtr createScalar(ScalarType scalarType) const;
|
||||
/**
|
||||
* Create an {@code Array} field.
|
||||
* @param elementType The {@code scalarType} for array elements
|
||||
* @return An {@code Array} Interface for the newly created object.
|
||||
*/
|
||||
ScalarArrayConstPtr createScalarArray(ScalarType elementType) const;
|
||||
/**
|
||||
* Create an {@code Array} field that is has element type <i>Structure</i>
|
||||
* @param fieldName The field name
|
||||
* @param elementStructure The {@code Structure} for each array element.
|
||||
* @return An {@code Array} Interface for the newly created object.
|
||||
*/
|
||||
StructureArrayConstPtr createStructureArray(StructureConstPtr const & structure) const;
|
||||
/**
|
||||
* Create a {@code Structure} field.
|
||||
* @param fieldNames The array of {@code fieldNames} for the structure.
|
||||
* @param fields The array of {@code fields} for the structure.
|
||||
* @return a {@code Structure} interface for the newly created object.
|
||||
*/
|
||||
StructureConstPtr createStructure (
|
||||
StringArray const & fieldNames,
|
||||
FieldConstPtrArray const & fields) const;
|
||||
/**
|
||||
* Create a {@code Structure} field with identification string.
|
||||
* @param id The identification string for the structure.
|
||||
* @param fieldNames The array of {@code fieldNames} for the structure.
|
||||
* @param fields The array of {@code fields} for the structure.
|
||||
* @return a {@code Structure} interface for the newly created object.
|
||||
*/
|
||||
StructureConstPtr createStructure (
|
||||
String const & id,
|
||||
StringArray const & fieldNames,
|
||||
FieldConstPtrArray const & fields) const;
|
||||
/**
|
||||
* Append a field to a structure.
|
||||
* @param structure The structure to which the field is appended.
|
||||
* @param fieldName The name of the field.
|
||||
* @param field The field.
|
||||
* @return a {@code Structure} interface for the newly created object.
|
||||
*/
|
||||
StructureConstPtr appendField(
|
||||
StructureConstPtr const & structure,
|
||||
String const & fieldName, FieldConstPtr const & field) const;
|
||||
/**
|
||||
* Append fields to a structure.
|
||||
* @param structure The structure to which the fields appended.
|
||||
* @param fieldName The names of the fields.
|
||||
* @param field The fields.
|
||||
* @return a {@code Structure} interface for the newly created object.
|
||||
*/
|
||||
StructureConstPtr appendFields(
|
||||
StructureConstPtr const & structure,
|
||||
StringArray const & fieldNames,
|
||||
FieldConstPtrArray const & fields) const;
|
||||
/**
|
||||
* Deserialize {@code Field} instance from given byte buffer.
|
||||
* @param buffer Buffer containing serialized {@code Field} instance.
|
||||
* @param control Deserialization control instance.
|
||||
* @return a deserialized {@code Field} instance.
|
||||
*/
|
||||
FieldConstPtr deserialize(ByteBuffer* buffer, DeserializableControl* control) const;
|
||||
|
||||
private:
|
||||
FieldCreate();
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the single class that implemnents FieldCreate,
|
||||
* @param The fieldCreate factory.
|
||||
*/
|
||||
extern FieldCreatePtr getFieldCreate();
|
||||
|
||||
}}
|
||||
#endif /* PVINTROSPECT_H */
|
||||
@@ -1,452 +0,0 @@
|
||||
/* pvType.h */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
*/
|
||||
|
||||
/* Definitions for the primitive types for pvData.
|
||||
* It also defines the arrays of the primitive types
|
||||
*/
|
||||
|
||||
#ifndef PVTYPE_H
|
||||
#define PVTYPE_H
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#ifdef __vxworks
|
||||
typedef int intptr_t;
|
||||
typedef unsigned int uintptr_t;
|
||||
#define INT64_MAX (0x7fffffffffffffffLL)
|
||||
#define UINT64_MAX (0xffffffffffffffffLL)
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#include <pv/sharedPtr.h>
|
||||
#include <pv/localStaticLock.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
/**
|
||||
* This is a set of typdefs used by pvData.
|
||||
*/
|
||||
|
||||
/**
|
||||
* boolean, i.e. can only have the values {@code false} or {@code true}
|
||||
*/
|
||||
typedef uint8_t boolean;
|
||||
/**
|
||||
* A 8 bit signed integer
|
||||
*/
|
||||
typedef int8_t int8;
|
||||
/**
|
||||
* A 16 bit signed integer
|
||||
*/
|
||||
typedef int16_t int16;
|
||||
/**
|
||||
* A 32 bit signed integer
|
||||
*/
|
||||
typedef int32_t int32;
|
||||
/**
|
||||
* A 64 bit signed integer
|
||||
*/
|
||||
typedef int64_t int64;
|
||||
/**
|
||||
* A 8 bit unsigned integer
|
||||
*/
|
||||
typedef uint8_t uint8;
|
||||
/**
|
||||
* A 16 bit unsigned integer
|
||||
*/
|
||||
typedef uint16_t uint16;
|
||||
/**
|
||||
* A 32 bit unsigned integer
|
||||
*/
|
||||
typedef uint32_t uint32;
|
||||
/**
|
||||
* A 64 bit unsigned integer
|
||||
*/
|
||||
typedef uint64_t uint64;
|
||||
|
||||
// float and double are types
|
||||
|
||||
/**
|
||||
* A string
|
||||
*/
|
||||
typedef std::string String;
|
||||
|
||||
/**
|
||||
* A boolean array.
|
||||
*/
|
||||
typedef std::vector<uint8> BooleanArray;
|
||||
typedef std::tr1::shared_ptr<BooleanArray> BooleanArrayPtr;
|
||||
/* get is same is ubyte*/
|
||||
typedef std::vector<uint8>::iterator BooleanArray_iterator;
|
||||
typedef std::vector<uint8>::const_iterator BooleanArray_const_iterator;
|
||||
|
||||
/**
|
||||
* A byte array.
|
||||
*/
|
||||
typedef std::vector<int8> ByteArray;
|
||||
typedef std::tr1::shared_ptr<ByteArray> ByteArrayPtr;
|
||||
inline int8 * get(ByteArray &value)
|
||||
{
|
||||
return &value[0];
|
||||
}
|
||||
inline int8 const * get(ByteArray const &value)
|
||||
{
|
||||
return static_cast<int8 const *>(&value[0]);
|
||||
}
|
||||
inline int8 * get(ByteArrayPtr &value)
|
||||
{
|
||||
return get(*value.get());
|
||||
}
|
||||
inline int8 const * get(ByteArrayPtr const &value)
|
||||
{
|
||||
return get(*value.get());
|
||||
}
|
||||
inline ByteArray & getVector(ByteArrayPtr &value)
|
||||
{
|
||||
return *value.get();
|
||||
}
|
||||
inline ByteArray const & getVector(ByteArrayPtr const &value)
|
||||
{
|
||||
return *value.get();
|
||||
}
|
||||
typedef std::vector<int8>::iterator ByteArray_iterator;
|
||||
typedef std::vector<int8>::const_iterator ByteArray_const_iterator;
|
||||
|
||||
/**
|
||||
* A short array.
|
||||
*/
|
||||
typedef std::vector<int16> ShortArray;
|
||||
typedef std::tr1::shared_ptr<ShortArray> ShortArrayPtr;
|
||||
inline int16 * get(ShortArray &value)
|
||||
{
|
||||
return &value[0];
|
||||
}
|
||||
inline int16 const * get(ShortArray const &value)
|
||||
{
|
||||
return static_cast<int16 const *>(&value[0]);
|
||||
}
|
||||
inline int16 * get(ShortArrayPtr &value)
|
||||
{
|
||||
return get(*value.get());
|
||||
}
|
||||
inline int16 const * get(ShortArrayPtr const &value)
|
||||
{
|
||||
return get(*value.get());
|
||||
}
|
||||
inline ShortArray & getVector(ShortArrayPtr &value)
|
||||
{
|
||||
return *value.get();
|
||||
}
|
||||
inline ShortArray const & getVector(ShortArrayPtr const &value)
|
||||
{
|
||||
return *value.get();
|
||||
}
|
||||
typedef std::vector<int16>::iterator ShortArray_iterator;
|
||||
typedef std::vector<int16>::const_iterator ShortArray_const_iterator;
|
||||
|
||||
/**
|
||||
* A int array.
|
||||
*/
|
||||
typedef std::vector<int32> IntArray;
|
||||
typedef std::tr1::shared_ptr<IntArray> IntArrayPtr;
|
||||
inline int32 * get(IntArray &value)
|
||||
{
|
||||
return &value[0];
|
||||
}
|
||||
inline int32 const * get(IntArray const &value)
|
||||
{
|
||||
return static_cast<int32 const *>(&value[0]);
|
||||
}
|
||||
inline int32 * get(IntArrayPtr &value)
|
||||
{
|
||||
return get(*value.get());
|
||||
}
|
||||
inline int32 const * get(IntArrayPtr const &value)
|
||||
{
|
||||
return get(*value.get());
|
||||
}
|
||||
inline IntArray & getVector(IntArrayPtr &value)
|
||||
{
|
||||
return *value.get();
|
||||
}
|
||||
inline IntArray const & getVector(IntArrayPtr const &value)
|
||||
{
|
||||
return *value.get();
|
||||
}
|
||||
typedef std::vector<int32>::iterator IntArray_iterator;
|
||||
typedef std::vector<int32>::const_iterator IntArray_const_iterator;
|
||||
|
||||
/**
|
||||
* A long array.
|
||||
*/
|
||||
typedef std::vector<int64> LongArray;
|
||||
typedef std::tr1::shared_ptr<LongArray> LongArrayPtr;
|
||||
inline int64 * get(LongArray &value)
|
||||
{
|
||||
return &value[0];
|
||||
}
|
||||
inline int64 const * get(LongArray const &value)
|
||||
{
|
||||
return static_cast<int64 const *>(&value[0]);
|
||||
}
|
||||
inline int64 * get(LongArrayPtr &value)
|
||||
{
|
||||
return get(*value.get());
|
||||
}
|
||||
inline int64 const * get(LongArrayPtr const &value)
|
||||
{
|
||||
return get(*value.get());
|
||||
}
|
||||
inline LongArray & getVector(LongArrayPtr &value)
|
||||
{
|
||||
return *value.get();
|
||||
}
|
||||
inline LongArray const & getVector(LongArrayPtr const &value)
|
||||
{
|
||||
return *value.get();
|
||||
}
|
||||
typedef std::vector<int64>::iterator LongArray_iterator;
|
||||
typedef std::vector<int64>::const_iterator LongArray_const_iterator;
|
||||
|
||||
/**
|
||||
* An unsigned byte array.
|
||||
*/
|
||||
typedef std::vector<uint8> UByteArray;
|
||||
typedef std::tr1::shared_ptr<UByteArray> UByteArrayPtr;
|
||||
inline uint8 * get(UByteArray &value)
|
||||
{
|
||||
return &value[0];
|
||||
}
|
||||
inline uint8 const * get(UByteArray const &value)
|
||||
{
|
||||
return static_cast<uint8 const *>(&value[0]);
|
||||
}
|
||||
inline uint8 * get(UByteArrayPtr &value)
|
||||
{
|
||||
return get(*value.get());
|
||||
}
|
||||
inline uint8 const * get(UByteArrayPtr const &value)
|
||||
{
|
||||
return get(*value.get());
|
||||
}
|
||||
inline UByteArray & getVector(UByteArrayPtr &value)
|
||||
{
|
||||
return *value.get();
|
||||
}
|
||||
inline UByteArray const & getVector(UByteArrayPtr const &value)
|
||||
{
|
||||
return *value.get();
|
||||
}
|
||||
typedef std::vector<uint8>::iterator UByteArray_iterator;
|
||||
typedef std::vector<uint8>::const_iterator UByteArray_const_iterator;
|
||||
|
||||
/**
|
||||
* An unsigned short array.
|
||||
*/
|
||||
typedef std::vector<uint16> UShortArray;
|
||||
typedef std::tr1::shared_ptr<UShortArray> UShortArrayPtr;
|
||||
inline uint16 * get(UShortArray &value)
|
||||
{
|
||||
return &value[0];
|
||||
}
|
||||
inline uint16 const * get(UShortArray const &value)
|
||||
{
|
||||
return static_cast<uint16 const *>(&value[0]);
|
||||
}
|
||||
inline uint16 * get(UShortArrayPtr &value)
|
||||
{
|
||||
return get(*value.get());
|
||||
}
|
||||
inline uint16 const * get(UShortArrayPtr const &value)
|
||||
{
|
||||
return get(*value.get());
|
||||
}
|
||||
inline UShortArray & getVector(UShortArrayPtr &value)
|
||||
{
|
||||
return *value.get();
|
||||
}
|
||||
inline UShortArray const & getVector(UShortArrayPtr const &value)
|
||||
{
|
||||
return *value.get();
|
||||
}
|
||||
typedef std::vector<uint16>::iterator UShortArray_iterator;
|
||||
typedef std::vector<uint16>::const_iterator UShortArray_const_iterator;
|
||||
|
||||
/**
|
||||
* An unsigned int array.
|
||||
*/
|
||||
typedef std::vector<uint32> UIntArray;
|
||||
typedef std::tr1::shared_ptr<UIntArray> UIntArrayPtr;
|
||||
inline uint32 * get(UIntArray &value)
|
||||
{
|
||||
return &value[0];
|
||||
}
|
||||
inline uint32 const * get(UIntArray const &value)
|
||||
{
|
||||
return static_cast<uint32 const *>(&value[0]);
|
||||
}
|
||||
inline uint32 * get(UIntArrayPtr &value)
|
||||
{
|
||||
return get(*value.get());
|
||||
}
|
||||
inline uint32 const * get(UIntArrayPtr const &value)
|
||||
{
|
||||
return get(*value.get());
|
||||
}
|
||||
inline UIntArray & getVector(UIntArrayPtr &value)
|
||||
{
|
||||
return *value.get();
|
||||
}
|
||||
inline UIntArray const & getVector(UIntArrayPtr const &value)
|
||||
{
|
||||
return *value.get();
|
||||
}
|
||||
typedef std::vector<uint32>::iterator UIntArray_iterator;
|
||||
typedef std::vector<uint32>::const_iterator UIntArray_const_iterator;
|
||||
|
||||
/**
|
||||
* An unsigned long array.
|
||||
*/
|
||||
typedef std::vector<uint64> ULongArray;
|
||||
typedef std::tr1::shared_ptr<ULongArray> ULongArrayPtr;
|
||||
inline uint64 * get(ULongArray &value)
|
||||
{
|
||||
return &value[0];
|
||||
}
|
||||
inline uint64 const * get(ULongArray const &value)
|
||||
{
|
||||
return static_cast<uint64 const *>(&value[0]);
|
||||
}
|
||||
inline uint64 * get(ULongArrayPtr &value)
|
||||
{
|
||||
return get(*value.get());
|
||||
}
|
||||
inline uint64 const * get(ULongArrayPtr const &value)
|
||||
{
|
||||
return get(*value.get());
|
||||
}
|
||||
inline ULongArray & getVector(ULongArrayPtr &value)
|
||||
{
|
||||
return *value.get();
|
||||
}
|
||||
inline ULongArray const & getVector(ULongArrayPtr const &value)
|
||||
{
|
||||
return *value.get();
|
||||
}
|
||||
typedef std::vector<uint64>::iterator ULongArray_iterator;
|
||||
typedef std::vector<uint64>::const_iterator ULongArray_const_iterator;
|
||||
|
||||
/**
|
||||
* A float array.
|
||||
*/
|
||||
typedef std::vector<float> FloatArray;
|
||||
typedef std::tr1::shared_ptr<FloatArray> FloatArrayPtr;
|
||||
inline float * get(FloatArray &value)
|
||||
{
|
||||
return &value[0];
|
||||
}
|
||||
inline float const * get(FloatArray const &value)
|
||||
{
|
||||
return static_cast<float const *>(&value[0]);
|
||||
}
|
||||
inline float * get(FloatArrayPtr &value)
|
||||
{
|
||||
return get(*value.get());
|
||||
}
|
||||
inline float const * get(FloatArrayPtr const &value)
|
||||
{
|
||||
return get(*value.get());
|
||||
}
|
||||
inline FloatArray & getVector(FloatArrayPtr &value)
|
||||
{
|
||||
return *value.get();
|
||||
}
|
||||
inline FloatArray const & getVector(FloatArrayPtr const &value)
|
||||
{
|
||||
return *value.get();
|
||||
}
|
||||
typedef std::vector<float>::iterator FloatArray_iterator;
|
||||
typedef std::vector<float>::const_iterator FloatArray_const_iterator;
|
||||
|
||||
/**
|
||||
* A double array.
|
||||
*/
|
||||
typedef std::vector<double> DoubleArray;
|
||||
typedef std::tr1::shared_ptr<DoubleArray> DoubleArrayPtr;
|
||||
inline double * get(DoubleArray &value)
|
||||
{
|
||||
return &value[0];
|
||||
}
|
||||
inline double const * get(DoubleArray const &value)
|
||||
{
|
||||
return static_cast<double const *>(&value[0]);
|
||||
}
|
||||
inline double * get(DoubleArrayPtr &value)
|
||||
{
|
||||
return get(*value.get());
|
||||
}
|
||||
inline double const * get(DoubleArrayPtr const &value)
|
||||
{
|
||||
return get(*value.get());
|
||||
}
|
||||
inline DoubleArray & getVector(DoubleArrayPtr &value)
|
||||
{
|
||||
return *value.get();
|
||||
}
|
||||
inline DoubleArray const & getVector(DoubleArrayPtr const &value)
|
||||
{
|
||||
return *value.get();
|
||||
}
|
||||
typedef std::vector<double>::iterator DoubleArray_iterator;
|
||||
typedef std::vector<double>::const_iterator DoubleArray_const_iterator;
|
||||
|
||||
/**
|
||||
* A string array.
|
||||
*/
|
||||
typedef std::vector<String> StringArray;
|
||||
typedef std::tr1::shared_ptr<StringArray> StringArrayPtr;
|
||||
inline String * get(StringArray &value)
|
||||
{
|
||||
return &value[0];
|
||||
}
|
||||
inline String const * get(StringArray const &value)
|
||||
{
|
||||
return static_cast<String const *>(&value[0]);
|
||||
}
|
||||
inline String * get(StringArrayPtr &value)
|
||||
{
|
||||
return get(*value.get());
|
||||
}
|
||||
inline String const * get(StringArrayPtr const &value)
|
||||
{
|
||||
return get(*value.get());
|
||||
}
|
||||
inline StringArray & getVector(StringArrayPtr &value)
|
||||
{
|
||||
return *value.get();
|
||||
}
|
||||
inline StringArray const & getVector(StringArrayPtr const &value)
|
||||
{
|
||||
return *value.get();
|
||||
}
|
||||
typedef std::vector<String>::iterator StringArray_iterator;
|
||||
typedef std::vector<String>::const_iterator StringArray_const_iterator;
|
||||
|
||||
/**
|
||||
* A convenience definition for toString methods
|
||||
*/
|
||||
typedef String * StringBuilder;
|
||||
|
||||
}}
|
||||
#endif /* PVTYPE_H */
|
||||
|
||||
|
||||
|
||||
@@ -1,130 +0,0 @@
|
||||
/* standardField.h */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
* Author - Marty Kraimer
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
*/
|
||||
#ifndef STANDARDFIELD_H
|
||||
#define STANDARDFIELD_H
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <pv/pvIntrospect.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
/**
|
||||
* Standard Fields is a class or creating or sharing Field objects for standard fields.
|
||||
* For each type of standard object two methods are defined:s
|
||||
* one with no properties and with properties
|
||||
* The property field is a comma separated string of property names of the following:
|
||||
* alarm, timeStamp, display, control, and valueAlarm.
|
||||
* An example is "alarm,timeStamp,valueAlarm".
|
||||
* The method with properties creates a structure with fields named fieldName
|
||||
* and each of the property names.
|
||||
* Each property field is a structure defining the property.
|
||||
* The details about each property is given in the section named "Property".
|
||||
* For example the call:
|
||||
* {@code
|
||||
StructureConstPtr example = standardField->scalar(
|
||||
String("value"),
|
||||
pvDouble,
|
||||
String("value,alarm,timeStamp"));
|
||||
* }
|
||||
* Will result in a Field definition that has the form: {@code
|
||||
structure example
|
||||
double value
|
||||
structure alarm
|
||||
int severity
|
||||
int status
|
||||
string message
|
||||
structure timeStamp
|
||||
long secondsPastEpoch
|
||||
int nanoSeconds
|
||||
int userTag
|
||||
* }
|
||||
* In addition there are methods that create each of the property structures,
|
||||
* i.e. the methods named: alarm, .... enumeratedAlarm."
|
||||
*
|
||||
* StandardField is a singleton class. The class is accessed via the statement: {@code
|
||||
StandardField *standardField = getStandardField();
|
||||
* }
|
||||
*/
|
||||
|
||||
class StandardField;
|
||||
typedef std::tr1::shared_ptr<StandardField> StandardFieldPtr;
|
||||
|
||||
class StandardField {
|
||||
public:
|
||||
static StandardFieldPtr getStandardField();
|
||||
~StandardField();
|
||||
StructureConstPtr scalar(ScalarType type,String const & properties);
|
||||
StructureConstPtr scalarArray(ScalarType elementType, String const & properties);
|
||||
StructureConstPtr structureArray(StructureConstPtr const & structure,String const & properties);
|
||||
StructureConstPtr enumerated();
|
||||
StructureConstPtr enumerated(String const & properties);
|
||||
StructureConstPtr alarm();
|
||||
StructureConstPtr timeStamp();
|
||||
StructureConstPtr display();
|
||||
StructureConstPtr control();
|
||||
StructureConstPtr booleanAlarm();
|
||||
StructureConstPtr byteAlarm();
|
||||
StructureConstPtr ubyteAlarm();
|
||||
StructureConstPtr shortAlarm();
|
||||
StructureConstPtr ushortAlarm();
|
||||
StructureConstPtr intAlarm();
|
||||
StructureConstPtr uintAlarm();
|
||||
StructureConstPtr longAlarm();
|
||||
StructureConstPtr ulongAlarm();
|
||||
StructureConstPtr floatAlarm();
|
||||
StructureConstPtr doubleAlarm();
|
||||
StructureConstPtr enumeratedAlarm();
|
||||
private:
|
||||
StandardField();
|
||||
void init();
|
||||
StructureConstPtr createProperties(String id,FieldConstPtr field,String properties);
|
||||
FieldCreatePtr fieldCreate;
|
||||
String notImplemented;
|
||||
String valueFieldName;
|
||||
StructureConstPtr alarmField;
|
||||
StructureConstPtr timeStampField;
|
||||
StructureConstPtr displayField;
|
||||
StructureConstPtr controlField;
|
||||
StructureConstPtr booleanAlarmField;
|
||||
StructureConstPtr byteAlarmField;
|
||||
StructureConstPtr shortAlarmField;
|
||||
StructureConstPtr intAlarmField;
|
||||
StructureConstPtr longAlarmField;
|
||||
StructureConstPtr ubyteAlarmField;
|
||||
StructureConstPtr ushortAlarmField;
|
||||
StructureConstPtr uintAlarmField;
|
||||
StructureConstPtr ulongAlarmField;
|
||||
StructureConstPtr floatAlarmField;
|
||||
StructureConstPtr doubleAlarmField;
|
||||
StructureConstPtr enumeratedAlarmField;
|
||||
void createAlarm();
|
||||
void createTimeStamp();
|
||||
void createDisplay();
|
||||
void createControl();
|
||||
void createBooleanAlarm();
|
||||
void createByteAlarm();
|
||||
void createShortAlarm();
|
||||
void createIntAlarm();
|
||||
void createLongAlarm();
|
||||
void createUByteAlarm();
|
||||
void createUShortAlarm();
|
||||
void createUIntAlarm();
|
||||
void createULongAlarm();
|
||||
void createFloatAlarm();
|
||||
void createDoubleAlarm();
|
||||
void createEnumeratedAlarm();
|
||||
friend StandardFieldPtr getStandardField();
|
||||
};
|
||||
|
||||
extern StandardFieldPtr getStandardField();
|
||||
|
||||
}}
|
||||
#endif /* STANDARDFIELD_H */
|
||||
@@ -1,54 +0,0 @@
|
||||
/* standardPVField.h */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
*/
|
||||
#ifndef STANDARDPVFIELD_H
|
||||
#define STANDARDPVFIELD_H
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <pv/pvIntrospect.h>
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/standardField.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
/**
|
||||
* StandardPVField is a class or creating standard data fields.
|
||||
* Like class StandardField it has two forms of the methods which create a fields:
|
||||
* one without properties and one with properties.
|
||||
* The properties are some combination of alarm, timeStamp, control, display, and valueAlarm.
|
||||
* Just like StandardField there are methods to create the standard properties.
|
||||
*
|
||||
* StandardPVField is a singleton class. The class is accessed via the statement: {@code
|
||||
StandardPVField *standardPVField = getStandardPVField();
|
||||
* }
|
||||
*/
|
||||
|
||||
class StandardPVField;
|
||||
typedef std::tr1::shared_ptr<StandardPVField> StandardPVFieldPtr;
|
||||
|
||||
class StandardPVField : private NoDefaultMethods {
|
||||
public:
|
||||
static StandardPVFieldPtr getStandardPVField();
|
||||
~StandardPVField();
|
||||
PVStructurePtr scalar(ScalarType type,String const & properties);
|
||||
PVStructurePtr scalarArray(ScalarType elementType, String const & properties);
|
||||
PVStructurePtr structureArray(StructureConstPtr const &structure,String const & properties);
|
||||
PVStructurePtr enumerated(StringArray const &choices);
|
||||
PVStructurePtr enumerated(StringArray const &choices, String const & properties);
|
||||
private:
|
||||
StandardPVField();
|
||||
StandardFieldPtr standardField;
|
||||
FieldCreatePtr fieldCreate;
|
||||
PVDataCreatePtr pvDataCreate;
|
||||
String notImplemented;
|
||||
};
|
||||
|
||||
extern StandardPVFieldPtr getStandardPVField();
|
||||
|
||||
}}
|
||||
#endif /* STANDARDPVFIELD_H */
|
||||
@@ -1 +0,0 @@
|
||||
// ADD PREDEFINED MACROS HERE!
|
||||
@@ -1 +0,0 @@
|
||||
[General]
|
||||
211
pvDataCPP.files
211
pvDataCPP.files
@@ -1,211 +0,0 @@
|
||||
configure/CONFIG
|
||||
configure/CONFIG_SITE
|
||||
configure/RELEASE
|
||||
configure/RELEASE.local
|
||||
configure/RULES
|
||||
configure/RULES.ioc
|
||||
configure/RULES_DIRS
|
||||
configure/RULES_TOP
|
||||
documentation/pvDataCPP.html
|
||||
documentation/pvDataCPP_20120927.html
|
||||
documentation/pvDataCPP_20121001.html
|
||||
documentation/pvDataCPP_20121026.html
|
||||
documentation/pvDataCPP_20121212.html
|
||||
jenkins/cloudbees_build
|
||||
pvDataApp/factory/Compare.cpp
|
||||
pvDataApp/factory/Convert.cpp
|
||||
pvDataApp/factory/factory.h
|
||||
pvDataApp/factory/FieldCreateFactory.cpp
|
||||
pvDataApp/factory/PVArray.cpp
|
||||
pvDataApp/factory/PVAuxInfoImpl.cpp
|
||||
pvDataApp/factory/PVDataCreateFactory.cpp
|
||||
pvDataApp/factory/PVDataCreateFactory.cpp.orig
|
||||
pvDataApp/factory/PVField.cpp
|
||||
pvDataApp/factory/PVScalar.cpp
|
||||
pvDataApp/factory/PVScalarArray.cpp
|
||||
pvDataApp/factory/PVStructure.cpp
|
||||
pvDataApp/factory/PVStructureArray.cpp
|
||||
pvDataApp/factory/StandardField.cpp
|
||||
pvDataApp/factory/StandardPVField.cpp
|
||||
pvDataApp/factory/TypeFunc.cpp
|
||||
pvDataApp/misc/bitSet.cpp
|
||||
pvDataApp/misc/bitSet.h
|
||||
pvDataApp/misc/byteBuffer.cpp
|
||||
pvDataApp/misc/byteBuffer.h
|
||||
pvDataApp/misc/destroyable.h
|
||||
pvDataApp/misc/epicsException.cpp
|
||||
pvDataApp/misc/epicsException.h
|
||||
pvDataApp/misc/event.cpp
|
||||
pvDataApp/misc/event.h
|
||||
pvDataApp/misc/executor.cpp
|
||||
pvDataApp/misc/executor.h
|
||||
pvDataApp/misc/localStaticLock.cpp
|
||||
pvDataApp/misc/localStaticLock.h
|
||||
pvDataApp/misc/localStaticLock.h.orig
|
||||
pvDataApp/misc/lock.h
|
||||
pvDataApp/misc/messageQueue.cpp
|
||||
pvDataApp/misc/messageQueue.h
|
||||
pvDataApp/misc/noDefaultMethods.h
|
||||
pvDataApp/misc/queue.h
|
||||
pvDataApp/misc/requester.cpp
|
||||
pvDataApp/misc/requester.h
|
||||
pvDataApp/misc/requester.h.orig
|
||||
pvDataApp/misc/serialize.h
|
||||
pvDataApp/misc/serializeHelper.cpp
|
||||
pvDataApp/misc/serializeHelper.h
|
||||
pvDataApp/misc/sharedPtr.h
|
||||
pvDataApp/misc/status.cpp
|
||||
pvDataApp/misc/status.h
|
||||
pvDataApp/misc/thread.h
|
||||
pvDataApp/misc/timeFunction.cpp
|
||||
pvDataApp/misc/timeFunction.h
|
||||
pvDataApp/misc/timer.cpp
|
||||
pvDataApp/misc/timer.h
|
||||
pvDataApp/monitor/monitor.h
|
||||
pvDataApp/O.linux-x86_64/alarm.d
|
||||
pvDataApp/O.linux-x86_64/bitSet.d
|
||||
pvDataApp/O.linux-x86_64/bitSetUtil.d
|
||||
pvDataApp/O.linux-x86_64/byteBuffer.d
|
||||
pvDataApp/O.linux-x86_64/Compare.d
|
||||
pvDataApp/O.linux-x86_64/Convert.d
|
||||
pvDataApp/O.linux-x86_64/epicsException.d
|
||||
pvDataApp/O.linux-x86_64/event.d
|
||||
pvDataApp/O.linux-x86_64/executor.d
|
||||
pvDataApp/O.linux-x86_64/FieldCreateFactory.d
|
||||
pvDataApp/O.linux-x86_64/libpvData.a
|
||||
pvDataApp/O.linux-x86_64/libpvData.so
|
||||
pvDataApp/O.linux-x86_64/localStaticLock.d
|
||||
pvDataApp/O.linux-x86_64/messageQueue.d
|
||||
pvDataApp/O.linux-x86_64/pvAlarm.d
|
||||
pvDataApp/O.linux-x86_64/PVArray.d
|
||||
pvDataApp/O.linux-x86_64/PVAuxInfoImpl.d
|
||||
pvDataApp/O.linux-x86_64/pvControl.d
|
||||
pvDataApp/O.linux-x86_64/PVDataCreateFactory.d
|
||||
pvDataApp/O.linux-x86_64/pvDisplay.d
|
||||
pvDataApp/O.linux-x86_64/pvEnumerated.d
|
||||
pvDataApp/O.linux-x86_64/PVField.d
|
||||
pvDataApp/O.linux-x86_64/PVScalar.d
|
||||
pvDataApp/O.linux-x86_64/PVScalarArray.d
|
||||
pvDataApp/O.linux-x86_64/PVStructure.d
|
||||
pvDataApp/O.linux-x86_64/PVStructureArray.d
|
||||
pvDataApp/O.linux-x86_64/pvTimeStamp.d
|
||||
pvDataApp/O.linux-x86_64/requester.d
|
||||
pvDataApp/O.linux-x86_64/serializeHelper.d
|
||||
pvDataApp/O.linux-x86_64/StandardField.d
|
||||
pvDataApp/O.linux-x86_64/StandardPVField.d
|
||||
pvDataApp/O.linux-x86_64/status.d
|
||||
pvDataApp/O.linux-x86_64/timeFunction.d
|
||||
pvDataApp/O.linux-x86_64/timer.d
|
||||
pvDataApp/O.linux-x86_64/timeStamp.d
|
||||
pvDataApp/O.linux-x86_64/TypeFunc.d
|
||||
pvDataApp/property/alarm.cpp
|
||||
pvDataApp/property/alarm.h
|
||||
pvDataApp/property/alarm.h.orig
|
||||
pvDataApp/property/control.h
|
||||
pvDataApp/property/display.h
|
||||
pvDataApp/property/pvAlarm.cpp
|
||||
pvDataApp/property/pvAlarm.h
|
||||
pvDataApp/property/pvControl.cpp
|
||||
pvDataApp/property/pvControl.h
|
||||
pvDataApp/property/pvDisplay.cpp
|
||||
pvDataApp/property/pvDisplay.h
|
||||
pvDataApp/property/pvEnumerated.cpp
|
||||
pvDataApp/property/pvEnumerated.h
|
||||
pvDataApp/property/pvTimeStamp.cpp
|
||||
pvDataApp/property/pvTimeStamp.h
|
||||
pvDataApp/property/timeStamp.cpp
|
||||
pvDataApp/property/timeStamp.h
|
||||
pvDataApp/property/timeStamp.h.orig
|
||||
pvDataApp/pv/convert.h
|
||||
pvDataApp/pv/convert.h.orig
|
||||
pvDataApp/pv/pvData.h
|
||||
pvDataApp/pv/pvData.h.orig
|
||||
pvDataApp/pv/pvIntrospect.h
|
||||
pvDataApp/pv/pvIntrospect.h.orig
|
||||
pvDataApp/pv/pvType.h
|
||||
pvDataApp/pv/standardField.h
|
||||
pvDataApp/pv/standardField.h.orig
|
||||
pvDataApp/pv/standardPVField.h
|
||||
pvDataApp/pv/standardPVField.h.orig
|
||||
pvDataApp/pvMisc/bitSetUtil.cpp
|
||||
pvDataApp/pvMisc/bitSetUtil.h
|
||||
testApp/capi/O.linux-x86_64/libtestc.a
|
||||
testApp/capi/O.linux-x86_64/libtestc.so
|
||||
testApp/capi/O.linux-x86_64/testc.d
|
||||
testApp/capi/testc.cpp
|
||||
testApp/capi/testc.py
|
||||
testApp/mb/O.linux-x86_64/mb_test
|
||||
testApp/mb/O.linux-x86_64/mb_test.d
|
||||
testApp/misc/O.linux-x86_64/testBaseException
|
||||
testApp/misc/O.linux-x86_64/testBaseException.d
|
||||
testApp/misc/O.linux-x86_64/testBitSet
|
||||
testApp/misc/O.linux-x86_64/testBitSet.d
|
||||
testApp/misc/O.linux-x86_64/testByteBuffer
|
||||
testApp/misc/O.linux-x86_64/testByteBuffer.d
|
||||
testApp/misc/O.linux-x86_64/testByteOrder
|
||||
testApp/misc/O.linux-x86_64/testByteOrder.d
|
||||
testApp/misc/O.linux-x86_64/testMessageQueue
|
||||
testApp/misc/O.linux-x86_64/testMessageQueue.d
|
||||
testApp/misc/O.linux-x86_64/testQueue
|
||||
testApp/misc/O.linux-x86_64/testQueue.d
|
||||
testApp/misc/O.linux-x86_64/testSerialization
|
||||
testApp/misc/O.linux-x86_64/testSerialization.d
|
||||
testApp/misc/O.linux-x86_64/testThread
|
||||
testApp/misc/O.linux-x86_64/testThread.d
|
||||
testApp/misc/O.linux-x86_64/testTimer
|
||||
testApp/misc/O.linux-x86_64/testTimer.d
|
||||
testApp/misc/O.linux-x86_64/testTimeStamp
|
||||
testApp/misc/O.linux-x86_64/testTimeStamp.d
|
||||
testApp/misc/testBaseException.cpp
|
||||
testApp/misc/testBitSet.cpp
|
||||
testApp/misc/testByteBuffer.cpp
|
||||
testApp/misc/testByteOrder.cpp
|
||||
testApp/misc/testMessageQueue.cpp
|
||||
testApp/misc/testQueue.cpp
|
||||
testApp/misc/testSerialization.cpp
|
||||
testApp/misc/testThread.cpp
|
||||
testApp/misc/testTimer.cpp
|
||||
testApp/misc/testTimeStamp.cpp
|
||||
testApp/monitor/O.linux-x86_64/testMonitor
|
||||
testApp/monitor/O.linux-x86_64/testMonitor.d
|
||||
testApp/monitor/testMonitor.cpp
|
||||
testApp/property/O.linux-x86_64/testProperty
|
||||
testApp/property/O.linux-x86_64/testProperty.d
|
||||
testApp/property/testProperty.cpp
|
||||
testApp/pv/O.linux-x86_64/testConvert
|
||||
testApp/pv/O.linux-x86_64/testConvert.d
|
||||
testApp/pv/O.linux-x86_64/testIntrospect
|
||||
testApp/pv/O.linux-x86_64/testIntrospect.d
|
||||
testApp/pv/O.linux-x86_64/testOperators
|
||||
testApp/pv/O.linux-x86_64/testOperators.d
|
||||
testApp/pv/O.linux-x86_64/testPVAppend
|
||||
testApp/pv/O.linux-x86_64/testPVAppend.d
|
||||
testApp/pv/O.linux-x86_64/testPVAuxInfo
|
||||
testApp/pv/O.linux-x86_64/testPVAuxInfo.d
|
||||
testApp/pv/O.linux-x86_64/testPVData
|
||||
testApp/pv/O.linux-x86_64/testPVData.d
|
||||
testApp/pv/O.linux-x86_64/testPVScalarArray
|
||||
testApp/pv/O.linux-x86_64/testPVScalarArray.d
|
||||
testApp/pv/O.linux-x86_64/testPVStructureArray
|
||||
testApp/pv/O.linux-x86_64/testPVStructureArray.d
|
||||
testApp/pv/O.linux-x86_64/testPVType
|
||||
testApp/pv/O.linux-x86_64/testPVType.d
|
||||
testApp/pv/O.linux-x86_64/testStandardField
|
||||
testApp/pv/O.linux-x86_64/testStandardField.d
|
||||
testApp/pv/O.linux-x86_64/testStandardPVField
|
||||
testApp/pv/O.linux-x86_64/testStandardPVField.d
|
||||
testApp/pv/testConvert.cpp
|
||||
testApp/pv/testIntrospect.cpp
|
||||
testApp/pv/testOperators.cpp
|
||||
testApp/pv/testPVAppend.cpp
|
||||
testApp/pv/testPVAuxInfo.cpp
|
||||
testApp/pv/testPVData.cpp
|
||||
testApp/pv/testPVScalarArray.cpp
|
||||
testApp/pv/testPVStructureArray.cpp
|
||||
testApp/pv/testPVType.cpp
|
||||
testApp/pv/testStandardField.cpp
|
||||
testApp/pv/testStandardPVField.cpp
|
||||
COPYRIGHT
|
||||
Doxyfile
|
||||
LICENSE
|
||||
README.html
|
||||
@@ -1,6 +0,0 @@
|
||||
/home/msekoranja/epicsV4/pvDataCPP/pvDataApp/factory
|
||||
/home/msekoranja/epicsV4/pvDataCPP/pvDataApp/misc
|
||||
/home/msekoranja/epicsV4/pvDataCPP/pvDataApp/monitor
|
||||
/home/msekoranja/epicsV4/pvDataCPP/pvDataApp/property
|
||||
/home/msekoranja/epicsV4/pvDataCPP/pvDataApp/pv
|
||||
/home/msekoranja/epicsV4/pvDataCPP/pvDataApp/pvMisc
|
||||
24
src/Makefile
Normal file
24
src/Makefile
Normal file
@@ -0,0 +1,24 @@
|
||||
# Makefile for the pvData library
|
||||
|
||||
TOP = ..
|
||||
include $(TOP)/configure/CONFIG
|
||||
|
||||
INSTALL_INCLUDE = $(INSTALL_LOCATION)/include/pv
|
||||
USR_INCLUDES += -I$(INSTALL_LOCATION)/include
|
||||
|
||||
PVDATA_SRC = $(TOP)/src
|
||||
|
||||
include $(PVDATA_SRC)/misc/Makefile
|
||||
include $(PVDATA_SRC)/pv/Makefile
|
||||
include $(PVDATA_SRC)/factory/Makefile
|
||||
include $(PVDATA_SRC)/property/Makefile
|
||||
include $(PVDATA_SRC)/copy/Makefile
|
||||
include $(PVDATA_SRC)/pvMisc/Makefile
|
||||
include $(PVDATA_SRC)/monitor/Makefile
|
||||
|
||||
LIBRARY = pvData
|
||||
|
||||
pvData_LIBS += Com
|
||||
|
||||
include $(TOP)/configure/RULES
|
||||
|
||||
9
src/copy/Makefile
Normal file
9
src/copy/Makefile
Normal file
@@ -0,0 +1,9 @@
|
||||
# This is a Makefile fragment, see ../Makefile
|
||||
|
||||
SRC_DIRS += $(PVDATA_SRC)/copy
|
||||
|
||||
INC += createRequest.h
|
||||
INC += pvCopy.h
|
||||
|
||||
LIBSRCS += createRequest.cpp
|
||||
LIBSRCS += pvCopy.cpp
|
||||
485
src/copy/createRequest.cpp
Normal file
485
src/copy/createRequest.cpp
Normal file
@@ -0,0 +1,485 @@
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* pvAccessCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/lock.h>
|
||||
#include <pv/createRequest.h>
|
||||
|
||||
using namespace epics::pvData;
|
||||
using std::ostringstream;
|
||||
using std::tr1::static_pointer_cast;
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
using std::string;
|
||||
using std::vector;
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
static PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
||||
static FieldCreatePtr fieldCreate = getFieldCreate();
|
||||
|
||||
class CreateRequestImpl : public CreateRequest {
|
||||
private:
|
||||
|
||||
struct Node
|
||||
{
|
||||
string name;
|
||||
vector<Node> nodes;
|
||||
Node(string name)
|
||||
: name(name)
|
||||
{}
|
||||
};
|
||||
|
||||
struct OptionPair
|
||||
{
|
||||
string name;
|
||||
string value;
|
||||
OptionPair(string name,string value)
|
||||
: name(name),
|
||||
value(value)
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
vector<OptionPair> optionList;
|
||||
string fullFieldName;
|
||||
|
||||
|
||||
public:
|
||||
CreateRequestImpl()
|
||||
{
|
||||
fullFieldName = "";
|
||||
}
|
||||
private:
|
||||
|
||||
|
||||
void removeBlanks(string& str)
|
||||
{
|
||||
while(true) {
|
||||
string::size_type pos = str.find_first_of(' ');
|
||||
if(pos==string::npos) return;
|
||||
str.erase(pos,1);
|
||||
}
|
||||
}
|
||||
|
||||
size_t findMatchingBrace(string& request, size_t index, int numOpen) {
|
||||
size_t openBrace = request.find('{', index+1);
|
||||
size_t closeBrace = request.find('}', index+1);
|
||||
if(openBrace == string::npos && closeBrace == string::npos){
|
||||
message = request + " mismatched {}";
|
||||
throw std::logic_error("message");
|
||||
}
|
||||
if (openBrace != string::npos && openBrace!=0) {
|
||||
if(openBrace<closeBrace) return findMatchingBrace(request,openBrace,numOpen+1);
|
||||
if(numOpen==1) return closeBrace;
|
||||
return findMatchingBrace(request,closeBrace,numOpen-1);
|
||||
}
|
||||
if(numOpen==1) return closeBrace;
|
||||
return findMatchingBrace(request,closeBrace,numOpen-1);
|
||||
}
|
||||
|
||||
size_t findMatchingBracket(string& request, size_t index) {
|
||||
for(size_t i=index+1; i< request.size(); ++i) {
|
||||
if(request[i] == ']') {
|
||||
if(i==index+1) {
|
||||
message = request + " mismatched []";
|
||||
throw std::logic_error("message");
|
||||
}
|
||||
return i;
|
||||
}
|
||||
}
|
||||
message = request + " missing ]";
|
||||
throw std::logic_error("message");
|
||||
}
|
||||
|
||||
size_t findEndField(string& request) {
|
||||
size_t ind = 0;
|
||||
size_t maxind = request.size() -1;
|
||||
while(true) {
|
||||
if(request[ind]==',') return ind;
|
||||
if(request[ind]=='[') {
|
||||
size_t closeBracket = findMatchingBracket(request,ind);
|
||||
if(closeBracket==string::npos) return closeBracket;
|
||||
ind = closeBracket;
|
||||
continue;
|
||||
}
|
||||
if(request[ind]=='{') {
|
||||
size_t closeBrace = findMatchingBrace(request,ind,1);
|
||||
if(closeBrace==string::npos) return closeBrace;
|
||||
if(ind>=request.size()) return request.size();
|
||||
ind = closeBrace;
|
||||
continue;
|
||||
}
|
||||
if(request[ind]=='.') {
|
||||
++ind;
|
||||
continue;
|
||||
}
|
||||
if(ind>=maxind) break;
|
||||
++ind;
|
||||
}
|
||||
return request.size();
|
||||
}
|
||||
|
||||
vector<string> split(string const & commaSeparatedList) {
|
||||
string::size_type numValues = 1;
|
||||
string::size_type index=0;
|
||||
while(true) {
|
||||
string::size_type pos = commaSeparatedList.find(',',index);
|
||||
if(pos==string::npos) break;
|
||||
numValues++;
|
||||
index = pos +1;
|
||||
}
|
||||
vector<string> valueList(numValues,"");
|
||||
index=0;
|
||||
for(size_t i=0; i<numValues; i++) {
|
||||
size_t pos = commaSeparatedList.find(',',index);
|
||||
string value = commaSeparatedList.substr(index,pos-index);
|
||||
valueList[i] = value;
|
||||
index = pos +1;
|
||||
}
|
||||
return valueList;
|
||||
}
|
||||
|
||||
Node createRequestOptions(
|
||||
string const & request)
|
||||
{
|
||||
if(request.length()<=1) {
|
||||
throw std::logic_error("logic error empty options");
|
||||
}
|
||||
vector<Node> top;
|
||||
vector<string> items = split(request);
|
||||
|
||||
size_t nitems = items.size();
|
||||
for(size_t j=0; j<nitems; j++) {
|
||||
string item = items[j];
|
||||
size_t equals = item.find('=');
|
||||
if(equals==string::npos || equals==0) {
|
||||
message = item + " illegal option " + request;
|
||||
throw std::logic_error("message");
|
||||
}
|
||||
top.push_back(Node(item.substr(0,equals)));
|
||||
string name = fullFieldName + "._options." + item.substr(0,equals);
|
||||
string value = item.substr(equals+1);
|
||||
optionList.push_back(OptionPair(name,value));
|
||||
}
|
||||
Node node("_options");
|
||||
node.nodes = top;
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
void createSubNode(Node &node,string const & crequest)
|
||||
{
|
||||
string request = crequest;
|
||||
size_t end = 0;
|
||||
for(size_t i=0; i<request.size(); ++i) {
|
||||
if(request[i]=='[') { end = i; break;}
|
||||
if(request[i]=='.') { end = i; break;}
|
||||
if(request[i]=='{') { end = i; break;}
|
||||
if(request[i]==',') { end = i; break;}
|
||||
}
|
||||
char chr = request[end];
|
||||
Node optionNode("");
|
||||
if(chr=='[') {
|
||||
string saveFullName = fullFieldName;
|
||||
fullFieldName += "." + request.substr(0,end);
|
||||
size_t endBracket = findMatchingBracket(request,end);
|
||||
string options = request.substr(end+1,endBracket -end -1);
|
||||
optionNode = createRequestOptions(options);
|
||||
fullFieldName = saveFullName;
|
||||
size_t next = endBracket+1;
|
||||
if(next<request.size()) {
|
||||
request = request.substr(0, end) + request.substr(endBracket+1);
|
||||
} else {
|
||||
request = request.substr(0, end);
|
||||
}
|
||||
end = 0;
|
||||
for(size_t i=0; i<request.size(); ++i) {
|
||||
if(request[i]=='.') { end = i; break;}
|
||||
if(request[i]=='{') { end = i; break;}
|
||||
if(request[i]==',') { end = i; break;}
|
||||
}
|
||||
chr = request[end];
|
||||
}
|
||||
if(end==0) end = request.size();
|
||||
string name = request.substr(0,end);
|
||||
if(name.size()<1) {
|
||||
throw std::logic_error("null field name " + request);
|
||||
}
|
||||
string saveFullName = fullFieldName;
|
||||
fullFieldName += "." + name;
|
||||
if(end==request.size()) {
|
||||
Node subNode(name);
|
||||
if(optionNode.name.size()>0) subNode.nodes.push_back(optionNode);
|
||||
node.nodes.push_back(subNode);
|
||||
fullFieldName = saveFullName;
|
||||
return;
|
||||
}
|
||||
if(chr==',') {
|
||||
Node subNode(name);
|
||||
if(optionNode.name.size()>0) subNode.nodes.push_back(optionNode);
|
||||
node.nodes.push_back(subNode);
|
||||
string rest = request.substr(end+1);
|
||||
fullFieldName = saveFullName;
|
||||
createSubNode(node,rest);
|
||||
return;
|
||||
}
|
||||
if(chr=='.') {
|
||||
request = request.substr(end+1);
|
||||
if(request.size()==string::npos || request.size()<1) {
|
||||
throw std::logic_error("null field name " + request);
|
||||
}
|
||||
Node subNode(name);
|
||||
if(optionNode.name.size()>0) subNode.nodes.push_back(optionNode);
|
||||
size_t endField = findEndField(request);
|
||||
string subRequest = request.substr(0, endField);
|
||||
createSubNode(subNode,subRequest);
|
||||
node.nodes.push_back(subNode);
|
||||
size_t next = endField+1;
|
||||
if(next>=request.size()) {
|
||||
fullFieldName = saveFullName;
|
||||
return;
|
||||
}
|
||||
request = request.substr(next);
|
||||
fullFieldName = saveFullName;
|
||||
createSubNode(node,request);
|
||||
return;
|
||||
}
|
||||
if(chr=='{') {
|
||||
size_t endBrace = findEndField(request);
|
||||
if((end+1)>=(endBrace-1)) {
|
||||
throw std::logic_error("illegal syntax " + request);
|
||||
}
|
||||
string subRequest = request.substr(end+1,endBrace-1 -end -1);
|
||||
if(subRequest.size()<1) {
|
||||
throw std::logic_error("empty {} " + request);
|
||||
}
|
||||
Node subNode(name);
|
||||
if(optionNode.name.size()>0) subNode.nodes.push_back(optionNode);
|
||||
createSubNode(subNode,subRequest);
|
||||
node.nodes.push_back(subNode);
|
||||
size_t next = endBrace + 1;
|
||||
if(next>=request.size()) {
|
||||
fullFieldName = saveFullName;
|
||||
return;
|
||||
}
|
||||
request = request.substr(next);
|
||||
fullFieldName = saveFullName;
|
||||
createSubNode(node,request);
|
||||
return;
|
||||
}
|
||||
throw std::logic_error("logic error");
|
||||
}
|
||||
|
||||
FieldConstPtr createSubStructure(vector<Node> & nodes)
|
||||
{
|
||||
size_t num = nodes.size();
|
||||
StringArray names(num);
|
||||
FieldConstPtrArray fields(num);
|
||||
for(size_t i=0; i<num; ++i) {
|
||||
Node node = nodes[i];
|
||||
names[i] = node.name;
|
||||
if(node.name.compare("_options")==0) {
|
||||
fields[i] = createOptions(node.nodes);
|
||||
} else {
|
||||
vector<Node> subNode = node.nodes;
|
||||
if(subNode.empty()) {
|
||||
fields[i] = fieldCreate->createStructure();
|
||||
} else {
|
||||
fields[i] = createSubStructure(subNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
StructureConstPtr structure = fieldCreate->createStructure(
|
||||
names, fields);
|
||||
return structure;
|
||||
}
|
||||
|
||||
StructureConstPtr createOptions(vector<Node> &nodes)
|
||||
{
|
||||
size_t num = nodes.size();
|
||||
StringArray names(num);
|
||||
FieldConstPtrArray fields(num);
|
||||
for(size_t i=0; i<num; ++i) {
|
||||
Node node = nodes[i];
|
||||
names[i] = node.name;
|
||||
fields[i] = fieldCreate->createScalar(pvString);
|
||||
}
|
||||
StructureConstPtr structure = fieldCreate->createStructure(names, fields);
|
||||
return structure;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
virtual PVStructurePtr createRequest(
|
||||
string const & crequest)
|
||||
{
|
||||
try {
|
||||
string request = crequest;
|
||||
if (!request.empty()) removeBlanks(request);
|
||||
if (request.empty())
|
||||
{
|
||||
return pvDataCreate->createPVStructure(fieldCreate->createStructure());
|
||||
}
|
||||
size_t offsetRecord = request.find("record[");
|
||||
size_t offsetField = request.find("field(");
|
||||
size_t offsetPutField = request.find("putField(");
|
||||
size_t offsetGetField = request.find("getField(");
|
||||
if(offsetRecord==string::npos
|
||||
&& offsetField==string::npos
|
||||
&& offsetPutField==string::npos
|
||||
&& offsetGetField==string::npos)
|
||||
{
|
||||
request = "field(" + request + ")";
|
||||
offsetField = request.find("field(");
|
||||
}
|
||||
int numParan = 0;
|
||||
int numBrace = 0;
|
||||
int numBracket = 0;
|
||||
for(size_t i=0; i< request.length() ; ++i) {
|
||||
char chr = request[i];
|
||||
if(chr=='(') numParan++;
|
||||
if(chr==')') numParan--;
|
||||
if(chr=='{') numBrace++;
|
||||
if(chr=='}') numBrace--;
|
||||
if(chr=='[') numBracket++;
|
||||
if(chr==']') numBracket--;
|
||||
}
|
||||
if(numParan!=0) {
|
||||
ostringstream oss;
|
||||
oss << "mismatched () " << numParan;
|
||||
message = oss.str();
|
||||
return PVStructurePtr();
|
||||
}
|
||||
if(numBrace!=0) {
|
||||
ostringstream oss;
|
||||
oss << "mismatched {} " << numBrace;
|
||||
message = oss.str();
|
||||
return PVStructurePtr();
|
||||
}
|
||||
if(numBracket!=0) {
|
||||
ostringstream oss;
|
||||
oss << "mismatched [] " << numBracket;
|
||||
message = oss.str();
|
||||
return PVStructurePtr();
|
||||
}
|
||||
vector<Node> top;
|
||||
try {
|
||||
if(offsetRecord!=string::npos) {
|
||||
fullFieldName = "record";
|
||||
size_t openBracket = request.find('[', offsetRecord);
|
||||
size_t closeBracket = request.find(']', openBracket);
|
||||
if(closeBracket==string::npos) {
|
||||
message = request.substr(offsetRecord) +
|
||||
"record[ does not have matching ]";
|
||||
return PVStructurePtr();
|
||||
}
|
||||
if(closeBracket-openBracket > 3) {
|
||||
Node node("record");
|
||||
Node optNode = createRequestOptions(
|
||||
request.substr(openBracket+1,closeBracket-openBracket-1));
|
||||
node.nodes.push_back(optNode);
|
||||
top.push_back(node);
|
||||
}
|
||||
}
|
||||
if(offsetField!=string::npos) {
|
||||
fullFieldName = "field";
|
||||
Node node("field");
|
||||
size_t openParan = request.find('(', offsetField);
|
||||
size_t closeParan = request.find(')', openParan);
|
||||
if(closeParan==string::npos) {
|
||||
message = request.substr(offsetField)
|
||||
+ " field( does not have matching )";
|
||||
return PVStructurePtr();
|
||||
}
|
||||
if(closeParan>openParan+1) {
|
||||
createSubNode(node,request.substr(openParan+1,closeParan-openParan-1));
|
||||
}
|
||||
top.push_back(node);
|
||||
}
|
||||
if(offsetGetField!=string::npos) {
|
||||
fullFieldName = "getField";
|
||||
Node node("getField");
|
||||
size_t openParan = request.find('(', offsetGetField);
|
||||
size_t closeParan = request.find(')', openParan);
|
||||
if(closeParan==string::npos) {
|
||||
message = request.substr(offsetField)
|
||||
+ " getField( does not have matching )";
|
||||
return PVStructurePtr();
|
||||
}
|
||||
if(closeParan>openParan+1) {
|
||||
createSubNode(node,request.substr(openParan+1,closeParan-openParan-1));
|
||||
}
|
||||
top.push_back(node);
|
||||
}
|
||||
if(offsetPutField!=string::npos) {
|
||||
fullFieldName = "putField";
|
||||
Node node("putField");
|
||||
size_t openParan = request.find('(', offsetPutField);
|
||||
size_t closeParan = request.find(')', openParan);
|
||||
if(closeParan==string::npos) {
|
||||
message = request.substr(offsetField)
|
||||
+ " putField( does not have matching )";
|
||||
return PVStructurePtr();
|
||||
}
|
||||
if(closeParan>openParan+1) {
|
||||
createSubNode(node,request.substr(openParan+1,closeParan-openParan-1));
|
||||
}
|
||||
top.push_back(node);
|
||||
}
|
||||
} catch (std::exception &e) {
|
||||
string xxx = e.what();
|
||||
message = "while creating Structure exception " + xxx;
|
||||
return PVStructurePtr();
|
||||
}
|
||||
size_t num = top.size();
|
||||
StringArray names(num);
|
||||
FieldConstPtrArray fields(num);
|
||||
for(size_t i=0; i<num; ++i) {
|
||||
Node node = top[i];
|
||||
names[i] = node.name;
|
||||
vector<Node> subNode = node.nodes;
|
||||
if(subNode.empty()) {
|
||||
fields[i] = fieldCreate->createStructure();
|
||||
} else {
|
||||
fields[i] = createSubStructure(subNode);
|
||||
}
|
||||
}
|
||||
StructureConstPtr structure = fieldCreate->createStructure(names, fields);
|
||||
if(!structure) throw std::invalid_argument("bad request " + crequest);
|
||||
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(structure);
|
||||
for(size_t i=0; i<optionList.size(); ++i) {
|
||||
OptionPair pair = optionList[i];
|
||||
string name = pair.name;
|
||||
string value = pair.value;
|
||||
PVStringPtr pvField = pvStructure->getSubField<PVString>(name);
|
||||
if(!pvField) throw std::invalid_argument("bad request " + crequest);
|
||||
pvField->put(value);
|
||||
}
|
||||
optionList.clear();
|
||||
return pvStructure;
|
||||
} catch (std::exception &e) {
|
||||
message = e.what();
|
||||
return PVStructurePtr();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
CreateRequest::shared_pointer CreateRequest::create()
|
||||
{
|
||||
CreateRequest::shared_pointer createRequest(new CreateRequestImpl());
|
||||
return createRequest;
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
60
src/copy/createRequest.h
Normal file
60
src/copy/createRequest.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/*createRequest.h*/
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* pvDataCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
|
||||
#ifndef CREATEREQUEST_H
|
||||
#define CREATEREQUEST_H
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/lock.h>
|
||||
|
||||
#include <shareLib.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
/**
|
||||
* @brief Create pvRequest structure for Channel methods.
|
||||
*
|
||||
* Many methods of the Channel class of pvAccess have an
|
||||
* argument <b>PVStructurePtr const * pvRequest</b>.
|
||||
* This class provides a method that creates a valid pvRequest.
|
||||
*
|
||||
*/
|
||||
class epicsShareClass CreateRequest {
|
||||
public:
|
||||
POINTER_DEFINITIONS(CreateRequest);
|
||||
/**
|
||||
* Create s new instance of CreateRequest
|
||||
* @returns A shared pointer to the new instance.
|
||||
*/
|
||||
static CreateRequest::shared_pointer create();
|
||||
virtual ~CreateRequest() {};
|
||||
/**
|
||||
* Create a request structure for the create calls in Channel.
|
||||
* See the package overview documentation for details.
|
||||
* @param request The field request. See the package overview documentation for details.
|
||||
* @return The request PVStructure if a valid request was given.
|
||||
* If a NULL PVStructure is returned then getMessage will return
|
||||
* the reason.
|
||||
*/
|
||||
virtual PVStructure::shared_pointer createRequest(std::string const & request) = 0;
|
||||
/**
|
||||
* Get the error message of createRequest returns NULL
|
||||
* return the error message
|
||||
*/
|
||||
std::string getMessage() {return message;}
|
||||
protected:
|
||||
CreateRequest() {}
|
||||
std::string message;
|
||||
};
|
||||
|
||||
|
||||
}}
|
||||
|
||||
#endif /* CREATEREQUEST_H */
|
||||
|
||||
658
src/copy/pvCopy.cpp
Normal file
658
src/copy/pvCopy.cpp
Normal file
@@ -0,0 +1,658 @@
|
||||
/* pvCopy.cpp */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author Marty Kraimer
|
||||
* @date 2013.04
|
||||
*/
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
|
||||
#include <pv/thread.h>
|
||||
|
||||
#include <pv/pvCopy.h>
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using std::tr1::dynamic_pointer_cast;
|
||||
using std::string;
|
||||
using std::size_t;
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
/**
|
||||
* Convenience method for implementing dump.
|
||||
* It generates a newline and inserts blanks at the beginning of the newline.
|
||||
* @param builder The std::string * being constructed.
|
||||
* @param indentLevel Indent level, Each level is four spaces.
|
||||
*/
|
||||
static void newLine(string *buffer, int indentLevel)
|
||||
{
|
||||
*buffer += "\n";
|
||||
*buffer += string(indentLevel*4, ' ');
|
||||
}
|
||||
|
||||
static PVCopyPtr NULLPVCopy;
|
||||
static FieldConstPtr NULLField;
|
||||
static StructureConstPtr NULLStructure;
|
||||
static PVStructurePtr NULLPVStructure;
|
||||
static CopyNodePtr NULLCopyNode;
|
||||
static CopyMasterNodePtr NULLCopyMasterNode;
|
||||
|
||||
struct CopyNode {
|
||||
CopyNode()
|
||||
: isStructure(false),
|
||||
structureOffset(0),
|
||||
nfields(0)
|
||||
{}
|
||||
bool isStructure;
|
||||
size_t structureOffset; // In the copy
|
||||
size_t nfields;
|
||||
PVStructurePtr options;
|
||||
};
|
||||
|
||||
struct CopyMasterNode : public CopyNode{
|
||||
PVFieldPtr masterPVField;
|
||||
};
|
||||
|
||||
typedef std::vector<CopyNodePtr> CopyNodePtrArray;
|
||||
typedef std::tr1::shared_ptr<CopyNodePtrArray> CopyNodePtrArrayPtr;
|
||||
|
||||
struct CopyStructureNode : public CopyNode {
|
||||
CopyNodePtrArrayPtr nodes;
|
||||
};
|
||||
|
||||
PVCopyPtr PVCopy::create(
|
||||
PVStructurePtr const &pvMaster,
|
||||
PVStructurePtr const &pvRequest,
|
||||
string const & structureName)
|
||||
{
|
||||
PVStructurePtr pvStructure(pvRequest);
|
||||
if(structureName.size()>0) {
|
||||
if(pvRequest->getStructure()->getNumberFields()>0) {
|
||||
pvStructure = pvRequest->getSubField<PVStructure>(structureName);
|
||||
if(!pvStructure) return NULLPVCopy;
|
||||
}
|
||||
} else if(pvStructure->getSubField("field")) {
|
||||
pvStructure = pvRequest->getSubField<PVStructure>("field");
|
||||
}
|
||||
PVCopyPtr pvCopy = PVCopyPtr(new PVCopy(pvMaster));
|
||||
bool result = pvCopy->init(pvStructure);
|
||||
if(!result) pvCopy.reset();
|
||||
return pvCopy;
|
||||
}
|
||||
|
||||
PVCopy::PVCopy(
|
||||
PVStructurePtr const &pvMaster)
|
||||
: pvMaster(pvMaster)
|
||||
{
|
||||
}
|
||||
|
||||
void PVCopy::destroy()
|
||||
{
|
||||
headNode.reset();
|
||||
}
|
||||
|
||||
PVStructurePtr PVCopy::getPVMaster()
|
||||
{
|
||||
return pvMaster;
|
||||
}
|
||||
|
||||
void PVCopy::traverseMaster(CopyNodePtr const &innode, PVCopyTraverseMasterCallbackPtr const & callback)
|
||||
{
|
||||
CopyNodePtr node = innode;
|
||||
if(!node->isStructure) {
|
||||
CopyMasterNodePtr masterNode = static_pointer_cast<CopyMasterNode>(node);
|
||||
callback->nextMasterPVField(masterNode->masterPVField);
|
||||
return;
|
||||
}
|
||||
CopyStructureNodePtr structNode = static_pointer_cast<CopyStructureNode>(node);
|
||||
CopyNodePtrArrayPtr nodes = structNode->nodes;
|
||||
for(size_t i=0; i< nodes->size(); i++) {
|
||||
node = (*nodes)[i];
|
||||
traverseMaster(node,callback);
|
||||
}
|
||||
}
|
||||
|
||||
StructureConstPtr PVCopy::getStructure()
|
||||
{
|
||||
return structure;
|
||||
}
|
||||
|
||||
PVStructurePtr PVCopy::createPVStructure()
|
||||
{
|
||||
if(cacheInitStructure) {
|
||||
PVStructurePtr save = cacheInitStructure;
|
||||
cacheInitStructure.reset();
|
||||
return save;
|
||||
}
|
||||
PVStructurePtr pvStructure =
|
||||
getPVDataCreate()->createPVStructure(structure);
|
||||
return pvStructure;
|
||||
}
|
||||
|
||||
PVStructurePtr PVCopy::getOptions(std::size_t fieldOffset)
|
||||
{
|
||||
if(fieldOffset==0) return headNode->options;
|
||||
CopyNodePtr node = headNode;
|
||||
while(true) {
|
||||
if(!node->isStructure) {
|
||||
if(node->structureOffset==fieldOffset) return node->options;
|
||||
return NULLPVStructure;
|
||||
}
|
||||
CopyStructureNodePtr structNode = static_pointer_cast<CopyStructureNode>(node);
|
||||
CopyNodePtrArrayPtr nodes = structNode->nodes;
|
||||
boolean okToContinue = false;
|
||||
for(size_t i=0; i< nodes->size(); i++) {
|
||||
node = (*nodes)[i];
|
||||
size_t soff = node->structureOffset;
|
||||
if(fieldOffset>=soff && fieldOffset<soff+node->nfields) {
|
||||
if(fieldOffset==soff) return node->options;
|
||||
if(!node->isStructure) {
|
||||
return NULLPVStructure;
|
||||
}
|
||||
okToContinue = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(okToContinue) continue;
|
||||
throw std::invalid_argument("fieldOffset not valid");
|
||||
}
|
||||
}
|
||||
|
||||
size_t PVCopy::getCopyOffset(PVFieldPtr const &masterPVField)
|
||||
{
|
||||
if(masterPVField->getFieldOffset()==0) return 0;
|
||||
if(!headNode->isStructure) {
|
||||
CopyMasterNodePtr masterNode = static_pointer_cast<CopyMasterNode>(headNode);
|
||||
if((masterNode->masterPVField.get())==masterPVField.get()) {
|
||||
return headNode->structureOffset;
|
||||
}
|
||||
PVStructure * parent = masterPVField->getParent();
|
||||
size_t offsetParent = parent->getFieldOffset();
|
||||
size_t off = masterPVField->getFieldOffset();
|
||||
size_t offdiff = off -offsetParent;
|
||||
if(offdiff<masterNode->nfields) return headNode->structureOffset + offdiff;
|
||||
return string::npos;
|
||||
}
|
||||
CopyStructureNodePtr node = static_pointer_cast<CopyStructureNode>(headNode);
|
||||
CopyMasterNodePtr masterNode = getCopyOffset(node,masterPVField);
|
||||
if(masterNode) return masterNode->structureOffset;
|
||||
return string::npos;
|
||||
}
|
||||
|
||||
size_t PVCopy::getCopyOffset(
|
||||
PVStructurePtr const &masterPVStructure,
|
||||
PVFieldPtr const &masterPVField)
|
||||
{
|
||||
CopyMasterNodePtr masterNode;
|
||||
if(!headNode->isStructure) {
|
||||
masterNode = static_pointer_cast<CopyMasterNode>(headNode);
|
||||
if(masterNode->masterPVField.get()!=masterPVStructure.get()) return string::npos;
|
||||
} else {
|
||||
CopyStructureNodePtr node = static_pointer_cast<CopyStructureNode>(headNode);
|
||||
masterNode = getCopyOffset(node,masterPVField);
|
||||
}
|
||||
if(!masterNode) return string::npos;
|
||||
size_t diff = masterPVField->getFieldOffset()
|
||||
- masterPVStructure->getFieldOffset();
|
||||
return masterNode->structureOffset + diff;
|
||||
}
|
||||
|
||||
PVFieldPtr PVCopy::getMasterPVField(size_t structureOffset)
|
||||
{
|
||||
CopyMasterNodePtr masterNode;
|
||||
if(!headNode->isStructure) {
|
||||
masterNode = static_pointer_cast<CopyMasterNode>(headNode);
|
||||
} else {
|
||||
CopyStructureNodePtr node = static_pointer_cast<CopyStructureNode>(headNode);
|
||||
masterNode = getMasterNode(node,structureOffset);
|
||||
}
|
||||
if(!masterNode) {
|
||||
throw std::invalid_argument(
|
||||
"PVCopy::getMasterPVField: setstructureOffset not valid");
|
||||
}
|
||||
size_t diff = structureOffset - masterNode->structureOffset;
|
||||
PVFieldPtr pvMasterField = masterNode->masterPVField;
|
||||
if(diff==0) return pvMasterField;
|
||||
PVStructurePtr pvStructure
|
||||
= static_pointer_cast<PVStructure>(pvMasterField);
|
||||
return pvStructure->getSubField(
|
||||
pvMasterField->getFieldOffset() + diff);
|
||||
}
|
||||
|
||||
void PVCopy::initCopy(
|
||||
PVStructurePtr const ©PVStructure,
|
||||
BitSetPtr const &bitSet)
|
||||
{
|
||||
bitSet->clear();
|
||||
bitSet->set(0);
|
||||
updateCopyFromBitSet(copyPVStructure,bitSet);
|
||||
}
|
||||
|
||||
void PVCopy::updateCopySetBitSet(
|
||||
PVStructurePtr const ©PVStructure,
|
||||
BitSetPtr const &bitSet)
|
||||
{
|
||||
if(headNode->isStructure) {
|
||||
CopyStructureNodePtr node = static_pointer_cast<CopyStructureNode>(headNode);
|
||||
updateStructureNodeSetBitSet(copyPVStructure,node,bitSet);
|
||||
} else {
|
||||
CopyMasterNodePtr masterNode = static_pointer_cast<CopyMasterNode>(headNode);
|
||||
PVFieldPtr pvMasterField= masterNode->masterPVField;
|
||||
PVFieldPtr copyPVField = copyPVStructure;
|
||||
PVFieldPtr pvField = pvMasterField;
|
||||
if(pvField->getField()->getType()==epics::pvData::structure) {
|
||||
updateSubFieldSetBitSet(copyPVField,pvMasterField,bitSet);
|
||||
return;
|
||||
}
|
||||
bool isEqual = (*copyPVField == *pvField);
|
||||
if(!isEqual) {
|
||||
copyPVField->copyUnchecked(*pvField);
|
||||
bitSet->set(copyPVField->getFieldOffset());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PVCopy::updateCopyFromBitSet(
|
||||
PVStructurePtr const ©PVStructure,
|
||||
BitSetPtr const &bitSet)
|
||||
{
|
||||
bool doAll = bitSet->get(0);
|
||||
if(headNode->isStructure) {
|
||||
CopyStructureNodePtr node = static_pointer_cast<CopyStructureNode>(headNode);
|
||||
updateStructureNodeFromBitSet(copyPVStructure,node,bitSet,true,doAll);
|
||||
} else {
|
||||
CopyMasterNodePtr masterNode = static_pointer_cast<CopyMasterNode>(headNode);
|
||||
updateSubFieldFromBitSet(copyPVStructure, masterNode->masterPVField,bitSet, true,doAll);
|
||||
}
|
||||
}
|
||||
|
||||
void PVCopy::updateMaster(
|
||||
PVStructurePtr const ©PVStructure,
|
||||
BitSetPtr const &bitSet)
|
||||
{
|
||||
bool doAll = bitSet->get(0);
|
||||
if(headNode->isStructure) {
|
||||
CopyStructureNodePtr node =
|
||||
static_pointer_cast<CopyStructureNode>(headNode);
|
||||
updateStructureNodeFromBitSet(
|
||||
copyPVStructure,node,bitSet,false,doAll);
|
||||
} else {
|
||||
CopyMasterNodePtr masterNode =
|
||||
static_pointer_cast<CopyMasterNode>(headNode);
|
||||
updateSubFieldFromBitSet( copyPVStructure,masterNode->masterPVField,bitSet,false,doAll);
|
||||
}
|
||||
}
|
||||
|
||||
string PVCopy::dump()
|
||||
{
|
||||
string builder;
|
||||
dump(&builder,headNode,0);
|
||||
return builder;
|
||||
}
|
||||
|
||||
void PVCopy::dump(string *builder,CopyNodePtr const &node,int indentLevel)
|
||||
{
|
||||
newLine(builder,indentLevel);
|
||||
std::stringstream ss;
|
||||
ss << (node->isStructure ? "structureNode" : "masterNode");
|
||||
ss << " structureOffset " << node->structureOffset;
|
||||
ss << " nfields " << node->nfields;
|
||||
*builder += ss.str();
|
||||
PVStructurePtr options = node->options;
|
||||
if(options) {
|
||||
newLine(builder,indentLevel +1);
|
||||
|
||||
// TODO !!! ugly
|
||||
std::ostringstream oss;
|
||||
oss << *options;
|
||||
*builder += oss.str();
|
||||
|
||||
newLine(builder,indentLevel);
|
||||
}
|
||||
if(!node->isStructure) {
|
||||
CopyMasterNodePtr masterNode = static_pointer_cast<CopyMasterNode>(node);
|
||||
string name = masterNode->masterPVField->getFullName();
|
||||
*builder += " masterField " + name;
|
||||
return;
|
||||
}
|
||||
CopyStructureNodePtr structureNode =
|
||||
static_pointer_cast<CopyStructureNode>(node);
|
||||
CopyNodePtrArrayPtr nodes = structureNode->nodes;
|
||||
for(size_t i=0; i<nodes->size(); ++i) {
|
||||
if((*nodes)[i].get()==NULL) {
|
||||
newLine(builder,indentLevel +1);
|
||||
ss.str("");
|
||||
ss << "node[" << i << "] is null";
|
||||
*builder += ss.str();
|
||||
continue;
|
||||
}
|
||||
dump(builder,(*nodes)[i],indentLevel+1);
|
||||
}
|
||||
}
|
||||
|
||||
bool PVCopy::init(epics::pvData::PVStructurePtr const &pvRequest)
|
||||
{
|
||||
PVStructurePtr pvMasterStructure = pvMaster;
|
||||
size_t len = pvRequest->getPVFields().size();
|
||||
bool entireMaster = false;
|
||||
if(len==string::npos) entireMaster = true;
|
||||
if(len==0) entireMaster = true;
|
||||
PVStructurePtr pvOptions;
|
||||
if(len==1 && pvRequest->getSubField("_options")) {
|
||||
pvOptions = pvRequest->getSubField<PVStructure>("_options");
|
||||
}
|
||||
if(entireMaster) {
|
||||
structure = pvMasterStructure->getStructure();
|
||||
CopyMasterNodePtr masterNode(new CopyMasterNode());
|
||||
headNode = masterNode;
|
||||
masterNode->options = pvOptions;
|
||||
masterNode->isStructure = false;
|
||||
masterNode->structureOffset = 0;
|
||||
masterNode->masterPVField = pvMasterStructure;
|
||||
masterNode->nfields = pvMasterStructure->getNumberFields();
|
||||
return true;
|
||||
}
|
||||
structure = createStructure(pvMasterStructure,pvRequest);
|
||||
if(!structure) return false;
|
||||
cacheInitStructure = createPVStructure();
|
||||
headNode = createStructureNodes(
|
||||
pvMaster,
|
||||
pvRequest,
|
||||
cacheInitStructure);
|
||||
return true;
|
||||
}
|
||||
|
||||
string PVCopy::dump(
|
||||
string const &value,
|
||||
CopyNodePtr const &node,
|
||||
int indentLevel)
|
||||
{
|
||||
throw std::logic_error(string("Not Implemented"));
|
||||
}
|
||||
|
||||
|
||||
StructureConstPtr PVCopy::createStructure(
|
||||
PVStructurePtr const &pvMaster,
|
||||
PVStructurePtr const &pvFromRequest)
|
||||
{
|
||||
if(pvFromRequest->getStructure()->getNumberFields()==0) {
|
||||
return pvMaster->getStructure();
|
||||
}
|
||||
PVFieldPtrArray const &pvFromRequestFields = pvFromRequest->getPVFields();
|
||||
StringArray const &fromRequestFieldNames = pvFromRequest->getStructure()->getFieldNames();
|
||||
size_t length = pvFromRequestFields.size();
|
||||
if(length==0) return NULLStructure;
|
||||
FieldConstPtrArray fields; fields.reserve(length);
|
||||
StringArray fieldNames; fields.reserve(length);
|
||||
for(size_t i=0; i<length; ++i) {
|
||||
string const &fieldName = fromRequestFieldNames[i];
|
||||
PVFieldPtr pvMasterField = pvMaster->getSubField(fieldName);
|
||||
if(!pvMasterField) continue;
|
||||
FieldConstPtr field = pvMasterField->getField();
|
||||
if(field->getType()==epics::pvData::structure) {
|
||||
PVStructurePtr pvRequestStructure = static_pointer_cast<PVStructure>(
|
||||
pvFromRequestFields[i]);
|
||||
if(pvRequestStructure->getNumberFields()>0) {
|
||||
StringArray const &names = pvRequestStructure->getStructure()->
|
||||
getFieldNames();
|
||||
size_t num = names.size();
|
||||
if(num>0 && names[0].compare("_options")==0) --num;
|
||||
if(num>0) {
|
||||
if(pvMasterField->getField()->getType()!=epics::pvData::structure) continue;
|
||||
fieldNames.push_back(fieldName);
|
||||
fields.push_back(createStructure(
|
||||
static_pointer_cast<PVStructure>(pvMasterField),
|
||||
pvRequestStructure));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
fieldNames.push_back(fieldName);
|
||||
fields.push_back(field);
|
||||
}
|
||||
size_t numsubfields = fields.size();
|
||||
if(numsubfields==0) return NULLStructure;
|
||||
return getFieldCreate()->createStructure(fieldNames, fields);
|
||||
}
|
||||
|
||||
CopyNodePtr PVCopy::createStructureNodes(
|
||||
PVStructurePtr const &pvMasterStructure,
|
||||
PVStructurePtr const &pvFromRequest,
|
||||
PVStructurePtr const &pvFromCopy)
|
||||
{
|
||||
PVFieldPtrArray const & copyPVFields = pvFromCopy->getPVFields();
|
||||
PVStructurePtr pvOptions;
|
||||
PVFieldPtr pvField = pvFromRequest->getSubField("_options");
|
||||
if(pvField) pvOptions = static_pointer_cast<PVStructure>(pvField);
|
||||
size_t number = copyPVFields.size();
|
||||
CopyNodePtrArrayPtr nodes(new CopyNodePtrArray());
|
||||
nodes->reserve(number);
|
||||
for(size_t i=0; i<number; i++) {
|
||||
PVFieldPtr copyPVField = copyPVFields[i];
|
||||
string fieldName = copyPVField->getFieldName();
|
||||
|
||||
PVStructurePtr requestPVStructure = static_pointer_cast<PVStructure>(
|
||||
pvFromRequest->getSubField(fieldName));
|
||||
PVStructurePtr pvSubFieldOptions;
|
||||
PVFieldPtr pvField = requestPVStructure->getSubField("_options");
|
||||
if(pvField) pvSubFieldOptions = static_pointer_cast<PVStructure>(pvField);
|
||||
PVFieldPtr pvMasterField;
|
||||
PVFieldPtrArray const & pvMasterFields = pvMasterStructure->getPVFields();
|
||||
for(size_t j=0; i<pvMasterFields.size(); j++ ) {
|
||||
if(pvMasterFields[j]->getFieldName().compare(fieldName)==0) {
|
||||
pvMasterField = pvMasterFields[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
size_t numberRequest = requestPVStructure->getPVFields().size();
|
||||
if(pvSubFieldOptions) numberRequest--;
|
||||
if(numberRequest>0) {
|
||||
nodes->push_back(createStructureNodes(
|
||||
static_pointer_cast<PVStructure>(pvMasterField),
|
||||
requestPVStructure,
|
||||
static_pointer_cast<PVStructure>(copyPVField)));
|
||||
continue;
|
||||
}
|
||||
CopyMasterNodePtr masterNode(new CopyMasterNode());
|
||||
masterNode->options = pvSubFieldOptions;
|
||||
masterNode->isStructure = false;
|
||||
masterNode->masterPVField = pvMasterField;
|
||||
masterNode->nfields = copyPVField->getNumberFields();
|
||||
masterNode->structureOffset = copyPVField->getFieldOffset();
|
||||
nodes->push_back(masterNode);
|
||||
}
|
||||
CopyStructureNodePtr structureNode(new CopyStructureNode());
|
||||
structureNode->isStructure = true;
|
||||
structureNode->nodes = nodes;
|
||||
structureNode->structureOffset = pvFromCopy->getFieldOffset();
|
||||
structureNode->nfields = pvFromCopy->getNumberFields();
|
||||
structureNode->options = pvOptions;
|
||||
return structureNode;
|
||||
}
|
||||
|
||||
void PVCopy::updateStructureNodeSetBitSet(
|
||||
PVStructurePtr const &pvCopy,
|
||||
CopyStructureNodePtr const &structureNode,
|
||||
epics::pvData::BitSetPtr const &bitSet)
|
||||
{
|
||||
for(size_t i=0; i<structureNode->nodes->size(); i++) {
|
||||
CopyNodePtr node = (*structureNode->nodes)[i];
|
||||
PVFieldPtr pvField = pvCopy->getSubField(node->structureOffset);
|
||||
if(node->isStructure) {
|
||||
PVStructurePtr xxx = static_pointer_cast<PVStructure>(pvField);
|
||||
CopyStructureNodePtr yyy =
|
||||
static_pointer_cast<CopyStructureNode>(node);
|
||||
updateStructureNodeSetBitSet(xxx,yyy,bitSet);
|
||||
} else {
|
||||
CopyMasterNodePtr masterNode =
|
||||
static_pointer_cast<CopyMasterNode>(node);
|
||||
updateSubFieldSetBitSet(pvField,masterNode->masterPVField,bitSet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PVCopy::updateSubFieldSetBitSet(
|
||||
PVFieldPtr const &pvCopy,
|
||||
PVFieldPtr const &pvMaster,
|
||||
BitSetPtr const &bitSet)
|
||||
{
|
||||
FieldConstPtr field = pvCopy->getField();
|
||||
Type type = field->getType();
|
||||
if(type!=epics::pvData::structure) {
|
||||
bool isEqual = (*pvCopy == *pvMaster);
|
||||
if(isEqual) {
|
||||
if(type==structureArray) {
|
||||
// always act as though a change occurred.
|
||||
// Note that array elements are shared.
|
||||
bitSet->set(pvCopy->getFieldOffset());
|
||||
}
|
||||
}
|
||||
if(isEqual) return;
|
||||
pvCopy->copyUnchecked(*pvMaster);
|
||||
bitSet->set(pvCopy->getFieldOffset());
|
||||
return;
|
||||
}
|
||||
PVStructurePtr pvCopyStructure = static_pointer_cast<PVStructure>(pvCopy);
|
||||
PVFieldPtrArray const & pvCopyFields = pvCopyStructure->getPVFields();
|
||||
PVStructurePtr pvMasterStructure =
|
||||
static_pointer_cast<PVStructure>(pvMaster);
|
||||
PVFieldPtrArray const & pvMasterFields =
|
||||
pvMasterStructure->getPVFields();
|
||||
size_t length = pvCopyFields.size();
|
||||
for(size_t i=0; i<length; i++) {
|
||||
updateSubFieldSetBitSet(pvCopyFields[i],pvMasterFields[i],bitSet);
|
||||
}
|
||||
}
|
||||
|
||||
void PVCopy::updateStructureNodeFromBitSet(
|
||||
PVStructurePtr const &pvCopy,
|
||||
CopyStructureNodePtr const &structureNode,
|
||||
BitSetPtr const &bitSet,
|
||||
bool toCopy,
|
||||
bool doAll)
|
||||
{
|
||||
size_t offset = structureNode->structureOffset;
|
||||
if(!doAll) {
|
||||
size_t nextSet = bitSet->nextSetBit(offset);
|
||||
if(nextSet==string::npos) return;
|
||||
}
|
||||
if(offset>=pvCopy->getNextFieldOffset()) return;
|
||||
if(!doAll) doAll = bitSet->get(offset);
|
||||
CopyNodePtrArrayPtr nodes = structureNode->nodes;
|
||||
for(size_t i=0; i<nodes->size(); i++) {
|
||||
CopyNodePtr node = (*nodes)[i];
|
||||
PVFieldPtr pvField = pvCopy->getSubField(node->structureOffset);
|
||||
if(node->isStructure) {
|
||||
PVStructurePtr xxx = static_pointer_cast<PVStructure>(pvField);
|
||||
CopyStructureNodePtr subStructureNode =
|
||||
static_pointer_cast<CopyStructureNode>(node);
|
||||
updateStructureNodeFromBitSet(
|
||||
xxx,subStructureNode,bitSet,toCopy,doAll);
|
||||
} else {
|
||||
CopyMasterNodePtr masterNode =
|
||||
static_pointer_cast<CopyMasterNode>(node);
|
||||
updateSubFieldFromBitSet(
|
||||
pvField,masterNode->masterPVField,bitSet,toCopy,doAll);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PVCopy::updateSubFieldFromBitSet(
|
||||
PVFieldPtr const &pvCopy,
|
||||
PVFieldPtr const &pvMasterField,
|
||||
BitSetPtr const &bitSet,
|
||||
bool toCopy,
|
||||
bool doAll)
|
||||
{
|
||||
if(!doAll) {
|
||||
doAll = bitSet->get(pvCopy->getFieldOffset());
|
||||
}
|
||||
if(!doAll) {
|
||||
size_t offset = pvCopy->getFieldOffset();
|
||||
size_t nextSet = bitSet->nextSetBit(offset);
|
||||
if(nextSet==string::npos) return;
|
||||
if(nextSet>=pvCopy->getNextFieldOffset()) return;
|
||||
}
|
||||
if(pvCopy->getField()->getType()==epics::pvData::structure) {
|
||||
PVStructurePtr pvCopyStructure =
|
||||
static_pointer_cast<PVStructure>(pvCopy);
|
||||
PVFieldPtrArray const & pvCopyFields = pvCopyStructure->getPVFields();
|
||||
if(pvMasterField->getField()->getType() !=epics::pvData::structure)
|
||||
{
|
||||
throw std::logic_error(string("Logic error"));
|
||||
}
|
||||
PVStructurePtr pvMasterStructure =
|
||||
static_pointer_cast<PVStructure>(pvMasterField);
|
||||
PVFieldPtrArray const & pvMasterFields =
|
||||
pvMasterStructure->getPVFields();
|
||||
for(size_t i=0; i<pvCopyFields.size(); i++) {
|
||||
updateSubFieldFromBitSet(
|
||||
pvCopyFields[i],
|
||||
pvMasterFields[i],
|
||||
bitSet,toCopy,doAll);
|
||||
}
|
||||
} else {
|
||||
if(toCopy) {
|
||||
pvCopy->copyUnchecked(*pvMasterField);
|
||||
} else {
|
||||
pvMasterField->copyUnchecked(*pvCopy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CopyMasterNodePtr PVCopy::getCopyOffset(
|
||||
CopyStructureNodePtr const &structureNode,
|
||||
PVFieldPtr const &masterPVField)
|
||||
{
|
||||
size_t offset = masterPVField->getFieldOffset();
|
||||
CopyNodePtrArrayPtr nodes = structureNode->nodes;
|
||||
for(size_t i=0; i< nodes->size(); i++) {
|
||||
CopyNodePtr node = (*nodes)[i];
|
||||
if(!node->isStructure) {
|
||||
CopyMasterNodePtr masterNode =
|
||||
static_pointer_cast<CopyMasterNode>(node);
|
||||
size_t off = masterNode->masterPVField->getFieldOffset();
|
||||
size_t nextOffset = masterNode->masterPVField->getNextFieldOffset();
|
||||
if(offset>= off && offset<nextOffset) return masterNode;
|
||||
} else {
|
||||
CopyStructureNodePtr subNode =
|
||||
static_pointer_cast<CopyStructureNode>(node);
|
||||
CopyMasterNodePtr masterNode =
|
||||
getCopyOffset(subNode,masterPVField);
|
||||
if(masterNode) return masterNode;
|
||||
}
|
||||
}
|
||||
return NULLCopyMasterNode;
|
||||
}
|
||||
|
||||
CopyMasterNodePtr PVCopy::getMasterNode(
|
||||
CopyStructureNodePtr const &structureNode,
|
||||
std::size_t structureOffset)
|
||||
{
|
||||
CopyNodePtrArrayPtr nodes = structureNode->nodes;
|
||||
for(size_t i=0; i< nodes->size(); i++) {
|
||||
CopyNodePtr node = (*nodes)[i];
|
||||
if(structureOffset>=(node->structureOffset + node->nfields)) continue;
|
||||
if(!node->isStructure) {
|
||||
CopyMasterNodePtr masterNode =
|
||||
static_pointer_cast<CopyMasterNode>(node);
|
||||
return masterNode;
|
||||
}
|
||||
CopyStructureNodePtr subNode =
|
||||
static_pointer_cast<CopyStructureNode>(node);
|
||||
return getMasterNode(subNode,structureOffset);
|
||||
}
|
||||
return NULLCopyMasterNode;
|
||||
}
|
||||
|
||||
}}
|
||||
233
src/copy/pvCopy.h
Normal file
233
src/copy/pvCopy.h
Normal file
@@ -0,0 +1,233 @@
|
||||
/* pvCopy.h */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author Marty Kraimer
|
||||
* @date 2013.04
|
||||
*/
|
||||
#ifndef PVCOPY_H
|
||||
#define PVCOPY_H
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <memory>
|
||||
|
||||
#include <shareLib.h>
|
||||
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/bitSet.h>
|
||||
|
||||
namespace epics { namespace pvData{
|
||||
|
||||
class PVCopyTraverseMasterCallback;
|
||||
typedef std::tr1::shared_ptr<PVCopyTraverseMasterCallback> PVCopyTraverseMasterCallbackPtr;
|
||||
|
||||
/**
|
||||
* @brief Callback for traversing master structure
|
||||
*
|
||||
* Must be implemented by code that creates pvCopy.
|
||||
*/
|
||||
class epicsShareClass PVCopyTraverseMasterCallback
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(PVCopyTraverseMasterCallback);
|
||||
virtual ~PVCopyTraverseMasterCallback() {}
|
||||
/**
|
||||
* Called once for each field in master.
|
||||
* @param pvField The field in master.
|
||||
*/
|
||||
virtual void nextMasterPVField(epics::pvData::PVFieldPtr const &pvField) = 0;
|
||||
};
|
||||
|
||||
|
||||
class PVCopy;
|
||||
typedef std::tr1::shared_ptr<PVCopy> PVCopyPtr;
|
||||
|
||||
struct CopyNode;
|
||||
typedef std::tr1::shared_ptr<CopyNode> CopyNodePtr;
|
||||
struct CopyMasterNode;
|
||||
typedef std::tr1::shared_ptr<CopyMasterNode> CopyMasterNodePtr;
|
||||
struct CopyStructureNode;
|
||||
typedef std::tr1::shared_ptr<CopyStructureNode> CopyStructureNodePtr;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Support for subset of fields in a pvStructure.
|
||||
*
|
||||
* Class that manages one or more PVStructures that holds an arbitrary subset of the fields
|
||||
* in another PVStructure called master.
|
||||
*/
|
||||
class epicsShareClass PVCopy :
|
||||
public std::tr1::enable_shared_from_this<PVCopy>
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(PVCopy);
|
||||
/**
|
||||
* Create a new pvCopy
|
||||
* @param pvMaster The top-level structure for which a copy of
|
||||
* an arbitrary subset of the fields in master will be created and managed.
|
||||
* @param pvRequest Selects the set of subfields desired and options for each field.
|
||||
* @param structureName The name for the top level of any PVStructure created.
|
||||
*/
|
||||
static PVCopyPtr create(
|
||||
PVStructurePtr const &pvMaster,
|
||||
PVStructurePtr const &pvRequest,
|
||||
std::string const & structureName);
|
||||
virtual ~PVCopy(){}
|
||||
virtual void destroy();
|
||||
/**
|
||||
* Get the top-level structure of master
|
||||
* @returns The master top-level structure.
|
||||
* This should not be modified.
|
||||
*/
|
||||
PVStructurePtr getPVMaster();
|
||||
/**
|
||||
* Traverse all the fields in master.
|
||||
* @param callback This is called for each field on master.
|
||||
*/
|
||||
void traverseMaster(PVCopyTraverseMasterCallbackPtr const & callback)
|
||||
{
|
||||
traverseMaster(headNode,callback);
|
||||
}
|
||||
/**
|
||||
* Get the introspection interface for a PVStructure for e copy.
|
||||
*/
|
||||
StructureConstPtr getStructure();
|
||||
/**
|
||||
* Create a copy instance. Monitors keep a queue of monitor elements.
|
||||
* Since each element needs a PVStructure, multiple top-level structures will be created.
|
||||
*/
|
||||
PVStructurePtr createPVStructure();
|
||||
/**
|
||||
* Given a field in pvMaster. return the offset in copy for the same field.
|
||||
* A value of std::string::npos means that the copy does not have this field.
|
||||
* @param masterPVField The field in master.
|
||||
*/
|
||||
std::size_t getCopyOffset(PVFieldPtr const &masterPVField);
|
||||
/**
|
||||
* Given a field in pvMaster. return the offset in copy for the same field.
|
||||
* A value of std::string::npos means that the copy does not have this field.
|
||||
* @param masterPVStructure A structure in master that has masterPVField.
|
||||
* @param masterPVField The field in master.
|
||||
*/
|
||||
std::size_t getCopyOffset(
|
||||
PVStructurePtr const &masterPVStructure,
|
||||
PVFieldPtr const &masterPVField);
|
||||
/**
|
||||
* Given an offset in the copy get the corresponding field in pvMaster.
|
||||
* @param structureOffset The offset in the copy.
|
||||
*/
|
||||
PVFieldPtr getMasterPVField(std::size_t structureOffset);
|
||||
/**
|
||||
* Initialize the fields in copyPVStructure by giving each field
|
||||
* the value from the corresponding field in pvMaster.
|
||||
* bitSet will be set to show that all fields are changed.
|
||||
* @param copyPVStructure A copy top-level structure.
|
||||
* @param bitSet A bitSet for copyPVStructure.
|
||||
*/
|
||||
void initCopy(
|
||||
PVStructurePtr const ©PVStructure,
|
||||
BitSetPtr const &bitSet);
|
||||
/**
|
||||
* Set all fields in copyPVStructure to the value of the corresponding field in pvMaster.
|
||||
* Each field that is changed has it's corresponding bit set in bitSet.
|
||||
* @param copyPVStructure A copy top-level structure.
|
||||
* @param bitSet A bitSet for copyPVStructure.
|
||||
*/
|
||||
void updateCopySetBitSet(
|
||||
PVStructurePtr const ©PVStructure,
|
||||
BitSetPtr const &bitSet);
|
||||
/**
|
||||
* For each set bit in bitSet
|
||||
* set the field in copyPVStructure to the value of the corresponding field in pvMaster.
|
||||
* @param copyPVStructure A copy top-level structure.
|
||||
* @param bitSet A bitSet for copyPVStructure.
|
||||
*/
|
||||
void updateCopyFromBitSet(
|
||||
PVStructurePtr const ©PVStructure,
|
||||
BitSetPtr const &bitSet);
|
||||
/**
|
||||
* For each set bit in bitSet
|
||||
* set the field in pvMaster to the value of the corresponding field in copyPVStructure
|
||||
* @param copyPVStructure A copy top-level structure.
|
||||
* @param bitSet A bitSet for copyPVStructure.
|
||||
*/
|
||||
void updateMaster(
|
||||
PVStructurePtr const ©PVStructure,
|
||||
BitSetPtr const &bitSet);
|
||||
/**
|
||||
* Get the options for the field at the specified offset.
|
||||
* @param fieldOffset the offset in copy.
|
||||
* @returns A NULL is returned if no options were specified for the field.
|
||||
* If options were specified,PVStructurePtr is a structures
|
||||
* with a set of PVString subfields that specify name,value pairs.s
|
||||
* name is the subField name and value is the subField value.
|
||||
*/
|
||||
PVStructurePtr getOptions(std::size_t fieldOffset);
|
||||
/**
|
||||
* For debugging.
|
||||
*/
|
||||
std::string dump();
|
||||
private:
|
||||
void dump(
|
||||
std::string *builder,
|
||||
CopyNodePtr const &node,
|
||||
int indentLevel);
|
||||
PVCopyPtr getPtrSelf()
|
||||
{
|
||||
return shared_from_this();
|
||||
}
|
||||
void traverseMaster(CopyNodePtr const &node, PVCopyTraverseMasterCallbackPtr const & callback);
|
||||
|
||||
PVStructurePtr pvMaster;
|
||||
StructureConstPtr structure;
|
||||
CopyNodePtr headNode;
|
||||
PVStructurePtr cacheInitStructure;
|
||||
PVCopy(PVStructurePtr const &pvMaster);
|
||||
friend class PVCopyMonitor;
|
||||
bool init(PVStructurePtr const &pvRequest);
|
||||
std::string dump(
|
||||
std::string const &value,
|
||||
CopyNodePtr const &node,
|
||||
int indentLevel);
|
||||
StructureConstPtr createStructure(
|
||||
PVStructurePtr const &pvMaster,
|
||||
PVStructurePtr const &pvFromRequest);
|
||||
CopyNodePtr createStructureNodes(
|
||||
PVStructurePtr const &pvMasterStructure,
|
||||
PVStructurePtr const &pvFromRequest,
|
||||
PVStructurePtr const &pvFromField);
|
||||
void updateStructureNodeSetBitSet(
|
||||
PVStructurePtr const &pvCopy,
|
||||
CopyStructureNodePtr const &structureNode,
|
||||
BitSetPtr const &bitSet);
|
||||
void updateSubFieldSetBitSet(
|
||||
PVFieldPtr const &pvCopy,
|
||||
PVFieldPtr const &pvMaster,
|
||||
BitSetPtr const &bitSet);
|
||||
void updateStructureNodeFromBitSet(
|
||||
PVStructurePtr const &pvCopy,
|
||||
CopyStructureNodePtr const &structureNode,
|
||||
BitSetPtr const &bitSet,
|
||||
bool toCopy,
|
||||
bool doAll);
|
||||
void updateSubFieldFromBitSet(
|
||||
PVFieldPtr const &pvCopy,
|
||||
PVFieldPtr const &pvMasterField,
|
||||
BitSetPtr const &bitSet,
|
||||
bool toCopy,
|
||||
bool doAll);
|
||||
CopyMasterNodePtr getCopyOffset(
|
||||
CopyStructureNodePtr const &structureNode,
|
||||
PVFieldPtr const &masterPVField);
|
||||
CopyMasterNodePtr getMasterNode(
|
||||
CopyStructureNodePtr const &structureNode,
|
||||
std::size_t structureOffset);
|
||||
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif /* PVCOPY_H */
|
||||
349
src/factory/Compare.cpp
Normal file
349
src/factory/Compare.cpp
Normal file
@@ -0,0 +1,349 @@
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mes
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <sstream>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/pvData.h>
|
||||
|
||||
using std::string;
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
// Introspection object comparison
|
||||
|
||||
/** 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;
|
||||
}
|
||||
case union_: {
|
||||
const Union &A=static_cast<const Union&>(a);
|
||||
const Union &B=static_cast<const Union&>(b);
|
||||
return A==B;
|
||||
}
|
||||
case unionArray: {
|
||||
const UnionArray &A=static_cast<const UnionArray&>(a);
|
||||
const UnionArray &B=static_cast<const UnionArray&>(b);
|
||||
return A==B;
|
||||
}
|
||||
default:
|
||||
throw std::logic_error("Invalid Field type in comparison");
|
||||
}
|
||||
}
|
||||
|
||||
bool operator==(const Scalar& a, const Scalar& b)
|
||||
{
|
||||
if(&a==&b)
|
||||
return true;
|
||||
return a.getScalarType()==b.getScalarType();
|
||||
}
|
||||
|
||||
bool operator==(const ScalarArray& a, const ScalarArray& b)
|
||||
{
|
||||
if(&a==&b)
|
||||
return true;
|
||||
return a.getElementType()==b.getElementType();
|
||||
}
|
||||
|
||||
bool operator==(const Structure& a, const Structure& b)
|
||||
{
|
||||
if(&a==&b)
|
||||
return true;
|
||||
if (a.getID()!=b.getID())
|
||||
return false;
|
||||
size_t nflds=a.getNumberFields();
|
||||
if (b.getNumberFields()!=nflds)
|
||||
return false;
|
||||
|
||||
// std::equals does not work, since FieldConstPtrArray is an array of shared_pointers
|
||||
FieldConstPtrArray const & af = a.getFields();
|
||||
FieldConstPtrArray const & bf = b.getFields();
|
||||
for (size_t i = 0; i < nflds; i++)
|
||||
if (*(af[i].get()) != *(bf[i].get()))
|
||||
return false;
|
||||
|
||||
StringArray const & an = a.getFieldNames();
|
||||
StringArray const & bn = b.getFieldNames();
|
||||
return std::equal( an.begin(), an.end(), bn.begin() );
|
||||
}
|
||||
|
||||
bool operator==(const StructureArray& a, const StructureArray& b)
|
||||
{
|
||||
return *(a.getStructure().get())==*(b.getStructure().get());
|
||||
}
|
||||
|
||||
bool operator==(const Union& a, const Union& b)
|
||||
{
|
||||
if(&a==&b)
|
||||
return true;
|
||||
if (a.getID()!=b.getID())
|
||||
return false;
|
||||
size_t nflds=a.getNumberFields();
|
||||
if (b.getNumberFields()!=nflds)
|
||||
return false;
|
||||
|
||||
// std::equals does not work, since FieldConstPtrArray is an array of shared_pointers
|
||||
FieldConstPtrArray const & af = a.getFields();
|
||||
FieldConstPtrArray const & bf = b.getFields();
|
||||
for (size_t i = 0; i < nflds; i++)
|
||||
if (*(af[i].get()) != *(bf[i].get()))
|
||||
return false;
|
||||
|
||||
StringArray const & an = a.getFieldNames();
|
||||
StringArray const & bn = b.getFieldNames();
|
||||
return std::equal( an.begin(), an.end(), bn.begin() );
|
||||
}
|
||||
|
||||
bool operator==(const UnionArray& a, const UnionArray& b)
|
||||
{
|
||||
return *(a.getUnion().get())==*(b.getUnion().get());
|
||||
}
|
||||
|
||||
bool operator==(const BoundedString& a, const BoundedString& b)
|
||||
{
|
||||
if(&a==&b)
|
||||
return true;
|
||||
return a.getMaximumLength()==b.getMaximumLength();
|
||||
}
|
||||
|
||||
// PVXXX object comparison
|
||||
|
||||
namespace {
|
||||
|
||||
// fully typed comparisons
|
||||
|
||||
template<typename T>
|
||||
bool compareScalar(const PVScalarValue<T>* left, const PVScalarValue<T>* right)
|
||||
{
|
||||
return left->get()==right->get();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool compareArray(const PVValueArray<T>* left, const PVValueArray<T>* right)
|
||||
{
|
||||
typename PVValueArray<T>::const_svector lhs(left->view()), rhs(right->view());
|
||||
return std::equal(lhs.begin(), lhs.end(), rhs.begin());
|
||||
}
|
||||
|
||||
// partially typed comparisons
|
||||
|
||||
bool compareField(const PVScalar* left, const PVScalar* right)
|
||||
{
|
||||
ScalarType lht = left->getScalar()->getScalarType();
|
||||
if(lht != right->getScalar()->getScalarType())
|
||||
return false;
|
||||
switch(lht) {
|
||||
#define OP(ENUM, TYPE) case ENUM: return compareScalar(static_cast<const PVScalarValue<TYPE>*>(left), static_cast<const PVScalarValue<TYPE>*>(right))
|
||||
OP(pvBoolean, uint8);
|
||||
OP(pvUByte, uint8);
|
||||
OP(pvByte, int8);
|
||||
OP(pvUShort, uint16);
|
||||
OP(pvShort, int16);
|
||||
OP(pvUInt, uint32);
|
||||
OP(pvInt, int32);
|
||||
OP(pvULong, uint64);
|
||||
OP(pvLong, int64);
|
||||
OP(pvFloat, float);
|
||||
OP(pvDouble, double);
|
||||
#undef OP
|
||||
case pvString: {
|
||||
const PVString *a=static_cast<const PVString*>(left), *b=static_cast<const PVString*>(right);
|
||||
return a->get()==b->get();
|
||||
}
|
||||
}
|
||||
throw std::logic_error("PVScalar with invalid scalar type!");
|
||||
}
|
||||
|
||||
bool compareField(const PVScalarArray* left, const PVScalarArray* right)
|
||||
{
|
||||
ScalarType lht = left->getScalarArray()->getElementType();
|
||||
if(lht != right->getScalarArray()->getElementType())
|
||||
return false;
|
||||
|
||||
if(left->getLength()!=right->getLength())
|
||||
return false;
|
||||
|
||||
switch(lht) {
|
||||
#define OP(ENUM, TYPE) case ENUM: return compareArray(static_cast<const PVValueArray<TYPE>*>(left), static_cast<const PVValueArray<TYPE>*>(right))
|
||||
OP(pvBoolean, uint8);
|
||||
OP(pvUByte, uint8);
|
||||
OP(pvByte, int8);
|
||||
OP(pvUShort, uint16);
|
||||
OP(pvShort, int16);
|
||||
OP(pvUInt, uint32);
|
||||
OP(pvInt, int32);
|
||||
OP(pvULong, uint64);
|
||||
OP(pvLong, int64);
|
||||
OP(pvFloat, float);
|
||||
OP(pvDouble, double);
|
||||
OP(pvString, string);
|
||||
#undef OP
|
||||
}
|
||||
throw std::logic_error("PVScalarArray with invalid element type!");
|
||||
}
|
||||
|
||||
bool compareField(const PVStructure* left, const PVStructure* right)
|
||||
{
|
||||
StructureConstPtr ls = left->getStructure();
|
||||
|
||||
if(*ls!=*right->getStructure())
|
||||
return false;
|
||||
|
||||
const PVFieldPtrArray& lf = left->getPVFields();
|
||||
const PVFieldPtrArray& rf = right->getPVFields();
|
||||
|
||||
for(size_t i=0, nfld=ls->getNumberFields(); i<nfld; i++) {
|
||||
if(*lf[i]!=*rf[i])
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool compareField(const PVStructureArray* left, const PVStructureArray* right)
|
||||
{
|
||||
if(*left->getStructureArray()->getStructure()
|
||||
!= *right->getStructureArray()->getStructure())
|
||||
return false;
|
||||
|
||||
PVStructureArray::const_svector ld=left->view(), rd=right->view();
|
||||
|
||||
if(ld.size()!=rd.size())
|
||||
return false;
|
||||
|
||||
PVStructureArray::const_svector::const_iterator lit, lend, rit;
|
||||
|
||||
for(lit=ld.begin(), lend=ld.end(), rit=rd.begin();
|
||||
lit!=lend;
|
||||
++lit, ++rit)
|
||||
{
|
||||
// element can be null
|
||||
if (!(*lit) || !(*rit))
|
||||
{
|
||||
if (*lit || *rit)
|
||||
return false;
|
||||
}
|
||||
else if (**lit != **rit)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool compareField(const PVUnion* left, const PVUnion* right)
|
||||
{
|
||||
UnionConstPtr ls = left->getUnion();
|
||||
|
||||
if(*ls!=*right->getUnion())
|
||||
return false;
|
||||
|
||||
if (ls->isVariant())
|
||||
{
|
||||
PVFieldPtr lval = left->get();
|
||||
if (lval.get() == 0)
|
||||
return right->get().get() == 0;
|
||||
else
|
||||
return *(lval.get()) == *(right->get().get());
|
||||
}
|
||||
else
|
||||
{
|
||||
int32 lix = left->getSelectedIndex();
|
||||
if (lix == right->getSelectedIndex())
|
||||
{
|
||||
if (lix == PVUnion::UNDEFINED_INDEX || *(left->get()) == *(right->get().get()))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool compareField(const PVUnionArray* left, const PVUnionArray* right)
|
||||
{
|
||||
if(*left->getUnionArray()->getUnion()
|
||||
!= *right->getUnionArray()->getUnion())
|
||||
return false;
|
||||
|
||||
PVUnionArray::const_svector ld=left->view(), rd=right->view();
|
||||
|
||||
if(ld.size()!=rd.size())
|
||||
return false;
|
||||
|
||||
PVUnionArray::const_svector::const_iterator lit, lend, rit;
|
||||
|
||||
for(lit=ld.begin(), lend=ld.end(), rit=rd.begin();
|
||||
lit!=lend;
|
||||
++lit, ++rit)
|
||||
{
|
||||
// element can be null
|
||||
if (!(*lit) || !(*rit))
|
||||
{
|
||||
if (*lit || *rit)
|
||||
return false;
|
||||
}
|
||||
else if (**lit != **rit)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // end namespace
|
||||
|
||||
// untyped comparison
|
||||
|
||||
bool operator==(const PVField& left, const PVField& right)
|
||||
{
|
||||
if(&left == &right)
|
||||
return true;
|
||||
|
||||
Type lht = left.getField()->getType();
|
||||
if(lht != right.getField()->getType())
|
||||
return false;
|
||||
|
||||
switch(lht) {
|
||||
case scalar: return compareField(static_cast<const PVScalar*>(&left), static_cast<const PVScalar*>(&right));
|
||||
case scalarArray: return compareField(static_cast<const PVScalarArray*>(&left), static_cast<const PVScalarArray*>(&right));
|
||||
case structure: return compareField(static_cast<const PVStructure*>(&left), static_cast<const PVStructure*>(&right));
|
||||
case structureArray: return compareField(static_cast<const PVStructureArray*>(&left), static_cast<const PVStructureArray*>(&right));
|
||||
case union_: return compareField(static_cast<const PVUnion*>(&left), static_cast<const PVUnion*>(&right));
|
||||
case unionArray: return compareField(static_cast<const PVUnionArray*>(&left), static_cast<const PVUnionArray*>(&right));
|
||||
}
|
||||
throw std::logic_error("PVField with invalid type!");
|
||||
}
|
||||
|
||||
}} // namespace epics::pvData
|
||||
164
src/factory/Convert.cpp
Normal file
164
src/factory/Convert.cpp
Normal file
@@ -0,0 +1,164 @@
|
||||
/* Convert.cpp */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
*/
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <stdexcept>
|
||||
#include <typeinfo>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/lock.h>
|
||||
#include <pv/pvIntrospect.h>
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/convert.h>
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using std::size_t;
|
||||
using std::string;
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
|
||||
static std::vector<string> split(string commaSeparatedList) {
|
||||
string::size_type numValues = 1;
|
||||
string::size_type index=0;
|
||||
while(true) {
|
||||
string::size_type pos = commaSeparatedList.find(',',index);
|
||||
if(pos==string::npos) break;
|
||||
numValues++;
|
||||
index = pos +1;
|
||||
}
|
||||
std::vector<string> valueList(numValues,"");
|
||||
index=0;
|
||||
for(size_t i=0; i<numValues; i++) {
|
||||
size_t pos = commaSeparatedList.find(',',index);
|
||||
string value = commaSeparatedList.substr(index,pos);
|
||||
valueList[i] = value;
|
||||
index = pos +1;
|
||||
}
|
||||
return valueList;
|
||||
}
|
||||
|
||||
void Convert::getString(string *buf,PVField const *pvField,int /*indentLevel*/)
|
||||
{
|
||||
// TODO indextLevel ignored
|
||||
std::ostringstream strm;
|
||||
pvField->dumpValue(strm);
|
||||
strm << std::endl;
|
||||
strm.str().swap(*buf);
|
||||
}
|
||||
|
||||
|
||||
size_t Convert::fromString(PVStructurePtr const &pvStructure, StringArray const & from, size_t fromStartIndex)
|
||||
{
|
||||
size_t processed = 0;
|
||||
|
||||
PVFieldPtrArray const & fieldsData = pvStructure->getPVFields();
|
||||
if (fieldsData.size() != 0) {
|
||||
size_t length = pvStructure->getStructure()->getNumberFields();
|
||||
for(size_t i=0; i<length; i++) {
|
||||
PVFieldPtr fieldField = fieldsData[i];
|
||||
|
||||
Type type = fieldField->getField()->getType();
|
||||
if(type==structure) {
|
||||
PVStructurePtr pv = static_pointer_cast<PVStructure>(fieldField);
|
||||
size_t count = fromString(pv, from, fromStartIndex);
|
||||
processed += count;
|
||||
fromStartIndex += count;
|
||||
}
|
||||
else if(type==scalarArray) {
|
||||
PVScalarArrayPtr pv = static_pointer_cast<PVScalarArray>(fieldField);
|
||||
size_t count = fromString(pv, from[fromStartIndex]);
|
||||
processed += count;
|
||||
fromStartIndex += count;
|
||||
}
|
||||
else if(type==scalar) {
|
||||
PVScalarPtr pv = static_pointer_cast<PVScalar>(fieldField);
|
||||
fromString(pv, from[fromStartIndex++]);
|
||||
processed++;
|
||||
}
|
||||
else {
|
||||
// union, structureArray, unionArray not supported
|
||||
std::ostringstream oss;
|
||||
oss << "Convert::fromString unsupported fieldType " << type;
|
||||
throw std::logic_error(oss.str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return processed;
|
||||
}
|
||||
|
||||
size_t Convert::fromString(PVScalarArrayPtr const &pv, string from)
|
||||
{
|
||||
if(from[0]=='[' && from[from.length()]==']') {
|
||||
size_t offset = from.rfind(']');
|
||||
from = from.substr(1, offset);
|
||||
}
|
||||
std::vector<string> valueList(split(from));
|
||||
size_t length = valueList.size();
|
||||
size_t num = fromStringArray(pv,0,length,valueList,0);
|
||||
if(num<length) length = num;
|
||||
pv->setLength(length);
|
||||
return length;
|
||||
}
|
||||
|
||||
size_t Convert::fromStringArray(PVScalarArrayPtr const &pv,
|
||||
size_t offset, size_t length,
|
||||
StringArray const & from,
|
||||
size_t fromOffset)
|
||||
{
|
||||
size_t alen = pv->getLength();
|
||||
|
||||
if(offset==0 && length>=alen) {
|
||||
// replace all existing elements
|
||||
assert(from.size()>=fromOffset+length);
|
||||
|
||||
PVStringArray::svector data(length);
|
||||
std::copy(from.begin()+fromOffset,
|
||||
from.begin()+fromOffset+length,
|
||||
data.begin());
|
||||
|
||||
PVStringArray::const_svector temp(freeze(data));
|
||||
pv->putFrom<string>(temp);
|
||||
return length;
|
||||
|
||||
} else {
|
||||
// partial update.
|
||||
throw std::runtime_error("fromStringArray: partial update not implemented");
|
||||
}
|
||||
}
|
||||
|
||||
size_t Convert::toStringArray(PVScalarArrayPtr const & pv,
|
||||
size_t offset, size_t length,
|
||||
StringArray &to, size_t toOffset)
|
||||
{
|
||||
PVStringArray::const_svector data;
|
||||
pv->getAs<string>(data);
|
||||
data.slice(offset, length);
|
||||
if(toOffset+data.size() > to.size())
|
||||
to.resize(toOffset+data.size());
|
||||
std::copy(data.begin()+toOffset, data.end(), to.begin());
|
||||
return data.size();
|
||||
}
|
||||
|
||||
ConvertPtr Convert::getConvert()
|
||||
{
|
||||
static ConvertPtr convert;
|
||||
static Mutex mutex;
|
||||
Lock xx(mutex);
|
||||
|
||||
if(convert.get()==0) {
|
||||
convert = ConvertPtr(new Convert());
|
||||
}
|
||||
return convert;
|
||||
}
|
||||
|
||||
}}
|
||||
1272
src/factory/FieldCreateFactory.cpp
Normal file
1272
src/factory/FieldCreateFactory.cpp
Normal file
File diff suppressed because it is too large
Load Diff
23
src/factory/Makefile
Normal file
23
src/factory/Makefile
Normal file
@@ -0,0 +1,23 @@
|
||||
# This is a Makefile fragment, see ../Makefile
|
||||
|
||||
SRC_DIRS += $(PVDATA_SRC)/factory
|
||||
|
||||
INC += factory.h
|
||||
LIBSRCS += TypeFunc.cpp
|
||||
LIBSRCS += FieldCreateFactory.cpp
|
||||
LIBSRCS += PVField.cpp
|
||||
LIBSRCS += PVScalar.cpp
|
||||
LIBSRCS += PVArray.cpp
|
||||
LIBSRCS += PVScalarArray.cpp
|
||||
LIBSRCS += PVStructure.cpp
|
||||
LIBSRCS += PVStructureArray.cpp
|
||||
LIBSRCS += PVUnion.cpp
|
||||
LIBSRCS += PVUnionArray.cpp
|
||||
LIBSRCS += PVDataCreateFactory.cpp
|
||||
LIBSRCS += Convert.cpp
|
||||
LIBSRCS += pvSubArrayCopy.cpp
|
||||
LIBSRCS += Compare.cpp
|
||||
LIBSRCS += StandardField.cpp
|
||||
LIBSRCS += StandardPVField.cpp
|
||||
LIBSRCS += printer.cpp
|
||||
|
||||
56
src/factory/PVArray.cpp
Normal file
56
src/factory/PVArray.cpp
Normal file
@@ -0,0 +1,56 @@
|
||||
/*PVArray.cpp*/
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
*/
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/factory.h>
|
||||
|
||||
using std::size_t;
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
PVArray::PVArray(FieldConstPtr const & field)
|
||||
: PVField(field),capacityMutable(true)
|
||||
{ }
|
||||
|
||||
void PVArray::setImmutable()
|
||||
{
|
||||
capacityMutable = false;
|
||||
PVField::setImmutable();
|
||||
}
|
||||
|
||||
bool PVArray::isCapacityMutable() const
|
||||
{
|
||||
if(PVField::isImmutable()) {
|
||||
return false;
|
||||
}
|
||||
return capacityMutable;
|
||||
}
|
||||
|
||||
void PVArray::setCapacityMutable(bool isMutable)
|
||||
{
|
||||
if(isMutable && PVField::isImmutable()) {
|
||||
throw std::runtime_error("field is immutable");
|
||||
}
|
||||
capacityMutable = isMutable;
|
||||
}
|
||||
|
||||
|
||||
std::ostream& operator<<(format::array_at_internal const& manip, const PVArray& array)
|
||||
{
|
||||
return array.dumpValue(manip.stream, manip.index);
|
||||
}
|
||||
|
||||
}}
|
||||
@@ -7,27 +7,57 @@
|
||||
/**
|
||||
* @author mrk
|
||||
*/
|
||||
|
||||
#ifdef _WIN32
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/lock.h>
|
||||
#include <pv/pvIntrospect.h>
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/convert.h>
|
||||
#include <pv/factory.h>
|
||||
#include <pv/serializeHelper.h>
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using std::size_t;
|
||||
using std::string;
|
||||
using std::min;
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
|
||||
template<> const ScalarType PVBoolean::typeCode = pvBoolean;
|
||||
template<> const ScalarType PVByte::typeCode = pvByte;
|
||||
template<> const ScalarType PVShort::typeCode = pvShort;
|
||||
template<> const ScalarType PVInt::typeCode = pvInt;
|
||||
template<> const ScalarType PVLong::typeCode = pvLong;
|
||||
template<> const ScalarType PVUByte::typeCode = pvUByte;
|
||||
template<> const ScalarType PVUShort::typeCode = pvUShort;
|
||||
template<> const ScalarType PVUInt::typeCode = pvUInt;
|
||||
template<> const ScalarType PVULong::typeCode = pvULong;
|
||||
template<> const ScalarType PVFloat::typeCode = pvFloat;
|
||||
template<> const ScalarType PVDouble::typeCode = pvDouble;
|
||||
template<> const ScalarType PVScalarValue<string>::typeCode = pvString;
|
||||
|
||||
template<> const ScalarType PVBooleanArray::typeCode = pvBoolean;
|
||||
template<> const ScalarType PVByteArray::typeCode = pvByte;
|
||||
template<> const ScalarType PVShortArray::typeCode = pvShort;
|
||||
template<> const ScalarType PVIntArray::typeCode = pvInt;
|
||||
template<> const ScalarType PVLongArray::typeCode = pvLong;
|
||||
template<> const ScalarType PVUByteArray::typeCode = pvUByte;
|
||||
template<> const ScalarType PVUShortArray::typeCode = pvUShort;
|
||||
template<> const ScalarType PVUIntArray::typeCode = pvUInt;
|
||||
template<> const ScalarType PVULongArray::typeCode = pvULong;
|
||||
template<> const ScalarType PVFloatArray::typeCode = pvFloat;
|
||||
template<> const ScalarType PVDoubleArray::typeCode = pvDouble;
|
||||
template<> const ScalarType PVStringArray::typeCode = pvString;
|
||||
|
||||
/** Default storage for scalar values
|
||||
*/
|
||||
template<typename T>
|
||||
@@ -53,7 +83,7 @@ template<typename T>
|
||||
BasePVScalar<T>::BasePVScalar(ScalarConstPtr const & scalar)
|
||||
: PVScalarValue<T>(scalar),value(0)
|
||||
{}
|
||||
//Note: '0' is a suitable default for all POD types (not String)
|
||||
//Note: '0' is a suitable default for all POD types (not string)
|
||||
|
||||
template<typename T>
|
||||
BasePVScalar<T>::~BasePVScalar() {}
|
||||
@@ -98,14 +128,14 @@ 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;
|
||||
typedef string value_type;
|
||||
typedef string* pointer;
|
||||
typedef const string* const_pointer;
|
||||
|
||||
BasePVString(ScalarConstPtr const & scalar);
|
||||
virtual ~BasePVString();
|
||||
virtual String get() const ;
|
||||
virtual void put(String val);
|
||||
virtual string get() const ;
|
||||
virtual void put(string val);
|
||||
virtual void serialize(ByteBuffer *pbuffer,
|
||||
SerializableControl *pflusher) const;
|
||||
virtual void deserialize(ByteBuffer *pbuffer,
|
||||
@@ -113,19 +143,29 @@ public:
|
||||
virtual void serialize(ByteBuffer *pbuffer,
|
||||
SerializableControl *pflusher, size_t offset, size_t count) const;
|
||||
private:
|
||||
String value;
|
||||
string value;
|
||||
std::size_t maxLength;
|
||||
};
|
||||
|
||||
BasePVString::BasePVString(ScalarConstPtr const & scalar)
|
||||
: PVString(scalar),value()
|
||||
{}
|
||||
{
|
||||
BoundedStringConstPtr boundedString = std::tr1::dynamic_pointer_cast<const BoundedString>(scalar);
|
||||
if (boundedString.get())
|
||||
maxLength = boundedString->getMaximumLength();
|
||||
else
|
||||
maxLength = 0;
|
||||
}
|
||||
|
||||
BasePVString::~BasePVString() {}
|
||||
|
||||
String BasePVString::get() const { return value;}
|
||||
string BasePVString::get() const { return value;}
|
||||
|
||||
void BasePVString::put(String val)
|
||||
void BasePVString::put(string val)
|
||||
{
|
||||
if (maxLength > 0 && val.length() > maxLength)
|
||||
throw std::overflow_error("string too long");
|
||||
|
||||
value = val;
|
||||
postPut();
|
||||
}
|
||||
@@ -159,6 +199,19 @@ void BasePVString::serialize(ByteBuffer *pbuffer,
|
||||
SerializeHelper::serializeSubstring(value, offset, count, pbuffer, pflusher);
|
||||
}
|
||||
|
||||
void PVArray::checkLength(size_t len)
|
||||
{
|
||||
Array::ArraySizeType type = getArray()->getArraySizeType();
|
||||
if (type != Array::variable)
|
||||
{
|
||||
size_t size = getArray()->getMaximumCapacity();
|
||||
if (type == Array::fixed && len != size)
|
||||
throw std::invalid_argument("invalid length for a fixed size array");
|
||||
else if (type == Array::bounded && len > size)
|
||||
throw std::invalid_argument("new array capacity too large for a bounded size array");
|
||||
}
|
||||
}
|
||||
|
||||
/** Default storage for arrays
|
||||
*/
|
||||
template<typename T>
|
||||
@@ -170,157 +223,97 @@ public:
|
||||
typedef const std::vector<T> const_vector;
|
||||
typedef std::tr1::shared_ptr<vector> shared_vector;
|
||||
|
||||
typedef ::epics::pvData::shared_vector<T> svector;
|
||||
typedef ::epics::pvData::shared_vector<const T> const_svector;
|
||||
|
||||
DefaultPVArray(ScalarArrayConstPtr const & scalarArray);
|
||||
virtual ~DefaultPVArray();
|
||||
|
||||
virtual size_t getLength() const {return value.size();}
|
||||
virtual size_t getCapacity() const {return value.capacity();}
|
||||
|
||||
virtual void setCapacity(size_t capacity);
|
||||
virtual void setLength(size_t length);
|
||||
virtual size_t get(size_t offset, size_t length, PVArrayData<T> &data) ;
|
||||
virtual size_t put(size_t offset,size_t length, const_pointer from,
|
||||
size_t fromOffset);
|
||||
virtual void shareData(
|
||||
std::tr1::shared_ptr<std::vector<T> > const & value,
|
||||
std::size_t capacity,
|
||||
std::size_t length);
|
||||
virtual pointer get() ;
|
||||
virtual pointer get() const ;
|
||||
virtual vector const & getVector() { return *value.get(); }
|
||||
virtual shared_vector const & getSharedVector(){return value;};
|
||||
|
||||
virtual const_svector view() const {return value;}
|
||||
virtual void swap(const_svector &other);
|
||||
virtual void replace(const const_svector& next);
|
||||
|
||||
// from Serializable
|
||||
virtual void serialize(ByteBuffer *pbuffer,SerializableControl *pflusher) const;
|
||||
virtual void deserialize(ByteBuffer *pbuffer,DeserializableControl *pflusher);
|
||||
virtual void serialize(ByteBuffer *pbuffer,
|
||||
SerializableControl *pflusher, size_t offset, size_t count) const;
|
||||
private:
|
||||
shared_vector value;
|
||||
const_svector value;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
T *DefaultPVArray<T>::get()
|
||||
{
|
||||
std::vector<T> *vec = value.get();
|
||||
T *praw = &((*vec)[0]);
|
||||
return praw;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T *DefaultPVArray<T>::get() const
|
||||
{
|
||||
std::vector<T> *vec = value.get();
|
||||
T *praw = &((*vec)[0]);
|
||||
return praw;
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
DefaultPVArray<T>::DefaultPVArray(ScalarArrayConstPtr const & scalarArray)
|
||||
: PVValueArray<T>(scalarArray),
|
||||
value(std::tr1::shared_ptr<std::vector<T> >(new std::vector<T>()))
|
||||
value()
|
||||
|
||||
{ }
|
||||
{
|
||||
ArrayConstPtr array = this->getArray();
|
||||
if (array->getArraySizeType() == Array::fixed)
|
||||
{
|
||||
// this->setLength(array->getMaximumCapacity());
|
||||
this->setCapacityMutable(false);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
DefaultPVArray<T>::~DefaultPVArray()
|
||||
{ }
|
||||
|
||||
template<typename T>
|
||||
void DefaultPVArray<T>::setCapacity(size_t capacity)
|
||||
{
|
||||
if(PVArray::getCapacity()==capacity) return;
|
||||
if(!PVArray::isCapacityMutable()) {
|
||||
std::string message("not capacityMutable");
|
||||
PVField::message(message, errorMessage);
|
||||
return;
|
||||
if(this->isCapacityMutable()) {
|
||||
this->checkLength(capacity);
|
||||
value.reserve(capacity);
|
||||
}
|
||||
size_t length = PVArray::getLength();
|
||||
if(length>capacity) length = capacity;
|
||||
size_t oldCapacity = PVArray::getCapacity();
|
||||
if(oldCapacity>capacity) {
|
||||
std::vector<T> array;
|
||||
array.reserve(capacity);
|
||||
array.resize(length);
|
||||
T * from = get();
|
||||
for (size_t i=0; i<length; i++) array[i] = from[i];
|
||||
value->swap(array);
|
||||
} else {
|
||||
value->reserve(capacity);
|
||||
}
|
||||
PVArray::setCapacityLength(capacity,length);
|
||||
else
|
||||
THROW_EXCEPTION2(std::logic_error, "capacity immutable");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void DefaultPVArray<T>::setLength(size_t length)
|
||||
{
|
||||
if(PVArray::getLength()==length) return;
|
||||
size_t capacity = PVArray::getCapacity();
|
||||
if(length>capacity) {
|
||||
if(!PVArray::isCapacityMutable()) {
|
||||
std::string message("not capacityMutable");
|
||||
PVField::message(message, errorMessage);
|
||||
return;
|
||||
}
|
||||
setCapacity(length);
|
||||
}
|
||||
value->resize(length);
|
||||
PVArray::setCapacityLength(capacity,length);
|
||||
if(this->isImmutable())
|
||||
THROW_EXCEPTION2(std::logic_error, "immutable");
|
||||
|
||||
if (length == value.size())
|
||||
return;
|
||||
|
||||
this->checkLength(length);
|
||||
|
||||
if (length < value.size())
|
||||
value.slice(0, length);
|
||||
else
|
||||
value.resize(length);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
size_t DefaultPVArray<T>::get(size_t offset, size_t len, PVArrayData<T> &data)
|
||||
void DefaultPVArray<T>::replace(const const_svector& next)
|
||||
{
|
||||
size_t n = len;
|
||||
size_t length = this->getLength();
|
||||
if(offset+len > length) {
|
||||
n = length-offset;
|
||||
//if(n<0) n = 0;
|
||||
}
|
||||
data.data = *value.get();
|
||||
data.offset = offset;
|
||||
return n;
|
||||
}
|
||||
this->checkLength(next.size());
|
||||
|
||||
template<typename T>
|
||||
size_t DefaultPVArray<T>::put(size_t offset,size_t len,
|
||||
const_pointer from,size_t fromOffset)
|
||||
{
|
||||
if(PVField::isImmutable()) {
|
||||
PVField::message("field is immutable",errorMessage);
|
||||
return 0;
|
||||
}
|
||||
T * pvalue = get();
|
||||
if(from==pvalue) return len;
|
||||
if(len<1) return 0;
|
||||
size_t length = this->getLength();
|
||||
size_t capacity = this->getCapacity();
|
||||
if(offset+len > length) {
|
||||
size_t newlength = offset + len;
|
||||
if(newlength>capacity) {
|
||||
setCapacity(newlength);
|
||||
newlength = this->getCapacity();
|
||||
len = newlength - offset;
|
||||
if(len<=0) return 0;
|
||||
}
|
||||
length = newlength;
|
||||
setLength(length);
|
||||
}
|
||||
pvalue = get();
|
||||
for(size_t i=0;i<len;i++) {
|
||||
pvalue[i+offset] = from[i+fromOffset];
|
||||
}
|
||||
this->setLength(length);
|
||||
value = next;
|
||||
this->postPut();
|
||||
return len;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void DefaultPVArray<T>::shareData(
|
||||
std::tr1::shared_ptr<std::vector<T> > const & sharedValue,
|
||||
std::size_t capacity,
|
||||
std::size_t length)
|
||||
void DefaultPVArray<T>::swap(const_svector &other)
|
||||
{
|
||||
value = sharedValue;
|
||||
PVArray::setCapacityLength(capacity,length);
|
||||
if (this->isImmutable())
|
||||
THROW_EXCEPTION2(std::logic_error, "immutable");
|
||||
|
||||
// no checkLength call here
|
||||
|
||||
value.swap(other);
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
void DefaultPVArray<T>::serialize(ByteBuffer *pbuffer,
|
||||
SerializableControl *pflusher) const {
|
||||
@@ -330,138 +323,136 @@ void DefaultPVArray<T>::serialize(ByteBuffer *pbuffer,
|
||||
template<typename T>
|
||||
void DefaultPVArray<T>::deserialize(ByteBuffer *pbuffer,
|
||||
DeserializableControl *pcontrol) {
|
||||
size_t size = SerializeHelper::readSize(pbuffer, pcontrol);
|
||||
// alignment 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);
|
||||
// set new length
|
||||
this->setLength(size);
|
||||
|
||||
// try to avoid deserializing from the buffer
|
||||
// this is only possible if we do not need to do endian-swapping
|
||||
if (!pbuffer->reverse<T>())
|
||||
if (pcontrol->directDeserialize(pbuffer, (char*)(get()), size, sizeof(T)))
|
||||
{
|
||||
// inform about the change?
|
||||
PVField::postPut();
|
||||
return;
|
||||
}
|
||||
size_t size = this->getArray()->getArraySizeType() == Array::fixed ?
|
||||
this->getArray()->getMaximumCapacity() :
|
||||
SerializeHelper::readSize(pbuffer, pcontrol);
|
||||
|
||||
// retrieve value from the buffer
|
||||
size_t i = 0;
|
||||
T * pvalue = get();
|
||||
while(true) {
|
||||
/*
|
||||
size_t maxIndex = min(size-i, (int)(pbuffer->getRemaining()/sizeof(T)))+i;
|
||||
for(; i<maxIndex; i++)
|
||||
value[i] = pbuffer->get<T>();
|
||||
*/
|
||||
size_t maxCount = min(size-i, (pbuffer->getRemaining()/sizeof(T)));
|
||||
pbuffer->getArray(pvalue+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;
|
||||
}
|
||||
svector nextvalue(thaw(value));
|
||||
nextvalue.resize(size); // TODO: avoid copy of stuff we will then overwrite
|
||||
|
||||
T* cur = nextvalue.data();
|
||||
|
||||
// try to avoid deserializing from the buffer
|
||||
// this is only possible if we do not need to do endian-swapping
|
||||
if (!pbuffer->reverse<T>())
|
||||
if (pcontrol->directDeserialize(pbuffer, (char*)cur, size, sizeof(T)))
|
||||
{
|
||||
// inform about the change?
|
||||
PVField::postPut();
|
||||
//}
|
||||
// TODO null arrays (size == -1) not supported
|
||||
return;
|
||||
}
|
||||
|
||||
// retrieve value from the buffer
|
||||
size_t remaining = size;
|
||||
while(remaining) {
|
||||
const size_t have_bytes = pbuffer->getRemaining();
|
||||
|
||||
// correctly rounds down in an element is partially received
|
||||
const size_t available = have_bytes/sizeof(T);
|
||||
|
||||
if(available == 0) {
|
||||
// get at least one element
|
||||
pcontrol->ensureData(sizeof(T));
|
||||
continue;
|
||||
}
|
||||
|
||||
const size_t n2read = std::min(remaining, available);
|
||||
|
||||
pbuffer->getArray(cur, n2read);
|
||||
cur += n2read;
|
||||
remaining -= n2read;
|
||||
}
|
||||
value = freeze(nextvalue);
|
||||
// TODO !!!
|
||||
// inform about the change?
|
||||
PVField::postPut();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void DefaultPVArray<T>::serialize(ByteBuffer *pbuffer,
|
||||
SerializableControl *pflusher, size_t offset, size_t count) const {
|
||||
// cache
|
||||
size_t length = this->getLength();
|
||||
SerializableControl *pflusher, size_t offset, size_t count) const
|
||||
{
|
||||
//TODO: avoid incrementing the ref counter...
|
||||
const_svector temp(value);
|
||||
temp.slice(offset, count);
|
||||
count = temp.size();
|
||||
|
||||
// check bounds
|
||||
/*if(offset<0)
|
||||
offset = 0;
|
||||
else*/ if(offset>length) offset = length;
|
||||
//if(count<0) count = length;
|
||||
|
||||
size_t 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));
|
||||
ArrayConstPtr array = this->getArray();
|
||||
if (array->getArraySizeType() != Array::fixed)
|
||||
SerializeHelper::writeSize(count, pbuffer, pflusher);
|
||||
else if (count != array->getMaximumCapacity())
|
||||
throw std::length_error("fixed array cannot be partially serialized");
|
||||
|
||||
const T* cur = temp.data();
|
||||
|
||||
// try to avoid copying into the buffer
|
||||
// this is only possible if we do not need to do endian-swapping
|
||||
if (!pbuffer->reverse<T>())
|
||||
if (pflusher->directSerialize(pbuffer, (const char*)(get()+offset), count, sizeof(T)))
|
||||
if (pflusher->directSerialize(pbuffer, (const char*)cur, count, sizeof(T)))
|
||||
return;
|
||||
|
||||
size_t end = offset+count;
|
||||
size_t i = offset;
|
||||
T * pvalue = const_cast<T *>(get());
|
||||
while(true) {
|
||||
|
||||
/*
|
||||
size_t maxIndex = min<int>(end-i, (int)(pbuffer->getRemaining()/sizeof(T)))+i;
|
||||
for(; i<maxIndex; i++)
|
||||
pbuffer->put<T>(value[i]);
|
||||
*/
|
||||
|
||||
size_t maxCount = min<int>(end-i, (int)(pbuffer->getRemaining()/sizeof(T)));
|
||||
pbuffer->putArray(pvalue+i, maxCount);
|
||||
i += maxCount;
|
||||
|
||||
if(i<end)
|
||||
while(count) {
|
||||
const size_t empty = pbuffer->getRemaining();
|
||||
const size_t space_for = empty/sizeof(T);
|
||||
|
||||
if(space_for==0) {
|
||||
pflusher->flushSerializeBuffer();
|
||||
else
|
||||
break;
|
||||
// Can we be certain that more space is now free???
|
||||
// If not then we spinnnnnnnnn
|
||||
continue;
|
||||
}
|
||||
|
||||
const size_t n2send = std::min(count, space_for);
|
||||
|
||||
pbuffer->putArray(cur, n2send);
|
||||
cur += n2send;
|
||||
count -= n2send;
|
||||
}
|
||||
}
|
||||
|
||||
// specializations for String
|
||||
// specializations for string
|
||||
|
||||
template<>
|
||||
void DefaultPVArray<String>::deserialize(ByteBuffer *pbuffer,
|
||||
void DefaultPVArray<string>::deserialize(ByteBuffer *pbuffer,
|
||||
DeserializableControl *pcontrol) {
|
||||
size_t size = SerializeHelper::readSize(pbuffer, pcontrol);
|
||||
//if(size>=0) {
|
||||
// prepare array, if necessary
|
||||
if(size>getCapacity()) setCapacity(size);
|
||||
// set new length
|
||||
setLength(size);
|
||||
// retrieve value from the buffer
|
||||
String * pvalue = get();
|
||||
for(size_t i = 0; i<size; i++) {
|
||||
pvalue[i] = SerializeHelper::deserializeString(pbuffer,
|
||||
pcontrol);
|
||||
}
|
||||
// inform about the change?
|
||||
postPut();
|
||||
//}
|
||||
// TODO null arrays (size == -1) not supported
|
||||
|
||||
size_t size = this->getArray()->getArraySizeType() == Array::fixed ?
|
||||
this->getArray()->getMaximumCapacity() :
|
||||
SerializeHelper::readSize(pbuffer, pcontrol);
|
||||
|
||||
svector nextvalue(thaw(value));
|
||||
|
||||
// Decide if we must re-allocate
|
||||
if(size > nextvalue.size() || !nextvalue.unique())
|
||||
nextvalue.resize(size);
|
||||
else if(size < nextvalue.size())
|
||||
nextvalue.slice(0, size);
|
||||
|
||||
|
||||
string * pvalue = nextvalue.data();
|
||||
for(size_t i = 0; i<size; i++) {
|
||||
pvalue[i] = SerializeHelper::deserializeString(pbuffer,
|
||||
pcontrol);
|
||||
}
|
||||
value = freeze(nextvalue);
|
||||
// inform about the change?
|
||||
postPut();
|
||||
}
|
||||
|
||||
template<>
|
||||
void DefaultPVArray<String>::serialize(ByteBuffer *pbuffer,
|
||||
void DefaultPVArray<string>::serialize(ByteBuffer *pbuffer,
|
||||
SerializableControl *pflusher, size_t offset, size_t count) const {
|
||||
size_t length = getLength();
|
||||
|
||||
// check bounds
|
||||
/*if(offset<0)
|
||||
offset = 0;
|
||||
else*/ if(offset>length) offset = length;
|
||||
//if(count<0) count = length;
|
||||
const_svector temp(value);
|
||||
temp.slice(offset, count);
|
||||
|
||||
size_t maxCount = length-offset;
|
||||
if(count>maxCount) count = maxCount;
|
||||
// TODO if fixed count == getArray()->getMaximumCapacity()
|
||||
if (this->getArray()->getArraySizeType() != Array::fixed)
|
||||
SerializeHelper::writeSize(temp.size(), pbuffer, pflusher);
|
||||
|
||||
// write
|
||||
SerializeHelper::writeSize(count, pbuffer, pflusher);
|
||||
size_t end = offset+count;
|
||||
String * pvalue = get();
|
||||
for(size_t i = offset; i<end; i++) {
|
||||
const string * pvalue = temp.data();
|
||||
for(size_t i = 0; i<temp.size(); i++) {
|
||||
SerializeHelper::serializeString(pvalue[i], pbuffer, pflusher);
|
||||
}
|
||||
}
|
||||
@@ -477,7 +468,7 @@ typedef DefaultPVArray<uint32> BasePVUIntArray;
|
||||
typedef DefaultPVArray<uint64> BasePVULongArray;
|
||||
typedef DefaultPVArray<float> BasePVFloatArray;
|
||||
typedef DefaultPVArray<double> BasePVDoubleArray;
|
||||
typedef DefaultPVArray<String> BasePVStringArray;
|
||||
typedef DefaultPVArray<string> BasePVStringArray;
|
||||
|
||||
// Factory
|
||||
|
||||
@@ -504,6 +495,14 @@ PVFieldPtr PVDataCreate::createPVField(FieldConstPtr const & field)
|
||||
StructureArrayConstPtr xx = static_pointer_cast<const StructureArray>(field);
|
||||
return createPVStructureArray(xx);
|
||||
}
|
||||
case union_: {
|
||||
UnionConstPtr xx = static_pointer_cast<const Union>(field);
|
||||
return createPVUnion(xx);
|
||||
}
|
||||
case unionArray: {
|
||||
UnionArrayConstPtr xx = static_pointer_cast<const UnionArray>(field);
|
||||
return createPVUnionArray(xx);
|
||||
}
|
||||
}
|
||||
throw std::logic_error("PVDataCreate::createPVField should never get here");
|
||||
}
|
||||
@@ -527,7 +526,7 @@ PVFieldPtr PVDataCreate::createPVField(PVFieldPtr const & fieldToClone)
|
||||
PVStructurePtr pvStructure
|
||||
= static_pointer_cast<PVStructure>(fieldToClone);
|
||||
StringArray const & fieldNames = pvStructure->getStructure()->getFieldNames();
|
||||
PVFieldPtrArray pvFieldPtrArray = pvStructure->getPVFields();
|
||||
PVFieldPtrArray const & pvFieldPtrArray = pvStructure->getPVFields();
|
||||
return createPVStructure(fieldNames,pvFieldPtrArray);
|
||||
}
|
||||
case structureArray:
|
||||
@@ -537,7 +536,22 @@ PVFieldPtr PVDataCreate::createPVField(PVFieldPtr const & fieldToClone)
|
||||
StructureArrayConstPtr structureArray = from->getStructureArray();
|
||||
PVStructureArrayPtr to = createPVStructureArray(
|
||||
structureArray);
|
||||
getConvert()->copyStructureArray(from, to);
|
||||
to->copyUnchecked(*from);
|
||||
return to;
|
||||
}
|
||||
case union_:
|
||||
{
|
||||
PVUnionPtr pvUnion
|
||||
= static_pointer_cast<PVUnion>(fieldToClone);
|
||||
return createPVUnion(pvUnion);
|
||||
}
|
||||
case unionArray:
|
||||
{
|
||||
PVUnionArrayPtr from
|
||||
= static_pointer_cast<PVUnionArray>(fieldToClone);
|
||||
UnionArrayConstPtr unionArray = from->getUnionArray();
|
||||
PVUnionArrayPtr to = createPVUnionArray(unionArray);
|
||||
to->copyUnchecked(*from);
|
||||
return to;
|
||||
}
|
||||
}
|
||||
@@ -587,17 +601,7 @@ PVScalarPtr PVDataCreate::createPVScalar(PVScalarPtr const & scalarToClone)
|
||||
{
|
||||
ScalarType scalarType = scalarToClone->getScalar()->getScalarType();
|
||||
PVScalarPtr pvScalar = createPVScalar(scalarType);
|
||||
getConvert()->copyScalar(scalarToClone, pvScalar);
|
||||
PVAuxInfoPtr from = scalarToClone->getPVAuxInfo();
|
||||
PVAuxInfoPtr to = pvScalar->getPVAuxInfo();
|
||||
PVAuxInfo::PVInfoMap & map = from->getInfoMap();
|
||||
for(PVAuxInfo::PVInfoIter iter = map.begin(); iter!= map.end(); ++iter) {
|
||||
String key = iter->first;
|
||||
PVScalarPtr pvFrom = iter->second;
|
||||
ScalarConstPtr scalar = pvFrom->getScalar();
|
||||
PVScalarPtr pvTo = to->createInfo(key,scalar->getScalarType());
|
||||
getConvert()->copyScalar(pvFrom,pvTo);
|
||||
}
|
||||
pvScalar->copyUnchecked(*scalarToClone);
|
||||
return pvScalar;
|
||||
}
|
||||
|
||||
@@ -646,17 +650,7 @@ PVScalarArrayPtr PVDataCreate::createPVScalarArray(
|
||||
{
|
||||
PVScalarArrayPtr pvArray = createPVScalarArray(
|
||||
arrayToClone->getScalarArray()->getElementType());
|
||||
getConvert()->copyScalarArray(arrayToClone,0, pvArray,0,arrayToClone->getLength());
|
||||
PVAuxInfoPtr from = arrayToClone->getPVAuxInfo();
|
||||
PVAuxInfoPtr to = pvArray->getPVAuxInfo();
|
||||
PVAuxInfo::PVInfoMap & map = from->getInfoMap();
|
||||
for(PVAuxInfo::PVInfoIter iter = map.begin(); iter!= map.end(); ++iter) {
|
||||
String key = iter->first;
|
||||
PVScalarPtr pvFrom = iter->second;
|
||||
ScalarConstPtr scalar = pvFrom->getScalar();
|
||||
PVScalarPtr pvTo = to->createInfo(key,scalar->getScalarType());
|
||||
getConvert()->copyScalar(pvFrom,pvTo);
|
||||
}
|
||||
pvArray->assign(*arrayToClone.get());
|
||||
return pvArray;
|
||||
}
|
||||
|
||||
@@ -672,6 +666,28 @@ PVStructurePtr PVDataCreate::createPVStructure(
|
||||
return PVStructurePtr(new PVStructure(structure));
|
||||
}
|
||||
|
||||
PVUnionArrayPtr PVDataCreate::createPVUnionArray(
|
||||
UnionArrayConstPtr const & unionArray)
|
||||
{
|
||||
return PVUnionArrayPtr(new PVUnionArray(unionArray));
|
||||
}
|
||||
|
||||
PVUnionPtr PVDataCreate::createPVUnion(
|
||||
UnionConstPtr const & punion)
|
||||
{
|
||||
return PVUnionPtr(new PVUnion(punion));
|
||||
}
|
||||
|
||||
PVUnionPtr PVDataCreate::createPVVariantUnion()
|
||||
{
|
||||
return PVUnionPtr(new PVUnion(fieldCreate->createVariantUnion()));
|
||||
}
|
||||
|
||||
PVUnionArrayPtr PVDataCreate::createPVVariantUnionArray()
|
||||
{
|
||||
return PVUnionArrayPtr(new PVUnionArray(fieldCreate->createVariantUnionArray()));
|
||||
}
|
||||
|
||||
PVStructurePtr PVDataCreate::createPVStructure(
|
||||
StringArray const & fieldNames,PVFieldPtrArray const & pvFields)
|
||||
{
|
||||
@@ -686,7 +702,8 @@ PVStructurePtr PVDataCreate::createPVStructure(
|
||||
PVStructurePtr PVDataCreate::createPVStructure(PVStructurePtr const & structToClone)
|
||||
{
|
||||
FieldConstPtrArray field;
|
||||
if(structToClone==0) {
|
||||
if(!structToClone) {
|
||||
// is this correct?!
|
||||
FieldConstPtrArray fields(0);
|
||||
StringArray fieldNames(0);
|
||||
StructureConstPtr structure = fieldCreate->createStructure(fieldNames,fields);
|
||||
@@ -694,10 +711,20 @@ PVStructurePtr PVDataCreate::createPVStructure(PVStructurePtr const & structToCl
|
||||
}
|
||||
StructureConstPtr structure = structToClone->getStructure();
|
||||
PVStructurePtr pvStructure(new PVStructure(structure));
|
||||
getConvert()->copyStructure(structToClone,pvStructure);
|
||||
pvStructure->copyUnchecked(*structToClone);
|
||||
return pvStructure;
|
||||
}
|
||||
|
||||
PVUnionPtr PVDataCreate::createPVUnion(PVUnionPtr const & unionToClone)
|
||||
{
|
||||
PVUnionPtr punion(new PVUnion(unionToClone->getUnion()));
|
||||
// set cloned value
|
||||
punion->set(unionToClone->getSelectedIndex(), createPVField(unionToClone->get()));
|
||||
return punion;
|
||||
}
|
||||
|
||||
// TODO not thread-safe (local static initializers)
|
||||
// TODO replace with non-locking singleton pattern
|
||||
PVDataCreatePtr PVDataCreate::getPVDataCreate()
|
||||
{
|
||||
static PVDataCreatePtr pvDataCreate;
|
||||
@@ -713,3 +740,12 @@ PVDataCreatePtr getPVDataCreate() {
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
namespace std{
|
||||
std::ostream& operator<<(std::ostream& o, const epics::pvData::PVField *ptr)
|
||||
{
|
||||
if(ptr) return o << *ptr;
|
||||
return o << "nullptr";
|
||||
}
|
||||
}
|
||||
|
||||
295
src/factory/PVField.cpp
Normal file
295
src/factory/PVField.cpp
Normal file
@@ -0,0 +1,295 @@
|
||||
/*PVField.cpp*/
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
*/
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/lock.h>
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/factory.h>
|
||||
|
||||
using std::tr1::const_pointer_cast;
|
||||
using std::size_t;
|
||||
using std::string;
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
PVField::PVField(FieldConstPtr field)
|
||||
: notImplemented("not implemented"),
|
||||
parent(NULL),field(field),
|
||||
fieldOffset(0), nextFieldOffset(0),
|
||||
immutable(false)
|
||||
{
|
||||
}
|
||||
|
||||
PVField::~PVField()
|
||||
{ }
|
||||
|
||||
|
||||
size_t PVField::getFieldOffset() const
|
||||
{
|
||||
if(nextFieldOffset==0) computeOffset(this);
|
||||
return fieldOffset;
|
||||
}
|
||||
|
||||
size_t PVField::getNextFieldOffset() const
|
||||
{
|
||||
if(nextFieldOffset==0) computeOffset(this);
|
||||
return nextFieldOffset;
|
||||
}
|
||||
|
||||
size_t PVField::getNumberFields() const
|
||||
{
|
||||
if(nextFieldOffset==0) computeOffset(this);
|
||||
return (nextFieldOffset - fieldOffset);
|
||||
}
|
||||
|
||||
|
||||
bool PVField::isImmutable() const {return immutable;}
|
||||
|
||||
void PVField::setImmutable() {immutable = true;}
|
||||
|
||||
const FieldConstPtr & PVField::getField() const {return field;}
|
||||
|
||||
PVStructure *PVField::getParent() const {return parent;}
|
||||
|
||||
void PVField::postPut()
|
||||
{
|
||||
if(postHandler.get()!=NULL) postHandler->postPut();
|
||||
}
|
||||
|
||||
void PVField::setPostHandler(PostHandlerPtr const &handler)
|
||||
{
|
||||
if(postHandler.get()!=NULL) {
|
||||
if(postHandler.get()==handler.get()) return;
|
||||
throw std::logic_error(
|
||||
"PVField::setPostHandler a postHandler is already registered");
|
||||
|
||||
}
|
||||
postHandler = handler;
|
||||
}
|
||||
|
||||
void PVField::setParentAndName(PVStructure * xxx,string const & name)
|
||||
{
|
||||
parent = xxx;
|
||||
fieldName = name;
|
||||
}
|
||||
|
||||
bool PVField::equals(PVField &pv)
|
||||
{
|
||||
return pv==*this;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& o, const PVField& f)
|
||||
{
|
||||
return f.dumpValue(o);
|
||||
};
|
||||
|
||||
string PVField::getFullName() const
|
||||
{
|
||||
string ret(fieldName);
|
||||
for(PVField *fld=getParent(); fld; fld=fld->getParent())
|
||||
{
|
||||
if(fld->getFieldName().size()==0) break;
|
||||
ret = fld->getFieldName() + '.' + ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void PVField::computeOffset(const PVField * pvField) {
|
||||
const PVStructure * pvTop = pvField->getParent();
|
||||
if(pvTop==NULL) {
|
||||
if(pvField->getField()->getType()!=structure) {
|
||||
PVField *xxx = const_cast<PVField *>(pvField);
|
||||
xxx->fieldOffset = 0;
|
||||
xxx->nextFieldOffset = 1;
|
||||
return;
|
||||
}
|
||||
pvTop = static_cast<const PVStructure *>(pvField);
|
||||
} else {
|
||||
while(pvTop->getParent()!=NULL) pvTop = pvTop->getParent();
|
||||
}
|
||||
size_t offset = 0;
|
||||
size_t nextOffset = 1;
|
||||
const PVFieldPtrArray & pvFields = pvTop->getPVFields();
|
||||
for(size_t i=0; i < pvTop->getStructure()->getNumberFields(); i++) {
|
||||
offset = nextOffset;
|
||||
PVField *pvField = pvFields[i].get();
|
||||
FieldConstPtr field = pvField->getField();
|
||||
switch(field->getType()) {
|
||||
case scalar:
|
||||
case scalarArray:
|
||||
case structureArray:
|
||||
case union_:
|
||||
case unionArray: {
|
||||
nextOffset++;
|
||||
pvField->fieldOffset = offset;
|
||||
pvField->nextFieldOffset = nextOffset;
|
||||
break;
|
||||
}
|
||||
case structure: {
|
||||
pvField->computeOffset(pvField,offset);
|
||||
nextOffset = pvField->getNextFieldOffset();
|
||||
}
|
||||
}
|
||||
}
|
||||
PVField *top = (PVField *)pvTop;
|
||||
PVField *xxx = const_cast<PVField *>(top);
|
||||
xxx->fieldOffset = 0;
|
||||
xxx->nextFieldOffset = nextOffset;
|
||||
}
|
||||
|
||||
void PVField::computeOffset(const PVField * pvField,size_t offset) {
|
||||
size_t beginOffset = offset;
|
||||
size_t nextOffset = offset + 1;
|
||||
const PVStructure *pvStructure = static_cast<const PVStructure *>(pvField);
|
||||
const PVFieldPtrArray & pvFields = pvStructure->getPVFields();
|
||||
for(size_t i=0; i < pvStructure->getStructure()->getNumberFields(); i++) {
|
||||
offset = nextOffset;
|
||||
PVField *pvSubField = pvFields[i].get();
|
||||
FieldConstPtr field = pvSubField->getField();
|
||||
switch(field->getType()) {
|
||||
case scalar:
|
||||
case scalarArray:
|
||||
case structureArray:
|
||||
case union_:
|
||||
case unionArray: {
|
||||
nextOffset++;
|
||||
pvSubField->fieldOffset = offset;
|
||||
pvSubField->nextFieldOffset = nextOffset;
|
||||
break;
|
||||
}
|
||||
case structure: {
|
||||
pvSubField->computeOffset(pvSubField,offset);
|
||||
nextOffset = pvSubField->getNextFieldOffset();
|
||||
}
|
||||
}
|
||||
}
|
||||
PVField *xxx = const_cast<PVField *>(pvField);
|
||||
xxx->fieldOffset = beginOffset;
|
||||
xxx->nextFieldOffset = nextOffset;
|
||||
}
|
||||
|
||||
void PVField::copy(const PVField& from)
|
||||
{
|
||||
if(isImmutable())
|
||||
throw std::invalid_argument("destination is immutable");
|
||||
|
||||
if (getField()->getType() != from.getField()->getType())
|
||||
throw std::invalid_argument("field types do not match");
|
||||
|
||||
switch(getField()->getType())
|
||||
{
|
||||
case scalar:
|
||||
{
|
||||
const PVScalar* fromS = static_cast<const PVScalar*>(&from);
|
||||
PVScalar* toS = static_cast<PVScalar*>(this);
|
||||
toS->copy(*fromS);
|
||||
break;
|
||||
}
|
||||
case scalarArray:
|
||||
{
|
||||
const PVScalarArray* fromS = static_cast<const PVScalarArray*>(&from);
|
||||
PVScalarArray* toS = static_cast<PVScalarArray*>(this);
|
||||
toS->copy(*fromS);
|
||||
break;
|
||||
}
|
||||
case structure:
|
||||
{
|
||||
const PVStructure* fromS = static_cast<const PVStructure*>(&from);
|
||||
PVStructure* toS = static_cast<PVStructure*>(this);
|
||||
toS->copy(*fromS);
|
||||
break;
|
||||
}
|
||||
case structureArray:
|
||||
{
|
||||
const PVStructureArray* fromS = static_cast<const PVStructureArray*>(&from);
|
||||
PVStructureArray* toS = static_cast<PVStructureArray*>(this);
|
||||
toS->copy(*fromS);
|
||||
break;
|
||||
}
|
||||
case union_:
|
||||
{
|
||||
const PVUnion* fromS = static_cast<const PVUnion*>(&from);
|
||||
PVUnion* toS = static_cast<PVUnion*>(this);
|
||||
toS->copy(*fromS);
|
||||
break;
|
||||
}
|
||||
case unionArray:
|
||||
{
|
||||
const PVUnionArray* fromS = static_cast<const PVUnionArray*>(&from);
|
||||
PVUnionArray* toS = static_cast<PVUnionArray*>(this);
|
||||
toS->copy(*fromS);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
throw std::logic_error("PVField::copy unknown type");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PVField::copyUnchecked(const PVField& from)
|
||||
{
|
||||
switch(getField()->getType())
|
||||
{
|
||||
case scalar:
|
||||
{
|
||||
const PVScalar* fromS = static_cast<const PVScalar*>(&from);
|
||||
PVScalar* toS = static_cast<PVScalar*>(this);
|
||||
toS->copyUnchecked(*fromS);
|
||||
break;
|
||||
}
|
||||
case scalarArray:
|
||||
{
|
||||
const PVScalarArray* fromS = static_cast<const PVScalarArray*>(&from);
|
||||
PVScalarArray* toS = static_cast<PVScalarArray*>(this);
|
||||
toS->copyUnchecked(*fromS);
|
||||
break;
|
||||
}
|
||||
case structure:
|
||||
{
|
||||
const PVStructure* fromS = static_cast<const PVStructure*>(&from);
|
||||
PVStructure* toS = static_cast<PVStructure*>(this);
|
||||
toS->copyUnchecked(*fromS);
|
||||
break;
|
||||
}
|
||||
case structureArray:
|
||||
{
|
||||
const PVStructureArray* fromS = static_cast<const PVStructureArray*>(&from);
|
||||
PVStructureArray* toS = static_cast<PVStructureArray*>(this);
|
||||
toS->copyUnchecked(*fromS);
|
||||
break;
|
||||
}
|
||||
case union_:
|
||||
{
|
||||
const PVUnion* fromS = static_cast<const PVUnion*>(&from);
|
||||
PVUnion* toS = static_cast<PVUnion*>(this);
|
||||
toS->copyUnchecked(*fromS);
|
||||
break;
|
||||
}
|
||||
case unionArray:
|
||||
{
|
||||
const PVUnionArray* fromS = static_cast<const PVUnionArray*>(&from);
|
||||
PVUnionArray* toS = static_cast<PVUnionArray*>(this);
|
||||
toS->copyUnchecked(*fromS);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
throw std::logic_error("PVField::copy unknown type");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}}
|
||||
@@ -11,6 +11,8 @@
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/factory.h>
|
||||
|
||||
@@ -31,7 +33,7 @@ namespace epics { namespace pvData {
|
||||
template<>
|
||||
std::ostream& PVScalarValue<int8>::dumpValue(std::ostream& o) const
|
||||
{
|
||||
return o << static_cast<int>(get());
|
||||
return o << static_cast<int>(get());
|
||||
}
|
||||
|
||||
template<>
|
||||
@@ -39,4 +41,10 @@ namespace epics { namespace pvData {
|
||||
{
|
||||
return o << static_cast<unsigned int>(get());
|
||||
}
|
||||
|
||||
template<>
|
||||
std::ostream& PVScalarValue<boolean>::dumpValue(std::ostream& o) const
|
||||
{
|
||||
return o << std::boolalpha << static_cast<bool>(get());
|
||||
}
|
||||
}}
|
||||
@@ -11,6 +11,8 @@
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/factory.h>
|
||||
|
||||
@@ -28,16 +30,4 @@ namespace epics { namespace pvData {
|
||||
return static_pointer_cast<const ScalarArray>(PVField::getField());
|
||||
}
|
||||
|
||||
template<>
|
||||
std::ostream& PVValueArray<int8>::dumpValue(std::ostream& o, size_t index) const
|
||||
{
|
||||
return o << static_cast<int>(*(get() + index));
|
||||
}
|
||||
|
||||
template<>
|
||||
std::ostream& PVValueArray<uint8>::dumpValue(std::ostream& o, size_t index) const
|
||||
{
|
||||
return o << static_cast<unsigned int>(*(get() + index));
|
||||
}
|
||||
|
||||
}}
|
||||
432
src/factory/PVStructure.cpp
Normal file
432
src/factory/PVStructure.cpp
Normal file
@@ -0,0 +1,432 @@
|
||||
/*PVStructure.cpp*/
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
*/
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <vector>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/pvIntrospect.h>
|
||||
#include <pv/factory.h>
|
||||
#include <pv/bitSet.h>
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using std::size_t;
|
||||
using std::string;
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
PVFieldPtr PVStructure::nullPVField;
|
||||
PVBooleanPtr PVStructure::nullPVBoolean;
|
||||
PVBytePtr PVStructure::nullPVByte;
|
||||
PVShortPtr PVStructure::nullPVShort;
|
||||
PVIntPtr PVStructure::nullPVInt;
|
||||
PVLongPtr PVStructure::nullPVLong;
|
||||
PVUBytePtr PVStructure::nullPVUByte;
|
||||
PVUShortPtr PVStructure::nullPVUShort;
|
||||
PVUIntPtr PVStructure::nullPVUInt;
|
||||
PVULongPtr PVStructure::nullPVULong;
|
||||
PVFloatPtr PVStructure::nullPVFloat;
|
||||
PVDoublePtr PVStructure::nullPVDouble;
|
||||
PVStringPtr PVStructure::nullPVString;
|
||||
PVStructurePtr PVStructure::nullPVStructure;
|
||||
PVStructureArrayPtr PVStructure::nullPVStructureArray;
|
||||
PVUnionPtr PVStructure::nullPVUnion;
|
||||
PVUnionArrayPtr PVStructure::nullPVUnionArray;
|
||||
PVScalarArrayPtr PVStructure::nullPVScalarArray;
|
||||
|
||||
PVStructure::PVStructure(StructureConstPtr const & structurePtr)
|
||||
: PVField(structurePtr),
|
||||
structurePtr(structurePtr),
|
||||
extendsStructureName("")
|
||||
{
|
||||
size_t numberFields = structurePtr->getNumberFields();
|
||||
FieldConstPtrArray const & fields = structurePtr->getFields();
|
||||
StringArray const & fieldNames = structurePtr->getFieldNames();
|
||||
// PVFieldPtrArray * xxx = const_cast<PVFieldPtrArray *>(&pvFields);
|
||||
pvFields.reserve(numberFields);
|
||||
PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
||||
for(size_t i=0; i<numberFields; i++) {
|
||||
pvFields.push_back(pvDataCreate->createPVField(fields[i]));
|
||||
}
|
||||
for(size_t i=0; i<numberFields; i++) {
|
||||
pvFields[i]->setParentAndName(this,fieldNames[i]);
|
||||
}
|
||||
}
|
||||
|
||||
PVStructure::PVStructure(StructureConstPtr const & structurePtr,
|
||||
PVFieldPtrArray const & pvs
|
||||
)
|
||||
: PVField(structurePtr),
|
||||
structurePtr(structurePtr),
|
||||
extendsStructureName("")
|
||||
{
|
||||
size_t numberFields = structurePtr->getNumberFields();
|
||||
StringArray const & fieldNames = structurePtr->getFieldNames();
|
||||
pvFields.reserve(numberFields);
|
||||
for(size_t i=0; i<numberFields; i++) {
|
||||
pvFields.push_back(pvs[i]);
|
||||
}
|
||||
for(size_t i=0; i<numberFields; i++) {
|
||||
pvFields[i]->setParentAndName(this,fieldNames[i]);
|
||||
}
|
||||
}
|
||||
|
||||
PVStructure::~PVStructure()
|
||||
{
|
||||
}
|
||||
|
||||
void PVStructure::setImmutable()
|
||||
{
|
||||
size_t numFields = pvFields.size();
|
||||
for(size_t i=0; i<numFields; i++) {
|
||||
PVFieldPtr pvField = pvFields[i];
|
||||
pvField->setImmutable();
|
||||
}
|
||||
PVField::setImmutable();
|
||||
}
|
||||
|
||||
StructureConstPtr PVStructure::getStructure() const
|
||||
{
|
||||
return structurePtr;
|
||||
}
|
||||
|
||||
const PVFieldPtrArray & PVStructure::getPVFields() const
|
||||
{
|
||||
return pvFields;
|
||||
}
|
||||
|
||||
PVFieldPtr PVStructure::getSubField(string const &fieldName) const
|
||||
{
|
||||
PVField * field = getSubFieldImpl(fieldName.c_str(), false);
|
||||
if (field)
|
||||
return field->shared_from_this();
|
||||
else
|
||||
return PVFieldPtr();
|
||||
}
|
||||
|
||||
|
||||
PVFieldPtr PVStructure::getSubField(size_t fieldOffset) const
|
||||
{
|
||||
if(fieldOffset<=getFieldOffset()) {
|
||||
return nullPVField;
|
||||
}
|
||||
if(fieldOffset>getNextFieldOffset()) return nullPVField;
|
||||
size_t numFields = pvFields.size();
|
||||
for(size_t i=0; i<numFields; i++) {
|
||||
PVFieldPtr pvField = pvFields[i];
|
||||
if(pvField->getFieldOffset()==fieldOffset) return pvFields[i];
|
||||
if(pvField->getNextFieldOffset()<=fieldOffset) continue;
|
||||
if(pvField->getField()->getType()==structure) {
|
||||
PVStructure *pvStructure = static_cast<PVStructure *>(pvField.get());
|
||||
return pvStructure->getSubField(fieldOffset);
|
||||
}
|
||||
}
|
||||
throw std::logic_error("PVStructure.getSubField: Logic error");
|
||||
}
|
||||
|
||||
PVFieldPtr PVStructure::getSubFieldT(std::size_t fieldOffset) const
|
||||
{
|
||||
PVFieldPtr pvField = getSubField(fieldOffset);
|
||||
if (pvField.get())
|
||||
return pvField;
|
||||
else
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "Failed to get field with offset "
|
||||
<< fieldOffset << "(Invalid offset)" ;
|
||||
throw std::runtime_error(ss.str());
|
||||
}
|
||||
}
|
||||
|
||||
PVField* PVStructure::getSubFieldImpl(const char *name, bool throws) const
|
||||
{
|
||||
const PVStructure *parent = this;
|
||||
if(!name)
|
||||
{
|
||||
if (throws)
|
||||
throw std::invalid_argument("Failed to get field: (Field name is NULL string)");
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
const char *fullName = name;
|
||||
while(true) {
|
||||
const char *sep=name;
|
||||
while(*sep!='\0' && *sep!='.' && *sep!=' ') sep++;
|
||||
if(*sep==' ')
|
||||
{
|
||||
if (throws)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "Failed to get field: " << fullName
|
||||
<< " (No spaces allowed in field name)";
|
||||
throw std::runtime_error(ss.str());
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
size_t N = sep-name;
|
||||
if(N==0)
|
||||
{
|
||||
if (throws)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "Failed to get field: " << fullName
|
||||
<< " (Zero-length field name encountered)";
|
||||
throw std::runtime_error(ss.str());
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const PVFieldPtrArray& pvFields = parent->getPVFields();
|
||||
|
||||
PVField *child = NULL;
|
||||
|
||||
for(size_t i=0, n=pvFields.size(); i!=n; i++) {
|
||||
const PVFieldPtr& fld = pvFields[i];
|
||||
const std::string& fname = fld->getFieldName();
|
||||
|
||||
if(fname.size()==N && memcmp(name, fname.c_str(), N)==0) {
|
||||
child = fld.get();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!child)
|
||||
{
|
||||
if (throws)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "Failed to get field: " << fullName << " ("
|
||||
<< std::string(fullName, sep) << " not found)";
|
||||
throw std::runtime_error(ss.str());
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(*sep) {
|
||||
// this is not the requested leaf
|
||||
parent = dynamic_cast<PVStructure*>(child);
|
||||
if(!parent)
|
||||
{
|
||||
if (throws)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "Failed to get field: " << fullName
|
||||
<< " (" << std::string(fullName, sep)
|
||||
<< " is not a structure)";
|
||||
throw std::runtime_error(ss.str());
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
child = NULL;
|
||||
name = sep+1; // skip past '.'
|
||||
// loop around to new parent
|
||||
|
||||
} else {
|
||||
return child;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PVStructure::serialize(ByteBuffer *pbuffer,
|
||||
SerializableControl *pflusher) const {
|
||||
size_t fieldsSize = pvFields.size();
|
||||
for(size_t i = 0; i<fieldsSize; i++)
|
||||
pvFields[i]->serialize(pbuffer, pflusher);
|
||||
}
|
||||
|
||||
void PVStructure::deserialize(ByteBuffer *pbuffer,
|
||||
DeserializableControl *pcontrol) {
|
||||
size_t fieldsSize = pvFields.size();
|
||||
for(size_t i = 0; i<fieldsSize; i++)
|
||||
pvFields[i]->deserialize(pbuffer, pcontrol);
|
||||
|
||||
}
|
||||
|
||||
void PVStructure::serialize(ByteBuffer *pbuffer,
|
||||
SerializableControl *pflusher, BitSet *pbitSet) const {
|
||||
PVStructure* nonConstThis = const_cast<PVStructure*>(this);
|
||||
size_t numberFields = nonConstThis->getNumberFields();
|
||||
size_t offset = nonConstThis->getFieldOffset();
|
||||
int32 next = pbitSet->nextSetBit(static_cast<uint32>(offset));
|
||||
|
||||
// no more changes or no changes in this structure
|
||||
if(next<0||next>=static_cast<int32>(offset+numberFields)) return;
|
||||
|
||||
// entire structure
|
||||
if(static_cast<int32>(offset)==next) {
|
||||
serialize(pbuffer, pflusher);
|
||||
return;
|
||||
}
|
||||
|
||||
size_t fieldsSize = pvFields.size();
|
||||
for(size_t i = 0; i<fieldsSize; i++) {
|
||||
PVFieldPtr pvField = pvFields[i];
|
||||
offset = pvField->getFieldOffset();
|
||||
int32 inumberFields = static_cast<int32>(pvField->getNumberFields());
|
||||
next = pbitSet->nextSetBit(static_cast<uint32>(offset));
|
||||
|
||||
// no more changes
|
||||
if(next<0) return;
|
||||
// no change in this pvField
|
||||
if(next>=static_cast<int32>(offset+inumberFields)) continue;
|
||||
|
||||
// serialize field or fields
|
||||
if(inumberFields==1) {
|
||||
pvField->serialize(pbuffer, pflusher);
|
||||
} else {
|
||||
PVStructurePtr pvStructure = std::tr1::static_pointer_cast<PVStructure>(pvField);
|
||||
pvStructure->serialize(pbuffer, pflusher, pbitSet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PVStructure::deserialize(ByteBuffer *pbuffer,
|
||||
DeserializableControl *pcontrol, BitSet *pbitSet) {
|
||||
size_t offset = getFieldOffset();
|
||||
size_t numberFields = getNumberFields();
|
||||
int32 next = pbitSet->nextSetBit(static_cast<uint32>(offset));
|
||||
|
||||
// no more changes or no changes in this structure
|
||||
if(next<0||next>=static_cast<int32>(offset+numberFields)) return;
|
||||
|
||||
// entire structure
|
||||
if(static_cast<int32>(offset)==next) {
|
||||
deserialize(pbuffer, pcontrol);
|
||||
return;
|
||||
}
|
||||
|
||||
size_t fieldsSize = pvFields.size();
|
||||
for(size_t i = 0; i<fieldsSize; i++) {
|
||||
PVFieldPtr pvField = pvFields[i];
|
||||
offset = pvField->getFieldOffset();
|
||||
int32 inumberFields = static_cast<int32>(pvField->getNumberFields());
|
||||
next = pbitSet->nextSetBit(static_cast<uint32>(offset));
|
||||
// no more changes
|
||||
if(next<0) return;
|
||||
// no change in this pvField
|
||||
if(next>=static_cast<int32>(offset+inumberFields)) continue;
|
||||
|
||||
// deserialize field or fields
|
||||
if(inumberFields==1) {
|
||||
pvField->deserialize(pbuffer, pcontrol);
|
||||
} else {
|
||||
PVStructurePtr pvStructure = std::tr1::static_pointer_cast<PVStructure>(pvField);
|
||||
pvStructure->deserialize(pbuffer, pcontrol, pbitSet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::ostream& PVStructure::dumpValue(std::ostream& o) const
|
||||
{
|
||||
o << format::indent() << getStructure()->getID() << ' ' << getFieldName();
|
||||
o << std::endl;
|
||||
{
|
||||
format::indent_scope s(o);
|
||||
|
||||
PVFieldPtrArray const & fieldsData = getPVFields();
|
||||
if (fieldsData.size() != 0) {
|
||||
size_t length = getStructure()->getNumberFields();
|
||||
for(size_t i=0; i<length; i++) {
|
||||
PVFieldPtr fieldField = fieldsData[i];
|
||||
Type type = fieldField->getField()->getType();
|
||||
if (type == scalar || type == scalarArray)
|
||||
o << format::indent() << fieldField->getField()->getID() << ' ' << fieldField->getFieldName() << ' ' << *(fieldField.get()) << std::endl;
|
||||
else
|
||||
o << *(fieldField.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
|
||||
void PVStructure::copy(const PVStructure& from)
|
||||
{
|
||||
if(isImmutable())
|
||||
throw std::invalid_argument("destination is immutable");
|
||||
|
||||
if(*getStructure() != *from.getStructure())
|
||||
throw std::invalid_argument("structure definitions do not match");
|
||||
|
||||
copyUnchecked(from);
|
||||
}
|
||||
|
||||
void PVStructure::copyUnchecked(const PVStructure& from)
|
||||
{
|
||||
if (this == &from)
|
||||
return;
|
||||
|
||||
PVFieldPtrArray const & fromPVFields = from.getPVFields();
|
||||
PVFieldPtrArray const & toPVFields = getPVFields();
|
||||
|
||||
size_t fieldsSize = fromPVFields.size();
|
||||
for(size_t i = 0; i<fieldsSize; i++) {
|
||||
toPVFields[i]->copyUnchecked(*fromPVFields[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void PVStructure::copyUnchecked(const PVStructure& from, const BitSet& maskBitSet, bool inverse)
|
||||
{
|
||||
if (this == &from)
|
||||
return;
|
||||
|
||||
size_t numberFields = from.getNumberFields();
|
||||
size_t offset = from.getFieldOffset();
|
||||
int32 next = inverse ?
|
||||
maskBitSet.nextClearBit(static_cast<uint32>(offset)) :
|
||||
maskBitSet.nextSetBit(static_cast<uint32>(offset));
|
||||
|
||||
// no more changes or no changes in this structure
|
||||
if(next<0||next>=static_cast<int32>(offset+numberFields)) return;
|
||||
|
||||
// entire structure
|
||||
if(static_cast<int32>(offset)==next) {
|
||||
copyUnchecked(from);
|
||||
return;
|
||||
}
|
||||
|
||||
PVFieldPtrArray const & fromPVFields = from.getPVFields();
|
||||
PVFieldPtrArray const & toPVFields = getPVFields();
|
||||
|
||||
size_t fieldsSize = fromPVFields.size();
|
||||
for(size_t i = 0; i<fieldsSize; i++) {
|
||||
PVFieldPtr pvField = fromPVFields[i];
|
||||
offset = pvField->getFieldOffset();
|
||||
int32 inumberFields = static_cast<int32>(pvField->getNumberFields());
|
||||
next = inverse ?
|
||||
maskBitSet.nextClearBit(static_cast<uint32>(offset)) :
|
||||
maskBitSet.nextSetBit(static_cast<uint32>(offset));
|
||||
|
||||
// no more changes
|
||||
if(next<0) return;
|
||||
// no change in this pvField
|
||||
if(next>=static_cast<int32>(offset+inumberFields)) continue;
|
||||
|
||||
// serialize field or fields
|
||||
if(inumberFields==1) {
|
||||
toPVFields[i]->copyUnchecked(*pvField);
|
||||
} else {
|
||||
PVStructure::shared_pointer fromPVStructure = std::tr1::static_pointer_cast<PVStructure>(pvField);
|
||||
PVStructure::shared_pointer toPVStructure = std::tr1::static_pointer_cast<PVStructure>(toPVFields[i]);
|
||||
toPVStructure->copyUnchecked(*fromPVStructure, maskBitSet, inverse);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}}
|
||||
263
src/factory/PVStructureArray.cpp
Normal file
263
src/factory/PVStructureArray.cpp
Normal file
@@ -0,0 +1,263 @@
|
||||
/*PVStructureArray.cpp*/
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
*/
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/factory.h>
|
||||
#include <pv/serializeHelper.h>
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using std::size_t;
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
size_t PVStructureArray::append(size_t number)
|
||||
{
|
||||
checkLength(value.size()+number);
|
||||
|
||||
svector data(reuse());
|
||||
data.resize(data.size()+number);
|
||||
|
||||
StructureConstPtr structure = structureArray->getStructure();
|
||||
|
||||
PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
||||
for(svector::reverse_iterator it = data.rbegin(); number; ++it, --number)
|
||||
*it = pvDataCreate->createPVStructure(structure);
|
||||
|
||||
size_t newLength = data.size();
|
||||
|
||||
const_svector cdata(freeze(data));
|
||||
swap(cdata);
|
||||
|
||||
return newLength;
|
||||
}
|
||||
|
||||
bool PVStructureArray::remove(size_t offset,size_t number)
|
||||
{
|
||||
if (number==0)
|
||||
return true;
|
||||
else if (offset+number>getLength())
|
||||
return false;
|
||||
else if (getArray()->getArraySizeType() == Array::fixed)
|
||||
return false;
|
||||
|
||||
svector vec(reuse());
|
||||
|
||||
size_t length = vec.size();
|
||||
|
||||
for(size_t i = offset; i+number < length; i++) {
|
||||
vec[i].swap(vec[i + number]);
|
||||
}
|
||||
|
||||
vec.resize(length - number);
|
||||
const_svector cdata(freeze(vec));
|
||||
swap(cdata);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PVStructureArray::compress() {
|
||||
if (getArray()->getArraySizeType() == Array::fixed)
|
||||
return;
|
||||
|
||||
svector vec(reuse()); // TODO: check for first NULL before realloc
|
||||
|
||||
size_t length = vec.size();
|
||||
size_t newLength = 0;
|
||||
|
||||
for(size_t i=0; i<length; i++) {
|
||||
if(vec[i].get()!=NULL) {
|
||||
newLength++;
|
||||
continue;
|
||||
}
|
||||
// find first non 0
|
||||
size_t notNull = 0;
|
||||
for(size_t j=i+1;j<length;j++) {
|
||||
if(vec[j].get()!=NULL) {
|
||||
notNull = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(notNull!=0) {
|
||||
vec[i] = vec[notNull];
|
||||
vec[notNull].reset();
|
||||
newLength++;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
vec.resize(newLength);
|
||||
const_svector cdata(freeze(vec));
|
||||
swap(cdata);
|
||||
}
|
||||
|
||||
void PVStructureArray::setCapacity(size_t capacity)
|
||||
{
|
||||
if (this->isCapacityMutable()) {
|
||||
checkLength(capacity);
|
||||
const_svector value;
|
||||
swap(value);
|
||||
if(value.capacity()<capacity) {
|
||||
svector mvalue(thaw(value));
|
||||
mvalue.reserve(capacity);
|
||||
value = freeze(mvalue);
|
||||
}
|
||||
swap(value);
|
||||
}
|
||||
else
|
||||
THROW_EXCEPTION2(std::logic_error, "capacity immutable");
|
||||
}
|
||||
|
||||
void PVStructureArray::setLength(size_t length)
|
||||
{
|
||||
if(this->isImmutable())
|
||||
THROW_EXCEPTION2(std::logic_error, "immutable");
|
||||
const_svector value;
|
||||
swap(value);
|
||||
|
||||
if (length == value.size())
|
||||
return;
|
||||
|
||||
checkLength(length);
|
||||
|
||||
if (length < value.size()) {
|
||||
value.slice(0, length);
|
||||
} else {
|
||||
svector mvalue(thaw(value));
|
||||
mvalue.resize(length);
|
||||
value = freeze(mvalue);
|
||||
}
|
||||
swap(value);
|
||||
}
|
||||
|
||||
void PVStructureArray::swap(const_svector &other)
|
||||
{
|
||||
if (this->isImmutable())
|
||||
THROW_EXCEPTION2(std::logic_error, "immutable");
|
||||
|
||||
// no checkLength call here
|
||||
|
||||
value.swap(other);
|
||||
}
|
||||
|
||||
void PVStructureArray::serialize(ByteBuffer *pbuffer,
|
||||
SerializableControl *pflusher) const {
|
||||
serialize(pbuffer, pflusher, 0, getLength());
|
||||
}
|
||||
|
||||
void PVStructureArray::deserialize(ByteBuffer *pbuffer,
|
||||
DeserializableControl *pcontrol) {
|
||||
svector data(reuse());
|
||||
|
||||
size_t size = this->getArray()->getArraySizeType() == Array::fixed ?
|
||||
this->getArray()->getMaximumCapacity() :
|
||||
SerializeHelper::readSize(pbuffer, pcontrol);
|
||||
|
||||
data.resize(size);
|
||||
|
||||
StructureConstPtr structure = structureArray->getStructure();
|
||||
|
||||
PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
||||
|
||||
for(size_t i = 0; i<size; i++) {
|
||||
pcontrol->ensureData(1);
|
||||
size_t temp = pbuffer->getByte();
|
||||
if(temp==0) {
|
||||
data[i].reset();
|
||||
}
|
||||
else {
|
||||
if(data[i].get()==NULL || !data[i].unique()) {
|
||||
data[i] = pvDataCreate->createPVStructure(structure);
|
||||
}
|
||||
data[i]->deserialize(pbuffer, pcontrol);
|
||||
}
|
||||
}
|
||||
replace(freeze(data)); // calls postPut()
|
||||
}
|
||||
|
||||
void PVStructureArray::serialize(ByteBuffer *pbuffer,
|
||||
SerializableControl *pflusher, size_t offset, size_t count) const {
|
||||
|
||||
const_svector temp(view());
|
||||
temp.slice(offset, count);
|
||||
|
||||
ArrayConstPtr array = this->getArray();
|
||||
if (array->getArraySizeType() != Array::fixed)
|
||||
SerializeHelper::writeSize(temp.size(), pbuffer, pflusher);
|
||||
else if (count != array->getMaximumCapacity())
|
||||
throw std::length_error("fixed array cannot be partially serialized");
|
||||
|
||||
for(size_t i = 0; i<count; i++) {
|
||||
if(pbuffer->getRemaining()<1)
|
||||
pflusher->flushSerializeBuffer();
|
||||
|
||||
if(temp[i].get()==NULL) {
|
||||
pbuffer->putByte(0);
|
||||
}
|
||||
else {
|
||||
pbuffer->putByte(1);
|
||||
temp[i]->serialize(pbuffer, pflusher);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::ostream& PVStructureArray::dumpValue(std::ostream& o) const
|
||||
{
|
||||
o << format::indent() << getStructureArray()->getID() << ' ' << getFieldName() << std::endl;
|
||||
size_t length = getLength();
|
||||
if (length > 0)
|
||||
{
|
||||
format::indent_scope s(o);
|
||||
|
||||
for (size_t i = 0; i < length; i++)
|
||||
dumpValue(o, i);
|
||||
}
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
std::ostream& PVStructureArray::dumpValue(std::ostream& o, std::size_t index) const
|
||||
{
|
||||
const_svector temp(view());
|
||||
if (index<temp.size())
|
||||
{
|
||||
if (temp[index])
|
||||
o << *temp[index];
|
||||
else
|
||||
o << format::indent() << "(none)" << std::endl;
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
void PVStructureArray::copy(const PVStructureArray& from)
|
||||
{
|
||||
if(isImmutable())
|
||||
throw std::invalid_argument("destination is immutable");
|
||||
|
||||
if(*getStructureArray() != *from.getStructureArray())
|
||||
throw std::invalid_argument("structureArray definitions do not match");
|
||||
|
||||
copyUnchecked(from);
|
||||
}
|
||||
|
||||
void PVStructureArray::copyUnchecked(const PVStructureArray& from)
|
||||
{
|
||||
if (this == &from)
|
||||
return;
|
||||
|
||||
replace(from.view());
|
||||
}
|
||||
|
||||
}}
|
||||
274
src/factory/PVUnion.cpp
Normal file
274
src/factory/PVUnion.cpp
Normal file
@@ -0,0 +1,274 @@
|
||||
/*PVUnion.cpp*/
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mse
|
||||
*/
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <vector>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/pvIntrospect.h>
|
||||
#include <pv/factory.h>
|
||||
#include <pv/serializeHelper.h>
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using std::size_t;
|
||||
using std::string;
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
#define PVUNION_UNDEFINED_INDEX -1
|
||||
int32 PVUnion::UNDEFINED_INDEX = PVUNION_UNDEFINED_INDEX;
|
||||
|
||||
PVDataCreatePtr PVUnion::pvDataCreate(getPVDataCreate());
|
||||
|
||||
PVUnion::PVUnion(UnionConstPtr const & unionPtr)
|
||||
: PVField(unionPtr),
|
||||
unionPtr(unionPtr),
|
||||
selector(PVUNION_UNDEFINED_INDEX), // to allow out-of-order static initialization
|
||||
value(),
|
||||
variant(unionPtr->isVariant())
|
||||
{
|
||||
}
|
||||
|
||||
#undef PVUNION_UNDEFINED_INDEX
|
||||
|
||||
PVUnion::~PVUnion()
|
||||
{
|
||||
}
|
||||
|
||||
UnionConstPtr PVUnion::getUnion() const
|
||||
{
|
||||
return unionPtr;
|
||||
}
|
||||
|
||||
PVFieldPtr PVUnion::get() const
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
int32 PVUnion::getSelectedIndex() const
|
||||
{
|
||||
return selector;
|
||||
}
|
||||
|
||||
string PVUnion::getSelectedFieldName() const
|
||||
{
|
||||
// no name for undefined and for variant unions
|
||||
if (selector == UNDEFINED_INDEX)
|
||||
return string();
|
||||
else
|
||||
return unionPtr->getFieldName(selector);
|
||||
}
|
||||
|
||||
PVFieldPtr PVUnion::select(int32 index)
|
||||
{
|
||||
// no change
|
||||
if (selector == index)
|
||||
return value;
|
||||
|
||||
if (index == UNDEFINED_INDEX)
|
||||
{
|
||||
selector = UNDEFINED_INDEX;
|
||||
value.reset();
|
||||
return value;
|
||||
}
|
||||
else if (variant)
|
||||
throw std::invalid_argument("index out of bounds");
|
||||
else if (index < 0 || index > static_cast<int32>(unionPtr->getFields().size()))
|
||||
throw std::invalid_argument("index out of bounds");
|
||||
|
||||
FieldConstPtr field = unionPtr->getField(index);
|
||||
selector = index;
|
||||
value = pvDataCreate->createPVField(field);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
PVFieldPtr PVUnion::select(string const & fieldName)
|
||||
{
|
||||
int32 index = variant ? -1 : static_cast<int32>(unionPtr->getFieldIndex(fieldName));
|
||||
if (index == -1)
|
||||
throw std::invalid_argument("no such fieldName");
|
||||
return select(index);
|
||||
}
|
||||
|
||||
void PVUnion::set(PVFieldPtr const & value)
|
||||
{
|
||||
set(selector, value);
|
||||
}
|
||||
|
||||
void PVUnion::set(int32 index, PVFieldPtr const & value)
|
||||
{
|
||||
if (variant && index != UNDEFINED_INDEX)
|
||||
throw std::invalid_argument("index out of bounds");
|
||||
else if (!variant)
|
||||
{
|
||||
if (index == UNDEFINED_INDEX)
|
||||
{
|
||||
// for undefined index we accept only null values
|
||||
if (value.get())
|
||||
throw std::invalid_argument("non-null value for index == UNDEFINED_INDEX");
|
||||
}
|
||||
else if (index < 0 || index > static_cast<int32>(unionPtr->getFields().size()))
|
||||
throw std::invalid_argument("index out of bounds");
|
||||
|
||||
// value type must match
|
||||
if (value->getField() != unionPtr->getField(index))
|
||||
throw std::invalid_argument("selected field and its introspection data do not match");
|
||||
}
|
||||
|
||||
selector = index;
|
||||
this->value = value;
|
||||
postPut();
|
||||
}
|
||||
|
||||
void PVUnion::set(string const & fieldName, PVFieldPtr const & value)
|
||||
{
|
||||
int32 index = variant ? -1 : static_cast<int32>(unionPtr->getFieldIndex(fieldName));
|
||||
if (index == -1)
|
||||
throw std::invalid_argument("no such fieldName");
|
||||
|
||||
set(index, value);
|
||||
}
|
||||
|
||||
void PVUnion::serialize(ByteBuffer *pbuffer, SerializableControl *pflusher) const
|
||||
{
|
||||
if (variant)
|
||||
{
|
||||
// write introspection data
|
||||
if (value.get() == 0)
|
||||
pbuffer->put((int8)-1);
|
||||
else
|
||||
{
|
||||
pflusher->cachedSerialize(value->getField(), pbuffer);
|
||||
value->serialize(pbuffer, pflusher);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// write selector value
|
||||
SerializeHelper::writeSize(selector, pbuffer, pflusher);
|
||||
// write value, no value for UNDEFINED_INDEX
|
||||
if (selector != UNDEFINED_INDEX)
|
||||
value->serialize(pbuffer, pflusher);
|
||||
}
|
||||
}
|
||||
|
||||
void PVUnion::deserialize(ByteBuffer *pbuffer, DeserializableControl *pcontrol)
|
||||
{
|
||||
if (variant)
|
||||
{
|
||||
FieldConstPtr field = pcontrol->cachedDeserialize(pbuffer);
|
||||
if (field.get())
|
||||
{
|
||||
// try to reuse existing field instance
|
||||
if (!value.get() || *value->getField() != *field)
|
||||
value = pvDataCreate->createPVField(field);
|
||||
value->deserialize(pbuffer, pcontrol);
|
||||
}
|
||||
else
|
||||
value.reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
int32 previousSelector = selector;
|
||||
selector = static_cast<int32>(SerializeHelper::readSize(pbuffer, pcontrol));
|
||||
if (selector != UNDEFINED_INDEX)
|
||||
{
|
||||
if (selector != previousSelector)
|
||||
{
|
||||
FieldConstPtr field = unionPtr->getField(selector);
|
||||
// try to reuse existing field instance
|
||||
if (!value.get() || *value->getField() != *field)
|
||||
value = pvDataCreate->createPVField(field);
|
||||
}
|
||||
value->deserialize(pbuffer, pcontrol);
|
||||
}
|
||||
else
|
||||
value.reset();
|
||||
}
|
||||
}
|
||||
|
||||
std::ostream& PVUnion::dumpValue(std::ostream& o) const
|
||||
{
|
||||
o << format::indent() << getUnion()->getID() << ' ' << getFieldName() << std::endl;
|
||||
{
|
||||
format::indent_scope s(o);
|
||||
PVFieldPtr fieldField = get();
|
||||
if (fieldField.get() == NULL)
|
||||
o << format::indent() << "(none)" << std::endl;
|
||||
else
|
||||
{
|
||||
Type type = fieldField->getField()->getType();
|
||||
if (type == scalar || type == scalarArray)
|
||||
o << format::indent() << fieldField->getField()->getID() << ' ' << fieldField->getFieldName() << ' ' << *(fieldField.get()) << std::endl;
|
||||
else
|
||||
o << *(fieldField.get());
|
||||
}
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
void PVUnion::copy(const PVUnion& from)
|
||||
{
|
||||
if(isImmutable())
|
||||
throw std::invalid_argument("destination is immutable");
|
||||
|
||||
if(*getUnion() != *from.getUnion())
|
||||
throw std::invalid_argument("union definitions do not match");
|
||||
|
||||
copyUnchecked(from);
|
||||
}
|
||||
|
||||
void PVUnion::copyUnchecked(const PVUnion& from)
|
||||
{
|
||||
|
||||
PVFieldPtr fromValue = from.get();
|
||||
if (from.getUnion()->isVariant())
|
||||
{
|
||||
if (fromValue.get() == 0)
|
||||
{
|
||||
set(PVField::shared_pointer());
|
||||
}
|
||||
else
|
||||
{
|
||||
PVFieldPtr toValue = get();
|
||||
if (toValue.get() == 0 || *toValue->getField() != *fromValue->getField())
|
||||
{
|
||||
toValue = pvDataCreate->createPVField(fromValue->getField());
|
||||
toValue->copyUnchecked(*fromValue);
|
||||
set(toValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
toValue->copyUnchecked(*fromValue);
|
||||
postPut();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fromValue.get() == 0)
|
||||
{
|
||||
select(PVUnion::UNDEFINED_INDEX);
|
||||
}
|
||||
else
|
||||
{
|
||||
select(from.getSelectedIndex())->copyUnchecked(*fromValue);
|
||||
}
|
||||
postPut();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}}
|
||||
263
src/factory/PVUnionArray.cpp
Normal file
263
src/factory/PVUnionArray.cpp
Normal file
@@ -0,0 +1,263 @@
|
||||
/*PVUnionArray.cpp*/
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
*/
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/factory.h>
|
||||
#include <pv/serializeHelper.h>
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using std::size_t;
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
size_t PVUnionArray::append(size_t number)
|
||||
{
|
||||
checkLength(value.size()+number);
|
||||
|
||||
svector data(reuse());
|
||||
data.resize(data.size()+number);
|
||||
|
||||
UnionConstPtr punion = unionArray->getUnion();
|
||||
|
||||
PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
||||
for(svector::reverse_iterator it = data.rbegin(); number; ++it, --number)
|
||||
*it = pvDataCreate->createPVUnion(punion);
|
||||
|
||||
size_t newLength = data.size();
|
||||
|
||||
const_svector cdata(freeze(data));
|
||||
swap(cdata);
|
||||
|
||||
return newLength;
|
||||
}
|
||||
|
||||
bool PVUnionArray::remove(size_t offset,size_t number)
|
||||
{
|
||||
if (number==0)
|
||||
return true;
|
||||
else if (offset+number>getLength())
|
||||
return false;
|
||||
else if (getArray()->getArraySizeType() == Array::fixed)
|
||||
return false;
|
||||
|
||||
svector vec(reuse());
|
||||
|
||||
size_t length = vec.size();
|
||||
|
||||
for(size_t i = offset; i+number < length; i++) {
|
||||
vec[i].swap(vec[i + number]);
|
||||
}
|
||||
|
||||
vec.resize(length - number);
|
||||
const_svector cdata(freeze(vec));
|
||||
swap(cdata);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PVUnionArray::compress() {
|
||||
if (getArray()->getArraySizeType() == Array::fixed)
|
||||
return;
|
||||
|
||||
svector vec(reuse()); // TODO: check for first NULL before realloc
|
||||
|
||||
size_t length = vec.size();
|
||||
size_t newLength = 0;
|
||||
|
||||
for(size_t i=0; i<length; i++) {
|
||||
if(vec[i].get()!=NULL) {
|
||||
newLength++;
|
||||
continue;
|
||||
}
|
||||
// find first non 0
|
||||
size_t notNull = 0;
|
||||
for(size_t j=i+1;j<length;j++) {
|
||||
if(vec[j].get()!=NULL) {
|
||||
notNull = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(notNull!=0) {
|
||||
vec[i] = vec[notNull];
|
||||
vec[notNull].reset();
|
||||
newLength++;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
vec.resize(newLength);
|
||||
const_svector cdata(freeze(vec));
|
||||
swap(cdata);
|
||||
}
|
||||
|
||||
void PVUnionArray::setCapacity(size_t capacity)
|
||||
{
|
||||
if(this->isCapacityMutable()) {
|
||||
checkLength(capacity);
|
||||
const_svector value;
|
||||
swap(value);
|
||||
if(value.capacity()<capacity) {
|
||||
svector mvalue(thaw(value));
|
||||
mvalue.reserve(capacity);
|
||||
value = freeze(mvalue);
|
||||
}
|
||||
swap(value);
|
||||
}
|
||||
else
|
||||
THROW_EXCEPTION2(std::logic_error, "capacity immutable");
|
||||
}
|
||||
|
||||
void PVUnionArray::setLength(size_t length)
|
||||
{
|
||||
if(this->isImmutable())
|
||||
THROW_EXCEPTION2(std::logic_error, "immutable");
|
||||
const_svector value;
|
||||
swap(value);
|
||||
if (length == value.size())
|
||||
return;
|
||||
|
||||
checkLength(length);
|
||||
|
||||
if (length < value.size()) {
|
||||
value.slice(0, length);
|
||||
} else {
|
||||
svector mvalue(thaw(value));
|
||||
mvalue.resize(length);
|
||||
value = freeze(mvalue);
|
||||
}
|
||||
swap(value);
|
||||
}
|
||||
|
||||
void PVUnionArray::swap(const_svector &other)
|
||||
{
|
||||
if(this->isImmutable())
|
||||
THROW_EXCEPTION2(std::logic_error,"Immutable");
|
||||
|
||||
// no checkLength call here
|
||||
|
||||
value.swap(other);
|
||||
}
|
||||
|
||||
void PVUnionArray::serialize(ByteBuffer *pbuffer,
|
||||
SerializableControl *pflusher) const {
|
||||
serialize(pbuffer, pflusher, 0, getLength());
|
||||
}
|
||||
|
||||
void PVUnionArray::deserialize(ByteBuffer *pbuffer,
|
||||
DeserializableControl *pcontrol) {
|
||||
svector data(reuse());
|
||||
|
||||
size_t size = this->getArray()->getArraySizeType() == Array::fixed ?
|
||||
this->getArray()->getMaximumCapacity() :
|
||||
SerializeHelper::readSize(pbuffer, pcontrol);
|
||||
|
||||
data.resize(size);
|
||||
|
||||
UnionConstPtr punion = unionArray->getUnion();
|
||||
|
||||
PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
||||
|
||||
for(size_t i = 0; i<size; i++) {
|
||||
pcontrol->ensureData(1);
|
||||
size_t temp = pbuffer->getByte();
|
||||
if(temp==0) {
|
||||
data[i].reset();
|
||||
}
|
||||
else {
|
||||
if(data[i].get()==NULL || !data[i].unique()) {
|
||||
data[i] = pvDataCreate->createPVUnion(punion);
|
||||
}
|
||||
data[i]->deserialize(pbuffer, pcontrol);
|
||||
}
|
||||
}
|
||||
replace(freeze(data)); // calls postPut()
|
||||
}
|
||||
|
||||
void PVUnionArray::serialize(ByteBuffer *pbuffer,
|
||||
SerializableControl *pflusher, size_t offset, size_t count) const {
|
||||
|
||||
const_svector temp(view());
|
||||
temp.slice(offset, count);
|
||||
|
||||
ArrayConstPtr array = this->getArray();
|
||||
if (array->getArraySizeType() != Array::fixed)
|
||||
SerializeHelper::writeSize(temp.size(), pbuffer, pflusher);
|
||||
else if (count != array->getMaximumCapacity())
|
||||
throw std::length_error("fixed array cannot be partially serialized");
|
||||
|
||||
for(size_t i = 0; i<count; i++) {
|
||||
if(pbuffer->getRemaining()<1)
|
||||
pflusher->flushSerializeBuffer();
|
||||
|
||||
if(temp[i].get()==NULL) {
|
||||
pbuffer->putByte(0);
|
||||
}
|
||||
else {
|
||||
pbuffer->putByte(1);
|
||||
temp[i]->serialize(pbuffer, pflusher);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::ostream& PVUnionArray::dumpValue(std::ostream& o) const
|
||||
{
|
||||
o << format::indent() << getUnionArray()->getID() << ' ' << getFieldName() << std::endl;
|
||||
size_t length = getLength();
|
||||
if (length > 0)
|
||||
{
|
||||
format::indent_scope s(o);
|
||||
|
||||
for (size_t i = 0; i < length; i++)
|
||||
dumpValue(o, i);
|
||||
}
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
std::ostream& PVUnionArray::dumpValue(std::ostream& o, std::size_t index) const
|
||||
{
|
||||
const_svector temp(view());
|
||||
if (index<temp.size())
|
||||
{
|
||||
if (temp[index])
|
||||
o << *temp[index];
|
||||
else
|
||||
o << format::indent() << "(none)" << std::endl;
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
void PVUnionArray::copy(const PVUnionArray& from)
|
||||
{
|
||||
if(isImmutable())
|
||||
throw std::invalid_argument("destination is immutable");
|
||||
|
||||
if(*getUnionArray() != *from.getUnionArray())
|
||||
throw std::invalid_argument("unionArray definitions do not match");
|
||||
|
||||
copyUnchecked(from);
|
||||
}
|
||||
|
||||
void PVUnionArray::copyUnchecked(const PVUnionArray& from)
|
||||
{
|
||||
if (this == &from)
|
||||
return;
|
||||
|
||||
replace(from.view());
|
||||
}
|
||||
|
||||
|
||||
}}
|
||||
@@ -10,13 +10,14 @@
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <stdexcept>
|
||||
#include <epicsThread.h>
|
||||
#include <epicsExit.h>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/lock.h>
|
||||
#include <pv/pvIntrospect.h>
|
||||
#include <pv/standardField.h>
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using std::string;
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
@@ -49,7 +50,7 @@ void StandardField::init()
|
||||
|
||||
StandardField::~StandardField(){}
|
||||
|
||||
StructureConstPtr StandardField::createProperties(String id,FieldConstPtr field,String properties)
|
||||
StructureConstPtr StandardField::createProperties(string id,FieldConstPtr field,string properties)
|
||||
{
|
||||
bool gotAlarm = false;
|
||||
bool gotTimeStamp = false;
|
||||
@@ -57,11 +58,11 @@ StructureConstPtr StandardField::createProperties(String id,FieldConstPtr field,
|
||||
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++; }
|
||||
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) {
|
||||
@@ -82,19 +83,19 @@ StructureConstPtr StandardField::createProperties(String id,FieldConstPtr field,
|
||||
case pvFloat: valueAlarm = floatAlarmField; break;
|
||||
case pvDouble: valueAlarm = doubleAlarmField; break;
|
||||
case pvString:
|
||||
throw std::logic_error(String("valueAlarm property not supported for pvString"));
|
||||
throw std::logic_error(string("valueAlarm property not supported for pvString"));
|
||||
}
|
||||
break;
|
||||
}
|
||||
if(type==structure) {
|
||||
StructureConstPtr structurePtr = static_pointer_cast<const Structure>(field);
|
||||
StringArray names = structurePtr->getFieldNames();
|
||||
StringArray const & names = structurePtr->getFieldNames();
|
||||
if(names.size()==2) {
|
||||
FieldConstPtrArray fields = structurePtr->getFields();
|
||||
FieldConstPtrArray const & fields = structurePtr->getFields();
|
||||
FieldConstPtr first = fields[0];
|
||||
FieldConstPtr second = fields[1];
|
||||
String nameFirst = names[0];
|
||||
String nameSecond = names[1];
|
||||
string nameFirst = names[0];
|
||||
string nameSecond = names[1];
|
||||
int compareFirst = nameFirst.compare("index");
|
||||
int compareSecond = nameSecond.compare("choices");
|
||||
if(compareFirst==0 && compareSecond==0) {
|
||||
@@ -112,7 +113,7 @@ StructureConstPtr StandardField::createProperties(String id,FieldConstPtr field,
|
||||
}
|
||||
}
|
||||
}
|
||||
throw std::logic_error(String("valueAlarm property for illegal type"));
|
||||
throw std::logic_error(string("valueAlarm property for illegal type"));
|
||||
}
|
||||
size_t numFields = numProp+1;
|
||||
FieldConstPtrArray fields(numFields);
|
||||
@@ -161,7 +162,7 @@ void StandardField::createTimeStamp() {
|
||||
FieldConstPtrArray fields(num);
|
||||
StringArray names(num);
|
||||
names[0] = "secondsPastEpoch";
|
||||
names[1] = "nanoSeconds";
|
||||
names[1] = "nanoseconds";
|
||||
names[2] = "userTag";
|
||||
fields[0] = fieldCreate->createScalar(pvLong);
|
||||
fields[1] = fieldCreate->createScalar(pvInt);
|
||||
@@ -227,7 +228,7 @@ void StandardField::createByteAlarm() {
|
||||
names[6] = "lowWarningSeverity";
|
||||
names[7] = "highWarningSeverity";
|
||||
names[8] = "highAlarmSeverity";
|
||||
names[9] = "hystersis";
|
||||
names[9] = "hysteresis";
|
||||
fields[0] = fieldCreate->createScalar(pvBoolean);
|
||||
fields[1] = fieldCreate->createScalar(pvByte);
|
||||
fields[2] = fieldCreate->createScalar(pvByte);
|
||||
@@ -254,7 +255,7 @@ void StandardField::createShortAlarm() {
|
||||
names[6] = "lowWarningSeverity";
|
||||
names[7] = "highWarningSeverity";
|
||||
names[8] = "highAlarmSeverity";
|
||||
names[9] = "hystersis";
|
||||
names[9] = "hysteresis";
|
||||
fields[0] = fieldCreate->createScalar(pvBoolean);
|
||||
fields[1] = fieldCreate->createScalar(pvShort);
|
||||
fields[2] = fieldCreate->createScalar(pvShort);
|
||||
@@ -281,7 +282,7 @@ void StandardField::createIntAlarm() {
|
||||
names[6] = "lowWarningSeverity";
|
||||
names[7] = "highWarningSeverity";
|
||||
names[8] = "highAlarmSeverity";
|
||||
names[9] = "hystersis";
|
||||
names[9] = "hysteresis";
|
||||
fields[0] = fieldCreate->createScalar(pvBoolean);
|
||||
fields[1] = fieldCreate->createScalar(pvInt);
|
||||
fields[2] = fieldCreate->createScalar(pvInt);
|
||||
@@ -308,7 +309,7 @@ void StandardField::createLongAlarm() {
|
||||
names[6] = "lowWarningSeverity";
|
||||
names[7] = "highWarningSeverity";
|
||||
names[8] = "highAlarmSeverity";
|
||||
names[9] = "hystersis";
|
||||
names[9] = "hysteresis";
|
||||
fields[0] = fieldCreate->createScalar(pvBoolean);
|
||||
fields[1] = fieldCreate->createScalar(pvLong);
|
||||
fields[2] = fieldCreate->createScalar(pvLong);
|
||||
@@ -335,7 +336,7 @@ void StandardField::createUByteAlarm() {
|
||||
names[6] = "lowWarningSeverity";
|
||||
names[7] = "highWarningSeverity";
|
||||
names[8] = "highAlarmSeverity";
|
||||
names[9] = "hystersis";
|
||||
names[9] = "hysteresis";
|
||||
fields[0] = fieldCreate->createScalar(pvBoolean);
|
||||
fields[1] = fieldCreate->createScalar(pvUByte);
|
||||
fields[2] = fieldCreate->createScalar(pvUByte);
|
||||
@@ -362,7 +363,7 @@ void StandardField::createUShortAlarm() {
|
||||
names[6] = "lowWarningSeverity";
|
||||
names[7] = "highWarningSeverity";
|
||||
names[8] = "highAlarmSeverity";
|
||||
names[9] = "hystersis";
|
||||
names[9] = "hysteresis";
|
||||
fields[0] = fieldCreate->createScalar(pvBoolean);
|
||||
fields[1] = fieldCreate->createScalar(pvUShort);
|
||||
fields[2] = fieldCreate->createScalar(pvUShort);
|
||||
@@ -389,7 +390,7 @@ void StandardField::createUIntAlarm() {
|
||||
names[6] = "lowWarningSeverity";
|
||||
names[7] = "highWarningSeverity";
|
||||
names[8] = "highAlarmSeverity";
|
||||
names[9] = "hystersis";
|
||||
names[9] = "hysteresis";
|
||||
fields[0] = fieldCreate->createScalar(pvBoolean);
|
||||
fields[1] = fieldCreate->createScalar(pvUInt);
|
||||
fields[2] = fieldCreate->createScalar(pvUInt);
|
||||
@@ -416,7 +417,7 @@ void StandardField::createULongAlarm() {
|
||||
names[6] = "lowWarningSeverity";
|
||||
names[7] = "highWarningSeverity";
|
||||
names[8] = "highAlarmSeverity";
|
||||
names[9] = "hystersis";
|
||||
names[9] = "hysteresis";
|
||||
fields[0] = fieldCreate->createScalar(pvBoolean);
|
||||
fields[1] = fieldCreate->createScalar(pvULong);
|
||||
fields[2] = fieldCreate->createScalar(pvULong);
|
||||
@@ -443,7 +444,7 @@ void StandardField::createFloatAlarm() {
|
||||
names[6] = "lowWarningSeverity";
|
||||
names[7] = "highWarningSeverity";
|
||||
names[8] = "highAlarmSeverity";
|
||||
names[9] = "hystersis";
|
||||
names[9] = "hysteresis";
|
||||
fields[0] = fieldCreate->createScalar(pvBoolean);
|
||||
fields[1] = fieldCreate->createScalar(pvFloat);
|
||||
fields[2] = fieldCreate->createScalar(pvFloat);
|
||||
@@ -470,7 +471,7 @@ void StandardField::createDoubleAlarm() {
|
||||
names[6] = "lowWarningSeverity";
|
||||
names[7] = "highWarningSeverity";
|
||||
names[8] = "highAlarmSeverity";
|
||||
names[9] = "hystersis";
|
||||
names[9] = "hysteresis";
|
||||
fields[0] = fieldCreate->createScalar(pvBoolean);
|
||||
fields[1] = fieldCreate->createScalar(pvDouble);
|
||||
fields[2] = fieldCreate->createScalar(pvDouble);
|
||||
@@ -499,26 +500,48 @@ void StandardField::createEnumeratedAlarm() {
|
||||
|
||||
|
||||
StructureConstPtr StandardField::scalar(
|
||||
ScalarType type,String const &properties)
|
||||
ScalarType type,string const &properties)
|
||||
{
|
||||
ScalarConstPtr field = fieldCreate->createScalar(type); // scalar_t
|
||||
return createProperties("uri:ev4:nt/2012/pwd:NTScalar",field,properties);
|
||||
return createProperties("epics:nt/NTScalar:1.0",field,properties);
|
||||
}
|
||||
|
||||
StructureConstPtr StandardField::regUnion(
|
||||
UnionConstPtr const &field,
|
||||
string const & properties)
|
||||
{
|
||||
return createProperties("epics:nt/NTUnion:1.0",field,properties);
|
||||
}
|
||||
|
||||
StructureConstPtr StandardField::variantUnion(
|
||||
string const & properties)
|
||||
{
|
||||
UnionConstPtr field = fieldCreate->createVariantUnion();
|
||||
return createProperties("epics:nt/NTUnion:1.0",field,properties);
|
||||
}
|
||||
|
||||
StructureConstPtr StandardField::scalarArray(
|
||||
ScalarType elementType, String const &properties)
|
||||
ScalarType elementType, string const &properties)
|
||||
{
|
||||
ScalarArrayConstPtr field = fieldCreate->createScalarArray(elementType); // scalar_t[]
|
||||
return createProperties("uri:ev4:nt/2012/pwd:NTScalarArray",field,properties);
|
||||
return createProperties("epics:nt/NTScalarArray:1.0",field,properties);
|
||||
}
|
||||
|
||||
|
||||
StructureConstPtr StandardField::structureArray(
|
||||
StructureConstPtr const & structure,String const &properties)
|
||||
StructureConstPtr const & structure,string const &properties)
|
||||
{
|
||||
StructureArrayConstPtr field = fieldCreate->createStructureArray(
|
||||
structure);
|
||||
return createProperties("uri:ev4:nt/2012/pwd:NTAny",field,properties);
|
||||
return createProperties("epics:nt/NTStructureArray:1.0",field,properties);
|
||||
}
|
||||
|
||||
StructureConstPtr StandardField::unionArray(
|
||||
UnionConstPtr const & punion,string const &properties)
|
||||
{
|
||||
UnionArrayConstPtr field = fieldCreate->createUnionArray(
|
||||
punion);
|
||||
return createProperties("epics:nt/NTUnionArray:1.0",field,properties);
|
||||
}
|
||||
|
||||
StructureConstPtr StandardField::enumerated()
|
||||
@@ -531,13 +554,13 @@ StructureConstPtr StandardField::enumerated()
|
||||
fields[0] = fieldCreate->createScalar(pvInt);
|
||||
fields[1] = fieldCreate->createScalarArray(pvString);
|
||||
return fieldCreate->createStructure("enum_t",names,fields);
|
||||
// NOTE: if this method is used to get NTEnum wihtout properties the ID will be wrong!
|
||||
// NOTE: if this method is used to get NTEnum without properties the ID will be wrong!
|
||||
}
|
||||
|
||||
StructureConstPtr StandardField::enumerated(String const &properties)
|
||||
StructureConstPtr StandardField::enumerated(string const &properties)
|
||||
{
|
||||
StructureConstPtr field = enumerated(); // enum_t
|
||||
return createProperties("uri:ev4:nt/2012/pwd:NTEnum",field,properties);
|
||||
return createProperties("epics:nt/NTEnum:1.0",field,properties);
|
||||
}
|
||||
|
||||
StructureConstPtr StandardField::alarm()
|
||||
@@ -9,15 +9,16 @@
|
||||
*/
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <epicsThread.h>
|
||||
#include <epicsExit.h>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/lock.h>
|
||||
#include <pv/pvIntrospect.h>
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/convert.h>
|
||||
#include <pv/standardField.h>
|
||||
#include <pv/standardPVField.h>
|
||||
|
||||
using std::string;
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
StandardPVField::StandardPVField()
|
||||
@@ -30,7 +31,7 @@ StandardPVField::StandardPVField()
|
||||
StandardPVField::~StandardPVField(){}
|
||||
|
||||
PVStructurePtr StandardPVField::scalar(
|
||||
ScalarType type,String const & properties)
|
||||
ScalarType type,string const & properties)
|
||||
{
|
||||
StructureConstPtr field = standardField->scalar(type,properties);
|
||||
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(field);
|
||||
@@ -38,7 +39,7 @@ PVStructurePtr StandardPVField::scalar(
|
||||
}
|
||||
|
||||
PVStructurePtr StandardPVField::scalarArray(
|
||||
ScalarType elementType, String const & properties)
|
||||
ScalarType elementType, string const & properties)
|
||||
{
|
||||
StructureConstPtr field = standardField->scalarArray(elementType,properties);
|
||||
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(field);
|
||||
@@ -46,39 +47,39 @@ PVStructurePtr StandardPVField::scalarArray(
|
||||
}
|
||||
|
||||
PVStructurePtr StandardPVField::structureArray(
|
||||
StructureConstPtr const & structure,String const & properties)
|
||||
StructureConstPtr const & structure,string const & properties)
|
||||
{
|
||||
StructureConstPtr field = standardField->structureArray(structure,properties);
|
||||
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(field);
|
||||
return pvStructure;
|
||||
}
|
||||
|
||||
PVStructurePtr StandardPVField::unionArray(
|
||||
UnionConstPtr const & punion,string const & properties)
|
||||
{
|
||||
StructureConstPtr field = standardField->unionArray(punion,properties);
|
||||
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(field);
|
||||
return pvStructure;
|
||||
}
|
||||
|
||||
PVStructurePtr StandardPVField::enumerated(StringArray const &choices)
|
||||
{
|
||||
StructureConstPtr field = standardField->enumerated();
|
||||
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(field);
|
||||
PVScalarArrayPtr pvScalarArray = pvStructure->getScalarArrayField(
|
||||
"choices",pvString);
|
||||
if(pvScalarArray.get()==NULL) {
|
||||
throw std::logic_error(String("StandardPVField::enumerated"));
|
||||
}
|
||||
PVStringArray * pvChoices = static_cast<PVStringArray *>(pvScalarArray.get());
|
||||
pvChoices->put(0,choices.size(),get(choices),0);
|
||||
PVStringArray::svector cdata(choices.size());
|
||||
std::copy(choices.begin(), choices.end(), cdata.begin());
|
||||
pvStructure->getSubField<PVStringArray>("choices")->replace(freeze(cdata));
|
||||
return pvStructure;
|
||||
}
|
||||
|
||||
PVStructurePtr StandardPVField::enumerated(
|
||||
StringArray const &choices,String const & properties)
|
||||
StringArray const &choices,string const & properties)
|
||||
{
|
||||
StructureConstPtr field = standardField->enumerated(properties);
|
||||
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(field);
|
||||
PVScalarArrayPtr pvScalarArray = pvStructure->getScalarArrayField(
|
||||
"value.choices",pvString);
|
||||
if(pvScalarArray.get()==NULL) {
|
||||
throw std::logic_error(String("StandardPVField::enumerated"));
|
||||
}
|
||||
PVStringArray * pvChoices = static_cast<PVStringArray *>(pvScalarArray.get());
|
||||
pvChoices->put(0,choices.size(),get(choices),0);
|
||||
PVStringArray::svector cdata(choices.size());
|
||||
std::copy(choices.begin(), choices.end(), cdata.begin());
|
||||
pvStructure->getSubField<PVStringArray>("value.choices")->replace(freeze(cdata));
|
||||
return pvStructure;
|
||||
}
|
||||
|
||||
@@ -12,27 +12,33 @@
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/pvIntrospect.h>
|
||||
#include <pv/epicsException.h>
|
||||
#include <pv/sharedVector.h>
|
||||
|
||||
#include "dbDefs.h" // for NELEMENTS
|
||||
|
||||
using std::string;
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
namespace TypeFunc {
|
||||
static const char* names[] = {
|
||||
"scalar", "scalarArray", "structure", "structureArray",
|
||||
"scalar", "scalarArray", "structure", "structureArray", "union", "unionArray"
|
||||
};
|
||||
const char* name(Type t) {
|
||||
if (t<int(pvBoolean) || t>int(pvString))
|
||||
if (t<int(scalar) || t>int(unionArray))
|
||||
THROW_EXCEPTION2(std::invalid_argument, "logic error unknown Type");
|
||||
return names[t];
|
||||
}
|
||||
void toString(StringBuilder buf,const Type type) {
|
||||
*buf += name(type);
|
||||
}
|
||||
} // namespace TypeFunc
|
||||
|
||||
std::ostream& operator<<(std::ostream& o, const Type& type)
|
||||
{
|
||||
return o << TypeFunc::name(type);
|
||||
}
|
||||
|
||||
|
||||
namespace ScalarTypeFunc {
|
||||
bool isInteger(ScalarType type) {
|
||||
@@ -61,7 +67,7 @@ namespace ScalarTypeFunc {
|
||||
"ubyte", "ushort", "uint", "ulong",
|
||||
"float", "double", "string",
|
||||
};
|
||||
ScalarType getScalarType(String pvalue) {
|
||||
ScalarType getScalarType(const string& pvalue) {
|
||||
for(size_t i=0; i<NELEMENTS(names); i++)
|
||||
if(pvalue==names[i])
|
||||
return ScalarType(i);
|
||||
@@ -74,10 +80,55 @@ namespace ScalarTypeFunc {
|
||||
return names[t];
|
||||
}
|
||||
|
||||
void toString(StringBuilder buf,const ScalarType scalarType) {
|
||||
*buf += name(scalarType);
|
||||
size_t elementSize(ScalarType id)
|
||||
{
|
||||
switch(id) {
|
||||
#define OP(ENUM, TYPE) case ENUM: return sizeof(TYPE)
|
||||
OP(pvBoolean, boolean);
|
||||
OP(pvUByte, uint8);
|
||||
OP(pvByte, int8);
|
||||
OP(pvUShort, uint16);
|
||||
OP(pvShort, int16);
|
||||
OP(pvUInt, uint32);
|
||||
OP(pvInt, int32);
|
||||
OP(pvULong, uint64);
|
||||
OP(pvLong, int64);
|
||||
OP(pvFloat, float);
|
||||
OP(pvDouble, double);
|
||||
OP(pvString, string);
|
||||
#undef OP
|
||||
default:
|
||||
THROW_EXCEPTION2(std::invalid_argument, "error unknown ScalarType");
|
||||
}
|
||||
}
|
||||
|
||||
shared_vector<void> allocArray(ScalarType id, size_t len)
|
||||
{
|
||||
switch(id) {
|
||||
#define OP(ENUM, TYPE) case ENUM: return static_shared_vector_cast<void>(shared_vector<TYPE>(len))
|
||||
OP(pvBoolean, boolean);
|
||||
OP(pvUByte, uint8);
|
||||
OP(pvByte, int8);
|
||||
OP(pvUShort, uint16);
|
||||
OP(pvShort, int16);
|
||||
OP(pvUInt, uint32);
|
||||
OP(pvInt, int32);
|
||||
OP(pvULong, uint64);
|
||||
OP(pvLong, int64);
|
||||
OP(pvFloat, float);
|
||||
OP(pvDouble, double);
|
||||
OP(pvString, string);
|
||||
#undef OP
|
||||
default:
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ScalarTypeFunc
|
||||
|
||||
std::ostream& operator<<(std::ostream& o, const ScalarType& scalarType)
|
||||
{
|
||||
return o << ScalarTypeFunc::name(scalarType);
|
||||
}
|
||||
|
||||
}}
|
||||
45
src/factory/printer.cpp
Normal file
45
src/factory/printer.cpp
Normal file
@@ -0,0 +1,45 @@
|
||||
/* printer.cpp */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
|
||||
#include <deque>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/pvIntrospect.h>
|
||||
|
||||
using std::string;
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
namespace format
|
||||
{
|
||||
static int indent_index = std::ios_base::xalloc();
|
||||
|
||||
long& indent_value(std::ios_base& ios)
|
||||
{
|
||||
return ios.iword(indent_index);
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, indent_level const& indent)
|
||||
{
|
||||
indent_value(os) = indent.level;
|
||||
return os;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, indent const&)
|
||||
{
|
||||
long il = indent_value(os);
|
||||
std::size_t spaces = static_cast<std::size_t>(il) * 4;
|
||||
return os << string(spaces, ' ');
|
||||
}
|
||||
|
||||
array_at_internal operator<<(std::ostream& str, array_at const& manip)
|
||||
{
|
||||
return array_at_internal(manip.index, str);
|
||||
}
|
||||
};
|
||||
|
||||
}}
|
||||
276
src/factory/pvSubArrayCopy.cpp
Normal file
276
src/factory/pvSubArrayCopy.cpp
Normal file
@@ -0,0 +1,276 @@
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author Marty Kraimer
|
||||
* @date 2013.07
|
||||
*/
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <memory>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/pvSubArrayCopy.h>
|
||||
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
using std::string;
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
template<typename T>
|
||||
void copy(
|
||||
PVValueArray<T> & pvFrom,
|
||||
size_t fromOffset,
|
||||
size_t fromStride,
|
||||
PVValueArray<T> & pvTo,
|
||||
size_t toOffset,
|
||||
size_t toStride,
|
||||
size_t count)
|
||||
{
|
||||
if(pvTo.isImmutable()) throw std::invalid_argument("pvSubArrayCopy: pvTo is immutable");
|
||||
if(fromStride<1 || toStride<1) throw std::invalid_argument("stride must be >=1");
|
||||
size_t fromLength = pvFrom.getLength();
|
||||
size_t maxcount = (fromLength -fromOffset + fromStride -1)/fromStride;
|
||||
if(count>maxcount) throw std::invalid_argument("pvSubArrayCopy pvFrom length error");
|
||||
size_t newLength = toOffset + count*toStride;
|
||||
size_t capacity = pvTo.getCapacity();
|
||||
if(newLength>capacity) capacity = newLength;
|
||||
shared_vector<T> temp(capacity);
|
||||
typename PVValueArray<T>::const_svector vecFrom = pvFrom.view();
|
||||
typename PVValueArray<T>::const_svector vecTo = pvTo.view();
|
||||
for(size_t i=0; i<pvTo.getLength(); ++i) temp[i] = vecTo[i];
|
||||
for(size_t i=pvTo.getLength(); i< capacity; ++i) temp[i] = T();
|
||||
for(size_t i=0; i<count; ++i) temp[i*toStride + toOffset] = vecFrom[i*fromStride+fromOffset];
|
||||
shared_vector<const T> temp2(freeze(temp));
|
||||
pvTo.replace(temp2);
|
||||
}
|
||||
|
||||
void copy(
|
||||
PVScalarArray & from,
|
||||
size_t fromOffset,
|
||||
size_t fromStride,
|
||||
PVScalarArray & to,
|
||||
size_t toOffset,
|
||||
size_t toStride,
|
||||
size_t count)
|
||||
{
|
||||
ScalarType scalarType = from.getScalarArray()->getElementType();
|
||||
ScalarType otherType = to.getScalarArray()->getElementType();
|
||||
if(scalarType!=otherType) {
|
||||
throw std::invalid_argument("pvSubArrayCopy element types do not match");
|
||||
}
|
||||
switch(scalarType)
|
||||
{
|
||||
case pvBoolean:
|
||||
{
|
||||
copy(dynamic_cast<PVValueArray<boolean> &>(from),fromOffset,fromStride,
|
||||
dynamic_cast<PVValueArray<boolean>& >(to),
|
||||
toOffset,toStride,count);
|
||||
}
|
||||
break;
|
||||
case pvByte:
|
||||
{
|
||||
copy(dynamic_cast<PVValueArray<int8> &>(from),fromOffset,fromStride,
|
||||
dynamic_cast<PVValueArray<int8>& >(to),
|
||||
toOffset,toStride,count);
|
||||
}
|
||||
break;
|
||||
case pvShort:
|
||||
{
|
||||
copy(dynamic_cast<PVValueArray<int16> &>(from),fromOffset,fromStride,
|
||||
dynamic_cast<PVValueArray<int16>& >(to),
|
||||
toOffset,toStride,count);
|
||||
}
|
||||
break;
|
||||
case pvInt:
|
||||
{
|
||||
copy(dynamic_cast<PVValueArray<int32> &>(from),fromOffset,fromStride,
|
||||
dynamic_cast<PVValueArray<int32>& >(to),
|
||||
toOffset,toStride,count);
|
||||
}
|
||||
break;
|
||||
case pvLong:
|
||||
{
|
||||
copy(dynamic_cast<PVValueArray<int64> &>(from),fromOffset,fromStride,
|
||||
dynamic_cast<PVValueArray<int64>& >(to),
|
||||
toOffset,toStride,count);
|
||||
}
|
||||
break;
|
||||
case pvUByte:
|
||||
{
|
||||
copy(dynamic_cast<PVValueArray<uint8> &>(from),fromOffset,fromStride,
|
||||
dynamic_cast<PVValueArray<uint8>& >(to),
|
||||
toOffset,toStride,count);
|
||||
}
|
||||
break;
|
||||
case pvUShort:
|
||||
{
|
||||
copy(dynamic_cast<PVValueArray<uint16> &>(from),fromOffset,fromStride,
|
||||
dynamic_cast<PVValueArray<uint16>& >(to),
|
||||
toOffset,toStride,count);
|
||||
}
|
||||
break;
|
||||
case pvUInt:
|
||||
{
|
||||
copy(dynamic_cast<PVValueArray<uint32> &>(from),fromOffset,fromStride,
|
||||
dynamic_cast<PVValueArray<uint32>& >(to),
|
||||
toOffset,toStride,count);
|
||||
}
|
||||
break;
|
||||
case pvULong:
|
||||
{
|
||||
copy(dynamic_cast<PVValueArray<uint64> &>(from),fromOffset,fromStride,
|
||||
dynamic_cast<PVValueArray<uint64>& >(to),
|
||||
toOffset,toStride,count);
|
||||
}
|
||||
break;
|
||||
case pvFloat:
|
||||
{
|
||||
copy(dynamic_cast<PVValueArray<float> &>(from),fromOffset,fromStride,
|
||||
dynamic_cast<PVValueArray<float>& >(to),
|
||||
toOffset,toStride,count);
|
||||
}
|
||||
break;
|
||||
case pvDouble:
|
||||
{
|
||||
copy(dynamic_cast<PVValueArray<double> &>(from),fromOffset,fromStride,
|
||||
dynamic_cast<PVValueArray<double>& >(to),
|
||||
toOffset,toStride,count);
|
||||
}
|
||||
break;
|
||||
case pvString:
|
||||
{
|
||||
copy(dynamic_cast<PVValueArray<string> &>(from),fromOffset,fromStride,
|
||||
dynamic_cast<PVValueArray<string>& >(to),
|
||||
toOffset,toStride,count);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void copy(
|
||||
PVStructureArray & pvFrom,
|
||||
size_t pvFromOffset,
|
||||
size_t pvFromStride,
|
||||
PVStructureArray & pvTo,
|
||||
size_t toOffset,
|
||||
size_t toStride,
|
||||
size_t count)
|
||||
{
|
||||
if(pvTo.isImmutable()) {
|
||||
throw std::logic_error("pvSubArrayCopy pvTo is immutable");
|
||||
}
|
||||
if(pvFromStride<1 || toStride<1) throw std::invalid_argument("stride must be >=1");
|
||||
StructureArrayConstPtr pvFromStructure = pvFrom.getStructureArray();
|
||||
StructureArrayConstPtr toStructure = pvTo.getStructureArray();
|
||||
if(pvFromStructure->getStructure()!=toStructure->getStructure()) {
|
||||
throw std::invalid_argument(
|
||||
"pvSubArrayCopy structureArray pvTo and pvFrom have different structures");
|
||||
}
|
||||
size_t pvFromLength = pvFrom.getLength();
|
||||
size_t maxcount = (pvFromLength -pvFromOffset + pvFromStride -1)/pvFromStride;
|
||||
if(count>maxcount) throw std::invalid_argument("pvSubArrayCopy pvFrom length error");
|
||||
size_t newLength = toOffset + count*toStride;
|
||||
size_t capacity = pvTo.getCapacity();
|
||||
if(newLength>capacity) capacity = newLength;
|
||||
shared_vector<PVStructurePtr> temp(capacity);
|
||||
PVValueArray<PVStructurePtr>::const_svector vecFrom = pvFrom.view();
|
||||
PVValueArray<PVStructurePtr>::const_svector vecTo = pvTo.view();
|
||||
for(size_t i=0; i<pvTo.getLength(); ++i) temp[i] = vecTo[i];
|
||||
for(size_t i=pvTo.getLength(); i< capacity; ++i)
|
||||
temp[i] = getPVDataCreate()->createPVStructure(toStructure->getStructure());
|
||||
for(size_t i=0; i<count; ++i) temp[i*toStride + toOffset] = vecFrom[i*pvFromStride+pvFromOffset];
|
||||
shared_vector<const PVStructurePtr> temp2(freeze(temp));
|
||||
pvTo.replace(temp2);
|
||||
}
|
||||
|
||||
void copy(
|
||||
PVUnionArray & pvFrom,
|
||||
size_t pvFromOffset,
|
||||
size_t pvFromStride,
|
||||
PVUnionArray & pvTo,
|
||||
size_t toOffset,
|
||||
size_t toStride,
|
||||
size_t count)
|
||||
{
|
||||
if(pvTo.isImmutable()) {
|
||||
throw std::logic_error("pvSubArrayCopy pvTo is immutable");
|
||||
}
|
||||
if(pvFromStride<1 || toStride<1) throw std::invalid_argument("stride must be >=1");
|
||||
UnionArrayConstPtr pvFromUnion = pvFrom.getUnionArray();
|
||||
UnionArrayConstPtr toUnion = pvTo.getUnionArray();
|
||||
if(pvFromUnion->getUnion()!=toUnion->getUnion()) {
|
||||
throw std::invalid_argument(
|
||||
"pvSubArrayCopy unionArray pvTo and pvFrom have different unions");
|
||||
}
|
||||
size_t pvFromLength = pvFrom.getLength();
|
||||
size_t maxcount = (pvFromLength -pvFromOffset + pvFromStride -1)/pvFromStride;
|
||||
if(count>maxcount) throw std::invalid_argument("pvSubArrayCopy pvFrom length error");
|
||||
size_t newLength = toOffset + count*toStride;
|
||||
size_t capacity = pvTo.getCapacity();
|
||||
if(newLength>capacity) capacity = newLength;
|
||||
shared_vector<PVUnionPtr> temp(capacity);
|
||||
PVValueArray<PVUnionPtr>::const_svector vecFrom = pvFrom.view();
|
||||
PVValueArray<PVUnionPtr>::const_svector vecTo = pvTo.view();
|
||||
for(size_t i=0; i<pvTo.getLength(); ++i) temp[i] = vecTo[i];
|
||||
for(size_t i=pvTo.getLength(); i< capacity; ++i)
|
||||
temp[i] = getPVDataCreate()->createPVUnion(toUnion->getUnion());
|
||||
for(size_t i=0; i<count; ++i) temp[i*toStride + toOffset] = vecFrom[i*pvFromStride+pvFromOffset];
|
||||
shared_vector<const PVUnionPtr> temp2(freeze(temp));
|
||||
pvTo.replace(temp2);
|
||||
}
|
||||
|
||||
void copy(
|
||||
PVArray & pvFrom,
|
||||
size_t pvFromOffset,
|
||||
size_t pvFromStride,
|
||||
PVArray & pvTo,
|
||||
size_t pvToOffset,
|
||||
size_t pvToStride,
|
||||
size_t count)
|
||||
{
|
||||
Type pvFromType = pvFrom.getField()->getType();
|
||||
Type pvToType = pvTo.getField()->getType();
|
||||
if(pvFromType!=pvToType) throw std::invalid_argument("pvSubArrayCopy: pvFrom and pvTo different types");
|
||||
if(pvFromType==scalarArray) {
|
||||
ScalarType pvFromScalarType= static_cast<ScalarType>(pvFromType);
|
||||
ScalarType pvToScalarType = static_cast<ScalarType>(pvToType);
|
||||
if(pvFromScalarType!=pvToScalarType){
|
||||
throw std::invalid_argument("pvSubArrayCopy: pvFrom and pvTo different types");
|
||||
}
|
||||
}
|
||||
if(pvTo.isImmutable()) throw std::invalid_argument("pvSubArrayCopy: pvTo is immutable");
|
||||
if(pvFromType==scalarArray) {
|
||||
copy(dynamic_cast<PVScalarArray &>(pvFrom) ,pvFromOffset,pvFromStride,
|
||||
dynamic_cast<PVScalarArray&>(pvTo),
|
||||
pvToOffset,pvToStride,count);
|
||||
}
|
||||
if(pvFromType==structureArray) {
|
||||
copy(dynamic_cast<PVStructureArray &>(pvFrom) ,pvFromOffset,pvFromStride,
|
||||
dynamic_cast<PVStructureArray&>(pvTo),
|
||||
pvToOffset,pvToStride,count);
|
||||
}
|
||||
if(pvFromType==unionArray) {
|
||||
copy(dynamic_cast<PVUnionArray &>(pvFrom) ,pvFromOffset,pvFromStride,
|
||||
dynamic_cast<PVUnionArray&>(pvTo),
|
||||
pvToOffset,pvToStride,count);
|
||||
}
|
||||
}
|
||||
|
||||
void copy(
|
||||
PVArray::shared_pointer const & pvFrom,
|
||||
size_t pvFromOffset,
|
||||
size_t pvFromStride,
|
||||
PVArray::shared_pointer & pvTo,
|
||||
size_t pvToOffset,
|
||||
size_t pvToStride,
|
||||
size_t count)
|
||||
{
|
||||
copy(*pvFrom,pvFromOffset,pvFromStride,*pvTo,pvToOffset,pvToStride,count);
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
43
src/misc/Makefile
Normal file
43
src/misc/Makefile
Normal file
@@ -0,0 +1,43 @@
|
||||
# This is a Makefile fragment, see ../Makefile
|
||||
|
||||
SRC_DIRS += $(PVDATA_SRC)/misc
|
||||
|
||||
INC += noDefaultMethods.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 += timeFunction.h
|
||||
INC += timer.h
|
||||
INC += queue.h
|
||||
INC += messageQueue.h
|
||||
INC += destroyable.h
|
||||
INC += status.h
|
||||
INC += sharedPtr.h
|
||||
INC += localStaticLock.h
|
||||
INC += typeCast.h
|
||||
INC += sharedVector.h
|
||||
INC += templateMeta.h
|
||||
INC += current_function.h
|
||||
|
||||
LIBSRCS += byteBuffer.cpp
|
||||
LIBSRCS += bitSet.cpp
|
||||
LIBSRCS += epicsException.cpp
|
||||
LIBSRCS += requester.cpp
|
||||
LIBSRCS += serializeHelper.cpp
|
||||
LIBSRCS += event.cpp
|
||||
LIBSRCS += executor.cpp
|
||||
LIBSRCS += timeFunction.cpp
|
||||
LIBSRCS += timer.cpp
|
||||
LIBSRCS += status.cpp
|
||||
LIBSRCS += messageQueue.cpp
|
||||
LIBSRCS += localStaticLock.cpp
|
||||
LIBSRCS += typeCast.cpp
|
||||
LIBSRCS += parseToPOD.cpp
|
||||
|
||||
@@ -7,11 +7,14 @@
|
||||
/**
|
||||
* @author mes
|
||||
*/
|
||||
#include "string.h"
|
||||
#include "stdio.h"
|
||||
#include <pv/bitSet.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/lock.h>
|
||||
#include <pv/serializeHelper.h>
|
||||
#include <pv/bitSet.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
@@ -199,6 +202,8 @@ namespace epics { namespace pvData {
|
||||
}
|
||||
|
||||
BitSet& BitSet::operator&=(const BitSet& set) {
|
||||
// Check for self-assignment!
|
||||
if (this == &set) return *this;
|
||||
|
||||
while (wordsInUse > set.wordsInUse)
|
||||
words[--wordsInUse] = 0;
|
||||
@@ -213,76 +218,49 @@ namespace epics { namespace pvData {
|
||||
}
|
||||
|
||||
BitSet& BitSet::operator|=(const BitSet& set) {
|
||||
|
||||
uint32 wordsInCommon;
|
||||
// Check for self-assignment!
|
||||
if (this == &set) return *this;
|
||||
uint32 wordsInCommon = wordsInUse;
|
||||
if(wordsInUse>set.wordsInUse) wordsInCommon = set.wordsInUse;
|
||||
if (wordsInUse < set.wordsInUse) {
|
||||
wordsInCommon = wordsInUse;
|
||||
//ensureCapacity(set.wordsInUse);
|
||||
//wordsInUse = set.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++)
|
||||
for (uint32 i =0; i < wordsInCommon; i++) {
|
||||
words[i] |= set.words[i];
|
||||
|
||||
// TODO what to do if BitSets are not the same size !!!
|
||||
|
||||
}
|
||||
// Copy any remaining words
|
||||
for(uint32 i=wordsInCommon; i<set.wordsInUse; ++i) {
|
||||
words[i] = set.words[i];
|
||||
}
|
||||
// recalculateWordsInUse() is not needed
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
BitSet& BitSet::operator^=(const BitSet& set) {
|
||||
|
||||
uint32 wordsInCommon;
|
||||
uint32 wordsInCommon = wordsInUse;
|
||||
if(wordsInUse>set.wordsInUse) wordsInCommon = set.wordsInUse;
|
||||
if (wordsInUse < set.wordsInUse) {
|
||||
wordsInCommon = wordsInUse;
|
||||
//ensureCapacity(set.wordsInUse);
|
||||
//wordsInUse = set.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++)
|
||||
// Perform logical OR on words in common
|
||||
for (uint32 i =0; 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;
|
||||
}
|
||||
// Copy any remaining words
|
||||
for(uint32 i=wordsInCommon; i<set.wordsInUse; ++i) {
|
||||
words[i] = set.words[i];
|
||||
}
|
||||
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;
|
||||
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)
|
||||
@@ -331,21 +309,6 @@ namespace epics { namespace pvData {
|
||||
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",(int)i); *buffer += tmp;
|
||||
for (i = nextSetBit(i+1); i >= 0; i = nextSetBit(i+1)) {
|
||||
int32 endOfRun = nextClearBit(i);
|
||||
do { *buffer += ", "; sprintf(tmp,"%d",(int)i); *buffer += tmp; } while (++i < endOfRun);
|
||||
}
|
||||
}
|
||||
*buffer += '}';
|
||||
}
|
||||
|
||||
void BitSet::serialize(ByteBuffer* buffer, SerializableControl* flusher) const {
|
||||
|
||||
uint32 n = wordsInUse;
|
||||
@@ -369,7 +332,7 @@ namespace epics { namespace pvData {
|
||||
|
||||
void BitSet::deserialize(ByteBuffer* buffer, DeserializableControl* control) {
|
||||
|
||||
uint32 bytes = SerializeHelper::readSize(buffer, control); // in bytes
|
||||
uint32 bytes = static_cast<uint32>(SerializeHelper::readSize(buffer, control)); // in bytes
|
||||
|
||||
wordsInUse = (bytes + 7) / 8;
|
||||
if (wordsInUse > wordsLength)
|
||||
@@ -396,5 +359,20 @@ namespace epics { namespace pvData {
|
||||
words[i] |= (buffer->getByte() & 0xffL) << (8 * j);
|
||||
|
||||
}
|
||||
|
||||
epicsShareExtern std::ostream& operator<<(std::ostream& o, const BitSet& b)
|
||||
{
|
||||
o << '{';
|
||||
int32 i = b.nextSetBit(0);
|
||||
if (i != -1) {
|
||||
o << i;
|
||||
for (i = b.nextSetBit(i+1); i >= 0; i = b.nextSetBit(i+1)) {
|
||||
int32 endOfRun = b.nextClearBit(i);
|
||||
do { o << ", " << i; } while (++i < endOfRun);
|
||||
}
|
||||
}
|
||||
o << '}';
|
||||
return o;
|
||||
}
|
||||
|
||||
}};
|
||||
@@ -9,27 +9,33 @@
|
||||
*/
|
||||
#ifndef BITSET_H
|
||||
#define BITSET_H
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include <pv/pvType.h>
|
||||
#include <pv/serialize.h>
|
||||
#include <pv/sharedPtr.h>
|
||||
|
||||
#include <shareLib.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
class BitSet;
|
||||
typedef std::tr1::shared_ptr<BitSet> BitSetPtr;
|
||||
|
||||
/**
|
||||
* @brief A vector of bits.
|
||||
*
|
||||
* This class implements a vector of bits that grows as needed. Each
|
||||
* component of the bit set has a {@code bool} value. The
|
||||
* bits of a {@code BitSet} are indexed by nonnegative integers.
|
||||
* Individual indexed bits can be examined, set, or cleared. One
|
||||
* {@code BitSet} may be used to modify the contents of another
|
||||
* {@code BitSet} through logical AND, logical inclusive OR, and
|
||||
* logical exclusive OR operations.
|
||||
* component of the bit set has a @c bool value. The bits of a
|
||||
* @c BitSet are indexed by nonnegative integers. Individual
|
||||
* indexed bits can be examined, set, or cleared. One @c BitSet may
|
||||
* be used to modify the contents of another @c BitSet through
|
||||
* logical AND, logical inclusive OR, and logical exclusive OR
|
||||
* operations.
|
||||
*
|
||||
* <p>By default, all bits in the set initially have the value
|
||||
* {@code false}.
|
||||
* @c false.
|
||||
*
|
||||
* <p>Every bit set has a current size, which is the number of bits
|
||||
* of space currently in use by the bit set. Note that the size is
|
||||
@@ -37,24 +43,24 @@ namespace epics { namespace pvData {
|
||||
* implementation. The length of a bit set relates to logical length
|
||||
* of a bit set and is defined independently of implementation.
|
||||
*
|
||||
* <p>A {@code BitSet} is not safe for multithreaded use without
|
||||
* external synchronization.
|
||||
* <p>A @c BitSet is not safe for multithreaded use without external
|
||||
* synchronization.
|
||||
*
|
||||
* Based on Java implementation.
|
||||
*/
|
||||
class BitSet : public Serializable {
|
||||
class epicsShareClass BitSet : public Serializable {
|
||||
public:
|
||||
POINTER_DEFINITIONS(BitSet);
|
||||
static BitSet::shared_pointer create(uint32 nbits);
|
||||
static BitSetPtr create(uint32 nbits);
|
||||
/**
|
||||
* Creates a new bit set. All bits are initially {@code false}.
|
||||
* Creates a new bit set. All bits are initially @c false.
|
||||
*/
|
||||
BitSet();
|
||||
|
||||
/**
|
||||
* Creates a bit set whose initial size is large enough to explicitly
|
||||
* represent bits with indices in the range {@code 0} through
|
||||
* {@code nbits-1}. All bits are initially {@code false}.
|
||||
* represent bits with indices in the range @c 0 through
|
||||
* @c nbits-1. All bits are initially @c false.
|
||||
*
|
||||
* @param nbits the initial size of the bit set
|
||||
*/
|
||||
@@ -74,14 +80,14 @@ namespace epics { namespace pvData {
|
||||
void flip(uint32 bitIndex);
|
||||
|
||||
/**
|
||||
* Sets the bit at the specified index to {@code true}.
|
||||
* Sets the bit at the specified index to @c true.
|
||||
*
|
||||
* @param bitIndex a bit index
|
||||
*/
|
||||
void set(uint32 bitIndex);
|
||||
|
||||
/**
|
||||
* Sets the bit specified by the index to {@code false}.
|
||||
* Sets the bit specified by the index to @c false.
|
||||
*
|
||||
* @param bitIndex the index of the bit to be cleared
|
||||
*/
|
||||
@@ -97,9 +103,8 @@ namespace epics { namespace pvData {
|
||||
|
||||
/**
|
||||
* Returns the value of the bit with the specified index. The value
|
||||
* is {@code true} if the bit with the index {@code bitIndex}
|
||||
* is currently set in this {@code BitSet}; otherwise, the result
|
||||
* is {@code false}.
|
||||
* is @c true if the bit with the index @c bitIndex is currently
|
||||
* set in this @c BitSet; otherwise, the result is @c false.
|
||||
*
|
||||
* @param bitIndex the bit index
|
||||
* @return the value of the bit with the specified index
|
||||
@@ -107,16 +112,16 @@ namespace epics { namespace pvData {
|
||||
bool get(uint32 bitIndex) const;
|
||||
|
||||
/**
|
||||
* Sets all of the bits in this BitSet to {@code false}.
|
||||
* Sets all of the bits in this BitSet to @c false.
|
||||
*/
|
||||
void clear();
|
||||
|
||||
/**
|
||||
* Returns the index of the first bit that is set to {@code true}
|
||||
* that occurs on or after the specified starting index. If no such
|
||||
* bit exists then {@code -1} is returned.
|
||||
* Returns the index of the first bit that is set to @c true that
|
||||
* occurs on or after the specified starting index. If no such bit
|
||||
* exists then @c -1 is returned.
|
||||
*
|
||||
* <p>To iterate over the {@code true} bits in a {@code BitSet},
|
||||
* <p>To iterate over the @c true bits in a @c BitSet,
|
||||
* use the following loop:
|
||||
*
|
||||
* <pre> {@code
|
||||
@@ -125,13 +130,13 @@ namespace epics { namespace pvData {
|
||||
* }}</pre>
|
||||
*
|
||||
* @param fromIndex the index to start checking from (inclusive)
|
||||
* @return the index of the next set bit, or {@code -1} if there
|
||||
* @return the index of the next set bit, or @c -1 if there
|
||||
* is no such bit
|
||||
*/
|
||||
int32 nextSetBit(uint32 fromIndex) const;
|
||||
|
||||
/**
|
||||
* Returns the index of the first bit that is set to {@code false}
|
||||
* Returns the index of the first bit that is set to @c false
|
||||
* that occurs on or after the specified starting index.
|
||||
*
|
||||
* @param fromIndex the index to start checking from (inclusive)
|
||||
@@ -140,23 +145,23 @@ namespace epics { namespace pvData {
|
||||
int32 nextClearBit(uint32 fromIndex) const;
|
||||
|
||||
/**
|
||||
* Returns true if this {@code BitSet} contains no bits that are set
|
||||
* to {@code true}.
|
||||
* Returns true if this @c BitSet contains no bits that are set
|
||||
* to @c true.
|
||||
*
|
||||
* @return indicating whether this {@code BitSet} is empty
|
||||
* @return indicating whether this @c BitSet is empty
|
||||
*/
|
||||
bool isEmpty() const;
|
||||
|
||||
/**
|
||||
* Returns the number of bits set to {@code true} in this {@code BitSet}.
|
||||
* Returns the number of bits set to @c true in this @c BitSet.
|
||||
*
|
||||
* @return the number of bits set to {@code true} in this {@code BitSet}
|
||||
* @return the number of bits set to @c true in this @c BitSet
|
||||
*/
|
||||
uint32 cardinality() const;
|
||||
|
||||
/**
|
||||
* Returns the number of bits of space actually in use by this
|
||||
* {@code BitSet} to represent bit values.
|
||||
* @c BitSet to represent bit values.
|
||||
* The maximum element in the set is the size - 1st element.
|
||||
*
|
||||
* @return the number of bits currently in this bit set
|
||||
@@ -166,9 +171,9 @@ namespace epics { namespace pvData {
|
||||
/**
|
||||
* Performs a logical <b>AND</b> of this target bit set with the
|
||||
* argument bit set. This bit set is modified so that each bit in it
|
||||
* has the value {@code true} if and only if it both initially
|
||||
* had the value {@code true} and the corresponding bit in the
|
||||
* bit set argument also had the value {@code true}.
|
||||
* has the value @c true if and only if it both initially
|
||||
* had the value @c true and the corresponding bit in the
|
||||
* bit set argument also had the value @c true.
|
||||
*
|
||||
* @param set a bit set
|
||||
*/
|
||||
@@ -177,9 +182,9 @@ namespace epics { namespace pvData {
|
||||
/**
|
||||
* Performs a logical <b>OR</b> of this bit set with the bit set
|
||||
* argument. This bit set is modified so that a bit in it has the
|
||||
* value {@code true} if and only if it either already had the
|
||||
* value {@code true} or the corresponding bit in the bit set
|
||||
* argument has the value {@code true}.
|
||||
* value @c true if and only if it either already had the
|
||||
* value @c true or the corresponding bit in the bit set
|
||||
* argument has the value @c true.
|
||||
*
|
||||
* @param set a bit set
|
||||
*/
|
||||
@@ -188,13 +193,13 @@ namespace epics { namespace pvData {
|
||||
/**
|
||||
* Performs a logical <b>XOR</b> of this bit set with the bit set
|
||||
* argument. This bit set is modified so that a bit in it has the
|
||||
* value {@code true} if and only if one of the following
|
||||
* value @c true if and only if one of the following
|
||||
* statements holds:
|
||||
* <ul>
|
||||
* <li>The bit initially has the value {@code true}, and the
|
||||
* corresponding bit in the argument has the value {@code false}.
|
||||
* <li>The bit initially has the value {@code false}, and the
|
||||
* corresponding bit in the argument has the value {@code true}.
|
||||
* <li>The bit initially has the value @c true, and the
|
||||
* corresponding bit in the argument has the value @c false.
|
||||
* <li>The bit initially has the value @c false, and the
|
||||
* corresponding bit in the argument has the value @c true.
|
||||
* </ul>
|
||||
*
|
||||
* @param set a bit set
|
||||
@@ -202,16 +207,7 @@ namespace epics { namespace pvData {
|
||||
BitSet& operator^=(const BitSet& set);
|
||||
|
||||
/**
|
||||
* Clears all of the bits in this {@code BitSet} whose corresponding
|
||||
* bit is set in the specified {@code BitSet}.
|
||||
*
|
||||
* @param set the {@code BitSet} with which to mask this
|
||||
* {@code BitSet}
|
||||
*/
|
||||
BitSet& operator-=(const BitSet& set);
|
||||
|
||||
/**
|
||||
* Assigment operator.
|
||||
* Assignment operator.
|
||||
*/
|
||||
BitSet& operator=(const BitSet &set);
|
||||
|
||||
@@ -230,8 +226,6 @@ namespace epics { namespace pvData {
|
||||
|
||||
bool operator!=(const BitSet &set) const;
|
||||
|
||||
void toString(StringBuilder buffer, int indentLevel = 0) const;
|
||||
|
||||
virtual void serialize(ByteBuffer *buffer,
|
||||
SerializableControl *flusher) const;
|
||||
virtual void deserialize(ByteBuffer *buffer,
|
||||
@@ -322,6 +316,8 @@ namespace epics { namespace pvData {
|
||||
static uint32 bitCount(uint64 i);
|
||||
|
||||
};
|
||||
|
||||
epicsShareExtern std::ostream& operator<<(std::ostream& o, const BitSet& b);
|
||||
|
||||
}}
|
||||
#endif /* BITSET_H */
|
||||
@@ -4,5 +4,5 @@
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mes
|
||||
* @author mse
|
||||
*/
|
||||
@@ -11,12 +11,25 @@
|
||||
#define BYTEBUFFER_H
|
||||
|
||||
#include <string>
|
||||
#include <pv/pvType.h>
|
||||
#include <epicsEndian.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef epicsExportSharedSymbols
|
||||
#define byteBufferepicsExportSharedSymbols
|
||||
#undef epicsExportSharedSymbols
|
||||
#endif
|
||||
|
||||
#include <epicsEndian.h>
|
||||
|
||||
#ifdef byteBufferepicsExportSharedSymbols
|
||||
#define epicsExportSharedSymbols
|
||||
#undef byteBufferepicsExportSharedSymbols
|
||||
#endif
|
||||
|
||||
#include <pv/pvType.h>
|
||||
#include <pv/epicsException.h>
|
||||
|
||||
#include <shareLib.h>
|
||||
|
||||
namespace epics {
|
||||
namespace pvData {
|
||||
|
||||
@@ -131,6 +144,24 @@ inline int64 swap(int64 val)
|
||||
return swap64(val);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline uint16 swap(uint16 val)
|
||||
{
|
||||
return swap16(val);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline uint32 swap(uint32 val)
|
||||
{
|
||||
return swap32(val);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline uint64 swap(uint64 val)
|
||||
{
|
||||
return swap64(val);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline float swap(float val)
|
||||
{
|
||||
@@ -175,8 +206,9 @@ inline double swap(double val)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This class implements {@code Bytebuffer} that is like the {@code java.nio.ByteBuffer}.
|
||||
* <p>A {@code BitSet} is not safe for multithreaded use without
|
||||
* @brief This class implements a Bytebuffer that is like the java.nio.ByteBuffer.
|
||||
*
|
||||
* <p>A @c BitSet is not safe for multithreaded use without
|
||||
* external synchronization.
|
||||
*
|
||||
* Based on Java implementation.
|
||||
@@ -189,22 +221,40 @@ public:
|
||||
*
|
||||
* @param size The number of bytes.
|
||||
* @param byteOrder The byte order.
|
||||
* Must be one of EPICS_BYTE_ORDER,EPICS_ENDIAN_LITTLE,EPICS_ENDIAN_BIG,
|
||||
* Must be one of EPICS_BYTE_ORDER,EPICS_ENDIAN_LITTLE,EPICS_ENDIAN_BIG.
|
||||
*/
|
||||
ByteBuffer(std::size_t size, int byteOrder = EPICS_BYTE_ORDER) :
|
||||
_buffer(0), _size(size),
|
||||
_reverseEndianess(byteOrder != EPICS_BYTE_ORDER),
|
||||
_reverseFloatEndianess(byteOrder != EPICS_FLOAT_WORD_ORDER)
|
||||
_reverseFloatEndianess(byteOrder != EPICS_FLOAT_WORD_ORDER),
|
||||
_wrapped(false)
|
||||
{
|
||||
_buffer = (char*)malloc(size);
|
||||
clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for wrapping existing buffers.
|
||||
* Given buffer will not be released by the ByteBuffer instance.
|
||||
* @param buffer Existing buffer.
|
||||
* @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(char* buffer, std::size_t size, int byteOrder = EPICS_BYTE_ORDER) :
|
||||
_buffer(buffer), _size(size),
|
||||
_reverseEndianess(byteOrder != EPICS_BYTE_ORDER),
|
||||
_reverseFloatEndianess(byteOrder != EPICS_FLOAT_WORD_ORDER),
|
||||
_wrapped(true)
|
||||
{
|
||||
clear();
|
||||
}
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~ByteBuffer()
|
||||
{
|
||||
if (_buffer) free(_buffer);
|
||||
if (_buffer && !_wrapped) free(_buffer);
|
||||
}
|
||||
/**
|
||||
* Set the byte order.
|
||||
@@ -323,7 +373,7 @@ public:
|
||||
template<typename T>
|
||||
inline void put(std::size_t index, T value);
|
||||
/**
|
||||
* Get the new object from the byte buffer. The item MUST have type {@code T}.
|
||||
* Get the new object from the byte buffer. The item MUST have type @c T.
|
||||
* The position is adjusted based on the type.
|
||||
*
|
||||
* @return The object.
|
||||
@@ -337,7 +387,7 @@ public:
|
||||
#endif
|
||||
/**
|
||||
* Get the new object from the byte buffer at the specified index.
|
||||
* The item MUST have type {@code T}.
|
||||
* The item MUST have type @c T.
|
||||
* The position is adjusted based on the type.
|
||||
*
|
||||
* @param index The location in the byte buffer.
|
||||
@@ -349,9 +399,9 @@ public:
|
||||
* 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,
|
||||
* @param src The source array.
|
||||
* @param src_offset The starting position within src.
|
||||
* @param count The number of bytes to put into the byte buffer,
|
||||
*/
|
||||
inline void put(const char* src, std::size_t src_offset, std::size_t count) {
|
||||
//if(count>getRemaining()) THROW_BASE_EXCEPTION("buffer overflow");
|
||||
@@ -362,9 +412,9 @@ public:
|
||||
* 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,
|
||||
* @param dest The destination array.
|
||||
* @param dest_offset The starting position within src.
|
||||
* @param count The number of bytes to put into the byte buffer.
|
||||
*/
|
||||
inline void get(char* dest, std::size_t dest_offset, std::size_t count) {
|
||||
//if(count>getRemaining()) THROW_BASE_EXCEPTION("buffer overflow");
|
||||
@@ -372,16 +422,16 @@ public:
|
||||
_position += count;
|
||||
}
|
||||
/**
|
||||
* Put an array of type {@code T} into the byte buffer.
|
||||
* Put an array of type @c 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, std::size_t count);
|
||||
inline void putArray(const T* values, std::size_t count);
|
||||
/**
|
||||
* Get an array of type {@code T} from the byte buffer.
|
||||
* Get an array of type @c T from the byte buffer.
|
||||
* The position is adjusted.
|
||||
*
|
||||
* @param values The destination array.
|
||||
@@ -587,7 +637,7 @@ public:
|
||||
/**
|
||||
* Get a boolean value from the byte buffer at the specified index.
|
||||
*
|
||||
* @param double The offset in the byte buffer.
|
||||
* @param index The offset in the byte buffer.
|
||||
* @return The value.
|
||||
*/
|
||||
inline double getDouble (std::size_t index) { return get<double>(index); }
|
||||
@@ -605,7 +655,8 @@ private:
|
||||
char* _limit;
|
||||
std::size_t _size;
|
||||
bool _reverseEndianess;
|
||||
bool _reverseFloatEndianess;
|
||||
bool _reverseFloatEndianess;
|
||||
bool _wrapped;
|
||||
};
|
||||
|
||||
template<>
|
||||
@@ -663,7 +714,7 @@ private:
|
||||
}
|
||||
else
|
||||
{
|
||||
// NOTE: this check and branching does not always payoff
|
||||
// NOTE: this check and branching does not always pay off
|
||||
if (ADAPTIVE_ACCESS && is_aligned(_position, sizeof(T)))
|
||||
{
|
||||
*((T*)_position) = value;
|
||||
@@ -706,12 +757,12 @@ private:
|
||||
|
||||
if (UNALIGNED_ACCESS)
|
||||
{
|
||||
// NOTE: some CPU handle unaligned access preety good (e.g. x86)
|
||||
// NOTE: some CPU handle unaligned access pretty good (e.g. x86)
|
||||
*((T*)(_buffer + index)) = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
// NOTE: this check and branching does not always payoff
|
||||
// NOTE: this check and branching does not always pay off
|
||||
if (ADAPTIVE_ACCESS && is_aligned(_position, sizeof(T)))
|
||||
{
|
||||
*((T*)(_buffer + index)) = value;
|
||||
@@ -754,13 +805,13 @@ private:
|
||||
|
||||
if (UNALIGNED_ACCESS)
|
||||
{
|
||||
// NOTE: some CPU handle unaligned access preety good (e.g. x86)
|
||||
// NOTE: some CPU handle unaligned access pretty good (e.g. x86)
|
||||
value = *((T*)_position);
|
||||
_position += sizeof(T);
|
||||
}
|
||||
else
|
||||
{
|
||||
// NOTE: this check and branching does not always payoff
|
||||
// NOTE: this check and branching does not always pay off
|
||||
if (ADAPTIVE_ACCESS && is_aligned(_position, sizeof(T)))
|
||||
{
|
||||
value = *((T*)_position);
|
||||
@@ -806,12 +857,12 @@ private:
|
||||
|
||||
if (UNALIGNED_ACCESS)
|
||||
{
|
||||
// NOTE: some CPU handle unaligned access preety good (e.g. x86)
|
||||
// NOTE: some CPU handle unaligned access pretty good (e.g. x86)
|
||||
value = *((T*)(_buffer + index));
|
||||
}
|
||||
else
|
||||
{
|
||||
// NOTE: this check and branching does not always payoff
|
||||
// NOTE: this check and branching does not always pay off
|
||||
if (ADAPTIVE_ACCESS && is_aligned(_position, sizeof(T)))
|
||||
{
|
||||
value = *((T*)(_buffer + index));
|
||||
@@ -842,7 +893,7 @@ private:
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline void ByteBuffer::putArray(T* values, std::size_t count)
|
||||
inline void ByteBuffer::putArray(const T* values, std::size_t count)
|
||||
{
|
||||
// this avoids int8 specialization, compiler will take care if optimization, -O2 or more
|
||||
if (sizeof(T) == 1)
|
||||
@@ -858,7 +909,7 @@ private:
|
||||
memcpy(_position, values, n);
|
||||
_position += n;
|
||||
|
||||
// ... so that we can be fast changing endianess
|
||||
// ... so that we can be fast changing endianness
|
||||
if (ENDIANESS_SUPPORT && reverse<T>())
|
||||
{
|
||||
for (std::size_t i = 0; i < count; i++)
|
||||
@@ -886,7 +937,7 @@ private:
|
||||
memcpy(values, _position, n);
|
||||
_position += n;
|
||||
|
||||
// ... so that we can be fast changing endianess
|
||||
// ... so that we can be fast changing endianness
|
||||
if (ENDIANESS_SUPPORT && reverse<T>())
|
||||
{
|
||||
for (std::size_t i = 0; i < count; i++)
|
||||
42
src/misc/current_function.h
Executable file
42
src/misc/current_function.h
Executable file
@@ -0,0 +1,42 @@
|
||||
#ifndef CURRENT_FUNCTION_HPP_INCLUDED
|
||||
#define CURRENT_FUNCTION_HPP_INCLUDED
|
||||
|
||||
// MS compatible compilers support #pragma once
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(__GNUC__) || (defined(__MWERKS__) && (__MWERKS__ >= 0x3000)) || (defined(__ICC) && (__ICC >= 600)) || defined(__ghs__)
|
||||
|
||||
# define CURRENT_FUNCTION __PRETTY_FUNCTION__
|
||||
|
||||
#elif defined(__DMC__) && (__DMC__ >= 0x810)
|
||||
|
||||
# define CURRENT_FUNCTION __PRETTY_FUNCTION__
|
||||
|
||||
#elif defined(__FUNCSIG__)
|
||||
|
||||
# define CURRENT_FUNCTION __FUNCSIG__
|
||||
|
||||
#elif (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 600)) || (defined(__IBMCPP__) && (__IBMCPP__ >= 500))
|
||||
|
||||
# define CURRENT_FUNCTION __FUNCTION__
|
||||
|
||||
#elif defined(__BORLANDC__) && (__BORLANDC__ >= 0x550)
|
||||
|
||||
# define CURRENT_FUNCTION __FUNC__
|
||||
|
||||
#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901)
|
||||
|
||||
# define CURRENT_FUNCTION __func__
|
||||
|
||||
#else
|
||||
|
||||
# define CURRENT_FUNCTION "(unknown)"
|
||||
|
||||
#endif
|
||||
|
||||
#endif // #ifndef BOOST_CURRENT_FUNCTION_HPP_INCLUDED
|
||||
|
||||
@@ -12,14 +12,17 @@
|
||||
|
||||
#include <pv/sharedPtr.h>
|
||||
|
||||
#include <shareLib.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
|
||||
/**
|
||||
* Instance declaring destroy method.
|
||||
* @brief Instance declaring destroy method.
|
||||
*
|
||||
* @author mse
|
||||
*/
|
||||
class Destroyable {
|
||||
class epicsShareClass Destroyable {
|
||||
public:
|
||||
POINTER_DEFINITIONS(Destroyable);
|
||||
/**
|
||||
@@ -7,14 +7,17 @@
|
||||
* @author mes
|
||||
*/
|
||||
|
||||
#include <pv/epicsException.h>
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
|
||||
namespace epics{namespace pvData{
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/epicsException.h>
|
||||
|
||||
using std::string;
|
||||
|
||||
namespace epics{ namespace pvData {
|
||||
|
||||
void
|
||||
ExceptionMixin::print(FILE *fp) const
|
||||
@@ -31,7 +34,7 @@ ExceptionMixin::print(FILE *fp) const
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string
|
||||
string
|
||||
ExceptionMixin::show() const
|
||||
{
|
||||
std::ostringstream out;
|
||||
@@ -61,7 +64,7 @@ BaseException::what() const throw()
|
||||
try{
|
||||
if (base_msg.size()==0) {
|
||||
const char *base=std::logic_error::what();
|
||||
std::string out, stack;
|
||||
string out, stack;
|
||||
|
||||
const ExceptionMixin *info=dynamic_cast<const ExceptionMixin*>(this);
|
||||
if(info) {
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user