Compare commits
163 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
95065787e6 | ||
|
|
fda9144505 | ||
|
|
ad4525317d | ||
|
|
acd19c10d0 | ||
|
|
0c2c6a4173 | ||
|
|
94781061cf | ||
|
|
fff9884b4c | ||
|
|
8c92f5035b | ||
|
|
cdb79f8a22 | ||
|
|
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 |
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-*
|
||||
8
.hgflow
8
.hgflow
@@ -1,8 +0,0 @@
|
||||
[branchname]
|
||||
master = master
|
||||
develop = default
|
||||
feature = feature/
|
||||
release = release/
|
||||
hotfix = hotfix/
|
||||
support = support/
|
||||
|
||||
12
.hgignore
12
.hgignore
@@ -1,12 +0,0 @@
|
||||
QtC-
|
||||
bin/
|
||||
lib/
|
||||
doc/
|
||||
include/
|
||||
db/
|
||||
dbd/
|
||||
documentation/html
|
||||
documentation/*.tag
|
||||
envPaths
|
||||
configure/.*\.local
|
||||
/O\..*
|
||||
12
.hgtags
12
.hgtags
@@ -1,12 +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
|
||||
4cecd4b200f88ab57bbb81978c45df2a67bbece1 3.0-pre1
|
||||
4cecd4b200f88ab57bbb81978c45df2a67bbece1 3.0.0
|
||||
2a289ff41e2ed3a0247877306c2db7b266f3b6b8 3.0.1
|
||||
58092712d092ee521d1e1c8fa596a67f7d113ee9 3.0.2
|
||||
40b681ffc5cd609320e3f8ffc8eb6aa3bfdfbf19 before_merge_changesAfter3_0_2
|
||||
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.
|
||||
|
||||
________________________________________________________________________
|
||||
|
||||
|
||||
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>
|
||||
58
README.md
Normal file
58
README.md
Normal file
@@ -0,0 +1,58 @@
|
||||
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).
|
||||
|
||||
|
||||
@@ -20,8 +20,8 @@ CHECK_RELEASE = YES
|
||||
# INSTALL_LOCATION here.
|
||||
#INSTALL_LOCATION=</path/name/to/install/top>
|
||||
|
||||
-include $(TOP)/../CONFIG_SITE.local
|
||||
-include $(TOP)/configure/CONFIG_SITE.local
|
||||
-include $(TOP)/../CONFIG.local
|
||||
|
||||
ifdef WITH_COVERAGE
|
||||
USR_CPPFLAGS += --coverage
|
||||
|
||||
@@ -21,5 +21,5 @@
|
||||
# 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
|
||||
|
||||
@@ -580,7 +580,7 @@ WARN_LOGFILE =
|
||||
# directories like "/usr/src/myproject". Separate the files or directories
|
||||
# with spaces.
|
||||
|
||||
INPUT = ../pvDataApp
|
||||
INPUT = ../include/pv
|
||||
|
||||
# This tag can be used to specify the character encoding of the source files
|
||||
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
|
||||
|
||||
255
documentation/RELEASE_NOTES.html
Normal file
255
documentation/RELEASE_NOTES.html
Normal file
@@ -0,0 +1,255 @@
|
||||
<h1>Release 5.0.4</h1>
|
||||
|
||||
<p>The changes since release 5.0.3 are:</p>
|
||||
|
||||
<ul>
|
||||
<li>Fixed bitset serialization (issue #24)</li>
|
||||
<li>Fixed truncation in BitSet::or_and (issue #27)</li>
|
||||
</ul>
|
||||
|
||||
<h2>Fixed bitset serialization (issue #24)</h2>
|
||||
|
||||
<p>C++ bitset serialization was not consistent with the C++ deserialization and
|
||||
Java code in some instances (depending on the endianness of the serializer and deserializer) when the number of bits was 56-63 modulo 64. C++ serialization
|
||||
has been fixed.</p>
|
||||
|
||||
<p>Fix exposed issue in deserialization on 32-bit platforms which
|
||||
has also been corrected. </p>
|
||||
|
||||
<h2>Fixed truncation in BitSet::or_and (issue #27)</h2>
|
||||
|
||||
<p>If n, n1 and n2 words are used to store the values of the bitsets bitset,
|
||||
bitset1 and bitset2 respectively then max(n, min(n1,n2)) words are needed
|
||||
to store bitset.or_(bitset1, bitset2).</p>
|
||||
|
||||
<p>Previously min(n1,n2) words were used and the result would be truncated in
|
||||
some instances. This has been fixed.</p>
|
||||
|
||||
<h1>Release 5.0.3</h1>
|
||||
|
||||
<p>The only change since release 5.0.2 is:</p>
|
||||
|
||||
<h2>Fixed buffer overflow in PVUnion::serialize() (issue #20)</h2>
|
||||
|
||||
<p>A PVUnion whose stored value was null was serialized without checking
|
||||
whether the buffer had sufficient capacity. This has been fixed by calling
|
||||
ensureBuffer().</p>
|
||||
|
||||
<h1>Release 5.0.2</h1>
|
||||
|
||||
<p>The main changes since release 4.0.3 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.3</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>
|
||||
@@ -1,9 +1,198 @@
|
||||
Release release/3.1 IN DEVELOPMENT
|
||||
===========
|
||||
Release 5.0.4
|
||||
=============
|
||||
|
||||
The changes since release 5.0.3 are:
|
||||
|
||||
* Fixed bitset serialization (issue #24)
|
||||
* Fixed truncation in BitSet::or_and (issue #27)
|
||||
|
||||
Fixed bitset serialization (issue #24)
|
||||
--------------------------------------
|
||||
|
||||
C++ bitset serialization was not consistent with the C++ deserialization and
|
||||
Java code in some instances (depending on the endianness of the serializer and
|
||||
deserializer) when the number of bits was 56-63 modulo 64. C++ serialization
|
||||
has been fixed.
|
||||
|
||||
Fix exposed issue in deserialization on 32-bit platforms which
|
||||
has also been corrected.
|
||||
|
||||
Fixed truncation in BitSet::or_and (issue #27)
|
||||
----------------------------------------------
|
||||
|
||||
If n, n1 and n2 words are used to store the values of the bitsets bitset,
|
||||
bitset1 and bitset2 respectively then max(n, min(n1,n2)) words are needed
|
||||
to store bitset.or_(bitset1, bitset2).
|
||||
|
||||
Previously min(n1,n2) words were used and the result would be truncated in
|
||||
some instances. This has been fixed.
|
||||
|
||||
|
||||
Release 5.0.3
|
||||
=============
|
||||
|
||||
The only change since release 5.0.2 is:
|
||||
|
||||
Fixed buffer overflow in PVUnion::serialize() (issue #20)
|
||||
---------------------------------------------------------
|
||||
|
||||
A PVUnion whose stored value was null was serialized without checking
|
||||
whether the buffer had sufficient capacity. This has been fixed by calling
|
||||
ensureBuffer().
|
||||
|
||||
|
||||
Release 5.0.2
|
||||
=============
|
||||
|
||||
The main changes since release 4.0.3 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.3
|
||||
=============
|
||||
|
||||
The main changes since release 3.0.2 are:
|
||||
|
||||
* array semantics now enforce Copy On Write.
|
||||
* String no longer defined.
|
||||
* timeStamp and valueAlarm name changes
|
||||
* toString replaced by stream I/O
|
||||
* union is new type.
|
||||
* copy is new.
|
||||
* monitorPlugin is new.
|
||||
@@ -16,6 +205,44 @@ In order to limit memory usage the storage for raw data is managed via a new sha
|
||||
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.
|
||||
------------
|
||||
|
||||
@@ -24,7 +251,7 @@ 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>varient union</b> The field can have any type.
|
||||
* <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.
|
||||
@@ -35,12 +262,13 @@ 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.
|
||||
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
|
||||
==========
|
||||
|
||||
@@ -1,54 +1,20 @@
|
||||
TODO
|
||||
===========
|
||||
|
||||
toString, dumpValue, printer, and streams
|
||||
------------
|
||||
|
||||
The way to print introspection and data instances is not consistent.
|
||||
This needs work.
|
||||
Some items that need work are:
|
||||
|
||||
* Introspection has no support for streams. Only for toString.
|
||||
* data has problems. toString is implemented by calling Convert::getString.
|
||||
It look like this was intended to use printer but that did nor properly indent fields of structures.
|
||||
|
||||
The current implementation is:
|
||||
|
||||
void Convert::getString(StringBuilder buf,PVField const *pvField,int /*indentLevel*/)
|
||||
{
|
||||
// TODO indextLevel ignored
|
||||
std::ostringstream strm;
|
||||
strm << pvField->dumpValue(strm) << std::endl;
|
||||
// PrinterPlain p;
|
||||
// p.setStream(strm);
|
||||
// p.print(*pvField);
|
||||
strm.str().swap(*buf);
|
||||
}
|
||||
|
||||
Thus it just uses dumpValue.
|
||||
What should it do?
|
||||
If printer is used it must do proper indentation.
|
||||
|
||||
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.
|
||||
|
||||
PVFieldConstPtr etc
|
||||
-------------------
|
||||
|
||||
In pvDataCPP.html look at the monoitorPlugin example.
|
||||
It has a discussion of a possible need for shared pointers that can not be used to modify data.
|
||||
This in addition to PVFieldPtr should PVFieldConstPtr exist.
|
||||
But this means that all methods defined in pvDataCPP must be checked.
|
||||
This is a BIG job.
|
||||
|
||||
Release 3.0.2
|
||||
==========
|
||||
This was the starting point for RELEASE_NOTES
|
||||
|
||||
@@ -52,7 +52,7 @@ 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 knowlege of PVRecord. The C++ version was implemented in pvDatabaseCPP
|
||||
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>
|
||||
@@ -65,13 +65,13 @@ At present only the C++ version of the new API for pvCopy is implemented.
|
||||
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 arbitrarary subset of the
|
||||
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 faculity used by channel providers.
|
||||
<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
|
||||
@@ -185,7 +185,7 @@ where
|
||||
This is the method for creating a PVCopy instance.<br/>
|
||||
<dl>
|
||||
<dt>pvMaster</dt>
|
||||
<dd>the top level sructure managed by the server.</dd>
|
||||
<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>
|
||||
@@ -241,12 +241,12 @@ where
|
||||
<dt>updateCopyFromBitSet</dt>
|
||||
<dd>
|
||||
For each set bit in bitSet set the field in copyPVStructure to the value
|
||||
of the corrseponding field in pvMaster.
|
||||
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 corrseponding field in copyPVStructure.
|
||||
of the corresponding field in copyPVStructure.
|
||||
|
||||
</dd>
|
||||
<dt>getOptions</dt>
|
||||
@@ -266,7 +266,7 @@ where
|
||||
<p>This consists of two components:
|
||||
<dl>
|
||||
<dt>monitor</dt>
|
||||
<dd>Used by code that implements pvAccess montors.</dd>
|
||||
<dd>Used by code that implements pvAccess monitors.</dd>
|
||||
<dt>monitorPlugin</dt>
|
||||
<dd>Code that provides special semantics for monitors.</dd>
|
||||
</dl>
|
||||
@@ -346,7 +346,7 @@ Note that each client has it's own queue that is not shared with other client.
|
||||
<dt>start</dt>
|
||||
<dd>
|
||||
Start monitoring.
|
||||
This will result in a an inital monitor that has the current value
|
||||
This will result in a an initial monitor that has the current value
|
||||
of all fields.
|
||||
</dd>
|
||||
<dt>stop</dt>
|
||||
@@ -356,11 +356,11 @@ Note that each client has it's own queue that is not shared with other client.
|
||||
<dt>poll</dt>
|
||||
<dd>
|
||||
Called to get a monitor element.
|
||||
If no new elemants are available then a null pointer is returned.
|
||||
If no new elements are available then a null pointer is returned.
|
||||
</dd>
|
||||
<dt>release</dt>
|
||||
<dd>
|
||||
Release the monotor element.
|
||||
Release the monitor element.
|
||||
The caller owns the monitor element between the calls to poll and release.
|
||||
</dd>
|
||||
<dl>
|
||||
@@ -488,7 +488,7 @@ It has methods:</p>
|
||||
<dd>
|
||||
MonitorPluginManager is a singleton.
|
||||
The first call to get will create the single instance.
|
||||
Further calls will rerurn the single instance.
|
||||
Further calls will return the single instance.
|
||||
</dd>
|
||||
<dt>addPlugin</dt>
|
||||
<dd>
|
||||
@@ -496,18 +496,18 @@ It has methods:</p>
|
||||
</dd>
|
||||
<dt>findPlugin</dt>
|
||||
<dd>
|
||||
Find a plugin. A NULL shared pointer is reurned if it has not been added.
|
||||
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 puugins that have been added.
|
||||
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 modfied.
|
||||
This would be posssible if the following was defined:
|
||||
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;
|
||||
@@ -519,7 +519,7 @@ virtual bool causeMonitor(
|
||||
PVStructureConstPtr const &pvTop,
|
||||
MonitorElementPtr const &monitorElement) = 0;
|
||||
</pre>
|
||||
But just adding these definitions is not sufficent.
|
||||
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.
|
||||
@@ -545,15 +545,15 @@ structure powerSupply
|
||||
structure power
|
||||
double value
|
||||
structure alarm
|
||||
struvture display
|
||||
structure display
|
||||
structure voltage
|
||||
double value
|
||||
structure alarm
|
||||
struvture display
|
||||
structure display
|
||||
structure current
|
||||
double value
|
||||
structure alarm
|
||||
struvture display
|
||||
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:
|
||||
@@ -578,7 +578,7 @@ client wants. It can be attached to any field via the following options:
|
||||
[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 monotor
|
||||
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.
|
||||
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -28,11 +28,11 @@ StructureConstPtr enum_t =
|
||||
// create a structure (cntd.)
|
||||
StructureConstPtr ntEnum =
|
||||
getFieldCreate()->createFieldBuilder()->
|
||||
setId("uri:ev4:nt/2012/pwd/NTEnum")->
|
||||
setId("epics:nt/NTEnum:1.0")->
|
||||
add("value", enum_t)->
|
||||
addNestedStructure("timeStamp")->
|
||||
setId("time_t")->
|
||||
add("secsPastEpoch", pvLong)->
|
||||
add("secondsPastEpoch", pvLong)->
|
||||
add("nanoseconds", pvInt)->
|
||||
add("userTag", pvInt)->
|
||||
endNested()->
|
||||
|
||||
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,792 +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 pvDataDiscussion</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 class="head">
|
||||
<h1>EPICS pvDataDiscussion</h1>
|
||||
<!-- Maturity: Working Draft or Request for Comments, or Recommendation, and date. -->
|
||||
|
||||
<h2 class="nocount">EPICS v4 Working Group, Working Draft, 03-Jul-2013</h2>
|
||||
|
||||
<dl>
|
||||
<dt>Latest version:</dt>
|
||||
<dd><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvDataCPP/raw-file/tip/documentation/pvDataDiscussion.html">pvDataDiscussion.html</a>
|
||||
</dd>
|
||||
<dt>This version:</dt>
|
||||
<dd>none</dd>
|
||||
<dt>Previous version:</dt>
|
||||
<dd>None</dd>
|
||||
<dt>Editors:</dt>
|
||||
<dd>Marty Kraimer, BNL<dd />
|
||||
</dl>
|
||||
|
||||
<p class="copyright">This product is made available subject to acceptance of the <a
|
||||
href="http://epics-pvdata.sourceforge.net/LICENSE.html">EPICS open source
|
||||
license.</a></p>
|
||||
<hr />
|
||||
</div>
|
||||
|
||||
|
||||
<div id="toc">
|
||||
<h2 class="nocount" style="page-break-before: always">Table of Contents</h2>
|
||||
</div>
|
||||
<div id="contents" class="contents">
|
||||
|
||||
|
||||
<h2>Introduction</h2>
|
||||
<p>As pvDataCPP progressed PVField and derived classes accumulated
|
||||
more and more member functions.
|
||||
These member functions have nothing to do with the primary primary
|
||||
purpose for pvData:
|
||||
<blockquote>pvData (Process Variable Data) defines and implements an efficent
|
||||
way to store, access, and communicate memory resident data structures.</blockquote>
|
||||
This statement appears as the first sentence of pvDataJava.html.
|
||||
A few sentances later the document makes it clear that communication
|
||||
includes efficent network communication.
|
||||
Thus pvData provides an interface for network accessible structured data.
|
||||
The problem of adding member functions that have nothing to do with the primary purpose
|
||||
started with the Java API.
|
||||
It already had extra methods that solved problems that should have had a different solution.
|
||||
This document removes the extra methods so that when new problems arise in the future
|
||||
the solution will not involve adding new member functions to the introspection and data API.
|
||||
</p>
|
||||
<p>The introspection and data API for pvData should only encapuslate methods that support the primary purpose
|
||||
stated above.
|
||||
The interfaces for C++ and Java should be similar so that
|
||||
someone who understands the interface in one of the languages
|
||||
and knows both languages will quickly understand the interface of the other language.</p>
|
||||
<p>There is another problem with the existing API. There are methods that allow the "structure"
|
||||
to change after an pvData object is created. An example is PVField::renameField(std::string newName).
|
||||
Such methods should not exist.</p>
|
||||
<p>There are methods regarding immutability: setImmutable, isImmutablei, setCapacityMutable, and isCapacityMutable.
|
||||
Should they exists? For now lets assume no.
|
||||
</p>
|
||||
<p>One last issue is the interface for array data. This document proposes a simplified
|
||||
version of what currently exists. It requires that the implementation always provides storage for
|
||||
the complete raw array. The existing APIs allow the implementation to provide the data in
|
||||
"chunks". Giving up this requirement simplifies the array interfaces.
|
||||
The existing C++ implementation of PVValueArray has serious problems.
|
||||
The shared_vector that is implemented in pvDataCP-md provides the solution to fixing
|
||||
the problems. This document describes an API that is very similar to the new Java API
|
||||
except that raw arrays are replaced by shared_vector.</p>
|
||||
<p>This document will first describe changes to the existing Java interfaces
|
||||
and then the corresponding C++ API.</p>
|
||||
<h2>Java API</h2>
|
||||
<p>The following shows which methods will be removed from the existing interfaces
|
||||
and what will be added.
|
||||
The methods to be removed are in <font color = "red">red</font>
|
||||
and methods to add are in <font color = "blue">blue</font>
|
||||
Also the removed methods are at the end with a comment above.
|
||||
The new methods also have a comment.
|
||||
</p>
|
||||
<h3>Introspection Interfaces</h3>
|
||||
|
||||
<pre>interface Field extends Serializable {
|
||||
std::string getId();
|
||||
Type getType();
|
||||
// following will be removed
|
||||
<font color = "red">void toString(StringBuilder buf);</font>
|
||||
<font color = "red">void toString(StringBuilder buf,int indentLevel);</font>
|
||||
<font color = "red">std::string toString();</font>
|
||||
}
|
||||
|
||||
<font color = "blue">
|
||||
// new interface
|
||||
interface FieldTostd::string {
|
||||
std::string toString(Field field);
|
||||
}</font>
|
||||
|
||||
interface Scalar extends Field {
|
||||
ScalarType getScalarType();
|
||||
}
|
||||
|
||||
interface ScalarArray extends Field {
|
||||
ScalarType getElementType();
|
||||
}
|
||||
|
||||
interface Structure extends Field {
|
||||
Field getField(std::string fieldName);
|
||||
int getFieldIndex(std::string fieldName);
|
||||
Field[] getFields();
|
||||
Field getField(int fieldIndex);
|
||||
std::string[] getFieldNames();
|
||||
std::string getFieldName(int fieldIndex)
|
||||
}
|
||||
|
||||
interface StructureArray extends Field {
|
||||
Structure getStructure();
|
||||
}
|
||||
|
||||
interface FieldCreate {
|
||||
Scalar createScalar(ScalarType scalarType);
|
||||
ScalarArray createScalarArray(ScalarType elementType);
|
||||
StructureArray createStructureArray(Structure elementStructure);
|
||||
Structure createStructure(std::string[] fieldNames, Field[] field);
|
||||
Structure createStructure(std::string id,std::string[] fieldNames, Field[] field);
|
||||
Structure createStructure(Structure structToClone);
|
||||
Field deserialize(ByteBuffer buffer, DeserializableControl control);
|
||||
// following will be removed
|
||||
<font color = "red">Structure appendField(Structure structure,std::string fieldName, Field field);</font>
|
||||
<font color = "red">Structure appendFields(Structure structure,std::string[] fieldNames, Field[] fields);</font>
|
||||
}
|
||||
</pre>
|
||||
<h3>Data Interfaces</h3>
|
||||
<pre>
|
||||
interface PVField extends Requester, Serializable {
|
||||
std::string getFieldName();
|
||||
void setRequester(Requester requester);
|
||||
int getFieldOffset();
|
||||
int getNextFieldOffset();
|
||||
int getNumberFields();
|
||||
Field getField();
|
||||
PVStructure getParent();
|
||||
void postPut();
|
||||
void setPostHandler(PostHandler postHandler);
|
||||
// following will be removed
|
||||
<font color = "red">PVAuxInfo getPVAuxInfo();</font>
|
||||
<font color = "red">boolean isImmutable();</font>
|
||||
<font color = "red">void setImmutable();</font>
|
||||
<font color = "red">void renameField(std::string newName);</font>
|
||||
<font color = "red">void toString(StringBuilder buf);</font>
|
||||
<font color = "red">void toString(StringBuilder buf,int indentLevel);</font>
|
||||
<font color = "red">std::string toString();</font>
|
||||
}
|
||||
|
||||
<font color = "blue">
|
||||
// The following is a new interface
|
||||
interface PVFieldTostd::string {
|
||||
std::string toString(PVField pvField);
|
||||
void setMaxInitialArrayElements(int num);
|
||||
void setMaxFinalArrayElements(int num);
|
||||
int getMaxInitialArrayElements();
|
||||
int getMaxFinalArrayElements();
|
||||
}</font>
|
||||
|
||||
interface PVScalar extends PVField{
|
||||
Scalar getScalar();
|
||||
}
|
||||
|
||||
interface PVDouble extends PVScalar{
|
||||
double get();
|
||||
void put(double value);
|
||||
}
|
||||
// also PVBoolean, PVByte, PVShort, PVInt, PVLong, PVFloat, and PVString
|
||||
|
||||
interface PVArray extends PVField, SerializableArray {
|
||||
int getLength();
|
||||
void setLength(int length);
|
||||
int getCapacity();
|
||||
void setCapacity(int length);
|
||||
// following will be removed
|
||||
<font color = "red">boolean isCapacityMutable();</font>
|
||||
<font color = "red">void setCapacityMutable(boolean isMutable);</font>
|
||||
}
|
||||
|
||||
interface PVScalarArray extends PVArray {
|
||||
ScalarArray getScalarArray();
|
||||
}
|
||||
|
||||
<font color = "red">
|
||||
//following will be removed
|
||||
public class DoubleArrayData {
|
||||
public double[] data;
|
||||
public int offset;
|
||||
}</font>
|
||||
|
||||
interface PVDoubleArray extends PVArray {
|
||||
// following are new
|
||||
<font color = "blue"> double[] get();</font>
|
||||
<font color = "blue"> void swap(double[] value);</font>
|
||||
//following will be removed
|
||||
<font color = "red"> int get(int offset, int len, DoubleArrayData data);</font>
|
||||
<font color = "red"> int put(int offset,int len, double[] from, int fromOffset)</font>;
|
||||
<font color = "red"> void shareData(double[] from);</font>
|
||||
}
|
||||
|
||||
// also PVBooleanArray, ..., PVStringArray
|
||||
|
||||
|
||||
interface PVStructure extends PVField , BitSetSerializable{
|
||||
Structure getStructure();
|
||||
PVField[] getPVFields();
|
||||
PVField getSubField(std::string fieldName);
|
||||
PVField getSubField(int fieldOffset);
|
||||
// The following are convenience methods
|
||||
PVBoolean getBooleanField(std::string fieldName);
|
||||
PVByte getByteField(std::string fieldName);
|
||||
PVShort getShortField(std::string fieldName);
|
||||
PVInt getIntField(std::string fieldName);
|
||||
PVLong getLongField(std::string fieldName);
|
||||
PVFloat getFloatField(std::string fieldName);
|
||||
PVDouble getDoubleField(std::string fieldName);
|
||||
PVString getStringField(std::string fieldName);
|
||||
PVScalarArray getScalarArrayField(std::string fieldName);
|
||||
PVStructureArray getStructureArrayField(std::string fieldName);
|
||||
PVStructure getStructureField(std::string fieldName);
|
||||
PVArray getArrayField(std::string fieldName,ScalarType elementType);
|
||||
// following will be removed
|
||||
<font color = "red"> void appendPVField(std::string fieldName,PVField pvField);</font>
|
||||
<font color = "red"> void appendPVFields(std::string[] fieldNames,PVField[] pvFields);</font>
|
||||
<font color = "red"> void removePVField(std::string fieldName);</font>
|
||||
<font color = "red"> void replacePVField(PVField oldPVField,PVField newPVField);</font>
|
||||
<font color = "red"> std::string getExtendsStructureName();</font>
|
||||
<font color = "red"> boolean putExtendsStructureName(std::string extendsStructureName);</font>
|
||||
<font color = "red"> public boolean checkValid();</font>
|
||||
}
|
||||
|
||||
<font color = "red">
|
||||
//following will be removed
|
||||
public class StructureArrayData {
|
||||
public PVStructure[] data;
|
||||
public int offset;
|
||||
}
|
||||
</font>
|
||||
|
||||
interface PVStructureArray extends PVArray{
|
||||
StructureArray getStructureArray();
|
||||
// following are new
|
||||
<font color = "blue"> PVStructure[] get();</font>
|
||||
<font color = "blue"> void swap(PVStructure[] value);</font>
|
||||
// following will be removed
|
||||
<font color = "red"> int get(int offset, int length, StructureArrayData data);</font>
|
||||
<font color = "red"> int put(int offset,int length, PVStructure[] from, int fromOffset);</font>
|
||||
<font color = "red"> void shareData(PVStructure[] from);</font>
|
||||
}
|
||||
|
||||
|
||||
public interface PVDataCreate {
|
||||
PVField createPVField(Field field);
|
||||
PVField createPVField(PVField fieldToClone);
|
||||
PVScalar createPVScalar(Scalar scalar);
|
||||
PVScalar createPVScalar(ScalarType fieldType);
|
||||
PVScalar createPVScalar(PVScalar scalarToClone);
|
||||
PVScalarArray createPVScalarArray(ScalarArray array);
|
||||
PVScalarArray createPVScalarArray(ScalarType elementType);
|
||||
PVScalarArray createPVScalarArray(PVScalarArray arrayToClone;
|
||||
PVStructureArray createPVStructureArray(StructureArray structureArray);
|
||||
PVStructure createPVStructure(Structure structure);
|
||||
PVStructure createPVStructure(std::string[] fieldNames,Field[] fields);
|
||||
PVStructure createPVStructure(PVStructure structToClone);
|
||||
// following will be removed
|
||||
<font color = "red">PVField[] flattenPVStructure(PVStructure pvStructure);</font>
|
||||
}
|
||||
</pre>
|
||||
<h3>PVFieldTostd::string</h3>
|
||||
<p>In addition to toString this has methods to limit the number of array element to display.
|
||||
The existing Java implementation of toString displayed all elements.
|
||||
For large arrays this is not desirable.
|
||||
The new methods provide a way for the client to limit the number of elements.
|
||||
The default might be set to something like display up to 10 elements with 5 fron the beginning and 5 from the end.</p>
|
||||
<p>For C++ this can be a replacement for dumpValue.</p>
|
||||
<h3>PVBooleanArray, ..., PVStructureArray</h3>
|
||||
<p>The old get and put are replaced by two new and simpler methods:
|
||||
<dl>
|
||||
<dt>get</dt>
|
||||
<dd>Returns the raw array. If the client code modifies the elements in the array then
|
||||
the client must call postPut. The client also has to realize that if the raw array held by the PVXXXArray changes
|
||||
then the client is no longer sharing data
|
||||
<dt>swap</dt>
|
||||
<dd>This exchanges the old raw data with the new raw data.</dd>
|
||||
</dl>
|
||||
</p>
|
||||
<p>
|
||||
The method <b>setCapacity</b> will always create a new raw array and copy old data from the old to the new array.
|
||||
This is not true now since the implementation does not create a new array if the old capacity is equal to the requested capacity.
|
||||
</p>
|
||||
<h2>C++ API</h2>
|
||||
<p>The C++ class definitions are similar to the Java definitions with two main exceptions:
|
||||
<dl>
|
||||
<dt>toString</dt>
|
||||
<dd>In c++ this is replaced by std::ostream.</dd>
|
||||
<dt>raw array data</dt>
|
||||
<dd>Java supports array data like <b>double[]</b>
|
||||
The C++ replacement is shared_vector<double>, which is implemented
|
||||
in pvDataCPP-md.</dd
|
||||
</dl>
|
||||
<h3>Introspection Interfaces</h3>
|
||||
|
||||
<pre>
|
||||
class Field :
|
||||
virtual public Serializable,
|
||||
public std::tr1::enable_shared_from_this<Field>
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(Field);
|
||||
virtual ~Field();
|
||||
Type getType() const{return m_type;}
|
||||
virtual std::string getID() const = 0;
|
||||
<font color = "red">
|
||||
// following will be removed
|
||||
virtual void toString(StringBuilder buf) const{toString(buf,0);}
|
||||
virtual void toString(StringBuilder buf,int indentLevel) const;
|
||||
</font>
|
||||
...
|
||||
};
|
||||
<font color = "blue">
|
||||
// new function
|
||||
std::ostream &toString(Field::const_reference field, std::ostream& o);
|
||||
</font>
|
||||
|
||||
class Scalar : public Field{
|
||||
public:
|
||||
POINTER_DEFINITIONS(Scalar);
|
||||
virtual ~Scalar();
|
||||
typedef Scalar& reference;
|
||||
typedef const Scalar& const_reference;
|
||||
|
||||
ScalarType getScalarType() const {return scalarType;}
|
||||
virtual void serialize(ByteBuffer *buffer, SerializableControl *control) const;
|
||||
virtual void deserialize(ByteBuffer *buffer, DeserializableContol *control);
|
||||
<font color = "red">
|
||||
// following will be removed
|
||||
virtual void toString(StringBuilder buf) const{toString(buf,0);}
|
||||
virtual void toString(StringBuilder buf,int indentLevel) const;
|
||||
virtual std::string getID() const;
|
||||
</font>
|
||||
...
|
||||
};
|
||||
class ScalarArray : public Field{
|
||||
public:
|
||||
POINTER_DEFINITIONS(ScalarArray);
|
||||
typedef ScalarArray& reference;
|
||||
typedef const ScalarArray& const_reference;
|
||||
|
||||
ScalarArray(ScalarType scalarType);
|
||||
ScalarType getElementType() const {return elementType;}
|
||||
virtual void serialize(ByteBuffer *buffer, SerializableControl *control) const;
|
||||
virtual void deserialize(ByteBuffer *buffer, DeserializableControl *control);
|
||||
<font color = "red">
|
||||
// following will be removed
|
||||
virtual void toString(StringBuilder buf) const{toString(buf,0);}
|
||||
virtual void toString(StringBuilder buf,int indentLevel) const;
|
||||
virtual std::string getID() const;
|
||||
</font>
|
||||
...
|
||||
};
|
||||
|
||||
class Structure : public Field {
|
||||
public:
|
||||
POINTER_DEFINITIONS(Structure);
|
||||
typedef Structure& reference;
|
||||
typedef const Structure& const_reference;
|
||||
|
||||
std::size_t getNumberFields() const {return numberFields;}
|
||||
FieldConstPtr getField(std::string const & fieldName) const;
|
||||
FieldConstPtr getField(std::size_t index) const;
|
||||
std::size_t getFieldIndex(std::string const &fieldName) const;
|
||||
FieldConstPtrArray const & getFields() const {return fields;}
|
||||
StringArray const & getFieldNames() const;
|
||||
std::string getFieldName(std::size_t fieldIndex);
|
||||
virtual void serialize(ByteBuffer *buffer, SerializableControl *control) const;
|
||||
virtual void deserialize(ByteBuffer *buffer, DeserializableControl *control);
|
||||
<font color = "red">
|
||||
// following will be removed
|
||||
void renameField(std::size_t fieldIndex,std::string const &newName);
|
||||
virtual void toString(StringBuilder buf,int indentLevel) const;
|
||||
virtual std::string getID() const;
|
||||
</font>
|
||||
...
|
||||
};
|
||||
|
||||
class StructureArray : public Field{
|
||||
public:
|
||||
POINTER_DEFINITIONS(StructureArray);
|
||||
typedef StructureArray& reference;
|
||||
typedef const StructureArray& const_reference;
|
||||
|
||||
StructureConstPtr getStructure() const {return pstructure;}
|
||||
virtual void serialize(ByteBuffer *buffer, SerializableControl *control) const;
|
||||
virtual void deserialize(ByteBuffer *buffer, DeserializableControl *control);
|
||||
<font color = "red">
|
||||
// following will be removed
|
||||
virtual void toString(StringBuilder buf,int indentLevel=0) const;
|
||||
virtual std::string getID() const;
|
||||
</font>
|
||||
...
|
||||
};
|
||||
|
||||
class FieldCreate {
|
||||
public:
|
||||
static FieldCreatePtr getFieldCreate();
|
||||
ScalarConstPtr createScalar(ScalarType scalarType) const
|
||||
ScalarArrayConstPtr createScalarArray(ScalarType elementType) const;
|
||||
StructureArrayConstPtr createStructureArray(StructureConstPtr const & structure) const;
|
||||
StructureConstPtr createStructure (
|
||||
StringArray const & fieldNames,
|
||||
FieldConstPtrArray const & fields) const;
|
||||
StructureConstPtr createStructure (
|
||||
std::string const &id,
|
||||
StringArray const & fieldNames,
|
||||
FieldConstPtrArray const & fields) const;
|
||||
FieldConstPtr deserialize(ByteBuffer* buffer, DeserializableControl* control) const;
|
||||
<font color = "red">
|
||||
// following will be removed
|
||||
StructureConstPtr appendField(
|
||||
StructureConstPtr const & structure,
|
||||
std::string const &fieldName, FieldConstPtr const & field) const;
|
||||
StructureConstPtr appendFields(
|
||||
StructureConstPtr const & structure,
|
||||
StringArray const & fieldNames,
|
||||
FieldConstPtrArray const & fields) const;
|
||||
</font>
|
||||
...
|
||||
};
|
||||
|
||||
extern FieldCreatePtr getFieldCreate();
|
||||
</pre>
|
||||
<h3>Data Interfaces</h3>
|
||||
<pre>
|
||||
class PVField
|
||||
: virtual public Serializable,
|
||||
public std::tr1::enable_shared_from_this<PVField>
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(PVField);
|
||||
virtual ~PVField();
|
||||
inline const std::string &getFieldName() const ;
|
||||
virtual void setRequester(RequesterPtr const &prequester);
|
||||
std::size_t getFieldOffset() const;
|
||||
std::size_t getNextFieldOffset() const;
|
||||
std::size_t getNumberFields() const;
|
||||
const FieldConstPtr & getField() const ;
|
||||
PVStructure * getParent() const
|
||||
void postPut() ;
|
||||
void setPostHandler(PostHandlerPtr const &postHandler);
|
||||
// following will be removed
|
||||
<font color = "red">
|
||||
virtual void message(std::string message,MessageType messageType);
|
||||
void replacePVField(const PVFieldPtr& newPVField);
|
||||
std::string getFullName() const;
|
||||
virtual bool equals(PVField &pv);
|
||||
PVAuxInfoPtr & getPVAuxInfo()
|
||||
bool isImmutable() const;
|
||||
virtual void setImmutable();
|
||||
void replacePVField(const PVFieldPtr& newPVField);
|
||||
void renameField(std::string const &newName);
|
||||
virtual void toString(StringBuilder buf) ;
|
||||
virtual void toString(StringBuilder buf,int indentLevel);
|
||||
std::ostream& dumpValue(std::ostream& o) const;
|
||||
</font>
|
||||
...
|
||||
};
|
||||
|
||||
<font color = "blue">
|
||||
// The following is a new class
|
||||
class PVFieldTostd::string {
|
||||
std::string toString(const PVFieldPtr &pvField);
|
||||
void setMaxInitialArrayElements(size_t num);
|
||||
void setMaxFinalArrayElements(size_t num);
|
||||
size_t getMaxInitialArrayElements();
|
||||
size_t getMaxFinalArrayElements();
|
||||
...
|
||||
}</font>
|
||||
|
||||
class PVScalar : public PVField {
|
||||
public:
|
||||
POINTER_DEFINITIONS(PVScalar);
|
||||
virtual ~PVScalar();
|
||||
typedef PVScalar &reference;
|
||||
typedef const PVScalar& const_reference;
|
||||
|
||||
const ScalarConstPtr getScalar() const ;
|
||||
...
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
class PVScalarValue : public PVScalar {
|
||||
public:
|
||||
POINTER_DEFINITIONS(PVScalarValue);
|
||||
typedef T value_type;
|
||||
typedef T* pointer;
|
||||
typedef const T* const_pointer;
|
||||
|
||||
virtual ~PVScalarValue() {}
|
||||
virtual T get() const = 0;
|
||||
virtual void put(T value) = 0;
|
||||
<font color = "red">
|
||||
// following will be removed
|
||||
std::ostream& dumpValue(std::ostream& o)
|
||||
void operator>>=(T& value) const;
|
||||
void operator<<=(T value);
|
||||
</font>
|
||||
...
|
||||
}
|
||||
|
||||
// PVString is special case, since it implements SerializableArray
|
||||
class PVString : public PVScalarValue<std::string>, SerializableArray {
|
||||
public:
|
||||
virtual ~PVString() {}
|
||||
...
|
||||
}
|
||||
class PVArray : public PVField, public SerializableArray {
|
||||
public:
|
||||
POINTER_DEFINITIONS(PVArray);
|
||||
virtual ~PVArray();
|
||||
std::size_t getLength() const;
|
||||
virtual void setLength(std::size_t length);
|
||||
std::size_t getCapacity() const;
|
||||
virtual void setCapacity(std::size_t capacity) = 0;
|
||||
<font color = "red">
|
||||
// following will be removed
|
||||
virtual void setImmutable();
|
||||
bool isCapacityMutable() const;
|
||||
void setCapacityMutable(bool isMutable);
|
||||
virtual std::ostream& dumpValue(std::ostream& o, std::size_t index) const = 0;
|
||||
</font>
|
||||
...
|
||||
};
|
||||
|
||||
class PVScalarArray : public PVArray {
|
||||
public:
|
||||
POINTER_DEFINITIONS(PVScalarArray);
|
||||
virtual ~PVScalarArray();
|
||||
typedef PVScalarArray &reference;
|
||||
typedef const PVScalarArray& const_reference;
|
||||
|
||||
const ScalarArrayConstPtr getScalarArray() const ;
|
||||
<font color = "red">
|
||||
// following will be removed
|
||||
virtual std::ostream& dumpValue(std::ostream& o, size_t index) const = 0;
|
||||
</font>
|
||||
...
|
||||
}
|
||||
|
||||
<font color = "red">
|
||||
// following will be removed
|
||||
template<typename T>
|
||||
class PVArrayData {
|
||||
private:
|
||||
std::vector<T> init;
|
||||
public:
|
||||
POINTER_DEFINITIONS(PVArrayData);
|
||||
typedef T value_type;
|
||||
typedef T* pointer;
|
||||
typedef const T* const_pointer;
|
||||
std::vector<T> & data;
|
||||
std::size_t offset;
|
||||
PVArrayData()
|
||||
: data(init)
|
||||
{}
|
||||
};
|
||||
</font>
|
||||
|
||||
template<typename T>
|
||||
class PVValueArray : public PVScalarArray {
|
||||
public:
|
||||
POINTER_DEFINITIONS(PVValueArray);
|
||||
typedef T value_type;
|
||||
typedef T* pointer;
|
||||
typedef const T* const_pointer;
|
||||
// following are new typeDefs
|
||||
<font color = "blue">typedef shared_vector<T> svector;</font>
|
||||
<font color = "blue">typedef shared_vector<const T> const_svector; </font>
|
||||
|
||||
virtual ~PVValueArray() {}
|
||||
// following are added
|
||||
<font color = "blue">svector get();</font>
|
||||
<font color = "blue">void swap(svector& value);</font>
|
||||
<font color = "red">
|
||||
// following are removed
|
||||
typedef PVValueArray & reference;
|
||||
typedef const PVValueArray & const_reference;
|
||||
typedef PVArrayData<T> ArrayDataType;
|
||||
typedef std::vector<T> vector;
|
||||
typedef const std::vector<T> const_vector;
|
||||
typedef std::tr1::shared_ptr<vector> shared_vector;
|
||||
|
||||
virtual std::size_t get(
|
||||
std::size_t offset, std::size_t length, ArrayDataType &data) = 0;
|
||||
virtual std::size_t put(std::size_t offset,
|
||||
std::size_t length, const_pointer from, std::size_t fromOffset) = 0;
|
||||
virtual std::size_t put(std::size_t offset,
|
||||
std::size_t length, const_vector &from, std::size_t fromOffset);
|
||||
virtual void shareData(
|
||||
shared_vector const & value,
|
||||
std::size_t capacity,
|
||||
std::size_t length) = 0;
|
||||
virtual pointer get() = 0;
|
||||
virtual pointer get() const = 0;
|
||||
virtual vector const & getVector() = 0;
|
||||
virtual shared_vector const & getSharedVector() = 0;
|
||||
std::ostream& dumpValue(std::ostream& o) const;
|
||||
std::ostream& dumpValue(std::ostream& o, size_t index) const;
|
||||
</font>
|
||||
...
|
||||
};
|
||||
|
||||
typedef PVValueArray<uint8> PVBooleanArray;
|
||||
typedef std::tr1::shared_ptr<PVBooleanArray> PVBooleanArrayPtr;
|
||||
...
|
||||
typedef PVValueArray<std::string> PVStringArray;
|
||||
typedef std::tr1::shared_ptr<PVStringArray> PVStringArrayPtr;
|
||||
|
||||
class PVStructure : public PVField,public BitSetSerializable {
|
||||
public:
|
||||
POINTER_DEFINITIONS(PVStructure);
|
||||
virtual ~PVStructure();
|
||||
typedef PVStructure & reference;
|
||||
typedef const PVStructure & const_reference;
|
||||
|
||||
StructureConstPtr getStructure() const;
|
||||
const PVFieldPtrArray & getPVFields() const;
|
||||
PVFieldPtr getSubField(std::string const &fieldName) const;
|
||||
PVFieldPtr getSubField(std::size_t fieldOffset) const;
|
||||
PVBooleanPtr getBooleanField(std::string const &fieldName) ;
|
||||
PVBytePtr getByteField(std::string const &fieldName) ;
|
||||
PVShortPtr getShortField(std::string const &fieldName) ;
|
||||
PVIntPtr getIntField(std::string const &fieldName) ;
|
||||
PVLongPtr getLongField(std::string const &fieldName) ;
|
||||
PVUBytePtr getUByteField(std::string const &fieldName) ;
|
||||
PVUShortPtr getUShortField(std::string const &fieldName) ;
|
||||
PVUIntPtr getUIntField(std::string const &fieldName) ;
|
||||
PVULongPtr getULongField(std::string const &fieldName) ;
|
||||
PVFloatPtr getFloatField(std::string const &fieldName) ;
|
||||
PVDoublePtr getDoubleField(std::string const &fieldName) ;
|
||||
PVStringPtr getStringField(std::string const &fieldName) ;
|
||||
PVStructurePtr getStructureField(std::string const &fieldName) ;
|
||||
PVScalarArrayPtr getScalarArrayField(
|
||||
std::string const &fieldName,ScalarType elementType) ;
|
||||
PVStructureArrayPtr getStructureArrayField(std::string const &fieldName) ;
|
||||
virtual void serialize(
|
||||
ByteBuffer *pbuffer,SerializableControl *pflusher) const ;
|
||||
virtual void deserialize(
|
||||
ByteBuffer *pbuffer,DeserializableControl *pflusher);
|
||||
virtual void serialize(ByteBuffer *pbuffer,
|
||||
SerializableControl *pflusher,BitSet *pbitSet) const;
|
||||
virtual void deserialize(ByteBuffer *pbuffer,
|
||||
DeserializableControl*pflusher,BitSet *pbitSet);
|
||||
PVStructure(StructureConstPtr const & structure);
|
||||
PVStructure(StructureConstPtr const & structure,PVFieldPtrArray const & pvFields);
|
||||
<font color = "red">
|
||||
// following are removed
|
||||
void appendPVField(
|
||||
std::string const &fieldName,
|
||||
PVFieldPtr const & pvField);
|
||||
void appendPVFields(
|
||||
StringArray const & fieldNames,
|
||||
PVFieldPtrArray const & pvFields);
|
||||
void removePVField(std::string const &fieldName);
|
||||
virtual void setImmutable();
|
||||
std::string getExtendsStructureName() const;
|
||||
bool putExtendsStructureName(
|
||||
std::string const &extendsStructureName);
|
||||
</font>
|
||||
};
|
||||
|
||||
<font color = "red">
|
||||
// following will be removed
|
||||
typedef PVArrayData<PVStructurePtr> StructureArrayData;
|
||||
</font>
|
||||
|
||||
class PVStructureArray : public PVArray
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(PVStructureArray);
|
||||
typedef PVStructurePtr value_type;
|
||||
typedef PVStructurePtr* pointer;
|
||||
typedef const PVStructurePtr* const_pointer;
|
||||
<font color = "blue">
|
||||
// following are new typeDefs
|
||||
typedef shared_vector<PVStructurePtr> svector;
|
||||
typedef shared_vector<const PVStructurePtr> const_svector;
|
||||
</font>
|
||||
|
||||
virtual ~PVStructureArray() {}
|
||||
virtual void setCapacity(size_t capacity);
|
||||
virtual void setLength(std::size_t length);
|
||||
virtual StructureArrayConstPtr getStructureArray() const ;
|
||||
virtual void serialize(ByteBuffer *pbuffer,
|
||||
SerializableControl *pflusher) const;
|
||||
virtual void deserialize(ByteBuffer *buffer,
|
||||
virtual void serialize(ByteBuffer *pbuffer,
|
||||
SerializableControl *pflusher, std::size_t offset, std::size_t count) const ;
|
||||
// following are new
|
||||
<font color = "blue"> svector get();</font>
|
||||
<font color = "blue"> void swap(svector & value);</font>
|
||||
<font color = "red">
|
||||
// following are removed
|
||||
typedef PVArrayData<PVStructurePtr> ArrayDataType;
|
||||
typedef std::vector<PVStructurePtr> vector;
|
||||
typedef const std::vector<PVStructurePtr> const_vector;
|
||||
typedef std::tr1::shared_ptr<vector> shared_vector;
|
||||
typedef PVStructureArray &reference;
|
||||
typedef const PVStructureArray& const_reference;
|
||||
|
||||
virtual std::size_t append(std::size_t number);
|
||||
virtual bool remove(std::size_t offset,std::size_t number);
|
||||
virtual void compress();
|
||||
virtual std::size_t get(std::size_t offset, std::size_t length,
|
||||
StructureArrayData &data);
|
||||
virtual std::size_t put(std::size_t offset,std::size_t length,
|
||||
const_vector const & from, std::size_t fromOffset);
|
||||
virtual void shareData(
|
||||
shared_vector const & value,
|
||||
std::size_t capacity,
|
||||
std::size_t length);
|
||||
virtual pointer get() { return &((*value.get())[0]); }
|
||||
virtual pointer get() const { return &((*value.get())[0]); }
|
||||
virtual vector const & getVector() {return *value;}
|
||||
virtual shared_vector const & getSharedVector() {return value;}
|
||||
</font>
|
||||
...
|
||||
};
|
||||
|
||||
class PVDataCreate {
|
||||
public:
|
||||
static PVDataCreatePtr getPVDataCreate();
|
||||
PVFieldPtr createPVField(FieldConstPtr const & field);
|
||||
PVFieldPtr createPVField(PVFieldPtr const & fieldToClone);
|
||||
PVScalarPtr createPVScalar(ScalarConstPtr const & scalar);
|
||||
PVScalarPtr createPVScalar(ScalarType scalarType);
|
||||
PVScalarPtr createPVScalar(PVScalarPtr const & scalarToClone);
|
||||
PVScalarArrayPtr createPVScalarArray(ScalarArrayConstPtr const & scalarArray);
|
||||
PVScalarArrayPtr createPVScalarArray(ScalarType elementType);
|
||||
PVScalarArrayPtr createPVScalarArray(PVScalarArrayPtr const & scalarArrayToClone);
|
||||
PVStructureArrayPtr createPVStructureArray(StructureArrayConstPtr const & structureArray);
|
||||
PVStructurePtr createPVStructure(StructureConstPtr const & structure);
|
||||
PVStructurePtr createPVStructure(
|
||||
StringArray const & fieldNames,PVFieldPtrArray const & pvFields);
|
||||
PVStructurePtr createPVStructure(PVStructurePtr const & structToClone);
|
||||
...
|
||||
};
|
||||
|
||||
extern PVDataCreatePtr getPVDataCreate();
|
||||
</pre>
|
||||
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -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,20 +44,13 @@ EPICS_BASE=${EPICS_BASE}
|
||||
EOF
|
||||
|
||||
make distclean all
|
||||
doxygen
|
||||
|
||||
###########################################
|
||||
# Test
|
||||
|
||||
# EPICS Test Harness tests
|
||||
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 +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
|
||||
@@ -14,10 +14,12 @@
|
||||
#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 {
|
||||
|
||||
@@ -27,6 +29,38 @@ 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) {
|
||||
@@ -40,8 +74,8 @@ private:
|
||||
size_t openBrace = request.find('{', index+1);
|
||||
size_t closeBrace = request.find('}', index+1);
|
||||
if(openBrace == string::npos && closeBrace == string::npos){
|
||||
message = request + " missing }";
|
||||
return 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);
|
||||
@@ -56,14 +90,14 @@ private:
|
||||
for(size_t i=index+1; i< request.size(); ++i) {
|
||||
if(request[i] == ']') {
|
||||
if(i==index+1) {
|
||||
message = request + " illegal []";
|
||||
return string::npos;
|
||||
message = request + " mismatched []";
|
||||
throw std::logic_error("message");
|
||||
}
|
||||
return i;
|
||||
}
|
||||
}
|
||||
message = request + " missing ]";
|
||||
return string::npos;
|
||||
message = request + " missing ]";
|
||||
throw std::logic_error("message");
|
||||
}
|
||||
|
||||
size_t findEndField(string& request) {
|
||||
@@ -84,13 +118,17 @@ private:
|
||||
ind = closeBrace;
|
||||
continue;
|
||||
}
|
||||
if(request[ind]=='.') {
|
||||
++ind;
|
||||
continue;
|
||||
}
|
||||
if(ind>=maxind) break;
|
||||
++ind;
|
||||
}
|
||||
return request.size();
|
||||
}
|
||||
|
||||
std::vector<string> split(string const & commaSeparatedList) {
|
||||
vector<string> split(string const & commaSeparatedList) {
|
||||
string::size_type numValues = 1;
|
||||
string::size_type index=0;
|
||||
while(true) {
|
||||
@@ -99,7 +137,7 @@ private:
|
||||
numValues++;
|
||||
index = pos +1;
|
||||
}
|
||||
std::vector<string> valueList(numValues,"");
|
||||
vector<string> valueList(numValues,"");
|
||||
index=0;
|
||||
for(size_t i=0; i<numValues; i++) {
|
||||
size_t pos = commaSeparatedList.find(',',index);
|
||||
@@ -110,417 +148,331 @@ private:
|
||||
return valueList;
|
||||
}
|
||||
|
||||
StructureConstPtr createRequestOptions(
|
||||
string request)
|
||||
Node createRequestOptions(
|
||||
string const & request)
|
||||
{
|
||||
if(request.length()<=1) return StructureConstPtr();
|
||||
std::vector<string> items = split(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();
|
||||
StringArray fieldNames(nitems);
|
||||
FieldConstPtrArray fields(nitems);
|
||||
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";
|
||||
StructureConstPtr xxx;
|
||||
return xxx;
|
||||
message = item + " illegal option " + request;
|
||||
throw std::logic_error("message");
|
||||
}
|
||||
fieldNames[j] = item.substr(0,equals);
|
||||
fields[j] = fieldCreate->createScalar(pvString);
|
||||
}
|
||||
return fieldCreate->createStructure(fieldNames,fields);
|
||||
}
|
||||
|
||||
void initRequestOptions(
|
||||
PVStructurePtr const & pvParent,
|
||||
string request)
|
||||
{
|
||||
if(request.length()<=1) return;
|
||||
std::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('=');
|
||||
string name = item.substr(0,equals);
|
||||
top.push_back(Node(item.substr(0,equals)));
|
||||
string name = fullFieldName + "._options." + item.substr(0,equals);
|
||||
string value = item.substr(equals+1);
|
||||
PVStringPtr pvValue = pvParent->getSubField<PVString>(name);
|
||||
pvValue->put(value);
|
||||
optionList.push_back(OptionPair(name,value));
|
||||
}
|
||||
}
|
||||
|
||||
StructureConstPtr createSubFieldRequest(
|
||||
StructureConstPtr parent,
|
||||
string request)
|
||||
{
|
||||
if(request.length()<=0) return parent;
|
||||
size_t period = request.find('.');
|
||||
size_t openBracket = request.find('[');
|
||||
size_t openBrace = request.find('{');
|
||||
|
||||
// name only
|
||||
if(period==string::npos
|
||||
&& openBracket==string::npos
|
||||
&& openBrace==string::npos)
|
||||
{
|
||||
StructureConstPtr subField = fieldCreate->createStructure();
|
||||
parent = fieldCreate->appendField(parent,request,subField);
|
||||
return parent;
|
||||
}
|
||||
|
||||
// period is first
|
||||
if(period!=string::npos
|
||||
&& (openBracket==string::npos || period<openBracket)
|
||||
&& (openBrace==string::npos || period<openBrace) )
|
||||
{
|
||||
string fieldName = request.substr(0,period);
|
||||
StructureConstPtr subField = fieldCreate->createStructure();
|
||||
subField = createSubFieldRequest(subField,request.substr(period+1));
|
||||
if(subField==NULL) return subField;
|
||||
parent = fieldCreate->appendField(parent,fieldName,subField);
|
||||
return parent;
|
||||
}
|
||||
|
||||
// brace before [ or .
|
||||
if(openBrace!=string::npos
|
||||
&& (openBracket==string::npos || openBrace<openBracket) )
|
||||
{
|
||||
string fieldName = request.substr(0,openBrace);
|
||||
size_t closeBrace = findMatchingBrace(request,openBrace,1);
|
||||
if(closeBrace==string::npos) return StructureConstPtr();
|
||||
size_t nextChar = closeBrace+1;
|
||||
if(nextChar>= request.size()) nextChar = string::npos;
|
||||
if(nextChar!=string::npos) {
|
||||
message = request + " syntax error " + request[nextChar] + " after } illegal";
|
||||
return StructureConstPtr();
|
||||
}
|
||||
StructureConstPtr subField = fieldCreate->createStructure();
|
||||
string subRequest = request.substr(openBrace+1,closeBrace-openBrace-1);
|
||||
subField = createFieldRequest(subField,subRequest);
|
||||
if(subField==NULL) return subField;
|
||||
parent = fieldCreate->appendField(parent,fieldName,subField);
|
||||
return parent;
|
||||
}
|
||||
|
||||
// [ is before brace or .
|
||||
if(openBracket!=string::npos
|
||||
&& (openBrace==string::npos || openBracket<openBrace) )
|
||||
{
|
||||
string fieldName = request.substr(0,openBracket);
|
||||
size_t closeBracket = findMatchingBracket(request,openBracket);
|
||||
if(closeBracket==string::npos) return StructureConstPtr();
|
||||
size_t nextChar = closeBracket+1;
|
||||
if(nextChar>= request.size()) nextChar = string::npos;
|
||||
if(nextChar==string::npos) {
|
||||
StringArray fieldNames(1);
|
||||
FieldConstPtrArray fields(1);
|
||||
fieldNames[0] = "_options";
|
||||
fields[0] = createRequestOptions(
|
||||
request.substr(openBracket+1,closeBracket-openBracket-1));
|
||||
StructureConstPtr subField = fieldCreate->createStructure(fieldNames,fields);
|
||||
parent = fieldCreate->appendField(parent,fieldName,subField);
|
||||
return parent;
|
||||
}
|
||||
if(request[nextChar]=='.') {
|
||||
StructureConstPtr subField = fieldCreate->createStructure();
|
||||
subField = createSubFieldRequest(subField,request.substr(nextChar+1));
|
||||
if(subField==NULL) return StructureConstPtr();
|
||||
if(subField->getNumberFields()!=1) {
|
||||
message = request + " logic error createSubFieldRequest openBracket subField";
|
||||
return StructureConstPtr();
|
||||
}
|
||||
StringArray fieldNames(2);
|
||||
FieldConstPtrArray fields(2);
|
||||
fieldNames[0] = "_options";
|
||||
fields[0] = createRequestOptions(
|
||||
request.substr(openBracket+1,closeBracket-openBracket-1));
|
||||
fieldNames[1] = subField->getFieldNames()[0];
|
||||
fields[1] = subField;
|
||||
subField = fieldCreate->createStructure(fieldNames,fields);
|
||||
parent = fieldCreate->appendField(parent,fieldName,subField);
|
||||
return parent;
|
||||
}
|
||||
if(request[nextChar]=='{') {
|
||||
size_t closeBrace = findMatchingBrace(request,openBrace,1);
|
||||
if(closeBrace==string::npos) return StructureConstPtr();
|
||||
StructureConstPtr subField = fieldCreate->createStructure();
|
||||
string subRequest = request.substr(openBrace+1,closeBrace-openBrace-1);
|
||||
subField = createFieldRequest(subField,subRequest);
|
||||
if(subField==NULL) return subField;
|
||||
size_t numSub = subField->getNumberFields();
|
||||
StringArray fieldNames(numSub + 1);
|
||||
FieldConstPtrArray fields(numSub+1);
|
||||
fieldNames[0] = "_options";
|
||||
fields[0] = createRequestOptions(
|
||||
request.substr(openBracket+1,closeBracket-openBracket-1));
|
||||
StringArray subNames = subField->getFieldNames();
|
||||
FieldConstPtrArray subFields = subField->getFields();
|
||||
for(size_t i=0; i<numSub; ++i) {
|
||||
fieldNames[i+1] = subNames[i];
|
||||
fields[i+1] = subFields[i];
|
||||
}
|
||||
subField = fieldCreate->appendFields(parent,fieldNames,fields);
|
||||
parent = fieldCreate->appendField(parent,fieldName,subField);
|
||||
return parent;
|
||||
}
|
||||
}
|
||||
message = request + " logic error createSubFieldRequest";
|
||||
return StructureConstPtr();
|
||||
Node node("_options");
|
||||
node.nodes = top;
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
StructureConstPtr createFieldRequest(
|
||||
StructureConstPtr parent,
|
||||
string request)
|
||||
void createSubNode(Node &node,string const & crequest)
|
||||
{
|
||||
size_t length = request.length();
|
||||
if(length<=0) return parent;
|
||||
size_t end = findEndField(request);
|
||||
if(end==string::npos) return StructureConstPtr();
|
||||
StringArray fieldNames;
|
||||
FieldConstPtrArray fields;
|
||||
StructureConstPtr subField = fieldCreate->createStructure();
|
||||
subField = createSubFieldRequest(subField,request.substr(0,end));
|
||||
if(subField==NULL) return subField;
|
||||
fieldNames.push_back(subField->getFieldNames()[0]);
|
||||
fields.push_back(subField->getFields()[0]);
|
||||
if(end!=length) {
|
||||
if(request[end]!=',') {
|
||||
message = request;
|
||||
message += " expected char ";
|
||||
message += length;
|
||||
message += " to be ,";
|
||||
return StructureConstPtr();
|
||||
}
|
||||
StructureConstPtr nextSubField = fieldCreate->createStructure();
|
||||
nextSubField = createFieldRequest(nextSubField,request.substr(end+1));
|
||||
if(nextSubField==NULL) return nextSubField;
|
||||
size_t numFields = nextSubField->getNumberFields();
|
||||
StringArray subNames = nextSubField->getFieldNames();
|
||||
FieldConstPtrArray subFields = nextSubField->getFields();
|
||||
for(size_t i=0; i<numFields; ++i) {
|
||||
fieldNames.push_back(subNames[i]);
|
||||
fields.push_back(subFields[i]);
|
||||
}
|
||||
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;}
|
||||
}
|
||||
parent = fieldCreate->appendFields(parent,fieldNames,fields);
|
||||
return parent;
|
||||
}
|
||||
|
||||
void initSubFieldOptions(
|
||||
PVStructurePtr const & pvParent,
|
||||
string request)
|
||||
{
|
||||
if(request.length()<=0) return;
|
||||
size_t period = request.find('.');
|
||||
size_t openBracket = request.find('[');
|
||||
size_t openBrace = request.find('{');
|
||||
// name only
|
||||
if(period==string::npos
|
||||
&& openBracket==string::npos
|
||||
&& openBrace==string::npos)
|
||||
{
|
||||
return;
|
||||
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];
|
||||
}
|
||||
|
||||
// period is first
|
||||
if(period!=string::npos
|
||||
&& (openBracket==string::npos || period<openBracket)
|
||||
&& (openBrace==string::npos || period<openBrace) )
|
||||
{
|
||||
PVStructurePtr pvSubField = static_pointer_cast<PVStructure>(pvParent->getPVFields()[0]);
|
||||
initSubFieldOptions(pvSubField,request.substr(period+1));
|
||||
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;
|
||||
}
|
||||
|
||||
// brace before [ or .
|
||||
if(openBrace!=string::npos
|
||||
&& (openBracket==string::npos || openBrace<openBracket) )
|
||||
{
|
||||
PVStructurePtr pvSubField = static_pointer_cast<PVStructure>(pvParent->getPVFields()[0]);
|
||||
size_t closeBrace = findMatchingBrace(request,openBrace,1);
|
||||
string subRequest = request.substr(openBrace+1,closeBrace-openBrace-1);
|
||||
initFieldOptions(pvSubField,subRequest);
|
||||
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;
|
||||
}
|
||||
PVStructurePtr pvOptions = pvParent->getSubField<PVStructure>("_options");
|
||||
if(pvOptions==NULL) throw std::logic_error("initSubFieldOptions pvOptions NULL");
|
||||
size_t closeBracket = findMatchingBracket(request,openBracket);
|
||||
initRequestOptions(pvOptions,request.substr(openBracket+1,closeBracket-openBracket-1));
|
||||
size_t nextChar = closeBracket+1;
|
||||
if(nextChar>= request.size()) nextChar = string::npos;
|
||||
if(nextChar==string::npos) return;
|
||||
if(request[nextChar]=='.') {
|
||||
PVStructurePtr pvSubField = static_pointer_cast<PVStructure>(pvParent->getPVFields()[1]);
|
||||
initSubFieldOptions(pvSubField,request.substr(nextChar+1));
|
||||
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(request[nextChar]!='{') throw std::logic_error("initSubFieldOptions request[nextChar]!='{'");
|
||||
size_t closeBrace = findMatchingBrace(request,openBrace,1);
|
||||
const PVFieldPtrArray &pvFields = pvParent->getPVFields();
|
||||
string subRequest = request.substr(openBrace+1,closeBrace-openBrace-1);
|
||||
for(size_t i=1; i<pvFields.size(); ++i) {
|
||||
PVStructurePtr pvSubField = static_pointer_cast<PVStructure>(pvFields[i]);
|
||||
size_t comma = subRequest.find(',');
|
||||
initSubFieldOptions(pvSubField, subRequest.substr(0,comma-1));
|
||||
subRequest = subRequest.substr(comma+1);
|
||||
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");
|
||||
}
|
||||
|
||||
void initFieldOptions(
|
||||
PVStructurePtr const & pvParent,
|
||||
string request)
|
||||
FieldConstPtr createSubStructure(vector<Node> & nodes)
|
||||
{
|
||||
if(request.find('[')==string::npos) return;
|
||||
size_t num = pvParent->getStructure()->getNumberFields();
|
||||
if(num==0) return;
|
||||
if(num==1) {
|
||||
initSubFieldOptions(pvParent,request);
|
||||
return;
|
||||
}
|
||||
size_t end = findEndField(request);
|
||||
size_t start = 0;
|
||||
size_t num = nodes.size();
|
||||
StringArray names(num);
|
||||
FieldConstPtrArray fields(num);
|
||||
for(size_t i=0; i<num; ++i) {
|
||||
PVStructurePtr pvSub = static_pointer_cast<PVStructure>(pvParent->getPVFields()[i]);
|
||||
string subRequest = request.substr(start, end - start);
|
||||
initSubFieldOptions(pvSub,subRequest);
|
||||
if(i==num-1) break;
|
||||
start = end +1;
|
||||
string xxx = request.substr(start);
|
||||
end += findEndField(xxx) + 1;
|
||||
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 PVStructure::shared_pointer createRequest(
|
||||
virtual PVStructurePtr createRequest(
|
||||
string const & crequest)
|
||||
{
|
||||
string request = crequest;
|
||||
StructureConstPtr topStructure = fieldCreate->createStructure();
|
||||
|
||||
if (!request.empty()) removeBlanks(request);
|
||||
if (request.empty())
|
||||
{
|
||||
PVFieldPtrArray pvFields;
|
||||
StringArray fieldNames;
|
||||
return pvDataCreate->createPVStructure(fieldNames,pvFields);
|
||||
}
|
||||
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(" + crequest + ")";
|
||||
offsetField = request.find("field(");
|
||||
}
|
||||
if (offsetRecord != string::npos) {
|
||||
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();
|
||||
}
|
||||
StructureConstPtr structure = createRequestOptions(
|
||||
request.substr(openBracket+1,closeBracket-openBracket-1));
|
||||
if(structure==NULL)
|
||||
try {
|
||||
string request = crequest;
|
||||
if (!request.empty()) removeBlanks(request);
|
||||
if (request.empty())
|
||||
{
|
||||
return PVStructurePtr();
|
||||
return pvDataCreate->createPVStructure(fieldCreate->createStructure());
|
||||
}
|
||||
topStructure = fieldCreate->appendField(topStructure,"record",structure);
|
||||
}
|
||||
if (offsetField != string::npos) {
|
||||
size_t openBrace = request.find('(', offsetField);
|
||||
size_t closeBrace = request.find(')', openBrace);
|
||||
if(closeBrace == string::npos) {
|
||||
message = request.substr(offsetField)
|
||||
+ " field( does not have matching )";
|
||||
return PVStructurePtr();
|
||||
}
|
||||
StructureConstPtr structure = fieldCreate->createStructure();
|
||||
structure = createFieldRequest(structure,request.substr(openBrace+1,closeBrace-openBrace-1));
|
||||
if(structure==NULL)
|
||||
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();
|
||||
}
|
||||
topStructure = fieldCreate->appendField(topStructure,"field",structure);
|
||||
}
|
||||
if (offsetPutField != string::npos) {
|
||||
size_t openBrace = request.find('(', offsetPutField);
|
||||
size_t closeBrace = request.find(')', openBrace);
|
||||
if(closeBrace == string::npos) {
|
||||
message = request.substr(offsetField)
|
||||
+ " putField( does not have matching )";
|
||||
if(numBrace!=0) {
|
||||
ostringstream oss;
|
||||
oss << "mismatched {} " << numBrace;
|
||||
message = oss.str();
|
||||
return PVStructurePtr();
|
||||
}
|
||||
StructureConstPtr structure = fieldCreate->createStructure();
|
||||
structure = createFieldRequest(structure,request.substr(openBrace+1,closeBrace-openBrace-1));
|
||||
if(structure==NULL)
|
||||
{
|
||||
if(numBracket!=0) {
|
||||
ostringstream oss;
|
||||
oss << "mismatched [] " << numBracket;
|
||||
message = oss.str();
|
||||
return PVStructurePtr();
|
||||
}
|
||||
topStructure = fieldCreate->appendField(topStructure,"putField",structure);
|
||||
}
|
||||
if (offsetGetField != string::npos) {
|
||||
size_t openBrace = request.find('(', offsetGetField);
|
||||
size_t closeBrace = request.find(')', openBrace);
|
||||
if(closeBrace == string::npos) {
|
||||
message = request.substr(offsetField)
|
||||
+ " getField( does not have matching )";
|
||||
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();
|
||||
}
|
||||
StructureConstPtr structure = fieldCreate->createStructure();
|
||||
structure = createFieldRequest(structure,request.substr(openBrace+1,closeBrace-openBrace-1));
|
||||
if(structure==NULL)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
topStructure = fieldCreate->appendField(topStructure,"getField",structure);
|
||||
}
|
||||
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(topStructure);
|
||||
if (offsetRecord != string::npos) {
|
||||
size_t openBracket = request.find('[', offsetRecord);
|
||||
size_t closeBracket = request.find(']', openBracket);
|
||||
initRequestOptions(
|
||||
pvStructure->getSubField<PVStructure>("record"),
|
||||
request.substr(openBracket+1,closeBracket-openBracket-1));
|
||||
}
|
||||
if (offsetField != string::npos) {
|
||||
size_t openParam = request.find('(', offsetField);
|
||||
size_t closeParam = request.find(')', openParam);
|
||||
PVStructurePtr pvSub = pvStructure->getSubField<PVStructure>("field");
|
||||
if(pvSub->getStructure()->getNumberFields()==1) {
|
||||
pvSub = static_pointer_cast<PVStructure>(pvSub->getPVFields()[0]);
|
||||
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);
|
||||
}
|
||||
if(pvSub!=NULL) initFieldOptions(pvSub,request.substr(openParam+1,closeParam-openParam-1));
|
||||
optionList.clear();
|
||||
return pvStructure;
|
||||
} catch (std::exception &e) {
|
||||
message = e.what();
|
||||
return PVStructurePtr();
|
||||
}
|
||||
if (offsetPutField != string::npos) {
|
||||
size_t openParam = request.find('(', offsetPutField);
|
||||
size_t closeParam = request.find(')', openParam);
|
||||
PVStructurePtr pvSub = pvStructure->getSubField<PVStructure>("putField");
|
||||
if(pvSub->getStructure()->getNumberFields()==1) {
|
||||
pvSub = static_pointer_cast<PVStructure>(pvSub->getPVFields()[0]);
|
||||
}
|
||||
if(pvSub!=NULL) initFieldOptions(pvSub,request.substr(openParam+1,closeParam-openParam-1));
|
||||
}
|
||||
if (offsetGetField != string::npos) {
|
||||
size_t openParam = request.find('(', offsetGetField);
|
||||
size_t closeParam = request.find(')', openParam);
|
||||
PVStructurePtr pvSub = pvStructure->getSubField<PVStructure>("getField");
|
||||
if(pvSub->getStructure()->getNumberFields()==1) {
|
||||
pvSub = static_pointer_cast<PVStructure>(pvSub->getPVFields()[0]);
|
||||
}
|
||||
if(pvSub!=NULL) initFieldOptions(pvSub,request.substr(openParam+1,closeParam-openParam-1));
|
||||
}
|
||||
return pvStructure;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
CreateRequest::shared_pointer CreateRequest::create()
|
||||
|
||||
@@ -18,7 +18,12 @@
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
/**
|
||||
* Class to create pvRequest structures to pass to pvAccess Channel methods.
|
||||
* @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:
|
||||
@@ -33,7 +38,6 @@ class epicsShareClass 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.
|
||||
* @param requester The requester;
|
||||
* @return The request PVStructure if a valid request was given.
|
||||
* If a NULL PVStructure is returned then getMessage will return
|
||||
* the reason.
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
#include <pv/thread.h>
|
||||
|
||||
#include <pv/pvCopy.h>
|
||||
#include <pv/convert.h>
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using std::tr1::dynamic_pointer_cast;
|
||||
@@ -29,6 +28,18 @@ 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;
|
||||
@@ -67,11 +78,11 @@ PVCopyPtr PVCopy::create(
|
||||
PVStructurePtr pvStructure(pvRequest);
|
||||
if(structureName.size()>0) {
|
||||
if(pvRequest->getStructure()->getNumberFields()>0) {
|
||||
pvStructure = pvRequest->getStructureField(structureName);
|
||||
if(pvStructure.get()==NULL) return NULLPVCopy;
|
||||
pvStructure = pvRequest->getSubField<PVStructure>(structureName);
|
||||
if(!pvStructure) return NULLPVCopy;
|
||||
}
|
||||
} else if(pvStructure->getSubField("field")!=NULL) {
|
||||
pvStructure = pvRequest->getStructureField("field");
|
||||
} else if(pvStructure->getSubField("field")) {
|
||||
pvStructure = pvRequest->getSubField<PVStructure>("field");
|
||||
}
|
||||
PVCopyPtr pvCopy = PVCopyPtr(new PVCopy(pvMaster));
|
||||
bool result = pvCopy->init(pvStructure);
|
||||
@@ -118,7 +129,7 @@ StructureConstPtr PVCopy::getStructure()
|
||||
|
||||
PVStructurePtr PVCopy::createPVStructure()
|
||||
{
|
||||
if(cacheInitStructure.get()!=NULL) {
|
||||
if(cacheInitStructure) {
|
||||
PVStructurePtr save = cacheInitStructure;
|
||||
cacheInitStructure.reset();
|
||||
return save;
|
||||
@@ -174,7 +185,7 @@ size_t PVCopy::getCopyOffset(PVFieldPtr const &masterPVField)
|
||||
}
|
||||
CopyStructureNodePtr node = static_pointer_cast<CopyStructureNode>(headNode);
|
||||
CopyMasterNodePtr masterNode = getCopyOffset(node,masterPVField);
|
||||
if(masterNode.get()!=NULL) return masterNode->structureOffset;
|
||||
if(masterNode) return masterNode->structureOffset;
|
||||
return string::npos;
|
||||
}
|
||||
|
||||
@@ -190,7 +201,7 @@ size_t PVCopy::getCopyOffset(
|
||||
CopyStructureNodePtr node = static_pointer_cast<CopyStructureNode>(headNode);
|
||||
masterNode = getCopyOffset(node,masterPVField);
|
||||
}
|
||||
if(masterNode.get()==NULL) return string::npos;
|
||||
if(!masterNode) return string::npos;
|
||||
size_t diff = masterPVField->getFieldOffset()
|
||||
- masterPVStructure->getFieldOffset();
|
||||
return masterNode->structureOffset + diff;
|
||||
@@ -205,7 +216,7 @@ PVFieldPtr PVCopy::getMasterPVField(size_t structureOffset)
|
||||
CopyStructureNodePtr node = static_pointer_cast<CopyStructureNode>(headNode);
|
||||
masterNode = getMasterNode(node,structureOffset);
|
||||
}
|
||||
if(masterNode.get()==NULL) {
|
||||
if(!masterNode) {
|
||||
throw std::invalid_argument(
|
||||
"PVCopy::getMasterPVField: setstructureOffset not valid");
|
||||
}
|
||||
@@ -243,10 +254,9 @@ void PVCopy::updateCopySetBitSet(
|
||||
updateSubFieldSetBitSet(copyPVField,pvMasterField,bitSet);
|
||||
return;
|
||||
}
|
||||
ConvertPtr convert = getConvert();
|
||||
bool isEqual = convert->equals(copyPVField,pvField);
|
||||
bool isEqual = (*copyPVField == *pvField);
|
||||
if(!isEqual) {
|
||||
convert->copy(pvField, copyPVField);
|
||||
copyPVField->copyUnchecked(*pvField);
|
||||
bitSet->set(copyPVField->getFieldOffset());
|
||||
}
|
||||
}
|
||||
@@ -292,22 +302,22 @@ string PVCopy::dump()
|
||||
|
||||
void PVCopy::dump(string *builder,CopyNodePtr const &node,int indentLevel)
|
||||
{
|
||||
getConvert()->newLine(builder,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.get()!=NULL) {
|
||||
getConvert()->newLine(builder,indentLevel +1);
|
||||
if(options) {
|
||||
newLine(builder,indentLevel +1);
|
||||
|
||||
// TODO !!! ugly
|
||||
std::ostringstream oss;
|
||||
oss << *options;
|
||||
*builder += oss.str();
|
||||
|
||||
getConvert()->newLine(builder,indentLevel);
|
||||
newLine(builder,indentLevel);
|
||||
}
|
||||
if(!node->isStructure) {
|
||||
CopyMasterNodePtr masterNode = static_pointer_cast<CopyMasterNode>(node);
|
||||
@@ -320,7 +330,7 @@ void PVCopy::dump(string *builder,CopyNodePtr const &node,int indentLevel)
|
||||
CopyNodePtrArrayPtr nodes = structureNode->nodes;
|
||||
for(size_t i=0; i<nodes->size(); ++i) {
|
||||
if((*nodes)[i].get()==NULL) {
|
||||
getConvert()->newLine(builder,indentLevel +1);
|
||||
newLine(builder,indentLevel +1);
|
||||
ss.str("");
|
||||
ss << "node[" << i << "] is null";
|
||||
*builder += ss.str();
|
||||
@@ -338,8 +348,8 @@ bool PVCopy::init(epics::pvData::PVStructurePtr const &pvRequest)
|
||||
if(len==string::npos) entireMaster = true;
|
||||
if(len==0) entireMaster = true;
|
||||
PVStructurePtr pvOptions;
|
||||
if(len==1 && pvRequest->getSubField("_options")!=NULL) {
|
||||
pvOptions = pvRequest->getStructureField("_options");
|
||||
if(len==1 && pvRequest->getSubField("_options")) {
|
||||
pvOptions = pvRequest->getSubField<PVStructure>("_options");
|
||||
}
|
||||
if(entireMaster) {
|
||||
structure = pvMasterStructure->getStructure();
|
||||
@@ -353,7 +363,7 @@ bool PVCopy::init(epics::pvData::PVStructurePtr const &pvRequest)
|
||||
return true;
|
||||
}
|
||||
structure = createStructure(pvMasterStructure,pvRequest);
|
||||
if(structure==NULL) return false;
|
||||
if(!structure) return false;
|
||||
cacheInitStructure = createPVStructure();
|
||||
headNode = createStructureNodes(
|
||||
pvMaster,
|
||||
@@ -387,7 +397,7 @@ StructureConstPtr PVCopy::createStructure(
|
||||
for(size_t i=0; i<length; ++i) {
|
||||
string const &fieldName = fromRequestFieldNames[i];
|
||||
PVFieldPtr pvMasterField = pvMaster->getSubField(fieldName);
|
||||
if(pvMasterField==NULL) continue;
|
||||
if(!pvMasterField) continue;
|
||||
FieldConstPtr field = pvMasterField->getField();
|
||||
if(field->getType()==epics::pvData::structure) {
|
||||
PVStructurePtr pvRequestStructure = static_pointer_cast<PVStructure>(
|
||||
@@ -423,7 +433,7 @@ CopyNodePtr PVCopy::createStructureNodes(
|
||||
PVFieldPtrArray const & copyPVFields = pvFromCopy->getPVFields();
|
||||
PVStructurePtr pvOptions;
|
||||
PVFieldPtr pvField = pvFromRequest->getSubField("_options");
|
||||
if(pvField!=NULL) pvOptions = static_pointer_cast<PVStructure>(pvField);
|
||||
if(pvField) pvOptions = static_pointer_cast<PVStructure>(pvField);
|
||||
size_t number = copyPVFields.size();
|
||||
CopyNodePtrArrayPtr nodes(new CopyNodePtrArray());
|
||||
nodes->reserve(number);
|
||||
@@ -435,7 +445,7 @@ CopyNodePtr PVCopy::createStructureNodes(
|
||||
pvFromRequest->getSubField(fieldName));
|
||||
PVStructurePtr pvSubFieldOptions;
|
||||
PVFieldPtr pvField = requestPVStructure->getSubField("_options");
|
||||
if(pvField!=NULL) pvSubFieldOptions = static_pointer_cast<PVStructure>(pvField);
|
||||
if(pvField) pvSubFieldOptions = static_pointer_cast<PVStructure>(pvField);
|
||||
PVFieldPtr pvMasterField;
|
||||
PVFieldPtrArray const & pvMasterFields = pvMasterStructure->getPVFields();
|
||||
for(size_t j=0; i<pvMasterFields.size(); j++ ) {
|
||||
@@ -445,7 +455,7 @@ CopyNodePtr PVCopy::createStructureNodes(
|
||||
}
|
||||
}
|
||||
size_t numberRequest = requestPVStructure->getPVFields().size();
|
||||
if(pvSubFieldOptions!=NULL) numberRequest--;
|
||||
if(pvSubFieldOptions) numberRequest--;
|
||||
if(numberRequest>0) {
|
||||
nodes->push_back(createStructureNodes(
|
||||
static_pointer_cast<PVStructure>(pvMasterField),
|
||||
@@ -499,17 +509,16 @@ void PVCopy::updateSubFieldSetBitSet(
|
||||
FieldConstPtr field = pvCopy->getField();
|
||||
Type type = field->getType();
|
||||
if(type!=epics::pvData::structure) {
|
||||
ConvertPtr convert = getConvert();
|
||||
bool isEqual = convert->equals(pvCopy,pvMaster);
|
||||
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());
|
||||
bitSet->set(pvCopy->getFieldOffset());
|
||||
}
|
||||
}
|
||||
if(isEqual) return;
|
||||
convert->copy(pvMaster, pvCopy);
|
||||
pvCopy->copyUnchecked(*pvMaster);
|
||||
bitSet->set(pvCopy->getFieldOffset());
|
||||
return;
|
||||
}
|
||||
@@ -574,7 +583,6 @@ void PVCopy::updateSubFieldFromBitSet(
|
||||
if(nextSet==string::npos) return;
|
||||
if(nextSet>=pvCopy->getNextFieldOffset()) return;
|
||||
}
|
||||
ConvertPtr convert = getConvert();
|
||||
if(pvCopy->getField()->getType()==epics::pvData::structure) {
|
||||
PVStructurePtr pvCopyStructure =
|
||||
static_pointer_cast<PVStructure>(pvCopy);
|
||||
@@ -595,9 +603,9 @@ void PVCopy::updateSubFieldFromBitSet(
|
||||
}
|
||||
} else {
|
||||
if(toCopy) {
|
||||
convert->copy(pvMasterField, pvCopy);
|
||||
pvCopy->copyUnchecked(*pvMasterField);
|
||||
} else {
|
||||
convert->copy(pvCopy, pvMasterField);
|
||||
pvMasterField->copyUnchecked(*pvCopy);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -621,7 +629,7 @@ CopyMasterNodePtr PVCopy::getCopyOffset(
|
||||
static_pointer_cast<CopyStructureNode>(node);
|
||||
CopyMasterNodePtr masterNode =
|
||||
getCopyOffset(subNode,masterPVField);
|
||||
if(masterNode.get()!=NULL) return masterNode;
|
||||
if(masterNode) return masterNode;
|
||||
}
|
||||
}
|
||||
return NULLCopyMasterNode;
|
||||
|
||||
@@ -25,7 +25,8 @@ class PVCopyTraverseMasterCallback;
|
||||
typedef std::tr1::shared_ptr<PVCopyTraverseMasterCallback> PVCopyTraverseMasterCallbackPtr;
|
||||
|
||||
/**
|
||||
* Callback for traversing master structure
|
||||
* @brief Callback for traversing master structure
|
||||
*
|
||||
* Must be implemented by code that creates pvCopy.
|
||||
*/
|
||||
class epicsShareClass PVCopyTraverseMasterCallback
|
||||
@@ -53,6 +54,8 @@ 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.
|
||||
*/
|
||||
@@ -63,8 +66,8 @@ public:
|
||||
POINTER_DEFINITIONS(PVCopy);
|
||||
/**
|
||||
* Create a new pvCopy
|
||||
* @param pvMaster The top level sructure for which a copy of
|
||||
* an arbritary subset of the fields in master will be created and managed.
|
||||
* @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.
|
||||
*/
|
||||
@@ -75,8 +78,8 @@ public:
|
||||
virtual ~PVCopy(){}
|
||||
virtual void destroy();
|
||||
/**
|
||||
* Get the top level structure of master
|
||||
* @returns The master top level structure.
|
||||
* Get the top-level structure of master
|
||||
* @returns The master top-level structure.
|
||||
* This should not be modified.
|
||||
*/
|
||||
PVStructurePtr getPVMaster();
|
||||
@@ -94,7 +97,7 @@ public:
|
||||
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.
|
||||
* Since each element needs a PVStructure, multiple top-level structures will be created.
|
||||
*/
|
||||
PVStructurePtr createPVStructure();
|
||||
/**
|
||||
@@ -113,15 +116,15 @@ public:
|
||||
PVStructurePtr const &masterPVStructure,
|
||||
PVFieldPtr const &masterPVField);
|
||||
/**
|
||||
* Given a offset in the copy get the corresponding field in pvMaster.
|
||||
* @param offset The offset in the copy.
|
||||
* 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 copyPVStructure A copy top-level structure.
|
||||
* @param bitSet A bitSet for copyPVStructure.
|
||||
*/
|
||||
void initCopy(
|
||||
@@ -130,7 +133,7 @@ public:
|
||||
/**
|
||||
* 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 copyPVStructure A copy top-level structure.
|
||||
* @param bitSet A bitSet for copyPVStructure.
|
||||
*/
|
||||
void updateCopySetBitSet(
|
||||
@@ -138,8 +141,8 @@ public:
|
||||
BitSetPtr const &bitSet);
|
||||
/**
|
||||
* For each set bit in bitSet
|
||||
* set the field in copyPVStructure to the value of the corrseponding field in pvMaster.
|
||||
* @param copyPVStructure A copy top level structure.
|
||||
* 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(
|
||||
@@ -147,8 +150,8 @@ public:
|
||||
BitSetPtr const &bitSet);
|
||||
/**
|
||||
* For each set bit in bitSet
|
||||
* set the field in pvMaster to the value of the corrseponding field in copyPVStructure
|
||||
* @param copyPVStructure A copy top level structure.
|
||||
* 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(
|
||||
@@ -156,7 +159,7 @@ public:
|
||||
BitSetPtr const &bitSet);
|
||||
/**
|
||||
* Get the options for the field at the specified offset.
|
||||
* @param offset the offset in copy.
|
||||
* @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
|
||||
|
||||
@@ -12,13 +12,13 @@
|
||||
#include <sstream>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/convert.h>
|
||||
#include <pv/pvData.h>
|
||||
|
||||
using std::string;
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
// Introspection object comparision
|
||||
// Introspection object comparison
|
||||
|
||||
/** Field equality conditions:
|
||||
* 1) same instance
|
||||
@@ -62,7 +62,7 @@ bool operator==(const Field& a, const Field& b)
|
||||
return A==B;
|
||||
}
|
||||
default:
|
||||
throw std::logic_error("Invalid Field type in comparision");
|
||||
throw std::logic_error("Invalid Field type in comparison");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,14 +91,14 @@ bool operator==(const Structure& a, const Structure& b)
|
||||
return false;
|
||||
|
||||
// std::equals does not work, since FieldConstPtrArray is an array of shared_pointers
|
||||
FieldConstPtrArray af = a.getFields();
|
||||
FieldConstPtrArray bf = b.getFields();
|
||||
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 an = a.getFieldNames();
|
||||
StringArray bn = b.getFieldNames();
|
||||
StringArray const & an = a.getFieldNames();
|
||||
StringArray const & bn = b.getFieldNames();
|
||||
return std::equal( an.begin(), an.end(), bn.begin() );
|
||||
}
|
||||
|
||||
@@ -118,14 +118,14 @@ bool operator==(const Union& a, const Union& b)
|
||||
return false;
|
||||
|
||||
// std::equals does not work, since FieldConstPtrArray is an array of shared_pointers
|
||||
FieldConstPtrArray af = a.getFields();
|
||||
FieldConstPtrArray bf = b.getFields();
|
||||
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 an = a.getFieldNames();
|
||||
StringArray bn = b.getFieldNames();
|
||||
StringArray const & an = a.getFieldNames();
|
||||
StringArray const & bn = b.getFieldNames();
|
||||
return std::equal( an.begin(), an.end(), bn.begin() );
|
||||
}
|
||||
|
||||
@@ -134,6 +134,13 @@ 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 {
|
||||
@@ -244,7 +251,13 @@ bool compareField(const PVStructureArray* left, const PVStructureArray* right)
|
||||
lit!=lend;
|
||||
++lit, ++rit)
|
||||
{
|
||||
if(**lit != **rit)
|
||||
// element can be null
|
||||
if (!(*lit) || !(*rit))
|
||||
{
|
||||
if (*lit || *rit)
|
||||
return false;
|
||||
}
|
||||
else if (**lit != **rit)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -297,7 +310,13 @@ bool compareField(const PVUnionArray* left, const PVUnionArray* right)
|
||||
lit!=lend;
|
||||
++lit, ++rit)
|
||||
{
|
||||
if(**lit != **rit)
|
||||
// element can be null
|
||||
if (!(*lit) || !(*rit))
|
||||
{
|
||||
if (*lit || *rit)
|
||||
return false;
|
||||
}
|
||||
else if (**lit != **rit)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
#include <pv/pvIntrospect.h>
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/convert.h>
|
||||
#include <pv/printer.h>
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using std::size_t;
|
||||
@@ -51,10 +50,8 @@ void Convert::getString(string *buf,PVField const *pvField,int /*indentLevel*/)
|
||||
{
|
||||
// TODO indextLevel ignored
|
||||
std::ostringstream strm;
|
||||
strm << pvField->dumpValue(strm) << std::endl;
|
||||
// PrinterPlain p;
|
||||
// p.setStream(strm);
|
||||
// p.print(*pvField);
|
||||
pvField->dumpValue(strm);
|
||||
strm << std::endl;
|
||||
strm.str().swap(*buf);
|
||||
}
|
||||
|
||||
@@ -152,374 +149,6 @@ size_t Convert::toStringArray(PVScalarArrayPtr const & pv,
|
||||
return data.size();
|
||||
}
|
||||
|
||||
bool Convert::isCopyCompatible(FieldConstPtr const &from, FieldConstPtr const &to)
|
||||
{
|
||||
if(from->getType()!=to->getType()) return false;
|
||||
switch(from->getType()) {
|
||||
case scalar:
|
||||
{
|
||||
ScalarConstPtr xxx = static_pointer_cast<const Scalar>(from);
|
||||
ScalarConstPtr yyy = static_pointer_cast<const Scalar>(to);
|
||||
return isCopyScalarCompatible(xxx,yyy);
|
||||
}
|
||||
case scalarArray:
|
||||
{
|
||||
ScalarArrayConstPtr xxx = static_pointer_cast<const ScalarArray>(from);
|
||||
ScalarArrayConstPtr yyy = static_pointer_cast<const ScalarArray>(to);
|
||||
return isCopyScalarArrayCompatible(xxx,yyy);
|
||||
}
|
||||
case structure:
|
||||
{
|
||||
StructureConstPtr xxx = static_pointer_cast<const Structure>(from);
|
||||
StructureConstPtr yyy = static_pointer_cast<const Structure>(to);
|
||||
return isCopyStructureCompatible(xxx,yyy);
|
||||
}
|
||||
case structureArray:
|
||||
{
|
||||
StructureArrayConstPtr xxx = static_pointer_cast<const StructureArray>(from);
|
||||
StructureArrayConstPtr yyy = static_pointer_cast<const StructureArray>(to);
|
||||
return isCopyStructureArrayCompatible(xxx,yyy);
|
||||
}
|
||||
case union_:
|
||||
{
|
||||
UnionConstPtr xxx = static_pointer_cast<const Union>(from);
|
||||
UnionConstPtr yyy = static_pointer_cast<const Union>(to);
|
||||
return isCopyUnionCompatible(xxx,yyy);
|
||||
}
|
||||
case unionArray:
|
||||
{
|
||||
UnionArrayConstPtr xxx = static_pointer_cast<const UnionArray>(from);
|
||||
UnionArrayConstPtr yyy = static_pointer_cast<const UnionArray>(to);
|
||||
return isCopyUnionArrayCompatible(xxx,yyy);
|
||||
}
|
||||
}
|
||||
string message("Convert::isCopyCompatible should never get here");
|
||||
throw std::logic_error(message);
|
||||
}
|
||||
|
||||
void Convert::copy(PVFieldPtr const & from, PVFieldPtr const & to)
|
||||
{
|
||||
switch(from->getField()->getType()) {
|
||||
case scalar:
|
||||
{
|
||||
PVScalarPtr xxx = static_pointer_cast<PVScalar>(from);
|
||||
PVScalarPtr yyy = static_pointer_cast<PVScalar>(to);
|
||||
copyScalar(xxx,yyy);
|
||||
return;
|
||||
}
|
||||
case scalarArray:
|
||||
{
|
||||
PVScalarArrayPtr fromArray = static_pointer_cast<PVScalarArray>(from);
|
||||
PVScalarArrayPtr toArray = static_pointer_cast<PVScalarArray>(to);
|
||||
toArray->assign(*fromArray.get());
|
||||
return;
|
||||
}
|
||||
case structure:
|
||||
{
|
||||
PVStructurePtr xxx = static_pointer_cast<PVStructure>(from);
|
||||
PVStructurePtr yyy = static_pointer_cast<PVStructure>(to);
|
||||
copyStructure(xxx,yyy);
|
||||
return;
|
||||
}
|
||||
case structureArray: {
|
||||
PVStructureArrayPtr fromArray = static_pointer_cast<PVStructureArray>(from);
|
||||
PVStructureArrayPtr toArray = static_pointer_cast<PVStructureArray>(to);
|
||||
copyStructureArray(fromArray,toArray);
|
||||
return;
|
||||
}
|
||||
case union_:
|
||||
{
|
||||
PVUnionPtr xxx = static_pointer_cast<PVUnion>(from);
|
||||
PVUnionPtr yyy = static_pointer_cast<PVUnion>(to);
|
||||
copyUnion(xxx,yyy);
|
||||
return;
|
||||
}
|
||||
case unionArray: {
|
||||
PVUnionArrayPtr fromArray = static_pointer_cast<PVUnionArray>(from);
|
||||
PVUnionArrayPtr toArray = static_pointer_cast<PVUnionArray>(to);
|
||||
copyUnionArray(fromArray,toArray);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Convert::isCopyScalarCompatible(
|
||||
ScalarConstPtr const & fromField, ScalarConstPtr const & toField)
|
||||
{
|
||||
ScalarType fromScalarType = fromField->getScalarType();
|
||||
ScalarType toScalarType = toField->getScalarType();
|
||||
if(fromScalarType==toScalarType) return true;
|
||||
if(ScalarTypeFunc::isNumeric(fromScalarType)
|
||||
&& ScalarTypeFunc::isNumeric(toScalarType)) return true;
|
||||
if(fromScalarType==pvString) return true;
|
||||
if(toScalarType==pvString) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void Convert::copyScalar(PVScalarPtr const & from, PVScalarPtr const & to)
|
||||
{
|
||||
if(to->isImmutable()) {
|
||||
if(from==to) return;
|
||||
string message("Convert.copyScalar destination is immutable");
|
||||
throw std::invalid_argument(message);
|
||||
}
|
||||
to->assign(*from.get());
|
||||
}
|
||||
|
||||
bool Convert::isCopyScalarArrayCompatible(ScalarArrayConstPtr const &fromArray,
|
||||
ScalarArrayConstPtr const &toArray)
|
||||
{
|
||||
ScalarType fromType = fromArray->getElementType();
|
||||
ScalarType toType = toArray->getElementType();
|
||||
if(fromType==toType) return true;
|
||||
if(ScalarTypeFunc::isNumeric(fromType)
|
||||
&& ScalarTypeFunc::isNumeric(toType)) return true;
|
||||
if(toType==pvString) return true;
|
||||
if(fromType==pvString) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Convert::isCopyStructureCompatible(
|
||||
StructureConstPtr const &fromStruct, StructureConstPtr const &toStruct)
|
||||
{
|
||||
FieldConstPtrArray fromFields = fromStruct->getFields();
|
||||
FieldConstPtrArray toFields = toStruct->getFields();
|
||||
size_t length = fromStruct->getNumberFields();
|
||||
if(length!=toStruct->getNumberFields()) return false;
|
||||
for(size_t i=0; i<length; i++) {
|
||||
FieldConstPtr from = fromFields[i];
|
||||
FieldConstPtr to = toFields[i];
|
||||
Type fromType = from->getType();
|
||||
Type toType = to->getType();
|
||||
if(fromType!=toType) return false;
|
||||
switch(fromType) {
|
||||
case scalar:
|
||||
{
|
||||
ScalarConstPtr xxx = static_pointer_cast<const Scalar>(from);
|
||||
ScalarConstPtr yyy = static_pointer_cast<const Scalar>(to);
|
||||
if(!isCopyScalarCompatible(xxx,yyy)) return false;
|
||||
}
|
||||
break;
|
||||
case scalarArray:
|
||||
{
|
||||
ScalarArrayConstPtr xxx = static_pointer_cast<const ScalarArray>(from);
|
||||
ScalarArrayConstPtr yyy = static_pointer_cast<const ScalarArray>(to);
|
||||
if(!isCopyScalarArrayCompatible(xxx,yyy)) return false;
|
||||
}
|
||||
break;
|
||||
case structure:
|
||||
{
|
||||
StructureConstPtr xxx = static_pointer_cast<const Structure>(from);
|
||||
StructureConstPtr yyy = static_pointer_cast<const Structure>(to);
|
||||
if(!isCopyStructureCompatible(xxx,yyy)) return false;
|
||||
}
|
||||
break;
|
||||
case structureArray:
|
||||
{
|
||||
StructureArrayConstPtr xxx = static_pointer_cast<const StructureArray>(from);
|
||||
StructureArrayConstPtr yyy = static_pointer_cast<const StructureArray>(to);
|
||||
if(!isCopyStructureArrayCompatible(xxx,yyy)) return false;
|
||||
}
|
||||
case union_:
|
||||
{
|
||||
UnionConstPtr xxx = static_pointer_cast<const Union>(from);
|
||||
UnionConstPtr yyy = static_pointer_cast<const Union>(to);
|
||||
if(!isCopyUnionCompatible(xxx,yyy)) return false;
|
||||
}
|
||||
break;
|
||||
case unionArray:
|
||||
{
|
||||
UnionArrayConstPtr xxx = static_pointer_cast<const UnionArray>(from);
|
||||
UnionArrayConstPtr yyy = static_pointer_cast<const UnionArray>(to);
|
||||
if(!isCopyUnionArrayCompatible(xxx,yyy)) return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Convert::copyStructure(PVStructurePtr const & from, PVStructurePtr const & to)
|
||||
{
|
||||
if(to->isImmutable()) {
|
||||
if(from==to) return;
|
||||
throw std::invalid_argument("Convert.copyStructure destination is immutable");
|
||||
}
|
||||
if(from==to) return;
|
||||
PVFieldPtrArray const & fromDatas = from->getPVFields();
|
||||
PVFieldPtrArray const & toDatas = to->getPVFields();
|
||||
if(from->getStructure()->getNumberFields()
|
||||
!= to->getStructure()->getNumberFields()) {
|
||||
string message("Convert.copyStructure Illegal copyStructure");
|
||||
throw std::invalid_argument(message);
|
||||
}
|
||||
size_t numberFields = from->getStructure()->getNumberFields();
|
||||
if(numberFields>=2) {
|
||||
string name0 = fromDatas[0]->getFieldName();
|
||||
string name1 = fromDatas[1]->getFieldName();
|
||||
// look for enumerated structure and copy choices first
|
||||
if(name0.compare("index")==0 && name1.compare("choices")==0) {
|
||||
FieldConstPtr fieldIndex = fromDatas[0]->getField();
|
||||
FieldConstPtr fieldChoices = fromDatas[1]->getField();
|
||||
if(fieldIndex->getType()==scalar
|
||||
&& fieldChoices->getType()==scalarArray) {
|
||||
PVScalarPtr pvScalar = static_pointer_cast<PVScalar>(fromDatas[0]);
|
||||
PVScalarArrayPtr pvArray =
|
||||
static_pointer_cast<PVScalarArray>(fromDatas[1]);
|
||||
if((pvScalar->getScalar()->getScalarType()==pvInt)
|
||||
&& (pvArray->getScalarArray()->getElementType()==pvString)) {
|
||||
PVScalarArrayPtr toArray =
|
||||
static_pointer_cast<PVScalarArray>(toDatas[1]);
|
||||
toArray->assign(*pvArray.get());
|
||||
PVScalarPtr toScalar = static_pointer_cast<PVScalar>(toDatas[0]);
|
||||
copyScalar(pvScalar,toScalar);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for(size_t i=0; i < numberFields; i++) {
|
||||
PVFieldPtr fromData = fromDatas[i];
|
||||
PVFieldPtr toData = toDatas[i];
|
||||
Type fromType = fromData->getField()->getType();
|
||||
Type toType = toData->getField()->getType();
|
||||
if(fromType!=toType) {
|
||||
string message("Convert.copyStructure Illegal copyStructure");
|
||||
throw std::invalid_argument(message);
|
||||
}
|
||||
if(toData->isImmutable()) {
|
||||
if(fromData==toData) return;
|
||||
throw std::invalid_argument("Convert.copyStructure destination is immutable");
|
||||
}
|
||||
switch(fromType) {
|
||||
case scalar:
|
||||
{
|
||||
PVScalarPtr xxx = static_pointer_cast<PVScalar>(fromData);
|
||||
PVScalarPtr yyy = static_pointer_cast<PVScalar>(toData);
|
||||
copyScalar(xxx,yyy);
|
||||
break;
|
||||
}
|
||||
case scalarArray:
|
||||
{
|
||||
PVScalarArrayPtr fromArray = static_pointer_cast<PVScalarArray>(fromData);
|
||||
PVScalarArrayPtr toArray = static_pointer_cast<PVScalarArray>(toData);
|
||||
toArray->assign(*fromArray.get());
|
||||
break;
|
||||
}
|
||||
case structure:
|
||||
{
|
||||
PVStructurePtr xxx = static_pointer_cast<PVStructure>(fromData);
|
||||
PVStructurePtr yyy = static_pointer_cast<PVStructure>(toData);
|
||||
copyStructure(xxx,yyy);
|
||||
break;
|
||||
}
|
||||
case structureArray:
|
||||
{
|
||||
PVStructureArrayPtr fromArray =
|
||||
static_pointer_cast<PVStructureArray>(fromData);
|
||||
PVStructureArrayPtr toArray =
|
||||
static_pointer_cast<PVStructureArray>(toData);
|
||||
copyStructureArray(fromArray,toArray);
|
||||
break;
|
||||
}
|
||||
case union_:
|
||||
{
|
||||
PVUnionPtr xxx = static_pointer_cast<PVUnion>(fromData);
|
||||
PVUnionPtr yyy = static_pointer_cast<PVUnion>(toData);
|
||||
copyUnion(xxx,yyy);
|
||||
break;
|
||||
}
|
||||
case unionArray:
|
||||
{
|
||||
PVUnionArrayPtr fromArray =
|
||||
static_pointer_cast<PVUnionArray>(fromData);
|
||||
PVUnionArrayPtr toArray =
|
||||
static_pointer_cast<PVUnionArray>(toData);
|
||||
copyUnionArray(fromArray,toArray);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Convert::isCopyUnionCompatible(
|
||||
UnionConstPtr const &from, UnionConstPtr const &to)
|
||||
{
|
||||
return *(from.get()) == *(to.get());
|
||||
}
|
||||
|
||||
void Convert::copyUnion(PVUnionPtr const & from, PVUnionPtr const & to)
|
||||
{
|
||||
if(to->isImmutable()) {
|
||||
if(from==to) return;
|
||||
throw std::invalid_argument("Convert.copyUnion destination is immutable");
|
||||
}
|
||||
if(from==to) return;
|
||||
if(!isCopyUnionCompatible(from->getUnion(), to->getUnion())) {
|
||||
throw std::invalid_argument("Illegal copyUnion");
|
||||
}
|
||||
|
||||
PVFieldPtr fromValue = from->get();
|
||||
if (from->getUnion()->isVariant())
|
||||
{
|
||||
if (fromValue.get() == 0)
|
||||
to->set(PVFieldPtr());
|
||||
else
|
||||
to->set(getPVDataCreate()->createPVField(fromValue)); // clone value // TODO cache getPVDataCreate()
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fromValue.get() == 0)
|
||||
to->select(PVUnion::UNDEFINED_INDEX);
|
||||
else
|
||||
to->set(from->getSelectedFieldName(),from->get());
|
||||
}
|
||||
}
|
||||
|
||||
bool Convert::isCopyStructureArrayCompatible(
|
||||
StructureArrayConstPtr const &from, StructureArrayConstPtr const &to)
|
||||
{
|
||||
StructureConstPtr xxx = from->getStructure();
|
||||
StructureConstPtr yyy = to->getStructure();
|
||||
return isCopyStructureCompatible(xxx,yyy);
|
||||
}
|
||||
|
||||
void Convert::copyStructureArray(
|
||||
PVStructureArrayPtr const & from, PVStructureArrayPtr const & to)
|
||||
{
|
||||
if(from==to) {
|
||||
return;
|
||||
} else if(to->isImmutable()) {
|
||||
throw std::invalid_argument("Convert.copyStructureArray destination is immutable");
|
||||
}
|
||||
to->replace(from->view());
|
||||
}
|
||||
|
||||
bool Convert::isCopyUnionArrayCompatible(
|
||||
UnionArrayConstPtr const &from, UnionArrayConstPtr const &to)
|
||||
{
|
||||
UnionConstPtr xxx = from->getUnion();
|
||||
UnionConstPtr yyy = to->getUnion();
|
||||
return isCopyUnionCompatible(xxx,yyy);
|
||||
}
|
||||
|
||||
void Convert::copyUnionArray(
|
||||
PVUnionArrayPtr const & from, PVUnionArrayPtr const & to)
|
||||
{
|
||||
if(from==to) {
|
||||
return;
|
||||
} else if(to->isImmutable()) {
|
||||
throw std::invalid_argument("Convert.copyUnionArray destination is immutable");
|
||||
}
|
||||
to->replace(from->view());
|
||||
}
|
||||
|
||||
void Convert::newLine(string *buffer, int indentLevel)
|
||||
{
|
||||
*buffer += "\n";
|
||||
*buffer += string(indentLevel*4, ' ');
|
||||
}
|
||||
|
||||
ConvertPtr Convert::getConvert()
|
||||
{
|
||||
static ConvertPtr convert;
|
||||
|
||||
@@ -17,11 +17,11 @@
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <stdexcept>
|
||||
#include <sstream>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/lock.h>
|
||||
#include <pv/pvIntrospect.h>
|
||||
#include <pv/convert.h>
|
||||
#include <pv/factory.h>
|
||||
#include <pv/serializeHelper.h>
|
||||
|
||||
@@ -51,7 +51,7 @@ Scalar::Scalar(ScalarType scalarType)
|
||||
: Field(scalar),scalarType(scalarType)
|
||||
{
|
||||
if(scalarType<0 || scalarType>MAX_SCALAR_TYPE)
|
||||
throw std::invalid_argument("Can't construct Scalar from invalid ScalarType");
|
||||
THROW_EXCEPTION2(std::invalid_argument, "Can't construct Scalar from invalid ScalarType");
|
||||
}
|
||||
|
||||
Scalar::~Scalar(){}
|
||||
@@ -80,7 +80,7 @@ string Scalar::getID() const
|
||||
return idScalarLUT[scalarType];
|
||||
}
|
||||
|
||||
int8 Scalar::getTypeCodeLUT() const
|
||||
int8 Scalar::getTypeCodeLUT(ScalarType scalarType)
|
||||
{
|
||||
static const int8 typeCodeLUT[] = {
|
||||
0x00, // pvBoolean
|
||||
@@ -88,10 +88,10 @@ int8 Scalar::getTypeCodeLUT() const
|
||||
0x21, // pvShort
|
||||
0x22, // pvInt
|
||||
0x23, // pvLong
|
||||
0x28, // pvUByte
|
||||
0x29, // pvUShort
|
||||
0x2A, // pvUInt
|
||||
0x2B, // pvULong
|
||||
0x24, // pvUByte
|
||||
0x25, // pvUShort
|
||||
0x26, // pvUInt
|
||||
0x27, // pvULong
|
||||
0x42, // pvFloat
|
||||
0x43, // pvDouble
|
||||
0x60 // pvString
|
||||
@@ -102,7 +102,7 @@ int8 Scalar::getTypeCodeLUT() const
|
||||
|
||||
void Scalar::serialize(ByteBuffer *buffer, SerializableControl *control) const {
|
||||
control->ensureBuffer(1);
|
||||
buffer->putByte(getTypeCodeLUT());
|
||||
buffer->putByte(getTypeCodeLUT(scalarType));
|
||||
}
|
||||
|
||||
void Scalar::deserialize(ByteBuffer* /*buffer*/, DeserializableControl* /*control*/) {
|
||||
@@ -110,6 +110,38 @@ void Scalar::deserialize(ByteBuffer* /*buffer*/, DeserializableControl* /*contro
|
||||
throw std::runtime_error("not valid operation, use FieldCreate::deserialize instead");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
std::string BoundedString::getID() const
|
||||
{
|
||||
std::ostringstream id;
|
||||
id << Scalar::getID() << '(' << maxLength << ')';
|
||||
return id.str();
|
||||
}
|
||||
|
||||
void BoundedString::serialize(ByteBuffer *buffer, SerializableControl *control) const
|
||||
{
|
||||
control->ensureBuffer(1);
|
||||
buffer->putByte(0x83);
|
||||
SerializeHelper::writeSize(maxLength, buffer, control);
|
||||
}
|
||||
|
||||
std::size_t BoundedString::getMaximumLength() const
|
||||
{
|
||||
return maxLength;
|
||||
}
|
||||
|
||||
BoundedString::BoundedString(std::size_t maxStringLength) :
|
||||
Scalar(pvString), maxLength(maxStringLength)
|
||||
{
|
||||
if (maxLength == 0)
|
||||
THROW_EXCEPTION2(std::invalid_argument, "maxLength == 0");
|
||||
}
|
||||
|
||||
BoundedString::~BoundedString() {}
|
||||
|
||||
|
||||
static string emptyStringtring;
|
||||
|
||||
static void serializeStructureField(const Structure* structure, ByteBuffer* buffer, SerializableControl* control)
|
||||
@@ -198,7 +230,8 @@ Array::Array(Type type)
|
||||
Array::~Array() {}
|
||||
|
||||
ScalarArray::ScalarArray(ScalarType elementType)
|
||||
: Array(scalarArray),elementType(elementType)
|
||||
: Array(scalarArray),
|
||||
elementType(elementType)
|
||||
{
|
||||
if(elementType<0 || elementType>MAX_SCALAR_TYPE)
|
||||
throw std::invalid_argument("Can't construct ScalarArray from invalid ScalarType");
|
||||
@@ -206,31 +239,12 @@ ScalarArray::ScalarArray(ScalarType 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
|
||||
"boolean[]", // pvBoolean
|
||||
"byte[]", // pvByte
|
||||
"short[]", // pvShort
|
||||
"int[]", // pvInt
|
||||
"long[]", // pvLong
|
||||
"ubyte[]", // pvUByte
|
||||
@@ -256,13 +270,59 @@ std::ostream& ScalarArray::dump(std::ostream& o) const
|
||||
|
||||
void ScalarArray::serialize(ByteBuffer *buffer, SerializableControl *control) const {
|
||||
control->ensureBuffer(1);
|
||||
buffer->putByte((int8)0x10 | getTypeCodeLUT());
|
||||
buffer->putByte((int8)0x08 | Scalar::getTypeCodeLUT(elementType));
|
||||
}
|
||||
|
||||
void ScalarArray::deserialize(ByteBuffer* /*buffer*/, DeserializableControl* /*control*/) {
|
||||
throw std::runtime_error("not valid operation, use FieldCreate::deserialize instead");
|
||||
}
|
||||
|
||||
|
||||
BoundedScalarArray::~BoundedScalarArray() {}
|
||||
|
||||
BoundedScalarArray::BoundedScalarArray(ScalarType elementType, size_t size)
|
||||
: ScalarArray(elementType),
|
||||
size(size)
|
||||
{
|
||||
}
|
||||
|
||||
string BoundedScalarArray::getID() const
|
||||
{
|
||||
char buffer[32];
|
||||
sprintf(buffer, "%s<%zu>", ScalarTypeFunc::name(getElementType()), size);
|
||||
return string(buffer);
|
||||
}
|
||||
|
||||
void BoundedScalarArray::serialize(ByteBuffer *buffer, SerializableControl *control) const {
|
||||
control->ensureBuffer(1);
|
||||
buffer->putByte((int8)0x10 | Scalar::getTypeCodeLUT(getElementType()));
|
||||
SerializeHelper::writeSize(size, buffer, control);
|
||||
}
|
||||
|
||||
|
||||
FixedScalarArray::~FixedScalarArray() {}
|
||||
|
||||
FixedScalarArray::FixedScalarArray(ScalarType elementType, size_t size)
|
||||
: ScalarArray(elementType),
|
||||
size(size)
|
||||
{
|
||||
}
|
||||
|
||||
string FixedScalarArray::getID() const
|
||||
{
|
||||
char buffer[32];
|
||||
sprintf(buffer, "%s[%zu]", ScalarTypeFunc::name(getElementType()), size);
|
||||
return string(buffer);
|
||||
}
|
||||
|
||||
void FixedScalarArray::serialize(ByteBuffer *buffer, SerializableControl *control) const {
|
||||
control->ensureBuffer(1);
|
||||
buffer->putByte((int8)0x18 | Scalar::getTypeCodeLUT(getElementType()));
|
||||
SerializeHelper::writeSize(size, buffer, control);
|
||||
}
|
||||
|
||||
|
||||
|
||||
StructureArray::StructureArray(StructureConstPtr const & structure)
|
||||
: Array(structureArray),pstructure(structure)
|
||||
{
|
||||
@@ -289,7 +349,7 @@ std::ostream& StructureArray::dump(std::ostream& o) const
|
||||
|
||||
void StructureArray::serialize(ByteBuffer *buffer, SerializableControl *control) const {
|
||||
control->ensureBuffer(1);
|
||||
buffer->putByte((int8)0x90);
|
||||
buffer->putByte((int8)0x88);
|
||||
control->cachedSerialize(pstructure, buffer);
|
||||
}
|
||||
|
||||
@@ -326,11 +386,11 @@ void UnionArray::serialize(ByteBuffer *buffer, SerializableControl *control) con
|
||||
if (punion->isVariant())
|
||||
{
|
||||
// unrestricted/variant union
|
||||
buffer->putByte((int8)0x92);
|
||||
buffer->putByte((int8)0x8A);
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer->putByte((int8)0x91);
|
||||
buffer->putByte((int8)0x89);
|
||||
control->cachedSerialize(punion, buffer);
|
||||
}
|
||||
}
|
||||
@@ -339,7 +399,13 @@ void UnionArray::deserialize(ByteBuffer* /*buffer*/, DeserializableControl* /*co
|
||||
throw std::runtime_error("not valid operation, use FieldCreate::deserialize instead");
|
||||
}
|
||||
|
||||
string Structure::DEFAULT_ID = "structure";
|
||||
const string Structure::DEFAULT_ID = Structure::defaultId();
|
||||
|
||||
const string & Structure::defaultId()
|
||||
{
|
||||
static const string id = "structure";
|
||||
return id;
|
||||
}
|
||||
|
||||
Structure::Structure (
|
||||
StringArray const & fieldNames,
|
||||
@@ -351,27 +417,27 @@ Structure::Structure (
|
||||
id(inid)
|
||||
{
|
||||
if(inid.empty()) {
|
||||
throw std::invalid_argument("id is empty");
|
||||
THROW_EXCEPTION2(std::invalid_argument, "Can't construct Structure, id is empty string");
|
||||
}
|
||||
if(fieldNames.size()!=fields.size()) {
|
||||
throw std::invalid_argument("fieldNames.size()!=fields.size()");
|
||||
THROW_EXCEPTION2(std::invalid_argument, "Can't construct Structure, fieldNames.size()!=fields.size()");
|
||||
}
|
||||
size_t number = fields.size();
|
||||
for(size_t i=0; i<number; i++) {
|
||||
const string& name = fieldNames[i];
|
||||
if(name.empty()) {
|
||||
throw std::invalid_argument("fieldNames has a zero length string");
|
||||
THROW_EXCEPTION2(std::invalid_argument, "Can't construct Structure, empty string in fieldNames");
|
||||
}
|
||||
if(fields[i].get()==NULL)
|
||||
throw std::invalid_argument("Can't construct Structure with NULL Field");
|
||||
THROW_EXCEPTION2(std::invalid_argument, "Can't construct Structure, NULL in fields");
|
||||
// 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 ");
|
||||
string message("Can't construct Structure, duplicate fieldName ");
|
||||
message += name;
|
||||
throw std::invalid_argument(message);
|
||||
THROW_EXCEPTION2(std::invalid_argument, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -436,7 +502,9 @@ void Structure::dumpFields(std::ostream& o) const
|
||||
case structureArray:
|
||||
{
|
||||
format::indent_scope s(o);
|
||||
o << *pfield;
|
||||
Field const *xxx = pfield.get();
|
||||
StructureArray const *pstructureArray = static_cast<StructureArray const*>(xxx);
|
||||
o << *pstructureArray->getStructure();
|
||||
break;
|
||||
}
|
||||
case union_:
|
||||
@@ -450,7 +518,9 @@ void Structure::dumpFields(std::ostream& o) const
|
||||
case unionArray:
|
||||
{
|
||||
format::indent_scope s(o);
|
||||
o << *pfield;
|
||||
Field const *xxx = pfield.get();
|
||||
UnionArray const *punionArray = static_cast<UnionArray const*>(xxx);
|
||||
o << *punionArray->getUnion();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -467,20 +537,30 @@ void Structure::deserialize(ByteBuffer* /*buffer*/, DeserializableControl* /*con
|
||||
throw std::runtime_error("not valid operation, use FieldCreate::deserialize instead");
|
||||
}
|
||||
|
||||
string Union::DEFAULT_ID = "union";
|
||||
const string Union::DEFAULT_ID = Union::defaultId();
|
||||
|
||||
#define UNION_ANY_ID "any"
|
||||
string Union::ANY_ID = UNION_ANY_ID;
|
||||
const string & Union::defaultId()
|
||||
{
|
||||
static const string id = "union";
|
||||
return id;
|
||||
}
|
||||
|
||||
const string Union::ANY_ID = Union::anyId();
|
||||
|
||||
const string & Union::anyId()
|
||||
{
|
||||
static const string id = "any";
|
||||
return id;
|
||||
}
|
||||
|
||||
Union::Union ()
|
||||
: Field(union_),
|
||||
fieldNames(),
|
||||
fields(),
|
||||
id(UNION_ANY_ID)
|
||||
id(anyId())
|
||||
{
|
||||
}
|
||||
|
||||
#undef UNION_ANY_ID
|
||||
|
||||
Union::Union (
|
||||
StringArray const & fieldNames,
|
||||
@@ -492,31 +572,31 @@ Union::Union (
|
||||
id(inid)
|
||||
{
|
||||
if(inid.empty()) {
|
||||
throw std::invalid_argument("id is empty");
|
||||
THROW_EXCEPTION2(std::invalid_argument, "Can't construct Union, id is empty string");
|
||||
}
|
||||
if(fieldNames.size()!=fields.size()) {
|
||||
throw std::invalid_argument("fieldNames.size()!=fields.size()");
|
||||
THROW_EXCEPTION2(std::invalid_argument, "Can't construct Union, fieldNames.size()!=fields.size()");
|
||||
}
|
||||
if(fields.size()==0 && inid!=ANY_ID) {
|
||||
throw std::invalid_argument("no fields but id is different than " + ANY_ID);
|
||||
THROW_EXCEPTION2(std::invalid_argument, "Can't construct Union, no fields only allowed when id = " + ANY_ID);
|
||||
}
|
||||
|
||||
size_t number = fields.size();
|
||||
for(size_t i=0; i<number; i++) {
|
||||
const string& name = fieldNames[i];
|
||||
if(name.empty()) {
|
||||
throw std::invalid_argument("fieldNames has a zero length string");
|
||||
THROW_EXCEPTION2(std::invalid_argument, "Can't construct Union, empty string in fieldNames");
|
||||
}
|
||||
if(fields[i].get()==NULL)
|
||||
throw std::invalid_argument("Can't construct Union with NULL Field");
|
||||
THROW_EXCEPTION2(std::invalid_argument, "Can't construct Union, NULL in fields");
|
||||
// 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 ");
|
||||
string message("Can't construct Union, duplicate fieldName ");
|
||||
message += name;
|
||||
throw std::invalid_argument(message);
|
||||
THROW_EXCEPTION2(std::invalid_argument, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -552,7 +632,7 @@ size_t Union::getFieldIndex(string const &fieldName) const {
|
||||
|
||||
std::ostream& Union::dump(std::ostream& o) const
|
||||
{
|
||||
o << getID() << std::endl;
|
||||
o << format::indent() << getID() << std::endl;
|
||||
{
|
||||
format::indent_scope s(o);
|
||||
dumpFields(o);
|
||||
@@ -655,6 +735,12 @@ FieldBuilderPtr FieldBuilder::add(string const & name, ScalarType scalarType)
|
||||
return shared_from_this();
|
||||
}
|
||||
|
||||
FieldBuilderPtr FieldBuilder::addBoundedString(std::string const & name, std::size_t maxLength)
|
||||
{
|
||||
fields.push_back(fieldCreate->createBoundedString(maxLength)); fieldNames.push_back(name);
|
||||
return shared_from_this();
|
||||
}
|
||||
|
||||
FieldBuilderPtr FieldBuilder::add(string const & name, FieldConstPtr const & field)
|
||||
{
|
||||
fields.push_back(field); fieldNames.push_back(name);
|
||||
@@ -667,6 +753,18 @@ FieldBuilderPtr FieldBuilder::addArray(string const & name, ScalarType scalarTyp
|
||||
return shared_from_this();
|
||||
}
|
||||
|
||||
FieldBuilderPtr FieldBuilder::addFixedArray(string const & name, ScalarType scalarType, size_t size)
|
||||
{
|
||||
fields.push_back(fieldCreate->createFixedScalarArray(scalarType, size)); fieldNames.push_back(name);
|
||||
return shared_from_this();
|
||||
}
|
||||
|
||||
FieldBuilderPtr FieldBuilder::addBoundedArray(string const & name, ScalarType scalarType, size_t size)
|
||||
{
|
||||
fields.push_back(fieldCreate->createBoundedScalarArray(scalarType, size)); fieldNames.push_back(name);
|
||||
return shared_from_this();
|
||||
}
|
||||
|
||||
FieldBuilderPtr FieldBuilder::addArray(string const & name, FieldConstPtr const & element)
|
||||
{
|
||||
switch (element->getType())
|
||||
@@ -678,10 +776,17 @@ FieldBuilderPtr FieldBuilder::addArray(string const & name, FieldConstPtr const
|
||||
fields.push_back(fieldCreate->createUnionArray(static_pointer_cast<const Union>(element)));
|
||||
break;
|
||||
case scalar:
|
||||
|
||||
if (std::tr1::dynamic_pointer_cast<const BoundedString>(element).get())
|
||||
THROW_EXCEPTION2(std::invalid_argument, "bounded string arrays are not supported");
|
||||
|
||||
fields.push_back(fieldCreate->createScalarArray(static_pointer_cast<const Scalar>(element)->getScalarType()));
|
||||
break;
|
||||
// scalarArray?
|
||||
default:
|
||||
throw std::invalid_argument("unsupported array element type:" + element->getType());
|
||||
std::ostringstream msg("unsupported array element type: ");
|
||||
msg << element->getType();
|
||||
THROW_EXCEPTION2(std::invalid_argument, msg.str());
|
||||
}
|
||||
|
||||
fieldNames.push_back(name);
|
||||
@@ -707,14 +812,18 @@ FieldConstPtr FieldBuilder::createFieldInternal(Type type)
|
||||
fieldCreate->createUnion(fieldNames, fields);
|
||||
}
|
||||
else
|
||||
throw std::invalid_argument("unsupported type: " + type);
|
||||
{
|
||||
std::ostringstream msg("unsupported type: ");
|
||||
msg << type;
|
||||
THROW_EXCEPTION2(std::invalid_argument, msg.str());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
StructureConstPtr FieldBuilder::createStructure()
|
||||
{
|
||||
if (parentBuilder.get())
|
||||
throw std::runtime_error("createStructure() called in nested FieldBuilder");
|
||||
THROW_EXCEPTION2(std::runtime_error, "createStructure() called in nested FieldBuilder");
|
||||
|
||||
StructureConstPtr field(static_pointer_cast<const Structure>(createFieldInternal(structure)));
|
||||
reset();
|
||||
@@ -724,7 +833,7 @@ StructureConstPtr FieldBuilder::createStructure()
|
||||
UnionConstPtr FieldBuilder::createUnion()
|
||||
{
|
||||
if (parentBuilder.get())
|
||||
throw std::runtime_error("createUnion() called in nested FieldBuilder");
|
||||
THROW_EXCEPTION2(std::runtime_error, "createUnion() called in nested FieldBuilder");
|
||||
|
||||
UnionConstPtr field(static_pointer_cast<const Union>(createFieldInternal(union_)));
|
||||
reset();
|
||||
@@ -756,7 +865,7 @@ FieldBuilderPtr FieldBuilder::addNestedUnionArray(string const & name)
|
||||
FieldBuilderPtr FieldBuilder::endNested()
|
||||
{
|
||||
if (!parentBuilder.get())
|
||||
throw std::runtime_error("this method can only be called to create nested fields");
|
||||
THROW_EXCEPTION2(std::runtime_error, "this method can only be called to create nested fields");
|
||||
|
||||
FieldConstPtr nestedField = createFieldInternal(nestedClassToBuild);
|
||||
if (nestedArray)
|
||||
@@ -775,20 +884,62 @@ FieldBuilderPtr FieldCreate::createFieldBuilder() const
|
||||
|
||||
ScalarConstPtr FieldCreate::createScalar(ScalarType scalarType) const
|
||||
{
|
||||
if(scalarType<0 || scalarType>MAX_SCALAR_TYPE)
|
||||
throw std::invalid_argument("Can't construct Scalar from invalid ScalarType");
|
||||
if(scalarType<0 || scalarType>MAX_SCALAR_TYPE) {
|
||||
std::ostringstream strm("Can't construct Scalar from invalid ScalarType ");
|
||||
strm << scalarType;
|
||||
THROW_EXCEPTION2(std::invalid_argument, strm.str());
|
||||
}
|
||||
|
||||
return scalars[scalarType];
|
||||
}
|
||||
|
||||
|
||||
BoundedStringConstPtr FieldCreate::createBoundedString(std::size_t maxLength) const
|
||||
{
|
||||
// TODO use std::make_shared
|
||||
std::tr1::shared_ptr<BoundedString> s(new BoundedString(maxLength), Field::Deleter());
|
||||
BoundedStringConstPtr sa = s;
|
||||
return sa;
|
||||
}
|
||||
|
||||
ScalarArrayConstPtr FieldCreate::createScalarArray(ScalarType elementType) const
|
||||
{
|
||||
if(elementType<0 || elementType>MAX_SCALAR_TYPE)
|
||||
throw std::invalid_argument("Can't construct ScalarArray from invalid ScalarType");
|
||||
if(elementType<0 || elementType>MAX_SCALAR_TYPE) {
|
||||
std::ostringstream strm("Can't construct ScalarArray from invalid ScalarType ");
|
||||
strm << elementType;
|
||||
THROW_EXCEPTION2(std::invalid_argument, strm.str());
|
||||
}
|
||||
|
||||
return scalarArrays[elementType];
|
||||
}
|
||||
|
||||
ScalarArrayConstPtr FieldCreate::createFixedScalarArray(ScalarType elementType, size_t size) const
|
||||
{
|
||||
if(elementType<0 || elementType>MAX_SCALAR_TYPE) {
|
||||
std::ostringstream strm("Can't construct fixed ScalarArray from invalid ScalarType ");
|
||||
strm << elementType;
|
||||
THROW_EXCEPTION2(std::invalid_argument, strm.str());
|
||||
}
|
||||
|
||||
// TODO use std::make_shared
|
||||
std::tr1::shared_ptr<ScalarArray> s(new FixedScalarArray(elementType, size), Field::Deleter());
|
||||
ScalarArrayConstPtr sa = s;
|
||||
return sa;
|
||||
}
|
||||
|
||||
ScalarArrayConstPtr FieldCreate::createBoundedScalarArray(ScalarType elementType, size_t size) const
|
||||
{
|
||||
if(elementType<0 || elementType>MAX_SCALAR_TYPE) {
|
||||
std::ostringstream strm("Can't construct bounded ScalarArray from invalid ScalarType ");
|
||||
strm << elementType;
|
||||
THROW_EXCEPTION2(std::invalid_argument, strm.str());
|
||||
}
|
||||
|
||||
// TODO use std::make_shared
|
||||
std::tr1::shared_ptr<ScalarArray> s(new BoundedScalarArray(elementType, size), Field::Deleter());
|
||||
ScalarArrayConstPtr sa = s;
|
||||
return sa;
|
||||
}
|
||||
|
||||
StructureConstPtr FieldCreate::createStructure () const
|
||||
{
|
||||
StringArray fieldNames;
|
||||
@@ -799,8 +950,9 @@ StructureConstPtr FieldCreate::createStructure () const
|
||||
StructureConstPtr FieldCreate::createStructure (
|
||||
StringArray const & fieldNames,FieldConstPtrArray const & fields) const
|
||||
{
|
||||
StructureConstPtr structure(
|
||||
new Structure(fieldNames,fields), Field::Deleter());
|
||||
// TODO use std::make_shared
|
||||
std::tr1::shared_ptr<Structure> sp(new Structure(fieldNames,fields), Field::Deleter());
|
||||
StructureConstPtr structure = sp;
|
||||
return structure;
|
||||
}
|
||||
|
||||
@@ -809,24 +961,27 @@ StructureConstPtr FieldCreate::createStructure (
|
||||
StringArray const & fieldNames,
|
||||
FieldConstPtrArray const & fields) const
|
||||
{
|
||||
StructureConstPtr structure(
|
||||
new Structure(fieldNames,fields,id), Field::Deleter());
|
||||
// TODO use std::make_shared
|
||||
std::tr1::shared_ptr<Structure> sp(new Structure(fieldNames,fields,id), Field::Deleter());
|
||||
StructureConstPtr structure = sp;
|
||||
return structure;
|
||||
}
|
||||
|
||||
StructureArrayConstPtr FieldCreate::createStructureArray(
|
||||
StructureConstPtr const & structure) const
|
||||
{
|
||||
StructureArrayConstPtr structureArray(
|
||||
new StructureArray(structure), Field::Deleter());
|
||||
// TODO use std::make_shared
|
||||
std::tr1::shared_ptr<StructureArray> sp(new StructureArray(structure), Field::Deleter());
|
||||
StructureArrayConstPtr structureArray = sp;
|
||||
return structureArray;
|
||||
}
|
||||
|
||||
UnionConstPtr FieldCreate::createUnion (
|
||||
StringArray const & fieldNames,FieldConstPtrArray const & fields) const
|
||||
{
|
||||
UnionConstPtr punion(
|
||||
new Union(fieldNames,fields), Field::Deleter());
|
||||
// TODO use std::make_shared
|
||||
std::tr1::shared_ptr<Union> sp(new Union(fieldNames,fields), Field::Deleter());
|
||||
UnionConstPtr punion = sp;
|
||||
return punion;
|
||||
}
|
||||
|
||||
@@ -835,8 +990,9 @@ UnionConstPtr FieldCreate::createUnion (
|
||||
StringArray const & fieldNames,
|
||||
FieldConstPtrArray const & fields) const
|
||||
{
|
||||
UnionConstPtr punion(
|
||||
new Union(fieldNames,fields,id), Field::Deleter());
|
||||
// TODO use std::make_shared
|
||||
std::tr1::shared_ptr<Union> sp(new Union(fieldNames,fields,id), Field::Deleter());
|
||||
UnionConstPtr punion = sp;
|
||||
return punion;
|
||||
}
|
||||
|
||||
@@ -848,8 +1004,9 @@ UnionConstPtr FieldCreate::createVariantUnion () const
|
||||
UnionArrayConstPtr FieldCreate::createUnionArray(
|
||||
UnionConstPtr const & punion) const
|
||||
{
|
||||
UnionArrayConstPtr unionArray(
|
||||
new UnionArray(punion), Field::Deleter());
|
||||
// TODO use std::make_shared
|
||||
std::tr1::shared_ptr<UnionArray> sp(new UnionArray(punion), Field::Deleter());
|
||||
UnionArrayConstPtr unionArray = sp;
|
||||
return unionArray;
|
||||
}
|
||||
|
||||
@@ -863,8 +1020,8 @@ StructureConstPtr FieldCreate::appendField(
|
||||
string const & fieldName,
|
||||
FieldConstPtr const & field) const
|
||||
{
|
||||
StringArray oldNames = structure->getFieldNames();
|
||||
FieldConstPtrArray oldFields = structure->getFields();
|
||||
StringArray const & oldNames = structure->getFieldNames();
|
||||
FieldConstPtrArray const & oldFields = structure->getFields();
|
||||
size_t oldLen = oldNames.size();
|
||||
StringArray newNames(oldLen+1);
|
||||
FieldConstPtrArray newFields(oldLen+1);
|
||||
@@ -882,8 +1039,8 @@ StructureConstPtr FieldCreate::appendFields(
|
||||
StringArray const & fieldNames,
|
||||
FieldConstPtrArray const & fields) const
|
||||
{
|
||||
StringArray oldNames = structure->getFieldNames();
|
||||
FieldConstPtrArray oldFields = structure->getFields();
|
||||
StringArray const & oldNames = structure->getFieldNames();
|
||||
FieldConstPtrArray const & oldFields = structure->getFields();
|
||||
size_t oldLen = oldNames.size();
|
||||
size_t extra = fieldNames.size();
|
||||
StringArray newNames(oldLen+extra);
|
||||
@@ -904,22 +1061,14 @@ 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,
|
||||
pvByte, // 8-bits
|
||||
pvShort, // 16-bits
|
||||
pvInt, // 32-bits
|
||||
pvLong, // 64-bits
|
||||
pvUByte, // unsigned 8-bits
|
||||
pvUShort, // unsigned 16-bits
|
||||
pvUInt, // unsigned 32-bits
|
||||
pvULong, // unsigned 64-bits
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1
|
||||
pvULong // unsigned 64-bits
|
||||
};
|
||||
|
||||
static const int floatLUT[] =
|
||||
@@ -931,22 +1080,14 @@ static int decodeScalar(int8 code)
|
||||
-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 1: return integerLUT[code & 0x07];
|
||||
case 2: return floatLUT[code & 0x07];
|
||||
case 3: return pvString;
|
||||
default: return -1;
|
||||
}
|
||||
@@ -959,8 +1100,9 @@ FieldConstPtr FieldCreate::deserialize(ByteBuffer* buffer, DeserializableControl
|
||||
if (code == -1)
|
||||
return FieldConstPtr();
|
||||
|
||||
int typeCode = code & 0xEF;
|
||||
bool notArray = ((code & 0x10) == 0);
|
||||
int typeCode = code & 0xE7;
|
||||
int scalarOrArray = code & 0x18;
|
||||
bool notArray = (scalarOrArray == 0);
|
||||
if (notArray)
|
||||
{
|
||||
if (typeCode < 0x80)
|
||||
@@ -986,33 +1128,90 @@ FieldConstPtr FieldCreate::deserialize(ByteBuffer* buffer, DeserializableControl
|
||||
// Type type = Type.union; variant union (aka any type)
|
||||
return variantUnion;
|
||||
}
|
||||
else if (typeCode == 0x83)
|
||||
{
|
||||
// TODO cache?
|
||||
// bounded string
|
||||
|
||||
size_t size = SerializeHelper::readSize(buffer, control);
|
||||
|
||||
// TODO use std::make_shared
|
||||
std::tr1::shared_ptr<Field> sp(
|
||||
new BoundedString(size),
|
||||
Field::Deleter());
|
||||
FieldConstPtr p = sp;
|
||||
return p;
|
||||
}
|
||||
else
|
||||
throw std::invalid_argument("invalid type encoding");
|
||||
}
|
||||
else // array
|
||||
{
|
||||
bool isVariable = (scalarOrArray == 0x08);
|
||||
// bounded == 0x10;
|
||||
bool isFixed = (scalarOrArray == 0x18);
|
||||
|
||||
size_t size = (isVariable ? 0 : SerializeHelper::readSize(buffer, control));
|
||||
|
||||
if (typeCode < 0x80)
|
||||
{
|
||||
// Type type = Type.scalarArray;
|
||||
int scalarType = decodeScalar(code);
|
||||
if (scalarType == -1)
|
||||
throw std::invalid_argument("invalid scalarArray type encoding");
|
||||
return scalarArrays[scalarType];
|
||||
if (isVariable)
|
||||
return scalarArrays[scalarType];
|
||||
else if (isFixed)
|
||||
{
|
||||
// TODO use std::make_shared
|
||||
std::tr1::shared_ptr<Field> sp(
|
||||
new FixedScalarArray(static_cast<epics::pvData::ScalarType>(scalarType), size),
|
||||
Field::Deleter());
|
||||
FieldConstPtr p = sp;
|
||||
return p;
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO use std::make_shared
|
||||
std::tr1::shared_ptr<Field> sp(
|
||||
new BoundedScalarArray(static_cast<epics::pvData::ScalarType>(scalarType), size),
|
||||
Field::Deleter());
|
||||
FieldConstPtr p = sp;
|
||||
return p;
|
||||
}
|
||||
}
|
||||
else if (typeCode == 0x80)
|
||||
{
|
||||
// TODO fixed and bounded array support
|
||||
if (!isVariable)
|
||||
throw std::invalid_argument("fixed and bounded structure array not supported");
|
||||
|
||||
// Type type = Type.structureArray;
|
||||
StructureConstPtr elementStructure = std::tr1::static_pointer_cast<const Structure>(control->cachedDeserialize(buffer));
|
||||
return FieldConstPtr(new StructureArray(elementStructure), Field::Deleter());
|
||||
// TODO use std::make_shared
|
||||
std::tr1::shared_ptr<Field> sp(new StructureArray(elementStructure), Field::Deleter());
|
||||
FieldConstPtr p = sp;
|
||||
return p;
|
||||
}
|
||||
else if (typeCode == 0x81)
|
||||
{
|
||||
// TODO fixed and bounded array support
|
||||
if (!isVariable)
|
||||
throw std::invalid_argument("fixed and bounded structure array not supported");
|
||||
|
||||
// Type type = Type.unionArray;
|
||||
UnionConstPtr elementUnion = std::tr1::static_pointer_cast<const Union>(control->cachedDeserialize(buffer));
|
||||
return FieldConstPtr(new UnionArray(elementUnion), Field::Deleter());
|
||||
// TODO use std::make_shared
|
||||
std::tr1::shared_ptr<Field> sp(new UnionArray(elementUnion), Field::Deleter());
|
||||
FieldConstPtr p = sp;
|
||||
return p;
|
||||
}
|
||||
else if (typeCode == 0x82)
|
||||
{
|
||||
// TODO fixed and bounded array support
|
||||
if (!isVariable)
|
||||
throw std::invalid_argument("fixed and bounded structure array not supported");
|
||||
|
||||
// Type type = Type.unionArray; variant union (aka any type)
|
||||
return variantUnionArray;
|
||||
}
|
||||
@@ -1037,11 +1236,24 @@ FieldCreate::FieldCreate()
|
||||
{
|
||||
for (int i = 0; i <= MAX_SCALAR_TYPE; i++)
|
||||
{
|
||||
scalars.push_back(ScalarConstPtr(new Scalar(static_cast<ScalarType>(i)), Field::Deleter()));
|
||||
scalarArrays.push_back(ScalarArrayConstPtr(new ScalarArray(static_cast<ScalarType>(i)), Field::Deleter()));
|
||||
// TODO use std::make_shared
|
||||
std::tr1::shared_ptr<Scalar> sp(new Scalar(static_cast<ScalarType>(i)), Field::Deleter());
|
||||
ScalarConstPtr p = sp;
|
||||
scalars.push_back(p);
|
||||
|
||||
// TODO use std::make_shared
|
||||
std::tr1::shared_ptr<ScalarArray> spa(new ScalarArray(static_cast<ScalarType>(i)), Field::Deleter());
|
||||
ScalarArrayConstPtr pa = spa;
|
||||
scalarArrays.push_back(spa);
|
||||
}
|
||||
variantUnion = UnionConstPtr(new Union(), Field::Deleter());
|
||||
variantUnionArray = UnionArrayConstPtr(new UnionArray(variantUnion), Field::Deleter());
|
||||
|
||||
// TODO use std::make_shared
|
||||
std::tr1::shared_ptr<Union> su(new Union(), Field::Deleter());
|
||||
variantUnion = su;
|
||||
|
||||
// TODO use std::make_shared
|
||||
std::tr1::shared_ptr<UnionArray> sua(new UnionArray(variantUnion), Field::Deleter());
|
||||
variantUnionArray = sua;
|
||||
}
|
||||
|
||||
FieldCreatePtr getFieldCreate() {
|
||||
@@ -1049,3 +1261,12 @@ FieldCreatePtr getFieldCreate() {
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
namespace std{
|
||||
std::ostream& operator<<(std::ostream& o, const epics::pvData::Field *ptr)
|
||||
{
|
||||
if(ptr) return o << *ptr;
|
||||
return o << "nullptr";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
#include <pv/lock.h>
|
||||
#include <pv/pvIntrospect.h>
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/convert.h>
|
||||
#include <pv/factory.h>
|
||||
#include <pv/serializeHelper.h>
|
||||
|
||||
@@ -145,11 +144,18 @@ public:
|
||||
SerializableControl *pflusher, size_t offset, size_t count) const;
|
||||
private:
|
||||
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() {}
|
||||
|
||||
@@ -157,6 +163,9 @@ string BasePVString::get() const { return value;}
|
||||
|
||||
void BasePVString::put(string val)
|
||||
{
|
||||
if (maxLength > 0 && val.length() > maxLength)
|
||||
throw std::overflow_error("string too long");
|
||||
|
||||
value = val;
|
||||
postPut();
|
||||
}
|
||||
@@ -190,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>
|
||||
@@ -231,7 +253,14 @@ DefaultPVArray<T>::DefaultPVArray(ScalarArrayConstPtr const & scalarArray)
|
||||
: PVValueArray<T>(scalarArray),
|
||||
value()
|
||||
|
||||
{ }
|
||||
{
|
||||
ArrayConstPtr array = this->getArray();
|
||||
if (array->getArraySizeType() == Array::fixed)
|
||||
{
|
||||
// this->setLength(array->getMaximumCapacity());
|
||||
this->setCapacityMutable(false);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
DefaultPVArray<T>::~DefaultPVArray()
|
||||
@@ -240,18 +269,25 @@ template<typename T>
|
||||
void DefaultPVArray<T>::setCapacity(size_t capacity)
|
||||
{
|
||||
if(this->isCapacityMutable()) {
|
||||
this->checkLength(capacity);
|
||||
value.reserve(capacity);
|
||||
}
|
||||
else
|
||||
THROW_EXCEPTION2(std::logic_error, "capacity immutable");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void DefaultPVArray<T>::setLength(size_t length)
|
||||
{
|
||||
if(this->isImmutable())
|
||||
THROW_EXCEPTION2(std::logic_error,"Immutable");
|
||||
if(length == value.size())
|
||||
THROW_EXCEPTION2(std::logic_error, "immutable");
|
||||
|
||||
if (length == value.size())
|
||||
return;
|
||||
else if(length < value.size())
|
||||
|
||||
this->checkLength(length);
|
||||
|
||||
if (length < value.size())
|
||||
value.slice(0, length);
|
||||
else
|
||||
value.resize(length);
|
||||
@@ -260,6 +296,8 @@ void DefaultPVArray<T>::setLength(size_t length)
|
||||
template<typename T>
|
||||
void DefaultPVArray<T>::replace(const const_svector& next)
|
||||
{
|
||||
this->checkLength(next.size());
|
||||
|
||||
value = next;
|
||||
this->postPut();
|
||||
}
|
||||
@@ -267,8 +305,10 @@ void DefaultPVArray<T>::replace(const const_svector& next)
|
||||
template<typename T>
|
||||
void DefaultPVArray<T>::swap(const_svector &other)
|
||||
{
|
||||
if(this->isImmutable())
|
||||
THROW_EXCEPTION2(std::logic_error,"Immutable");
|
||||
if (this->isImmutable())
|
||||
THROW_EXCEPTION2(std::logic_error, "immutable");
|
||||
|
||||
// no checkLength call here
|
||||
|
||||
value.swap(other);
|
||||
}
|
||||
@@ -283,7 +323,10 @@ void DefaultPVArray<T>::serialize(ByteBuffer *pbuffer,
|
||||
template<typename T>
|
||||
void DefaultPVArray<T>::deserialize(ByteBuffer *pbuffer,
|
||||
DeserializableControl *pcontrol) {
|
||||
size_t size = SerializeHelper::readSize(pbuffer, pcontrol);
|
||||
|
||||
size_t size = this->getArray()->getArraySizeType() == Array::fixed ?
|
||||
this->getArray()->getMaximumCapacity() :
|
||||
SerializeHelper::readSize(pbuffer, pcontrol);
|
||||
|
||||
svector nextvalue(thaw(value));
|
||||
nextvalue.resize(size); // TODO: avoid copy of stuff we will then overwrite
|
||||
@@ -321,6 +364,7 @@ void DefaultPVArray<T>::deserialize(ByteBuffer *pbuffer,
|
||||
remaining -= n2read;
|
||||
}
|
||||
value = freeze(nextvalue);
|
||||
// TODO !!!
|
||||
// inform about the change?
|
||||
PVField::postPut();
|
||||
}
|
||||
@@ -334,7 +378,11 @@ void DefaultPVArray<T>::serialize(ByteBuffer *pbuffer,
|
||||
temp.slice(offset, count);
|
||||
count = temp.size();
|
||||
|
||||
SerializeHelper::writeSize(temp.size(), pbuffer, pflusher);
|
||||
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();
|
||||
|
||||
@@ -368,7 +416,10 @@ void DefaultPVArray<T>::serialize(ByteBuffer *pbuffer,
|
||||
template<>
|
||||
void DefaultPVArray<string>::deserialize(ByteBuffer *pbuffer,
|
||||
DeserializableControl *pcontrol) {
|
||||
size_t size = SerializeHelper::readSize(pbuffer, pcontrol);
|
||||
|
||||
size_t size = this->getArray()->getArraySizeType() == Array::fixed ?
|
||||
this->getArray()->getMaximumCapacity() :
|
||||
SerializeHelper::readSize(pbuffer, pcontrol);
|
||||
|
||||
svector nextvalue(thaw(value));
|
||||
|
||||
@@ -396,7 +447,9 @@ void DefaultPVArray<string>::serialize(ByteBuffer *pbuffer,
|
||||
const_svector temp(value);
|
||||
temp.slice(offset, count);
|
||||
|
||||
SerializeHelper::writeSize(temp.size(), pbuffer, pflusher);
|
||||
// TODO if fixed count == getArray()->getMaximumCapacity()
|
||||
if (this->getArray()->getArraySizeType() != Array::fixed)
|
||||
SerializeHelper::writeSize(temp.size(), pbuffer, pflusher);
|
||||
|
||||
const string * pvalue = temp.data();
|
||||
for(size_t i = 0; i<temp.size(); i++) {
|
||||
@@ -473,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:
|
||||
@@ -483,7 +536,7 @@ 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_:
|
||||
@@ -498,7 +551,7 @@ PVFieldPtr PVDataCreate::createPVField(PVFieldPtr const & fieldToClone)
|
||||
= static_pointer_cast<PVUnionArray>(fieldToClone);
|
||||
UnionArrayConstPtr unionArray = from->getUnionArray();
|
||||
PVUnionArrayPtr to = createPVUnionArray(unionArray);
|
||||
getConvert()->copyUnionArray(from, to);
|
||||
to->copyUnchecked(*from);
|
||||
return to;
|
||||
}
|
||||
}
|
||||
@@ -548,7 +601,7 @@ PVScalarPtr PVDataCreate::createPVScalar(PVScalarPtr const & scalarToClone)
|
||||
{
|
||||
ScalarType scalarType = scalarToClone->getScalar()->getScalarType();
|
||||
PVScalarPtr pvScalar = createPVScalar(scalarType);
|
||||
getConvert()->copyScalar(scalarToClone, pvScalar);
|
||||
pvScalar->copyUnchecked(*scalarToClone);
|
||||
return pvScalar;
|
||||
}
|
||||
|
||||
@@ -649,7 +702,7 @@ 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);
|
||||
@@ -658,7 +711,7 @@ PVStructurePtr PVDataCreate::createPVStructure(PVStructurePtr const & structToCl
|
||||
}
|
||||
StructureConstPtr structure = structToClone->getStructure();
|
||||
PVStructurePtr pvStructure(new PVStructure(structure));
|
||||
getConvert()->copyStructure(structToClone,pvStructure);
|
||||
pvStructure->copyUnchecked(*structToClone);
|
||||
return pvStructure;
|
||||
}
|
||||
|
||||
@@ -687,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";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
#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;
|
||||
@@ -121,7 +120,7 @@ void PVField::computeOffset(const PVField * pvField) {
|
||||
}
|
||||
size_t offset = 0;
|
||||
size_t nextOffset = 1;
|
||||
PVFieldPtrArray pvFields = pvTop->getPVFields();
|
||||
const PVFieldPtrArray & pvFields = pvTop->getPVFields();
|
||||
for(size_t i=0; i < pvTop->getStructure()->getNumberFields(); i++) {
|
||||
offset = nextOffset;
|
||||
PVField *pvField = pvFields[i].get();
|
||||
@@ -153,7 +152,7 @@ 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();
|
||||
const PVFieldPtrArray & pvFields = pvStructure->getPVFields();
|
||||
for(size_t i=0; i < pvStructure->getStructure()->getNumberFields(); i++) {
|
||||
offset = nextOffset;
|
||||
PVField *pvSubField = pvFields[i].get();
|
||||
@@ -180,4 +179,117 @@ void PVField::computeOffset(const PVField * pvField,size_t offset) {
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}}
|
||||
|
||||
@@ -33,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<>
|
||||
@@ -41,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());
|
||||
}
|
||||
}}
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/pvIntrospect.h>
|
||||
#include <pv/convert.h>
|
||||
#include <pv/factory.h>
|
||||
#include <pv/bitSet.h>
|
||||
|
||||
@@ -45,18 +44,14 @@ PVUnionPtr PVStructure::nullPVUnion;
|
||||
PVUnionArrayPtr PVStructure::nullPVUnionArray;
|
||||
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();
|
||||
FieldConstPtrArray const & fields = structurePtr->getFields();
|
||||
StringArray const & fieldNames = structurePtr->getFieldNames();
|
||||
// PVFieldPtrArray * xxx = const_cast<PVFieldPtrArray *>(&pvFields);
|
||||
pvFields.reserve(numberFields);
|
||||
PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
||||
@@ -76,7 +71,7 @@ PVStructure::PVStructure(StructureConstPtr const & structurePtr,
|
||||
extendsStructureName("")
|
||||
{
|
||||
size_t numberFields = structurePtr->getNumberFields();
|
||||
StringArray fieldNames = structurePtr->getFieldNames();
|
||||
StringArray const & fieldNames = structurePtr->getFieldNames();
|
||||
pvFields.reserve(numberFields);
|
||||
for(size_t i=0; i<numberFields; i++) {
|
||||
pvFields.push_back(pvs[i]);
|
||||
@@ -112,7 +107,11 @@ const PVFieldPtrArray & PVStructure::getPVFields() const
|
||||
|
||||
PVFieldPtr PVStructure::getSubField(string const &fieldName) const
|
||||
{
|
||||
return findSubField(fieldName,this);
|
||||
PVField * field = getSubFieldImpl(fieldName.c_str(), false);
|
||||
if (field)
|
||||
return field->shared_from_this();
|
||||
else
|
||||
return PVFieldPtr();
|
||||
}
|
||||
|
||||
|
||||
@@ -135,107 +134,111 @@ PVFieldPtr PVStructure::getSubField(size_t fieldOffset) const
|
||||
throw std::logic_error("PVStructure.getSubField: Logic error");
|
||||
}
|
||||
|
||||
|
||||
PVBooleanPtr PVStructure::getBooleanField(string const &fieldName)
|
||||
PVFieldPtr PVStructure::getSubFieldT(std::size_t fieldOffset) const
|
||||
{
|
||||
return getSubField<PVBoolean>(fieldName);
|
||||
}
|
||||
|
||||
PVBytePtr PVStructure::getByteField(string const &fieldName)
|
||||
{
|
||||
return getSubField<PVByte>(fieldName);
|
||||
}
|
||||
|
||||
PVShortPtr PVStructure::getShortField(string const &fieldName)
|
||||
{
|
||||
return getSubField<PVShort>(fieldName);
|
||||
}
|
||||
|
||||
PVIntPtr PVStructure::getIntField(string const &fieldName)
|
||||
{
|
||||
return getSubField<PVInt>(fieldName);
|
||||
}
|
||||
|
||||
PVLongPtr PVStructure::getLongField(string const &fieldName)
|
||||
{
|
||||
return getSubField<PVLong>(fieldName);
|
||||
}
|
||||
|
||||
PVUBytePtr PVStructure::getUByteField(string const &fieldName)
|
||||
{
|
||||
return getSubField<PVUByte>(fieldName);
|
||||
}
|
||||
|
||||
PVUShortPtr PVStructure::getUShortField(string const &fieldName)
|
||||
{
|
||||
return getSubField<PVUShort>(fieldName);
|
||||
}
|
||||
|
||||
PVUIntPtr PVStructure::getUIntField(string const &fieldName)
|
||||
{
|
||||
return getSubField<PVUInt>(fieldName);
|
||||
}
|
||||
|
||||
PVULongPtr PVStructure::getULongField(string const &fieldName)
|
||||
{
|
||||
return getSubField<PVULong>(fieldName);
|
||||
}
|
||||
|
||||
PVFloatPtr PVStructure::getFloatField(string const &fieldName)
|
||||
{
|
||||
return getSubField<PVFloat>(fieldName);
|
||||
}
|
||||
|
||||
PVDoublePtr PVStructure::getDoubleField(string const &fieldName)
|
||||
{
|
||||
return getSubField<PVDouble>(fieldName);
|
||||
}
|
||||
|
||||
PVStringPtr PVStructure::getStringField(string const &fieldName)
|
||||
{
|
||||
return getSubField<PVString>(fieldName);
|
||||
}
|
||||
|
||||
PVStructurePtr PVStructure::getStructureField(string const &fieldName)
|
||||
{
|
||||
return getSubField<PVStructure>(fieldName);
|
||||
}
|
||||
|
||||
PVUnionPtr PVStructure::getUnionField(string const &fieldName)
|
||||
{
|
||||
return getSubField<PVUnion>(fieldName);
|
||||
}
|
||||
|
||||
PVScalarArrayPtr PVStructure::getScalarArrayField(
|
||||
string const &fieldName,ScalarType elementType)
|
||||
{
|
||||
PVFieldPtr pvField = findSubField(fieldName,this);
|
||||
if(pvField.get()==NULL) {
|
||||
return nullPVScalarArray;
|
||||
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());
|
||||
}
|
||||
FieldConstPtr field = pvField->getField();
|
||||
Type type = field->getType();
|
||||
if(type!=scalarArray) {
|
||||
return nullPVScalarArray;
|
||||
}
|
||||
ScalarArrayConstPtr pscalarArray
|
||||
= static_pointer_cast<const ScalarArray>(pvField->getField());
|
||||
if(pscalarArray->getElementType()!=elementType) {
|
||||
return nullPVScalarArray;
|
||||
}
|
||||
return std::tr1::static_pointer_cast<PVScalarArray>(pvField);
|
||||
}
|
||||
|
||||
PVStructureArrayPtr PVStructure::getStructureArrayField(
|
||||
string const &fieldName)
|
||||
PVField* PVStructure::getSubFieldImpl(const char *name, bool throws) const
|
||||
{
|
||||
return getSubField<PVStructureArray>(fieldName);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
PVUnionArrayPtr PVStructure::getUnionArrayField(
|
||||
string const &fieldName)
|
||||
{
|
||||
return getSubField<PVUnionArray>(fieldName);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -328,37 +331,6 @@ void PVStructure::deserialize(ByteBuffer *pbuffer,
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
@@ -382,4 +354,79 @@ std::ostream& PVStructure::dumpValue(std::ostream& o) const
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}}
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/convert.h>
|
||||
#include <pv/factory.h>
|
||||
#include <pv/serializeHelper.h>
|
||||
|
||||
@@ -25,6 +24,8 @@ namespace epics { namespace pvData {
|
||||
|
||||
size_t PVStructureArray::append(size_t number)
|
||||
{
|
||||
checkLength(value.size()+number);
|
||||
|
||||
svector data(reuse());
|
||||
data.resize(data.size()+number);
|
||||
|
||||
@@ -44,9 +45,11 @@ size_t PVStructureArray::append(size_t number)
|
||||
|
||||
bool PVStructureArray::remove(size_t offset,size_t number)
|
||||
{
|
||||
if(number==0)
|
||||
if (number==0)
|
||||
return true;
|
||||
else if(offset+number>getLength())
|
||||
else if (offset+number>getLength())
|
||||
return false;
|
||||
else if (getArray()->getArraySizeType() == Array::fixed)
|
||||
return false;
|
||||
|
||||
svector vec(reuse());
|
||||
@@ -65,6 +68,9 @@ bool PVStructureArray::remove(size_t offset,size_t number)
|
||||
}
|
||||
|
||||
void PVStructureArray::compress() {
|
||||
if (getArray()->getArraySizeType() == Array::fixed)
|
||||
return;
|
||||
|
||||
svector vec(reuse()); // TODO: check for first NULL before realloc
|
||||
|
||||
size_t length = vec.size();
|
||||
@@ -99,7 +105,8 @@ void PVStructureArray::compress() {
|
||||
|
||||
void PVStructureArray::setCapacity(size_t capacity)
|
||||
{
|
||||
if(this->isCapacityMutable()) {
|
||||
if (this->isCapacityMutable()) {
|
||||
checkLength(capacity);
|
||||
const_svector value;
|
||||
swap(value);
|
||||
if(value.capacity()<capacity) {
|
||||
@@ -109,17 +116,23 @@ void PVStructureArray::setCapacity(size_t capacity)
|
||||
}
|
||||
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");
|
||||
THROW_EXCEPTION2(std::logic_error, "immutable");
|
||||
const_svector value;
|
||||
swap(value);
|
||||
if(length == value.size()) {
|
||||
// nothing
|
||||
} else if(length < value.size()) {
|
||||
|
||||
if (length == value.size())
|
||||
return;
|
||||
|
||||
checkLength(length);
|
||||
|
||||
if (length < value.size()) {
|
||||
value.slice(0, length);
|
||||
} else {
|
||||
svector mvalue(thaw(value));
|
||||
@@ -131,8 +144,10 @@ void PVStructureArray::setLength(size_t length)
|
||||
|
||||
void PVStructureArray::swap(const_svector &other)
|
||||
{
|
||||
if(this->isImmutable())
|
||||
THROW_EXCEPTION2(std::logic_error,"Immutable");
|
||||
if (this->isImmutable())
|
||||
THROW_EXCEPTION2(std::logic_error, "immutable");
|
||||
|
||||
// no checkLength call here
|
||||
|
||||
value.swap(other);
|
||||
}
|
||||
@@ -146,7 +161,10 @@ void PVStructureArray::deserialize(ByteBuffer *pbuffer,
|
||||
DeserializableControl *pcontrol) {
|
||||
svector data(reuse());
|
||||
|
||||
size_t size = SerializeHelper::readSize(pbuffer, pcontrol);
|
||||
size_t size = this->getArray()->getArraySizeType() == Array::fixed ?
|
||||
this->getArray()->getMaximumCapacity() :
|
||||
SerializeHelper::readSize(pbuffer, pcontrol);
|
||||
|
||||
data.resize(size);
|
||||
|
||||
StructureConstPtr structure = structureArray->getStructure();
|
||||
@@ -160,7 +178,7 @@ void PVStructureArray::deserialize(ByteBuffer *pbuffer,
|
||||
data[i].reset();
|
||||
}
|
||||
else {
|
||||
if(data[i].get()==NULL) {
|
||||
if(data[i].get()==NULL || !data[i].unique()) {
|
||||
data[i] = pvDataCreate->createPVStructure(structure);
|
||||
}
|
||||
data[i]->deserialize(pbuffer, pcontrol);
|
||||
@@ -175,7 +193,11 @@ void PVStructureArray::serialize(ByteBuffer *pbuffer,
|
||||
const_svector temp(view());
|
||||
temp.slice(offset, count);
|
||||
|
||||
SerializeHelper::writeSize(temp.size(), pbuffer, pflusher);
|
||||
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)
|
||||
@@ -209,9 +231,33 @@ std::ostream& PVStructureArray::dumpValue(std::ostream& o) const
|
||||
std::ostream& PVStructureArray::dumpValue(std::ostream& o, std::size_t index) const
|
||||
{
|
||||
const_svector temp(view());
|
||||
if(index<temp.size())
|
||||
o << *temp[index];
|
||||
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());
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/pvIntrospect.h>
|
||||
#include <pv/convert.h>
|
||||
#include <pv/factory.h>
|
||||
#include <pv/serializeHelper.h>
|
||||
|
||||
@@ -29,6 +28,8 @@ 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),
|
||||
@@ -87,7 +88,7 @@ PVFieldPtr PVUnion::select(int32 index)
|
||||
|
||||
FieldConstPtr field = unionPtr->getField(index);
|
||||
selector = index;
|
||||
value = getPVDataCreate()->createPVField(field);
|
||||
value = pvDataCreate->createPVField(field);
|
||||
|
||||
return value;
|
||||
}
|
||||
@@ -144,10 +145,10 @@ void PVUnion::serialize(ByteBuffer *pbuffer, SerializableControl *pflusher) cons
|
||||
if (variant)
|
||||
{
|
||||
// write introspection data
|
||||
if (value.get() == 0)
|
||||
if (value.get() == 0) {
|
||||
pflusher->ensureBuffer(1);
|
||||
pbuffer->put((int8)-1);
|
||||
else
|
||||
{
|
||||
}else {
|
||||
pflusher->cachedSerialize(value->getField(), pbuffer);
|
||||
value->serialize(pbuffer, pflusher);
|
||||
}
|
||||
@@ -169,7 +170,9 @@ void PVUnion::deserialize(ByteBuffer *pbuffer, DeserializableControl *pcontrol)
|
||||
FieldConstPtr field = pcontrol->cachedDeserialize(pbuffer);
|
||||
if (field.get())
|
||||
{
|
||||
value = getPVDataCreate()->createPVField(field);
|
||||
// try to reuse existing field instance
|
||||
if (!value.get() || *value->getField() != *field)
|
||||
value = pvDataCreate->createPVField(field);
|
||||
value->deserialize(pbuffer, pcontrol);
|
||||
}
|
||||
else
|
||||
@@ -177,11 +180,17 @@ void PVUnion::deserialize(ByteBuffer *pbuffer, DeserializableControl *pcontrol)
|
||||
}
|
||||
else
|
||||
{
|
||||
int32 previousSelector = selector;
|
||||
selector = static_cast<int32>(SerializeHelper::readSize(pbuffer, pcontrol));
|
||||
if (selector != UNDEFINED_INDEX)
|
||||
{
|
||||
FieldConstPtr field = unionPtr->getField(selector);
|
||||
value = getPVDataCreate()->createPVField(field);
|
||||
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
|
||||
@@ -209,4 +218,57 @@ std::ostream& PVUnion::dumpValue(std::ostream& o) const
|
||||
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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}}
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/convert.h>
|
||||
#include <pv/factory.h>
|
||||
#include <pv/serializeHelper.h>
|
||||
|
||||
@@ -25,6 +24,8 @@ namespace epics { namespace pvData {
|
||||
|
||||
size_t PVUnionArray::append(size_t number)
|
||||
{
|
||||
checkLength(value.size()+number);
|
||||
|
||||
svector data(reuse());
|
||||
data.resize(data.size()+number);
|
||||
|
||||
@@ -44,9 +45,11 @@ size_t PVUnionArray::append(size_t number)
|
||||
|
||||
bool PVUnionArray::remove(size_t offset,size_t number)
|
||||
{
|
||||
if(number==0)
|
||||
if (number==0)
|
||||
return true;
|
||||
else if(offset+number>getLength())
|
||||
else if (offset+number>getLength())
|
||||
return false;
|
||||
else if (getArray()->getArraySizeType() == Array::fixed)
|
||||
return false;
|
||||
|
||||
svector vec(reuse());
|
||||
@@ -65,6 +68,9 @@ bool PVUnionArray::remove(size_t offset,size_t number)
|
||||
}
|
||||
|
||||
void PVUnionArray::compress() {
|
||||
if (getArray()->getArraySizeType() == Array::fixed)
|
||||
return;
|
||||
|
||||
svector vec(reuse()); // TODO: check for first NULL before realloc
|
||||
|
||||
size_t length = vec.size();
|
||||
@@ -100,6 +106,7 @@ void PVUnionArray::compress() {
|
||||
void PVUnionArray::setCapacity(size_t capacity)
|
||||
{
|
||||
if(this->isCapacityMutable()) {
|
||||
checkLength(capacity);
|
||||
const_svector value;
|
||||
swap(value);
|
||||
if(value.capacity()<capacity) {
|
||||
@@ -109,17 +116,22 @@ void PVUnionArray::setCapacity(size_t capacity)
|
||||
}
|
||||
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");
|
||||
THROW_EXCEPTION2(std::logic_error, "immutable");
|
||||
const_svector value;
|
||||
swap(value);
|
||||
if(length == value.size()) {
|
||||
// nothing
|
||||
} else if(length < value.size()) {
|
||||
if (length == value.size())
|
||||
return;
|
||||
|
||||
checkLength(length);
|
||||
|
||||
if (length < value.size()) {
|
||||
value.slice(0, length);
|
||||
} else {
|
||||
svector mvalue(thaw(value));
|
||||
@@ -134,6 +146,8 @@ void PVUnionArray::swap(const_svector &other)
|
||||
if(this->isImmutable())
|
||||
THROW_EXCEPTION2(std::logic_error,"Immutable");
|
||||
|
||||
// no checkLength call here
|
||||
|
||||
value.swap(other);
|
||||
}
|
||||
|
||||
@@ -146,7 +160,10 @@ void PVUnionArray::deserialize(ByteBuffer *pbuffer,
|
||||
DeserializableControl *pcontrol) {
|
||||
svector data(reuse());
|
||||
|
||||
size_t size = SerializeHelper::readSize(pbuffer, pcontrol);
|
||||
size_t size = this->getArray()->getArraySizeType() == Array::fixed ?
|
||||
this->getArray()->getMaximumCapacity() :
|
||||
SerializeHelper::readSize(pbuffer, pcontrol);
|
||||
|
||||
data.resize(size);
|
||||
|
||||
UnionConstPtr punion = unionArray->getUnion();
|
||||
@@ -160,7 +177,7 @@ void PVUnionArray::deserialize(ByteBuffer *pbuffer,
|
||||
data[i].reset();
|
||||
}
|
||||
else {
|
||||
if(data[i].get()==NULL) {
|
||||
if(data[i].get()==NULL || !data[i].unique()) {
|
||||
data[i] = pvDataCreate->createPVUnion(punion);
|
||||
}
|
||||
data[i]->deserialize(pbuffer, pcontrol);
|
||||
@@ -175,7 +192,11 @@ void PVUnionArray::serialize(ByteBuffer *pbuffer,
|
||||
const_svector temp(view());
|
||||
temp.slice(offset, count);
|
||||
|
||||
SerializeHelper::writeSize(temp.size(), pbuffer, pflusher);
|
||||
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)
|
||||
@@ -209,9 +230,34 @@ std::ostream& PVUnionArray::dumpValue(std::ostream& o) const
|
||||
std::ostream& PVUnionArray::dumpValue(std::ostream& o, std::size_t index) const
|
||||
{
|
||||
const_svector temp(view());
|
||||
if(index<temp.size())
|
||||
o << *temp[index];
|
||||
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());
|
||||
}
|
||||
|
||||
|
||||
}}
|
||||
|
||||
@@ -89,9 +89,9 @@ StructureConstPtr StandardField::createProperties(string id,FieldConstPtr field,
|
||||
}
|
||||
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];
|
||||
@@ -162,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);
|
||||
@@ -228,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);
|
||||
@@ -255,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);
|
||||
@@ -282,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);
|
||||
@@ -309,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);
|
||||
@@ -336,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);
|
||||
@@ -363,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);
|
||||
@@ -390,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);
|
||||
@@ -417,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);
|
||||
@@ -444,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);
|
||||
@@ -471,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);
|
||||
@@ -503,28 +503,28 @@ StructureConstPtr StandardField::scalar(
|
||||
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("uri:ev4:nt/2012/pwd:NTUnion",field,properties);
|
||||
return createProperties("epics:nt/NTUnion:1.0",field,properties);
|
||||
}
|
||||
|
||||
StructureConstPtr StandardField::variantUnion(
|
||||
string const & properties)
|
||||
{
|
||||
UnionConstPtr field = fieldCreate->createVariantUnion();
|
||||
return createProperties("uri:ev4:nt/2012/pwd:NTUnion",field,properties);
|
||||
return createProperties("epics:nt/NTUnion:1.0",field,properties);
|
||||
}
|
||||
|
||||
StructureConstPtr StandardField::scalarArray(
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@@ -533,7 +533,7 @@ StructureConstPtr StandardField::structureArray(
|
||||
{
|
||||
StructureArrayConstPtr field = fieldCreate->createStructureArray(
|
||||
structure);
|
||||
return createProperties("uri:ev4:nt/2012/pwd:NTStructureArray",field,properties);
|
||||
return createProperties("epics:nt/NTStructureArray:1.0",field,properties);
|
||||
}
|
||||
|
||||
StructureConstPtr StandardField::unionArray(
|
||||
@@ -541,7 +541,7 @@ StructureConstPtr StandardField::unionArray(
|
||||
{
|
||||
UnionArrayConstPtr field = fieldCreate->createUnionArray(
|
||||
punion);
|
||||
return createProperties("uri:ev4:nt/2012/pwd:NTUnionArray",field,properties);
|
||||
return createProperties("epics:nt/NTUnionArray:1.0",field,properties);
|
||||
}
|
||||
|
||||
StructureConstPtr StandardField::enumerated()
|
||||
@@ -554,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 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()
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
#include <pv/lock.h>
|
||||
#include <pv/pvIntrospect.h>
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/convert.h>
|
||||
#include <pv/standardField.h>
|
||||
#include <pv/standardPVField.h>
|
||||
|
||||
@@ -67,11 +66,9 @@ PVStructurePtr StandardPVField::enumerated(StringArray const &choices)
|
||||
{
|
||||
StructureConstPtr field = standardField->enumerated();
|
||||
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(field);
|
||||
PVScalarArrayPtr pvScalarArray = pvStructure->getScalarArrayField(
|
||||
"choices",pvString);
|
||||
PVStringArray::svector cdata(choices.size());
|
||||
std::copy(choices.begin(), choices.end(), cdata.begin());
|
||||
static_cast<PVStringArray&>(*pvScalarArray).replace(freeze(cdata));
|
||||
pvStructure->getSubField<PVStringArray>("choices")->replace(freeze(cdata));
|
||||
return pvStructure;
|
||||
}
|
||||
|
||||
@@ -80,11 +77,9 @@ PVStructurePtr StandardPVField::enumerated(
|
||||
{
|
||||
StructureConstPtr field = standardField->enumerated(properties);
|
||||
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(field);
|
||||
PVScalarArrayPtr pvScalarArray = pvStructure->getScalarArrayField(
|
||||
"value.choices",pvString);
|
||||
PVStringArray::svector cdata(choices.size());
|
||||
std::copy(choices.begin(), choices.end(), cdata.begin());
|
||||
static_cast<PVStringArray&>(*pvScalarArray).replace(freeze(cdata));
|
||||
pvStructure->getSubField<PVStringArray>("value.choices")->replace(freeze(cdata));
|
||||
return pvStructure;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,25 +8,22 @@
|
||||
#include <deque>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/printer.h>
|
||||
#include <pv/pvIntrospect.h>
|
||||
|
||||
using std::string;
|
||||
|
||||
namespace {
|
||||
|
||||
void indentN(std::ostream& strm, size_t N)
|
||||
{
|
||||
while(N--)
|
||||
strm.put(' ');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
namespace format
|
||||
{
|
||||
std::ostream& operator<<(std::ostream& os, indent_level const& indent)
|
||||
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;
|
||||
@@ -45,246 +42,4 @@ namespace format
|
||||
}
|
||||
};
|
||||
|
||||
PrinterBase::PrinterBase()
|
||||
:strm(NULL)
|
||||
{}
|
||||
|
||||
PrinterBase::~PrinterBase() {}
|
||||
|
||||
void PrinterBase::setStream(std::ostream& s)
|
||||
{
|
||||
strm = &s;
|
||||
}
|
||||
|
||||
void PrinterBase::clearStream()
|
||||
{
|
||||
strm = NULL;
|
||||
}
|
||||
|
||||
void PrinterBase::print(const PVField& pv)
|
||||
{
|
||||
if(!strm)
|
||||
throw std::runtime_error("No stream set for PV Printer");
|
||||
impl_print(pv);
|
||||
}
|
||||
|
||||
void PrinterBase::beginStructure(const PVStructure&) {}
|
||||
void PrinterBase::endStructure(const PVStructure&) {}
|
||||
|
||||
void PrinterBase::beginStructureArray(const PVStructureArray&) {}
|
||||
void PrinterBase::endStructureArray(const PVStructureArray&) {}
|
||||
|
||||
void PrinterBase::beginUnion(const PVUnion&) {}
|
||||
void PrinterBase::endUnion(const PVUnion&) {}
|
||||
|
||||
void PrinterBase::beginUnionArray(const PVUnionArray&) {}
|
||||
void PrinterBase::endUnionArray(const PVUnionArray&) {}
|
||||
|
||||
void PrinterBase::encodeScalar(const PVScalar&) {}
|
||||
|
||||
void PrinterBase::encodeArray(const PVScalarArray&) {}
|
||||
|
||||
void PrinterBase::encodeNull() {}
|
||||
|
||||
void PrinterBase::impl_print(const PVField& pv)
|
||||
{
|
||||
static const PVField* marker = (const PVField*)▮
|
||||
|
||||
/* Depth first recursive iteration.
|
||||
* Each PV to be printed is appended to the todo queue.
|
||||
* The last child of a structure is followed by a NULL.
|
||||
* As the tree is walked structures and structarrays
|
||||
* are appended to the inprog queue.
|
||||
*/
|
||||
std::deque<const PVField*> todo, inprog;
|
||||
|
||||
todo.push_back(&pv);
|
||||
|
||||
while(!todo.empty()) {
|
||||
const PVField *next = todo.front();
|
||||
todo.pop_front();
|
||||
|
||||
if(next==marker) {
|
||||
// finished with a structure or structarray,
|
||||
// now we fall back to its parent.
|
||||
assert(!inprog.empty());
|
||||
switch(inprog.back()->getField()->getType()) {
|
||||
case structure:
|
||||
endStructure(*static_cast<const PVStructure *>(inprog.back()));
|
||||
break;
|
||||
|
||||
case structureArray:
|
||||
endStructureArray(*static_cast<const PVStructureArray *>(inprog.back()));
|
||||
break;
|
||||
|
||||
case union_:
|
||||
endUnion(*static_cast<const PVUnion *>(inprog.back()));
|
||||
break;
|
||||
|
||||
case unionArray:
|
||||
endUnionArray(*static_cast<const PVUnionArray *>(inprog.back()));
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(false); // oops!
|
||||
return;
|
||||
}
|
||||
inprog.pop_back();
|
||||
|
||||
} else {
|
||||
// real field
|
||||
|
||||
if(!next) {
|
||||
// NULL entry in a structure array
|
||||
encodeNull();
|
||||
continue;
|
||||
}
|
||||
|
||||
switch(next->getField()->getType()) {
|
||||
case scalar:
|
||||
encodeScalar(*static_cast<const PVScalar*>(next));
|
||||
break;
|
||||
case scalarArray:
|
||||
encodeArray(*static_cast<const PVScalarArray*>(next));
|
||||
break;
|
||||
case structure: {
|
||||
const PVStructure &fld = *static_cast<const PVStructure*>(next);
|
||||
const PVFieldPtrArray& vals = fld.getPVFields();
|
||||
|
||||
inprog.push_back(next);
|
||||
|
||||
beginStructure(fld);
|
||||
for(size_t i=0, nfld=fld.getStructure()->getNumberFields(); i<nfld; i++)
|
||||
todo.push_back(vals[i].get());
|
||||
|
||||
todo.push_back(marker);
|
||||
break;
|
||||
}
|
||||
case structureArray: {
|
||||
const PVStructureArray &fld = *static_cast<const PVStructureArray*>(next);
|
||||
PVStructureArray::const_svector vals(fld.view());
|
||||
|
||||
inprog.push_back(next);
|
||||
|
||||
beginStructureArray(fld);
|
||||
for(PVStructureArray::const_svector::const_iterator it=vals.begin();
|
||||
it!=vals.end(); ++it)
|
||||
{
|
||||
todo.push_back(it->get());
|
||||
}
|
||||
|
||||
todo.push_back(marker);
|
||||
break;
|
||||
}
|
||||
case union_: {
|
||||
const PVUnion &fld = *static_cast<const PVUnion*>(next);
|
||||
|
||||
inprog.push_back(next);
|
||||
|
||||
beginUnion(fld);
|
||||
PVFieldPtr val = fld.get();
|
||||
if (val.get()) // TODO print "(none)" ?
|
||||
todo.push_back(val.get());
|
||||
|
||||
todo.push_back(marker);
|
||||
break;
|
||||
}
|
||||
case unionArray: {
|
||||
const PVUnionArray &fld = *static_cast<const PVUnionArray*>(next);
|
||||
PVUnionArray::const_svector vals(fld.view());
|
||||
|
||||
inprog.push_back(next);
|
||||
|
||||
beginUnionArray(fld);
|
||||
for(PVUnionArray::const_svector::const_iterator it=vals.begin();
|
||||
it!=vals.end(); ++it)
|
||||
{
|
||||
todo.push_back(it->get());
|
||||
}
|
||||
|
||||
todo.push_back(marker);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PrinterPlain::PrinterPlain()
|
||||
:PrinterBase()
|
||||
,ilvl(0)
|
||||
{}
|
||||
|
||||
PrinterPlain::~PrinterPlain() {}
|
||||
|
||||
void PrinterPlain::beginStructure(const PVStructure& pv)
|
||||
{
|
||||
indentN(S(), ilvl);
|
||||
S() << pv.getStructure()->getID() << " " << pv.getFieldName();
|
||||
S() << std::endl;
|
||||
ilvl++;
|
||||
}
|
||||
|
||||
void PrinterPlain::endStructure(const PVStructure&) {ilvl--;}
|
||||
|
||||
void PrinterPlain::beginStructureArray(const PVStructureArray& pv)
|
||||
{
|
||||
indentN(S(), ilvl);
|
||||
S() << pv.getStructureArray()->getID() << " "
|
||||
<< pv.getFieldName() << "[] ";
|
||||
ilvl++;
|
||||
}
|
||||
|
||||
void PrinterPlain::endStructureArray(const PVStructureArray&) {ilvl--;}
|
||||
|
||||
void PrinterPlain::beginUnion(const PVUnion& pv)
|
||||
{
|
||||
indentN(S(), ilvl);
|
||||
S() << pv.getUnion()->getID() << " " << pv.getFieldName() << std::endl;
|
||||
ilvl++;
|
||||
}
|
||||
|
||||
void PrinterPlain::endUnion(const PVUnion&) {ilvl--;}
|
||||
|
||||
void PrinterPlain::beginUnionArray(const PVUnionArray& pv)
|
||||
{
|
||||
indentN(S(), ilvl);
|
||||
S() << pv.getUnionArray()->getID() << " "
|
||||
<< pv.getFieldName() << "[] ";
|
||||
ilvl++;
|
||||
}
|
||||
|
||||
void PrinterPlain::endUnionArray(const PVUnionArray&) {ilvl--;}
|
||||
|
||||
void PrinterPlain::encodeScalar(const PVScalar& pv)
|
||||
{
|
||||
indentN(S(), ilvl);
|
||||
S() << pv.getScalar()->getID() << " "
|
||||
<< pv.getFieldName() << " "
|
||||
<< pv.getAs<string>() << std::endl;
|
||||
}
|
||||
|
||||
void PrinterPlain::encodeArray(const PVScalarArray& pv)
|
||||
{
|
||||
indentN(S(), ilvl);
|
||||
shared_vector<const string> temp;
|
||||
pv.getAs<string>(temp);
|
||||
|
||||
S() << pv.getScalarArray()->getID() << " "
|
||||
<< pv.getFieldName() << " [";
|
||||
for(size_t i=0, len=pv.getLength(); i<len; i++) {
|
||||
S() << temp[i];
|
||||
if(i!=len-1)
|
||||
S().put(',');
|
||||
}
|
||||
S() << "]" << std::endl;
|
||||
}
|
||||
|
||||
void PrinterPlain::encodeNull()
|
||||
{
|
||||
indentN(S(), ilvl);
|
||||
S() << "NULL" << std::endl;
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
@@ -22,7 +22,6 @@ INC += status.h
|
||||
INC += sharedPtr.h
|
||||
INC += localStaticLock.h
|
||||
INC += typeCast.h
|
||||
INC += printer.h
|
||||
INC += sharedVector.h
|
||||
INC += templateMeta.h
|
||||
INC += current_function.h
|
||||
|
||||
@@ -279,7 +279,8 @@ namespace epics { namespace pvData {
|
||||
uint32 inUse = (set1.wordsInUse < set2.wordsInUse) ? set1.wordsInUse : set2.wordsInUse;
|
||||
|
||||
ensureCapacity(inUse);
|
||||
wordsInUse = inUse;
|
||||
if(inUse>wordsInUse)
|
||||
wordsInUse = inUse;
|
||||
|
||||
// Perform logical AND on words in common
|
||||
for (uint32 i = 0; i < inUse; i++)
|
||||
@@ -322,12 +323,14 @@ namespace epics { namespace pvData {
|
||||
|
||||
SerializeHelper::writeSize(len, buffer, flusher);
|
||||
flusher->ensureBuffer(len);
|
||||
|
||||
for (uint32 i = 0; i < n - 1; i++)
|
||||
|
||||
n = len / 8;
|
||||
for (uint32 i = 0; i < n; i++)
|
||||
buffer->putLong(words[i]);
|
||||
|
||||
for (uint64 x = words[n - 1]; x != 0; x >>= 8)
|
||||
buffer->putByte((int8) (x & 0xff));
|
||||
|
||||
if (n < wordsInUse)
|
||||
for (uint64 x = words[wordsInUse - 1]; x != 0; x >>= 8)
|
||||
buffer->putByte((int8) (x & 0xff));
|
||||
}
|
||||
|
||||
void BitSet::deserialize(ByteBuffer* buffer, DeserializableControl* control) {
|
||||
@@ -356,7 +359,7 @@ namespace epics { namespace pvData {
|
||||
words[j] = 0;
|
||||
|
||||
for (uint32 remaining = (bytes - longs * 8), j = 0; j < remaining; j++)
|
||||
words[i] |= (buffer->getByte() & 0xffL) << (8 * j);
|
||||
words[i] |= (buffer->getByte() & 0xffLL) << (8 * j);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -24,16 +24,18 @@ namespace epics { namespace pvData {
|
||||
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
|
||||
@@ -41,8 +43,8 @@ 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.
|
||||
*/
|
||||
@@ -51,14 +53,14 @@ namespace epics { namespace pvData {
|
||||
POINTER_DEFINITIONS(BitSet);
|
||||
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
|
||||
*/
|
||||
@@ -78,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
|
||||
*/
|
||||
@@ -101,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
|
||||
@@ -111,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
|
||||
@@ -129,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)
|
||||
@@ -144,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
|
||||
@@ -170,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
|
||||
*/
|
||||
@@ -181,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
|
||||
*/
|
||||
@@ -192,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
|
||||
@@ -206,7 +207,7 @@ namespace epics { namespace pvData {
|
||||
BitSet& operator^=(const BitSet& set);
|
||||
|
||||
/**
|
||||
* Assigment operator.
|
||||
* Assignment operator.
|
||||
*/
|
||||
BitSet& operator=(const BitSet &set);
|
||||
|
||||
|
||||
@@ -144,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)
|
||||
{
|
||||
@@ -188,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.
|
||||
@@ -354,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.
|
||||
@@ -368,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.
|
||||
@@ -380,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");
|
||||
@@ -393,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");
|
||||
@@ -403,7 +422,7 @@ 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.
|
||||
@@ -412,7 +431,7 @@ public:
|
||||
template<typename T>
|
||||
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.
|
||||
@@ -618,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); }
|
||||
@@ -695,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;
|
||||
@@ -738,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;
|
||||
@@ -786,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);
|
||||
@@ -838,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));
|
||||
@@ -890,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++)
|
||||
@@ -918,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++)
|
||||
|
||||
@@ -18,7 +18,8 @@ namespace epics { namespace pvData {
|
||||
|
||||
|
||||
/**
|
||||
* Instance declaring destroy method.
|
||||
* @brief Instance declaring destroy method.
|
||||
*
|
||||
* @author mse
|
||||
*/
|
||||
class epicsShareClass Destroyable {
|
||||
|
||||
@@ -202,13 +202,26 @@ do { \
|
||||
#define THROW_EXCEPTION2(E,A) do{throw (E)(A);}while(0)
|
||||
|
||||
#endif // THROW_EXCEPTION_COMPAT
|
||||
|
||||
/**
|
||||
* @brief Base for pvData exceptions.
|
||||
*
|
||||
*/
|
||||
class epicsShareClass BaseException : public std::logic_error {
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
explicit BaseException(const std::string msg) : std::logic_error(msg) {}
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
virtual ~BaseException() throw(){};
|
||||
|
||||
/**
|
||||
*
|
||||
* Reason for excepton.
|
||||
*/
|
||||
virtual const char* what() const throw();
|
||||
|
||||
private:
|
||||
|
||||
@@ -38,8 +38,7 @@ Event::~Event() {
|
||||
|
||||
|
||||
Event::Event(bool full)
|
||||
: id(epicsEventCreate(full?epicsEventFull : epicsEventEmpty)),
|
||||
alreadyOn("already on list")
|
||||
: id(epicsEventCreate(full?epicsEventFull : epicsEventEmpty))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -35,18 +35,44 @@ namespace epics { namespace pvData {
|
||||
class Event;
|
||||
typedef std::tr1::shared_ptr<Event> EventPtr;
|
||||
|
||||
/**
|
||||
* @brief C++ wrapper for epicsEvent from EPICS base.
|
||||
*
|
||||
*/
|
||||
class epicsShareClass Event {
|
||||
public:
|
||||
POINTER_DEFINITIONS(Event);
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
explicit Event(bool = false);
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
~Event();
|
||||
/**
|
||||
* Signal the event i.e. ensures that the next or current call to wait completes.
|
||||
*/
|
||||
void signal();
|
||||
/**
|
||||
* wait
|
||||
* @return (false,true) if (some error, event signaled).
|
||||
* The next wait or tryWait will clear signal.
|
||||
*/
|
||||
bool wait (); /* blocks until full */
|
||||
/**
|
||||
* wait for up to timeOut seconds.
|
||||
* @param timeOut max number of seconds to wait
|
||||
* @return (false, true) if (timeout or error, event signaled).
|
||||
*/
|
||||
bool wait ( double timeOut ); /* false if empty at time out */
|
||||
/**
|
||||
* See if a signal has been called.
|
||||
* @return (false, true) if (timeout or error, event signaled).
|
||||
*/
|
||||
bool tryWait (); /* false if empty */
|
||||
private:
|
||||
epicsEventId id;
|
||||
std::string alreadyOn;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
@@ -54,14 +54,14 @@ void Executor::run()
|
||||
{
|
||||
Lock xx(mutex);
|
||||
while(true) {
|
||||
while(head.get()==NULL) {
|
||||
while(!head.get()) {
|
||||
xx.unlock();
|
||||
moreWork.wait();
|
||||
xx.lock();
|
||||
}
|
||||
CommandPtr command = head;
|
||||
head = command->next;
|
||||
if(command.get()==NULL) continue;
|
||||
if(!command.get()) continue;
|
||||
if(command.get()==shutdown.get()) break;
|
||||
xx.unlock();
|
||||
try {
|
||||
@@ -82,13 +82,13 @@ void Executor::execute(CommandPtr const & command)
|
||||
{
|
||||
Lock xx(mutex);
|
||||
command->next.reset();
|
||||
if(head.get()==NULL) {
|
||||
if(!head.get()) {
|
||||
head = command;
|
||||
moreWork.signal();
|
||||
return;
|
||||
}
|
||||
CommandPtr tail = head;
|
||||
while(tail->next!=NULL) tail = tail->next;
|
||||
while(tail->next) tail = tail->next;
|
||||
tail->next = command;
|
||||
}
|
||||
|
||||
|
||||
@@ -27,22 +27,56 @@ class Executor;
|
||||
typedef std::tr1::shared_ptr<Command> CommandPtr;
|
||||
typedef std::tr1::shared_ptr<Executor> ExecutorPtr;
|
||||
|
||||
/**
|
||||
* @brief A command to be called by Executor
|
||||
*
|
||||
*/
|
||||
class epicsShareClass Command {
|
||||
public:
|
||||
POINTER_DEFINITIONS(Command);
|
||||
/**
|
||||
*
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~Command(){}
|
||||
/**
|
||||
*
|
||||
* The command that is executed.
|
||||
*/
|
||||
virtual void command() = 0;
|
||||
private:
|
||||
CommandPtr next;
|
||||
friend class Executor;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A class that executes commands.
|
||||
*
|
||||
*/
|
||||
class epicsShareClass Executor : public Runnable{
|
||||
public:
|
||||
POINTER_DEFINITIONS(Executor);
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param threadName name for the executor thread.
|
||||
* @param priority The thread priority.
|
||||
*/
|
||||
Executor(std::string const & threadName,ThreadPriority priority);
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~Executor();
|
||||
void execute(CommandPtr const &node);
|
||||
/**
|
||||
*
|
||||
* Request to execute a command.
|
||||
* @param command A shared pointer to the command instance.
|
||||
*/
|
||||
void execute(CommandPtr const &command);
|
||||
/**
|
||||
*
|
||||
* The thread run method.
|
||||
*/
|
||||
virtual void run();
|
||||
private:
|
||||
CommandPtr head;
|
||||
|
||||
@@ -38,12 +38,30 @@ namespace epics { namespace pvData {
|
||||
|
||||
typedef epicsMutex Mutex;
|
||||
|
||||
/**
|
||||
* @brief A lock for multithreading
|
||||
*
|
||||
* This is based on item 14 of
|
||||
* * Effective C++, Third Edition, Scott Meyers
|
||||
*/
|
||||
class epicsShareClass Lock : private NoDefaultMethods {
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
* @param m The mutex for the facility being locked.
|
||||
*/
|
||||
explicit Lock(Mutex &m)
|
||||
: mutexPtr(m), locked(true)
|
||||
{ mutexPtr.lock();}
|
||||
/**
|
||||
* Destructor
|
||||
* Note that destructor does an automatic unlock.
|
||||
*/
|
||||
~Lock(){unlock();}
|
||||
/**
|
||||
* Take the lock
|
||||
* Recursive locks are supported but each lock must be matched with an unlock.
|
||||
*/
|
||||
void lock()
|
||||
{
|
||||
if(!locked)
|
||||
@@ -52,6 +70,9 @@ public:
|
||||
locked = true;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* release the lock.
|
||||
*/
|
||||
void unlock()
|
||||
{
|
||||
if(locked)
|
||||
@@ -60,6 +81,10 @@ public:
|
||||
locked=false;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* If lock is not held take the lock.
|
||||
* @return (false,true) if caller (does not have, has) the lock.
|
||||
*/
|
||||
bool tryLock()
|
||||
{
|
||||
if(locked) return true;
|
||||
@@ -69,6 +94,10 @@ public:
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* See if caller has the lock,
|
||||
* @return (false,true) if caller (does not have, has) the lock.
|
||||
*/
|
||||
bool ownsLock() const{return locked;}
|
||||
private:
|
||||
Mutex &mutexPtr;
|
||||
|
||||
@@ -28,10 +28,26 @@ typedef std::tr1::shared_ptr<MessageNode> MessageNodePtr;
|
||||
typedef std::vector<MessageNodePtr> MessageNodePtrArray;
|
||||
typedef std::tr1::shared_ptr<MessageQueue> MessageQueuePtr;
|
||||
|
||||
/**
|
||||
* @brief A node that can be put on a MessageQueue.
|
||||
*
|
||||
*/
|
||||
class epicsShareClass MessageNode {
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
MessageNode();
|
||||
/**
|
||||
*
|
||||
* Get the message value.
|
||||
* @return The message value.
|
||||
*/
|
||||
std::string getMessage() const;
|
||||
/**
|
||||
* Get the message type.
|
||||
* @return The message type which is defined in Requester.
|
||||
*/
|
||||
MessageType getMessageType() const;
|
||||
private:
|
||||
std::string message;
|
||||
@@ -39,19 +55,65 @@ private:
|
||||
friend class MessageQueue;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A bounded queue for messages.
|
||||
*
|
||||
*
|
||||
*/
|
||||
class epicsShareClass MessageQueue : public Queue<MessageNode> {
|
||||
public:
|
||||
POINTER_DEFINITIONS(MessageQueue);
|
||||
/**
|
||||
* Factory method to create a MessageQueue.
|
||||
* @param size The number of MessageNodes in the queue.
|
||||
* @return shared_ptr to MessageQueue.
|
||||
*/
|
||||
static MessageQueuePtr create(int size);
|
||||
/**
|
||||
* Constructor
|
||||
* @param nodeArray an array of shared_ptr to MessageNodes,
|
||||
*/
|
||||
MessageQueue(MessageNodePtrArray &nodeArray);
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~MessageQueue();
|
||||
/**
|
||||
* get the next MessageNode of the queue.
|
||||
* @return A shared_ptr to the MessageNode.
|
||||
* This will be a null pointer if queue is empty.
|
||||
* If get is successful then release for this MessageNode
|
||||
* must be called before another get can be issued.
|
||||
*/
|
||||
MessageNodePtr &get();
|
||||
// must call release before next get
|
||||
/**
|
||||
* Release the MessageNode that was returned by the previous call to get.
|
||||
*/
|
||||
void release();
|
||||
// return (false,true) if message (was not, was) put into queue
|
||||
/**
|
||||
*
|
||||
* put a message into the message queue
|
||||
* @param message The message string.
|
||||
* @param messageType The message type as defined in Requester,
|
||||
* @param replaceLast If true and queue is full then replace.
|
||||
* @return (false,true) if a message (was not, was) put in queiue.
|
||||
*/
|
||||
bool put(std::string message,MessageType messageType,bool replaceLast);
|
||||
/**
|
||||
* Is queue empty?
|
||||
* @return (false,true) if (is not, is) empty.
|
||||
*/
|
||||
bool isEmpty() ;
|
||||
/**
|
||||
* Is queue full?
|
||||
* @return (false,true) if (is not, is) full.
|
||||
*/
|
||||
bool isFull() ;
|
||||
/**
|
||||
*
|
||||
* Clear number of times queue was overrun and return the number
|
||||
* of times the queue was overrun.
|
||||
*/
|
||||
int getClearOverrun();
|
||||
private:
|
||||
MessageNodePtr nullNode;
|
||||
|
||||
@@ -17,17 +17,26 @@ namespace epics { namespace pvData {
|
||||
* Effective C++, Third Edition, Scott Meyers
|
||||
*/
|
||||
|
||||
|
||||
class epicsShareClass NoDefaultMethods {
|
||||
protected:
|
||||
// allow by derived objects
|
||||
/**
|
||||
* @brief Base class for not allowing default methods.
|
||||
*
|
||||
* Note that copy constructor a copy methods are declared private.
|
||||
*/
|
||||
class epicsShareClass NoDefaultMethods {
|
||||
protected:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
NoDefaultMethods(){};
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~NoDefaultMethods(){}
|
||||
private:
|
||||
// do not implment
|
||||
// do not implement
|
||||
NoDefaultMethods(const NoDefaultMethods&);
|
||||
NoDefaultMethods & operator=(const NoDefaultMethods &);
|
||||
};
|
||||
};
|
||||
|
||||
}}
|
||||
#endif /* NO_DEFAULT_METHODS_H */
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
using std::string;
|
||||
|
||||
// need to use "long long" when sizeof(int)==sizeof(long)
|
||||
#if (ULONG_MAX == 0xfffffffful) || defined(_WIN32) || defined(__rtems__)
|
||||
#if (ULONG_MAX == 0xfffffffful) || defined(_WIN32) || defined(__rtems__) || defined(__APPLE__)
|
||||
#define NEED_LONGLONG
|
||||
#endif
|
||||
|
||||
@@ -27,7 +27,7 @@ using std::string;
|
||||
#endif
|
||||
|
||||
#if EPICS_VERSION_INT < VERSION_INT(3,15,0,1)
|
||||
/* integer conversion primatives added to epicsStdlib.c in 3.15.0.1 */
|
||||
/* integer conversion primitives added to epicsStdlib.c in 3.15.0.1 */
|
||||
|
||||
#define S_stdlib_noConversion 1 /* No digits to convert */
|
||||
#define S_stdlib_extraneous 2 /* Extraneous characters */
|
||||
@@ -249,7 +249,18 @@ epicsParseFloat(const char *str, float *to, char **units)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(NEED_LONGLONG) && (defined(__vxworks) || defined (_WIN32))
|
||||
// MS Visual Studio 2013 defines strtoll, etc.
|
||||
#if defined(_WIN32)
|
||||
# if (_MSC_VER >= 1800)
|
||||
# define WIN_NEEDS_OLL_FUNC 0
|
||||
# else
|
||||
# define WIN_NEEDS_OLL_FUNC 1
|
||||
# endif
|
||||
#else
|
||||
# define WIN_NEEDS_OLL_FUNC 0
|
||||
#endif
|
||||
|
||||
#if defined(NEED_LONGLONG) && (defined(__vxworks) || WIN_NEEDS_OLL_FUNC)
|
||||
static
|
||||
long long strtoll(const char *ptr, char ** endp, int base)
|
||||
{
|
||||
@@ -297,6 +308,71 @@ noconvert:
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(__vxworks)
|
||||
/* vxworks version of std::istringstream >>uint64_t is buggy, we use out own implementation */
|
||||
static
|
||||
unsigned long long strtoull(const char *nptr, char **endptr, int base)
|
||||
{
|
||||
const char *s = nptr;
|
||||
unsigned long long acc;
|
||||
int c;
|
||||
unsigned long long cutoff;
|
||||
int neg = 0, any, cutlim;
|
||||
|
||||
do
|
||||
c = *s++;
|
||||
while (isspace(c));
|
||||
if (c == '-')
|
||||
{
|
||||
neg = 1;
|
||||
c = *s++;
|
||||
}
|
||||
else if (c == '+')
|
||||
c = *s++;
|
||||
if ((base == 0 || base == 16) &&
|
||||
c == '0' && (*s == 'x' || *s == 'X'))
|
||||
{
|
||||
c = s[1];
|
||||
s += 2;
|
||||
base = 16;
|
||||
}
|
||||
if (base == 0)
|
||||
base = c == '0' ? 8 : 10;
|
||||
|
||||
cutoff = (unsigned long long) UINT64_MAX / (unsigned long long) base;
|
||||
cutlim = (unsigned long long) UINT64_MAX % (unsigned long long) base;
|
||||
|
||||
for (acc = 0, any = 0;; c = *s++)
|
||||
{
|
||||
if (isdigit(c))
|
||||
c -= '0';
|
||||
else if (isalpha(c))
|
||||
c -= isupper(c) ? 'A' - 10 : 'a' - 10;
|
||||
else
|
||||
break;
|
||||
if (c >= base)
|
||||
break;
|
||||
if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
|
||||
any = -1;
|
||||
else
|
||||
{
|
||||
any = 1;
|
||||
acc *= base;
|
||||
acc += c;
|
||||
}
|
||||
}
|
||||
if (any < 0)
|
||||
{
|
||||
acc = UINT64_MAX;
|
||||
errno = ERANGE;
|
||||
}
|
||||
else if (neg)
|
||||
acc = -acc;
|
||||
if (endptr != 0)
|
||||
*endptr = any ? (char *) s - 1 : (char *) nptr;
|
||||
return (acc);
|
||||
}
|
||||
#else
|
||||
static
|
||||
unsigned long long strtoull(const char *ptr, char ** endp, int base)
|
||||
{
|
||||
@@ -339,7 +415,7 @@ noconvert:
|
||||
*endp = (char*)ptr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* do we need long long? */
|
||||
@@ -475,6 +551,26 @@ void parseToPOD(const string& in, float *out) {
|
||||
void parseToPOD(const string& in, double *out) {
|
||||
int err = epicsParseDouble(in.c_str(), out, NULL);
|
||||
if(err) handleParseError(err);
|
||||
#if defined(__vxworks)
|
||||
/* vxWorks strtod returns [-]epicsINF when it should return ERANGE error
|
||||
* if [-]epicsINF is returned and first char is a digit then translate this into ERANGE error
|
||||
*/
|
||||
else if (*out == epicsINF || *out == -epicsINF) {
|
||||
const char* s = in.c_str();
|
||||
int c;
|
||||
|
||||
/* skip spaces and the sign */
|
||||
do {
|
||||
c = *s++;
|
||||
} while (isspace(c));
|
||||
|
||||
if (c == '-' || c == '+')
|
||||
c = *s++;
|
||||
|
||||
if (isdigit(c))
|
||||
handleParseError(S_stdlib_overflow);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
}}}
|
||||
|
||||
@@ -18,6 +18,12 @@
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
/**
|
||||
* @brief Template class for a bounded queue.
|
||||
*
|
||||
* An instance can make a queueElement be any class desired
|
||||
* but must create a std::vector of shared_ptr to queueElements.
|
||||
*/
|
||||
template <typename T>
|
||||
class Queue
|
||||
{
|
||||
@@ -25,15 +31,58 @@ public:
|
||||
POINTER_DEFINITIONS(Queue);
|
||||
typedef std::tr1::shared_ptr<T> queueElementPtr;
|
||||
typedef std::vector<queueElementPtr> queueElementPtrArray;
|
||||
Queue(queueElementPtrArray &);
|
||||
/**
|
||||
* Constructor
|
||||
* @param elementArray The vector of shared_ptr to queue elements.
|
||||
*/
|
||||
Queue(queueElementPtrArray & elementArray);
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~Queue();
|
||||
/**
|
||||
* Clear the queue.
|
||||
*/
|
||||
void clear();
|
||||
/**
|
||||
* get the capacity of the queue, i. e. number of queue elements,
|
||||
* @return The capacity.
|
||||
*/
|
||||
int capacity();
|
||||
/**
|
||||
* Get the number of free elements in the queue.
|
||||
* @return The number.
|
||||
*/
|
||||
int getNumberFree();
|
||||
/**
|
||||
* Get the number of used elements in the queue.
|
||||
* This is the number that have been setUsed but not released.
|
||||
* @return The number.
|
||||
*/
|
||||
int getNumberUsed();
|
||||
/**
|
||||
* Get the next free element.
|
||||
* @return a shared_ptr to the queue element.
|
||||
* This is null if queue was full.
|
||||
*/
|
||||
queueElementPtr & getFree();
|
||||
/**
|
||||
* Set the element returned by getFree as used.
|
||||
* Until this is called getUsed will not return it.
|
||||
* @param element The element. It must be the element returned
|
||||
* by the most recent call to getUsed.
|
||||
*/
|
||||
void setUsed(queueElementPtr const &element);
|
||||
/**
|
||||
* Get the oldest used element;
|
||||
* @return a shared_ptr to the queue element.
|
||||
* This is null if no used element is available.`
|
||||
*/
|
||||
queueElementPtr & getUsed();
|
||||
/**
|
||||
* Release the element obtained by the most recent call to getUsed.
|
||||
* @param element The element.
|
||||
*/
|
||||
void releaseUsed(queueElementPtr const &element);
|
||||
private:
|
||||
queueElementPtr nullElement;
|
||||
|
||||
@@ -28,11 +28,43 @@ enum MessageType {
|
||||
|
||||
epicsShareExtern std::string getMessageTypeName(MessageType messageType);
|
||||
|
||||
/**
|
||||
* @brief Callback class for passing messages to a requester.
|
||||
*
|
||||
* This is used by many other classes and also extended by other classes.
|
||||
* The request is passed a message and a messageType.
|
||||
* A message is just a string and a messageType is:
|
||||
@code
|
||||
enum MessageType {
|
||||
infoMessage,warningMessage,errorMessage,fatalErrorMessage
|
||||
};
|
||||
@endcode
|
||||
*
|
||||
*/
|
||||
|
||||
class epicsShareClass Requester {
|
||||
public:
|
||||
POINTER_DEFINITIONS(Requester);
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~Requester(){}
|
||||
/**
|
||||
* The requester must have a name.
|
||||
* @return The requester's name.
|
||||
*/
|
||||
virtual std::string getRequesterName() = 0;
|
||||
/**
|
||||
*
|
||||
* A message for the requester.
|
||||
* @param message The message.
|
||||
* @param messageType The type of message:
|
||||
@code
|
||||
enum MessageType {
|
||||
infoMessage,warningMessage,errorMessage,fatalErrorMessage
|
||||
};
|
||||
@endcode
|
||||
*/
|
||||
virtual void message(std::string const & message,MessageType messageType) = 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -25,51 +25,184 @@ namespace epics { namespace pvData {
|
||||
class BitSet;
|
||||
class Field;
|
||||
|
||||
/**
|
||||
* @brief Callback class for serialization.
|
||||
*
|
||||
* This must be provided by code that calls serialize.
|
||||
*/
|
||||
class epicsShareClass SerializableControl {
|
||||
public:
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
virtual ~SerializableControl(){}
|
||||
/**
|
||||
* Done with this buffer. Flush it.
|
||||
*/
|
||||
virtual void flushSerializeBuffer() =0;
|
||||
/**
|
||||
* Make sure buffer has at least size bytes remaining.
|
||||
* If not flush existing buffer and provide a new one.
|
||||
* @param size The number of bytes.
|
||||
*/
|
||||
virtual void ensureBuffer(std::size_t size) =0;
|
||||
/**
|
||||
* Add pad bytes to buffer.
|
||||
* @param alignment alignment required.
|
||||
*/
|
||||
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;
|
||||
/**
|
||||
* method for serializing array data.
|
||||
* This should only be used for arrays of primitive types.
|
||||
* i. e. boolean,byte,...,double.
|
||||
* It can not be called for string, structure, or union arrays.
|
||||
* @param existingBuffer the existing buffer from the caller.
|
||||
* @param toSerialize location of data to be put into buffer.
|
||||
* @param elementCount number of elements.
|
||||
* @param elementSize element size.
|
||||
*/
|
||||
virtual bool directSerialize(
|
||||
ByteBuffer *existingBuffer,
|
||||
const char* toSerialize,
|
||||
std::size_t elementCount,
|
||||
std::size_t elementSize) = 0;
|
||||
/**
|
||||
* serialize via cache
|
||||
* @param field instance to be serialized
|
||||
* @param buffer buffer to be serialized to
|
||||
*/
|
||||
virtual void cachedSerialize(
|
||||
std::tr1::shared_ptr<const Field> const & field,
|
||||
ByteBuffer* buffer) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Callback class for deserialization.
|
||||
*
|
||||
* This must be provided by code that calls deserialize.
|
||||
*/
|
||||
class epicsShareClass DeserializableControl {
|
||||
public:
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
virtual ~DeserializableControl(){}
|
||||
/**
|
||||
* Helper method.
|
||||
* Ensures specified size of bytes, provides it if necessary.
|
||||
* @param size The number of bytes.
|
||||
*/
|
||||
virtual void ensureData(std::size_t size) =0;
|
||||
/**
|
||||
* Align buffer.
|
||||
* Note that this takes care only current buffer alignment.
|
||||
* If streaming protocol is used,
|
||||
* care must be taken that entire stream is aligned.
|
||||
* @param alignment size in bytes, must be power of two.
|
||||
*/
|
||||
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;
|
||||
/**
|
||||
* method for deserializing array data.
|
||||
* This should only be used for arrays of primitive types.
|
||||
* i. e. boolean,byte,...,double.
|
||||
* It can not be called for string, structure, or union arrays.
|
||||
* @param existingBuffer the existing buffer from the caller.
|
||||
* @param deserializeTo location of data.
|
||||
* @param elementCount number of elements.
|
||||
* @param elementSize element size.
|
||||
*/
|
||||
virtual bool directDeserialize(
|
||||
ByteBuffer *existingBuffer,
|
||||
char* deserializeTo,
|
||||
std::size_t elementCount,
|
||||
std::size_t elementSize) = 0;
|
||||
/**
|
||||
* deserialize via cache
|
||||
* @param buffer buffer to be deserialized from
|
||||
*/
|
||||
virtual std::tr1::shared_ptr<const Field> cachedDeserialize(
|
||||
ByteBuffer* buffer) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Base class for serialization.
|
||||
*
|
||||
*/
|
||||
class epicsShareClass Serializable {
|
||||
public:
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
virtual ~Serializable(){}
|
||||
/**
|
||||
* Serialize field into given buffer.
|
||||
* @param buffer serialization buffer.
|
||||
* @param flusher flush interface.
|
||||
*/
|
||||
virtual void serialize(ByteBuffer *buffer,
|
||||
SerializableControl *flusher) const = 0;
|
||||
/**
|
||||
* Deserialize buffer.
|
||||
* @param buffer serialization buffer.
|
||||
* @param flusher deserialization control.
|
||||
*/
|
||||
virtual void deserialize(ByteBuffer *buffer,
|
||||
DeserializableControl *flusher) = 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Class for serializing bitSets.
|
||||
*
|
||||
*/
|
||||
class epicsShareClass BitSetSerializable {
|
||||
public:
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
virtual ~BitSetSerializable(){}
|
||||
/**
|
||||
* Serialize field into given buffer.
|
||||
* @param buffer serialization buffer.
|
||||
* @param flusher flush interface.
|
||||
* @param bitSet The bitSet to serialize.
|
||||
*/
|
||||
virtual void serialize(ByteBuffer *buffer,
|
||||
SerializableControl *flusher,BitSet *bitSet) const = 0;
|
||||
/**
|
||||
* Deserialize buffer.
|
||||
* @param buffer serialization buffer.
|
||||
* @param flusher deserialization control.
|
||||
* @param bitSet The bitSet to deserialize.
|
||||
*/
|
||||
virtual void deserialize(ByteBuffer *buffer,
|
||||
DeserializableControl *flusher,BitSet *bitSet) = 0;
|
||||
};
|
||||
|
||||
|
||||
class epicsShareClass SerializableArray : virtual public Serializable {
|
||||
/**
|
||||
* @brief Class for serializing arrays.
|
||||
*
|
||||
*/
|
||||
class epicsShareClass SerializableArray : public virtual Serializable {
|
||||
public:
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
virtual ~SerializableArray(){}
|
||||
virtual void serialize(ByteBuffer *buffer,
|
||||
SerializableControl *flusher, std::size_t offset, std::size_t count) const = 0;
|
||||
using Serializable::serialize;
|
||||
/**
|
||||
* Serialize field into given buffer.
|
||||
* @param buffer serialization buffer.
|
||||
* @param flusher flush interface.
|
||||
* @param offset offset in elements.
|
||||
* @param count number of elements
|
||||
*/
|
||||
virtual void serialize(
|
||||
ByteBuffer *buffer,
|
||||
SerializableControl *flusher,
|
||||
std::size_t offset,
|
||||
std::size_t count) const = 0;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* serializeHelper.cpp
|
||||
*
|
||||
* Created on: Oct 22, 2010
|
||||
* Author: Miha vitorovic
|
||||
* Author: Miha Vitorovic
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
@@ -23,23 +23,33 @@
|
||||
namespace epics {
|
||||
namespace pvData {
|
||||
|
||||
/**
|
||||
* @brief Serialization helper.
|
||||
*
|
||||
*/
|
||||
class epicsShareClass SerializeHelper : public NoDefaultMethods {
|
||||
public:
|
||||
|
||||
/**
|
||||
* Serialize array size.
|
||||
* Serialize the specified array size into the specified
|
||||
* buffer, flushing when necessary.
|
||||
* The specified SerializableControl manages any flushing
|
||||
* required.
|
||||
*
|
||||
* @param[in] s size to encode
|
||||
* @param[in] buffer serialization buffer
|
||||
* @param[in] flusher flusher
|
||||
* @param[in] flusher SerializableControl to manage the flushing
|
||||
*/
|
||||
static void writeSize(std::size_t s, ByteBuffer* buffer,
|
||||
SerializableControl* flusher);
|
||||
|
||||
/**
|
||||
* Deserialize array size.
|
||||
* The specified DeserializableControl ensures
|
||||
* sufficient bytes are available.
|
||||
*
|
||||
* @param[in] buffer deserialization buffer.
|
||||
* @param[in] control the DeserializableControl.
|
||||
* @returns array size.
|
||||
*/
|
||||
static std::size_t readSize(ByteBuffer* buffer,
|
||||
@@ -59,7 +69,7 @@ namespace epics {
|
||||
* std::string serialization helper method.
|
||||
*
|
||||
* @param[in] value std::string to serialize
|
||||
* @param[in] offset start of the substring in {@code value}
|
||||
* @param[in] offset start of the substring in value
|
||||
* @param[in] count the number of characters to write
|
||||
* @param[in] buffer serialization buffer
|
||||
* @param[in] flusher flusher
|
||||
|
||||
@@ -44,6 +44,25 @@
|
||||
# undef SHARED_FROM_TR1
|
||||
#endif
|
||||
|
||||
#if defined(__clang__)
|
||||
# undef SHARED_FROM_BOOST
|
||||
# undef SHARED_FROM_TR1
|
||||
|
||||
#include <memory>
|
||||
|
||||
// import std classes into std::tr1
|
||||
namespace std {
|
||||
namespace tr1 {
|
||||
using std::shared_ptr;
|
||||
using std::weak_ptr;
|
||||
using std::static_pointer_cast;
|
||||
using std::dynamic_pointer_cast;
|
||||
using std::const_pointer_cast;
|
||||
using std::enable_shared_from_this;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// go and get it
|
||||
|
||||
#if defined(SHARED_FROM_TR1)
|
||||
|
||||
@@ -230,7 +230,7 @@ namespace detail {
|
||||
};
|
||||
}
|
||||
|
||||
/** @brief A holder for a contigious piece of memory.
|
||||
/** @brief A holder for a contiguous piece of memory.
|
||||
*
|
||||
* Data is shared, but offset and length are not.
|
||||
* This allows one vector to have access to only a
|
||||
@@ -427,7 +427,7 @@ public:
|
||||
* owner of the data array.
|
||||
*
|
||||
* If a copy is needed, memory is allocated with new[]. If this is
|
||||
* not desireable then do something like the following.
|
||||
* not desirable then do something like the following.
|
||||
@code
|
||||
shared_vector<E> original(...);
|
||||
|
||||
@@ -527,9 +527,12 @@ public:
|
||||
|
||||
};
|
||||
|
||||
//! Specialization for storing untyped pointers
|
||||
//! Does not allow access or iteration of contents
|
||||
//! other than as void* or const void*
|
||||
/**
|
||||
* @brief Specialization for storing untyped pointers.
|
||||
*
|
||||
* Does not allow access or iteration of contents
|
||||
* other than as void* or const void*
|
||||
*/
|
||||
template<typename E>
|
||||
class shared_vector<E, typename meta::is_void<E>::type >
|
||||
: public detail::shared_vector_base<E>
|
||||
@@ -861,7 +864,7 @@ std::ostream& operator<<(std::ostream& strm, const epics::pvData::shared_vector<
|
||||
* The copy constructor and assignment operator allow implicit
|
||||
* casting from type 'shared_vector<T>' to 'shared_vector<const T>'.
|
||||
*
|
||||
* To faciliate safe modification the methods unique() and
|
||||
* To facilitate safe modification the methods unique() and
|
||||
* make_unique() are provided.
|
||||
*
|
||||
* The slice() method selects a sub-set of the shared_vector.
|
||||
|
||||
@@ -21,7 +21,9 @@
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
/**
|
||||
* Status.
|
||||
* @brief Status.
|
||||
*
|
||||
* This is a class for returning status to clients.
|
||||
* @author mse
|
||||
*/
|
||||
class epicsShareClass Status : public epics::pvData::Serializable {
|
||||
|
||||
@@ -47,9 +47,28 @@ typedef std::tr1::shared_ptr<epicsThread> EpicsThreadPtr;
|
||||
|
||||
typedef epicsThreadRunable Runnable;
|
||||
|
||||
/**
|
||||
* @brief C++ wrapper for epicsThread from EPICS base.
|
||||
*
|
||||
*/
|
||||
class epicsShareClass Thread : public epicsThread, private NoDefaultMethods {
|
||||
public:
|
||||
|
||||
/**
|
||||
*
|
||||
* Constructor
|
||||
* @param name thread name.
|
||||
* @param priority priority is one of:
|
||||
@code
|
||||
enum ThreadPriority {
|
||||
lowestPriority, lowerPriority, lowPriority,
|
||||
middlePriority,
|
||||
highPriority, higherPriority, highestPriority
|
||||
};
|
||||
@endcode
|
||||
* @param runnable this is a c function
|
||||
* @param stkcls stack size as specified by epicsThreadStackSizeClass
|
||||
*/
|
||||
Thread(std::string name,
|
||||
ThreadPriority priority,
|
||||
Runnable *runnable,
|
||||
@@ -62,6 +81,21 @@ public:
|
||||
this->start();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Constructor
|
||||
* @param runnable this is a c function
|
||||
* @name thread name.
|
||||
* @param stkcls stack size as specified by epicsThreadStackSizeClass
|
||||
* @param priority priority is one of:
|
||||
@code
|
||||
enum ThreadPriority {
|
||||
lowestPriority, lowerPriority, lowPriority,
|
||||
middlePriority,
|
||||
highPriority, higherPriority, highestPriority
|
||||
};
|
||||
@endcode
|
||||
*/
|
||||
Thread(Runnable &runnable,
|
||||
std::string name,
|
||||
unsigned int stksize,
|
||||
@@ -74,6 +108,9 @@ public:
|
||||
this->start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~Thread()
|
||||
{
|
||||
this->exitWait();
|
||||
|
||||
@@ -21,19 +21,46 @@ class TimeFunction;
|
||||
typedef std::tr1::shared_ptr<TimeFunctionRequester> TimeFunctionRequesterPtr;
|
||||
typedef std::tr1::shared_ptr<TimeFunction> TimeFunctionPtr;
|
||||
|
||||
/**
|
||||
* @brief Class that must be implemented by timeFunction requester.
|
||||
*
|
||||
*/
|
||||
class epicsShareClass TimeFunctionRequester {
|
||||
public:
|
||||
POINTER_DEFINITIONS(TimeFunctionRequester);
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~TimeFunctionRequester(){}
|
||||
/**
|
||||
* function to be timed.
|
||||
* It will get called multiple times.
|
||||
*/
|
||||
virtual void function() = 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Class for measuring time it takes to execute a function.
|
||||
*
|
||||
*/
|
||||
class epicsShareClass TimeFunction {
|
||||
public:
|
||||
POINTER_DEFINITIONS(TimeFunction);
|
||||
/**
|
||||
* Constructor
|
||||
* @param requester The class that has a function method.
|
||||
*/
|
||||
TimeFunction(TimeFunctionRequesterPtr const & requester);
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~TimeFunction();
|
||||
/**
|
||||
* Time the function.
|
||||
* @return the time in seconds to execute the function.
|
||||
* Note that the function may be called many times.
|
||||
*/
|
||||
double timeCall();
|
||||
private:
|
||||
TimeFunctionRequesterPtr requester;
|
||||
|
||||
@@ -14,9 +14,9 @@
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/convert.h>
|
||||
#include <pv/timer.h>
|
||||
|
||||
using std::string;
|
||||
|
||||
@@ -32,12 +32,28 @@ class Timer;
|
||||
typedef std::tr1::shared_ptr<TimerCallback> TimerCallbackPtr;
|
||||
typedef std::tr1::shared_ptr<Timer> TimerPtr;
|
||||
|
||||
/**
|
||||
* @brief Class that must be implemented by code that makes Timer requests.
|
||||
*
|
||||
*/
|
||||
class epicsShareClass TimerCallback {
|
||||
public:
|
||||
POINTER_DEFINITIONS(TimerCallback);
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
TimerCallback();
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~TimerCallback(){}
|
||||
/**
|
||||
* The method that is called when a timer expires.
|
||||
*/
|
||||
virtual void callback() = 0;
|
||||
/**
|
||||
* The timer has stopped.
|
||||
*/
|
||||
virtual void timerStopped() = 0;
|
||||
private:
|
||||
TimerCallbackPtr next;
|
||||
@@ -47,22 +63,60 @@ private:
|
||||
friend class Timer;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Support for delayed or periodic callback execution.
|
||||
*
|
||||
*/
|
||||
class epicsShareClass Timer : public Runnable {
|
||||
public:
|
||||
POINTER_DEFINITIONS(Timer);
|
||||
/**
|
||||
* Constructor
|
||||
* @param threadName name for the timer thread.
|
||||
* @param priority thread priority
|
||||
*/
|
||||
Timer(std::string threadName, ThreadPriority priority);
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~Timer();
|
||||
/**
|
||||
* The thread run method. This is called automatically.
|
||||
*/
|
||||
virtual void run();
|
||||
/**
|
||||
* schedule a callback after a delay.
|
||||
* @param timerCallback the timerCallback instance.
|
||||
* @param delay number of seconds before calling callback.
|
||||
*/
|
||||
void scheduleAfterDelay(
|
||||
TimerCallbackPtr const &timerCallback,
|
||||
double delay);
|
||||
/**
|
||||
* schedule a periodic callback.`
|
||||
* @param timerCallback the timerCallback instance.
|
||||
* @param delay number of seconds before first callback.
|
||||
* @param period time in seconds between each callback.
|
||||
*/
|
||||
void schedulePeriodic(
|
||||
TimerCallbackPtr const &timerCallback,
|
||||
double delay,
|
||||
double period);
|
||||
/**
|
||||
* cancel a callback.
|
||||
* @param timerCallback the timerCallback to cancel.
|
||||
*/
|
||||
void cancel(TimerCallbackPtr const &timerCallback);
|
||||
/**
|
||||
* Is the callback scheduled to be called?
|
||||
* @param timerCallback the timerCallback.
|
||||
* @return (false,true) if (not, is) scheduled.
|
||||
*/
|
||||
bool isScheduled(TimerCallbackPtr const &timerCallback);
|
||||
|
||||
/**
|
||||
* show the elements in the timer queue.
|
||||
* @param o The output stream for the output
|
||||
*/
|
||||
void dump(std::ostream& o);
|
||||
|
||||
private:
|
||||
|
||||
@@ -59,7 +59,7 @@ namespace detail {
|
||||
typedef T return_t;
|
||||
static FORCE_INLINE return_t op(const T& i) { return i; }
|
||||
};
|
||||
// trick std::ostream into treating char's as numbers
|
||||
// trick std::ostream into treating chars as numbers
|
||||
// by promoting char to int
|
||||
template<>
|
||||
struct print_convolute<int8> {
|
||||
@@ -142,7 +142,7 @@ namespace detail {
|
||||
* - float -> double
|
||||
*
|
||||
* Conversions where out of range inputs always produce
|
||||
* a defined result, but may not be reversable.
|
||||
* a defined result, but may not be reversible.
|
||||
*
|
||||
* - double -> float. When abs(value) is outside the range
|
||||
* [FLT_MIN, FLT_MAX] the value is clipped to FLT_MIN or FLT_MAX
|
||||
|
||||
@@ -30,6 +30,8 @@ typedef std::tr1::shared_ptr<Monitor> MonitorPtr;
|
||||
|
||||
|
||||
/**
|
||||
* @brief An element for a monitorQueue.
|
||||
*
|
||||
* Class instance representing monitor element.
|
||||
* @author mrk
|
||||
*/
|
||||
@@ -48,7 +50,9 @@ class epicsShareClass MonitorElement {
|
||||
};
|
||||
|
||||
/**
|
||||
* Interface for Monitor.
|
||||
* @brief Monitor changes to fields of a pvStructure.
|
||||
*
|
||||
* This is used by pvAccess to implement monitors.
|
||||
* @author mrk
|
||||
*/
|
||||
class epicsShareClass Monitor : public Destroyable{
|
||||
@@ -73,6 +77,7 @@ class epicsShareClass Monitor : public Destroyable{
|
||||
virtual MonitorElementPtr poll() = 0;
|
||||
/**
|
||||
* Release a MonitorElement that was returned by poll.
|
||||
* A poll() must be called after the release() to check the presence of any modified data.
|
||||
* @param monitorElement
|
||||
*/
|
||||
virtual void release(MonitorElementPtr const & monitorElement) = 0;
|
||||
@@ -80,6 +85,8 @@ class epicsShareClass Monitor : public Destroyable{
|
||||
|
||||
|
||||
/**
|
||||
* @brief Callback implemented by monitor clients.
|
||||
*
|
||||
* Requester for ChannelMonitor.
|
||||
* @author mrk
|
||||
*/
|
||||
|
||||
@@ -23,7 +23,7 @@ MonitorPluginManagerPtr MonitorPluginManager::get()
|
||||
static MonitorPluginManagerPtr pluginManager;
|
||||
static Mutex mutex;
|
||||
Lock xx(mutex);
|
||||
if(pluginManager==NULL) {
|
||||
if(!pluginManager) {
|
||||
pluginManager = MonitorPluginManagerPtr(new MonitorPluginManager());
|
||||
}
|
||||
return pluginManager;
|
||||
|
||||
@@ -20,32 +20,25 @@
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
/**
|
||||
* typedef for a pointer to a MonitorPlugin
|
||||
*/
|
||||
class MonitorPlugin;
|
||||
typedef std::tr1::shared_ptr<MonitorPlugin> MonitorPluginPtr;
|
||||
|
||||
|
||||
/**
|
||||
* typedef for a pointer to a MonitorPluginCreator
|
||||
*/
|
||||
class MonitorPluginCreator;
|
||||
typedef std::tr1::shared_ptr<MonitorPluginCreator> MonitorPluginCreatorPtr;
|
||||
|
||||
|
||||
/**
|
||||
* typedef for a pointer to a MonitorPluginManager
|
||||
*/
|
||||
class MonitorPluginManager;
|
||||
typedef std::tr1::shared_ptr<MonitorPluginManager> MonitorPluginManagerPtr;
|
||||
|
||||
|
||||
/** A plugin for raising monitors;
|
||||
/**
|
||||
* @brief A plugin for raising monitors;
|
||||
*
|
||||
* This is for use by pvAccess servers that support monitors.
|
||||
* Since the interface has only a dependence on pvData it
|
||||
* can be used for other purposes.
|
||||
* A monitor is assumed to be associated with a field of a top level
|
||||
* A monitor is assumed to be associated with a field of a top-level
|
||||
* structure.
|
||||
*/
|
||||
class epicsShareClass MonitorPlugin
|
||||
@@ -60,8 +53,8 @@ public:
|
||||
/**
|
||||
* Should a monitor be raised?
|
||||
* @param pvField The field being monitored.
|
||||
* @param pvTop The top level sructure in which the field resides.
|
||||
* @param monitorElement The client data and bitSets.
|
||||
* @param pvTop The top-level structure in which the field resides.
|
||||
* @param monitorElement The client data and bitsets.
|
||||
* @returns true or false.
|
||||
* True is returned if the change to this field should cause a monitor.
|
||||
* False is returned in a change only to this field should not cause a
|
||||
@@ -73,9 +66,6 @@ public:
|
||||
MonitorElementPtr const &monitorElement) = 0;
|
||||
/**
|
||||
* A monitor will be sent to the client.
|
||||
* @param pvField The copy of the field being monitored.
|
||||
* The plugin can modify the data.
|
||||
* @param pvTop The top level sructure in which the field resides.
|
||||
* @param monitorElement The data for the client.
|
||||
* The plugin is allowed to change the data values.
|
||||
*/
|
||||
@@ -100,7 +90,9 @@ public:
|
||||
virtual void endGroupPut() {};
|
||||
};
|
||||
|
||||
/** A class that creates a plugin.
|
||||
/**
|
||||
* @brief A class that creates a plugin.
|
||||
*
|
||||
* Normlly a plugin is created for a single client.
|
||||
*/
|
||||
class epicsShareClass MonitorPluginCreator
|
||||
@@ -110,7 +102,7 @@ public:
|
||||
/**
|
||||
* Create a monitor plugin.
|
||||
* @param field The introspection interface for the field monitored.
|
||||
* @param top The introspsction interface for the client structure.
|
||||
* @param top The introspection interface for the client structure.
|
||||
* @param pvFieldOptions The options the client requested.
|
||||
* The structure has a set of PVString subfields.
|
||||
* The options are a set of name,value pairs.
|
||||
@@ -130,6 +122,8 @@ public:
|
||||
|
||||
|
||||
/**
|
||||
* @brief Manager for plugins.
|
||||
*
|
||||
* This manages a set of monitor plugins.
|
||||
* @author mrk
|
||||
*/
|
||||
|
||||
@@ -18,37 +18,129 @@
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
/** @brief enum definition of AlarmSeverity
|
||||
*
|
||||
* AlarmSeverity is:
|
||||
@code
|
||||
enum AlarmSeverity {
|
||||
noAlarm,minorAlarm,majorAlarm,invalidAlarm,undefinedAlarm
|
||||
};
|
||||
@endcode
|
||||
*
|
||||
*/
|
||||
enum AlarmSeverity {
|
||||
noAlarm,minorAlarm,majorAlarm,invalidAlarm,undefinedAlarm
|
||||
};
|
||||
|
||||
/** @brief enum definition of AlarmStatus
|
||||
*
|
||||
* AlarmStatus is:
|
||||
@code
|
||||
enum AlarmStatus {
|
||||
noStatus,deviceStatus,driverStatus,recordStatus,
|
||||
dbStatus,confStatus,undefinedStatus,clientStatus
|
||||
};
|
||||
@endcode
|
||||
*
|
||||
*/
|
||||
enum AlarmStatus {
|
||||
noStatus,deviceStatus,driverStatus,recordStatus,
|
||||
dbStatus,confStatus,undefinedStatus,clientStatus
|
||||
};
|
||||
|
||||
|
||||
/** @brief methods for AlarmSeverity
|
||||
*
|
||||
*/
|
||||
class epicsShareClass AlarmSeverityFunc {
|
||||
public:
|
||||
/**
|
||||
* Get the severity.
|
||||
* @param value Get the alarm severity corresponding to the integer value.
|
||||
* @return The severity.
|
||||
* @throw if severity value is out of range.
|
||||
*/
|
||||
static AlarmSeverity getSeverity(int value);
|
||||
/**
|
||||
* Get the array of severity names.
|
||||
* @return The array of severity names.
|
||||
*/
|
||||
static StringArrayPtr getSeverityNames();
|
||||
};
|
||||
|
||||
/** @brief methods for AlarmStatus
|
||||
*
|
||||
*/
|
||||
class epicsShareClass AlarmStatusFunc {
|
||||
public:
|
||||
/**
|
||||
* Get the status.
|
||||
* @param value Get the alarm status corresponding to the integer value.
|
||||
* @return The status.
|
||||
* @throw if status value is out of range.
|
||||
*/
|
||||
static AlarmStatus getStatus(int value);
|
||||
/**
|
||||
* Get the array of status names.
|
||||
* @return The array of status names.
|
||||
*/
|
||||
static StringArrayPtr getStatusNames();
|
||||
};
|
||||
|
||||
/** @brief Methods for manipulating alarm.
|
||||
*
|
||||
* An alarm structure has the following fields:
|
||||
@code
|
||||
structure
|
||||
int severity
|
||||
int status
|
||||
string message
|
||||
@endcode
|
||||
* This is a class that holds values corresponding to the fields in
|
||||
* an alarm structure.
|
||||
* It is meant to be used together with pvAlarm
|
||||
* which allows values to be copied between an alarm structure
|
||||
* and this class.
|
||||
* This class should not be extended.
|
||||
*/
|
||||
class epicsShareClass Alarm {
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Alarm() : severity(0),status(0), message(std::string("")) {}
|
||||
//default constructors and destructor are OK
|
||||
/**
|
||||
* get the current message.
|
||||
* @return The message.
|
||||
*/
|
||||
std::string getMessage() const {return message;}
|
||||
/**
|
||||
* set the current message.
|
||||
* @param value The new message value.
|
||||
*/
|
||||
void setMessage(std::string const &value) {message = value;}
|
||||
/**
|
||||
* get the current severity.
|
||||
* @return The severity.
|
||||
*/
|
||||
AlarmSeverity getSeverity() const;
|
||||
/**
|
||||
* set the current severity.
|
||||
* @param value The new severity.
|
||||
* @throw if severity value is out of range.
|
||||
*/
|
||||
void setSeverity(AlarmSeverity value) {severity = value;}
|
||||
/**
|
||||
* get the current status.
|
||||
* @return The status.
|
||||
*/
|
||||
AlarmStatus getStatus() const;
|
||||
/**
|
||||
* set the current status.
|
||||
* @param value The new status.
|
||||
* @throw if status value is out of range.
|
||||
*/
|
||||
void setStatus(AlarmStatus value) { status = value;}
|
||||
private:
|
||||
int32 severity;
|
||||
|
||||
@@ -14,15 +14,58 @@
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
/** @brief Methods for a control structure.
|
||||
*
|
||||
* An control structure has the following fields:
|
||||
@code
|
||||
structure
|
||||
double limitLow
|
||||
double limitHigh
|
||||
double minStep
|
||||
@endcode
|
||||
* This is a class that holds values corresponding to the fields in
|
||||
* a control structure.
|
||||
* It is meant to be used together with pvControl
|
||||
* which allows values to be copied between an control structure
|
||||
* and this class.
|
||||
* This class should not be extended.
|
||||
*/
|
||||
class epicsShareClass Control {
|
||||
public:
|
||||
Control() : low(0.0), high(0.0) {}
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Control() : low(0.0), high(0.0), minStep(0.0) {}
|
||||
//default constructors and destructor are OK
|
||||
/**
|
||||
* get limitLow
|
||||
* @return the current value.
|
||||
*/
|
||||
double getLow() const {return low;}
|
||||
/**
|
||||
* get limitHigh
|
||||
* @return the current value.
|
||||
*/
|
||||
double getHigh() const {return high;}
|
||||
/**
|
||||
* get minStep
|
||||
* @return the current value.
|
||||
*/
|
||||
double getMinStep() const {return minStep;}
|
||||
/**
|
||||
* set limitLow
|
||||
* @param value The new value.
|
||||
*/
|
||||
void setLow(double value) {low = value;}
|
||||
/**
|
||||
* set limitHigh
|
||||
* @param value The new value.
|
||||
*/
|
||||
void setHigh(double value) {high = value;}
|
||||
/**
|
||||
* set minStep
|
||||
* @param value The new value.
|
||||
*/
|
||||
void setMinStep(double value) {minStep = value;}
|
||||
private:
|
||||
double low;
|
||||
|
||||
@@ -19,21 +19,83 @@
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
/** @brief Methods for a display structure.
|
||||
*
|
||||
* An display structure has the following fields:
|
||||
@code
|
||||
structure
|
||||
double limitLow
|
||||
double limitHigh
|
||||
string description
|
||||
string format
|
||||
string units
|
||||
@endcode
|
||||
* This is a class that holds values corresponding to the fields in
|
||||
* a display structure.
|
||||
* It is meant to be used together with pvDisplay
|
||||
* which allows values to be copied between an display structure
|
||||
* and this class.
|
||||
* This class should not be extended.
|
||||
*/
|
||||
class epicsShareClass Display {
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Display()
|
||||
: description(std::string("")),format(std::string("")),units(std::string("")),
|
||||
low(0.0),high(0.0) {}
|
||||
//default constructors and destructor are OK
|
||||
/**
|
||||
* Get the current value of limitLow.
|
||||
* @return The current value.
|
||||
*/
|
||||
double getLow() const {return low;}
|
||||
/**
|
||||
* Get the current value of limitHigh.
|
||||
* @return The current value.
|
||||
*/
|
||||
double getHigh() const{ return high;}
|
||||
/**
|
||||
* Set limitLow to a new value.
|
||||
* @param value The value.
|
||||
*/
|
||||
void setLow(double value){low = value;}
|
||||
/**
|
||||
* Set limitHigh to a new value.
|
||||
* @param value The value.
|
||||
*/
|
||||
void setHigh(double value){high = value;}
|
||||
/**
|
||||
* Get the current value of description.
|
||||
* @return The current value.
|
||||
*/
|
||||
std::string getDescription() const {return description;}
|
||||
/**
|
||||
* Set description to a new value.
|
||||
* @param value The value.
|
||||
*/
|
||||
void setDescription(std::string const & value) {description = value;}
|
||||
/**
|
||||
* Get the current value of format.
|
||||
* @return The current value.
|
||||
*/
|
||||
std::string getFormat() const {return format;}
|
||||
/**
|
||||
* Set format to a new value.
|
||||
* @param value The value.
|
||||
* The rules for a valid syntax has not been specified.
|
||||
*/
|
||||
void setFormat(std::string const & value) {format = value;}
|
||||
/**
|
||||
* Get the current value of units.
|
||||
* @return The current value.
|
||||
*/
|
||||
std::string getUnits() const {return units;}
|
||||
/**
|
||||
* Set units to a new value.
|
||||
* @param value The value.
|
||||
*/
|
||||
void setUnits(std::string const & value) {units = value;}
|
||||
private:
|
||||
std::string description;
|
||||
|
||||
@@ -28,14 +28,14 @@ bool PVAlarm::attach(PVFieldPtr const & pvField)
|
||||
{
|
||||
if(pvField->getField()->getType()!=structure) return false;
|
||||
PVStructurePtr pvStructure = static_pointer_cast<PVStructure>(pvField);
|
||||
pvSeverity = pvStructure->getIntField("severity");
|
||||
pvSeverity = pvStructure->getSubField<PVInt>("severity");
|
||||
if(pvSeverity.get()==NULL) return false;
|
||||
pvStatus = pvStructure->getIntField("status");
|
||||
pvStatus = pvStructure->getSubField<PVInt>("status");
|
||||
if(pvStatus.get()==NULL) {
|
||||
pvSeverity.reset();
|
||||
return false;
|
||||
}
|
||||
pvMessage = pvStructure->getStringField("message");
|
||||
pvMessage = pvStructure->getSubField<PVString>("message");
|
||||
if(pvMessage.get()==NULL) {
|
||||
pvSeverity.reset();
|
||||
pvStatus.reset();
|
||||
|
||||
@@ -20,18 +20,65 @@
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
/** @brief Methods for accessing an alarm structure.
|
||||
*
|
||||
* An alarm structure has the following fields:
|
||||
@code
|
||||
structure
|
||||
int severity
|
||||
int status
|
||||
string message
|
||||
@endcode
|
||||
* This class can be attached to an alarm structure field of any
|
||||
* PVData object.
|
||||
* The methods provide access to the fields in the attached structure,
|
||||
* via an instance of class Alarm.
|
||||
* This class should not be extended.
|
||||
*/
|
||||
class epicsShareClass PVAlarm {
|
||||
public:
|
||||
/**
|
||||
*
|
||||
* Constructor
|
||||
*/
|
||||
PVAlarm() {}
|
||||
//default constructors and destructor are OK
|
||||
//returns (false,true) if pvField(isNot, is valid enumerated structure
|
||||
//returns (false,true) if pvField(is not, is) a valid alarm structure
|
||||
//An automatic detach is issued if already attached.
|
||||
/*
|
||||
* Attach to a field of a PVData object.
|
||||
* @param pvField The pvField.
|
||||
* @return (false,true) if the pvField (is not, is) an alarm structure.
|
||||
*/
|
||||
/*
|
||||
* Attach to a field of a PVData object.
|
||||
* @param pvField The pvField.
|
||||
* @return (false,true) if the pvField (is not, is) an alarm structure.
|
||||
*/
|
||||
bool attach(PVFieldPtr const & pvField);
|
||||
/**
|
||||
* Detach for pvField.
|
||||
*/
|
||||
void detach();
|
||||
/**
|
||||
* Is the PVAlarm attached to a pvField?
|
||||
* @return (false,true) (is not,is) attached to a pvField.
|
||||
*/
|
||||
bool isAttached();
|
||||
// each of the following throws logic_error is not attached to PVField
|
||||
// set returns false if field is immutable
|
||||
/**
|
||||
* copy the alarm structure values to Alarm
|
||||
* @param alarm An instance of class Alarm
|
||||
* @throw If not attached to a pvField.
|
||||
*/
|
||||
void get(Alarm & alarm) const;
|
||||
/**
|
||||
* copy the values from Alarm to the alarm structure.
|
||||
* @param alarm An instance of class Alarm
|
||||
* @return (false,true) if pvField (immutable, mutable)
|
||||
* @throw If not attached to a pvField.
|
||||
*/
|
||||
bool set(Alarm const & alarm);
|
||||
private:
|
||||
PVIntPtr pvSeverity;
|
||||
|
||||
@@ -28,13 +28,19 @@ bool PVControl::attach(PVFieldPtr const & pvField)
|
||||
{
|
||||
if(pvField->getField()->getType()!=structure) return false;
|
||||
PVStructurePtr pvStructure = static_pointer_cast<PVStructure>(pvField);
|
||||
pvLow = pvStructure->getDoubleField("limitLow");
|
||||
pvLow = pvStructure->getSubField<PVDouble>("limitLow");
|
||||
if(pvLow.get()==NULL) return false;
|
||||
pvHigh = pvStructure->getDoubleField(string("limitHigh"));
|
||||
pvHigh = pvStructure->getSubField<PVDouble>("limitHigh");
|
||||
if(pvHigh.get()==NULL) {
|
||||
pvLow.reset();
|
||||
return false;
|
||||
}
|
||||
pvMinStep = pvStructure->getSubField<PVDouble>("minStep");
|
||||
if(pvMinStep.get()==NULL) {
|
||||
pvLow.reset();
|
||||
pvHigh.reset();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -56,6 +62,7 @@ void PVControl::get(Control &control) const
|
||||
}
|
||||
control.setLow(pvLow->get());
|
||||
control.setHigh(pvHigh->get());
|
||||
control.setMinStep(pvMinStep->get());
|
||||
}
|
||||
|
||||
bool PVControl::set(Control const & control)
|
||||
@@ -63,9 +70,10 @@ bool PVControl::set(Control const & control)
|
||||
if(pvLow.get()==NULL) {
|
||||
throw std::logic_error(notAttached);
|
||||
}
|
||||
if(pvLow->isImmutable() || pvHigh->isImmutable()) return false;
|
||||
if(pvLow->isImmutable() || pvHigh->isImmutable() || pvMinStep->isImmutable()) return false;
|
||||
pvLow->put(control.getLow());
|
||||
pvHigh->put(control.getHigh());
|
||||
pvMinStep->put(control.getMinStep());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,22 +17,65 @@
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
/** @brief Methods for accessing an control structure.
|
||||
*
|
||||
* An control structure has the following fields:
|
||||
@code
|
||||
structure
|
||||
double limitLow
|
||||
double limitHigh
|
||||
double minStep
|
||||
@endcode
|
||||
* This class can be attached to an control structure field of any
|
||||
* PVData object.
|
||||
* The methods provide access to the fields in the attached structure,
|
||||
* via an instance of class Control.
|
||||
* This class should not be extended.
|
||||
*/
|
||||
class epicsShareClass PVControl {
|
||||
public:
|
||||
/**
|
||||
*
|
||||
* Constructor
|
||||
*/
|
||||
PVControl(){}
|
||||
//default constructors and destructor are OK
|
||||
//returns (false,true) if pvField(isNot, is valid enumerated structure
|
||||
//returns (false,true) if pvField(is not, is) a valid control structure
|
||||
//An automatic detach is issued if already attached.
|
||||
/*
|
||||
* Attach to a field of a PVData object.
|
||||
* @param pvField The pvField.
|
||||
* @return (false,true) if the pvField (is not, is) an control structure.
|
||||
*/
|
||||
bool attach(PVFieldPtr const & pvField);
|
||||
/**
|
||||
* Detach for pvField.
|
||||
*/
|
||||
void detach();
|
||||
/**
|
||||
* Is the PVControl attached to a pvField?
|
||||
* @return (false,true) (is not,is) attached to a pvField.
|
||||
*/
|
||||
bool isAttached();
|
||||
// each of the following throws logic_error is not attached to PVField
|
||||
// each of the following throws logic_error if not attached to PVField
|
||||
// set returns false if field is immutable
|
||||
void get(Control &) const;
|
||||
/**
|
||||
* copy the control structure values to Control
|
||||
* @param control An instance of class Control
|
||||
* @throw If not attached to a pvField.
|
||||
*/
|
||||
void get(Control & control) const;
|
||||
/**
|
||||
* copy the values from Control to the control structure.
|
||||
* @param control An instance of class Control
|
||||
* @return (false,true) if pvField (immutable, mutable)
|
||||
* @throw If not attached to a pvField.
|
||||
*/
|
||||
bool set(Control const & control);
|
||||
private:
|
||||
PVDoublePtr pvLow;
|
||||
PVDoublePtr pvHigh;
|
||||
PVDoublePtr pvMinStep;
|
||||
static std::string noControlFound;
|
||||
static std::string notAttached;
|
||||
};
|
||||
|
||||
@@ -28,24 +28,24 @@ bool PVDisplay::attach(PVFieldPtr const & pvField)
|
||||
{
|
||||
if(pvField->getField()->getType()!=structure) return false;
|
||||
PVStructurePtr pvStructure = static_pointer_cast<PVStructure>(pvField);
|
||||
pvDescription = pvStructure->getStringField("description");
|
||||
pvDescription = pvStructure->getSubField<PVString>("description");
|
||||
if(pvDescription.get()==NULL) return false;
|
||||
pvFormat = pvStructure->getStringField("format");
|
||||
pvFormat = pvStructure->getSubField<PVString>("format");
|
||||
if(pvFormat.get()==NULL) {
|
||||
detach();
|
||||
return false;
|
||||
}
|
||||
pvUnits = pvStructure->getStringField("units");
|
||||
pvUnits = pvStructure->getSubField<PVString>("units");
|
||||
if(pvUnits.get()==NULL) {
|
||||
detach();
|
||||
return false;
|
||||
}
|
||||
pvLow = pvStructure->getDoubleField(string("limitLow"));
|
||||
pvLow = pvStructure->getSubField<PVDouble>(string("limitLow"));
|
||||
if(pvLow.get()==NULL) {
|
||||
detach();
|
||||
return false;
|
||||
}
|
||||
pvHigh = pvStructure->getDoubleField(string("limitHigh"));
|
||||
pvHigh = pvStructure->getSubField<PVDouble>(string("limitHigh"));
|
||||
if(pvHigh.get()==NULL) {
|
||||
detach();
|
||||
return false;
|
||||
|
||||
@@ -20,17 +20,61 @@
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
/** @brief Methods for accessing an display structure.
|
||||
*
|
||||
* A display structure has the following fields:
|
||||
@code
|
||||
structure
|
||||
double limitLow
|
||||
double limitHigh
|
||||
string description
|
||||
string format
|
||||
string units
|
||||
@endcode
|
||||
* This class can be attached to a display structure field of any
|
||||
* PVData object.
|
||||
* The methods provide access to the fields in the attached structure,
|
||||
* via an instance of class Display.
|
||||
* This class should not be extended.
|
||||
*/
|
||||
class epicsShareClass PVDisplay {
|
||||
public:
|
||||
/**
|
||||
*
|
||||
* Constructor
|
||||
*/
|
||||
PVDisplay() {}
|
||||
//default constructors and destructor are OK
|
||||
//An automatic detach is issued if already attached.
|
||||
/*
|
||||
* Attach to a field of a PVData object.
|
||||
* @param pvField The pvField.
|
||||
* @return (false,true) if the pvField (is not, is) an display structure.
|
||||
*/
|
||||
bool attach(PVFieldPtr const & pvField);
|
||||
/**
|
||||
* Detach for pvField.
|
||||
*/
|
||||
void detach();
|
||||
/**
|
||||
* Is the PVDisplay attached to a pvField?
|
||||
* @return (false,true) (is not,is) attached to a pvField.
|
||||
*/
|
||||
bool isAttached();
|
||||
// each of the following throws logic_error is not attached to PVField
|
||||
// each of the following throws logic_error if not attached to PVField
|
||||
// a set returns false if field is immutable
|
||||
void get(Display &) const;
|
||||
/**
|
||||
* copy the display structure values to Display
|
||||
* @param display An instance of class Display
|
||||
* @throw If not attached to a pvField.
|
||||
*/
|
||||
void get(Display & display) const;
|
||||
/**
|
||||
* copy the values from Display to the display structure.
|
||||
* @param display An instance of class Display
|
||||
* @return (false,true) if pvField (immutable, mutable)
|
||||
* @throw If not attached to a pvField.
|
||||
*/
|
||||
bool set(Display const & display);
|
||||
private:
|
||||
static std::string noDisplayFound;
|
||||
|
||||
@@ -28,15 +28,14 @@ bool PVEnumerated::attach(PVFieldPtr const & pvField)
|
||||
{
|
||||
if(pvField->getField()->getType()!=structure) return false;
|
||||
PVStructurePtr pvStructure = static_pointer_cast<PVStructure>(pvField);
|
||||
pvIndex = pvStructure->getIntField("index");
|
||||
pvIndex = pvStructure->getSubField<PVInt>("index");
|
||||
if(pvIndex.get()==NULL) return false;
|
||||
PVScalarArrayPtr pvScalarArray = pvStructure->getScalarArrayField(
|
||||
"choices",pvString);
|
||||
if(pvScalarArray.get()==NULL) {
|
||||
PVStringArrayPtr pvStringArray = pvStructure->getSubField<PVStringArray>("choices");
|
||||
if(pvStringArray.get()==NULL) {
|
||||
pvIndex.reset();
|
||||
return false;
|
||||
}
|
||||
pvChoices = static_pointer_cast<PVStringArray>(pvScalarArray);
|
||||
pvChoices = pvStringArray;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -74,8 +73,12 @@ string PVEnumerated::getChoice()
|
||||
if(pvIndex.get()==NULL ) {
|
||||
throw std::logic_error(notAttached);
|
||||
}
|
||||
int index = pvIndex->get();
|
||||
size_t index = pvIndex->get();
|
||||
const PVStringArray::const_svector& data(pvChoices->view());
|
||||
if(/*index<0 ||*/ index>=data.size()) {
|
||||
string nullString;
|
||||
return nullString;
|
||||
}
|
||||
return data[index];
|
||||
}
|
||||
|
||||
|
||||
@@ -19,24 +19,89 @@
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
/** @brief Methods for accessing an enumerated structure.
|
||||
*
|
||||
* An enumerated structure has the following fields:
|
||||
@code
|
||||
structure
|
||||
int index
|
||||
string[] choices
|
||||
@endcode
|
||||
* This class can be attached to an enumerated structure field of any
|
||||
* PVData object.
|
||||
* The methods provide access to the fields in the attached structure.
|
||||
* This class should not be extended.
|
||||
*/
|
||||
class epicsShareClass PVEnumerated {
|
||||
public:
|
||||
/*
|
||||
* Constructor.
|
||||
*/
|
||||
PVEnumerated() {}
|
||||
//default constructors and destructor are OK
|
||||
//This class should not be extended
|
||||
//returns (false,true) if pvField(isNot, is valid enumerated structure
|
||||
//returns (false,true) if pvField(is not, is) a valid enumerated structure
|
||||
//An automatic detach is issued if already attached.
|
||||
/*
|
||||
* Attach to a field of a PVData object.
|
||||
* @param pvField The pvField.
|
||||
* @return (false,true) if the pvField (is not, is) an enumerated structure.
|
||||
*/
|
||||
bool attach(PVFieldPtr const & pvField);
|
||||
/**
|
||||
* Detach for pvField.
|
||||
*/
|
||||
void detach();
|
||||
/**
|
||||
* Is the PVEnumerated attached to a pvField?
|
||||
* @return (false,true) (is not,is) attached to a pvField.
|
||||
*/
|
||||
bool isAttached();
|
||||
// each of the following throws logic_error is not attached to PVField
|
||||
// a set returns false if field is immutable
|
||||
/**
|
||||
* Set the index.
|
||||
* @param index The new index.
|
||||
* @throw if not attached.
|
||||
* The index will be changed even if it is out of range of size of choices.
|
||||
*/
|
||||
bool setIndex(int32 index);
|
||||
/**
|
||||
* Get the index.
|
||||
* @return The current index.
|
||||
* @throw if not attached.
|
||||
*/
|
||||
int32 getIndex();
|
||||
/**
|
||||
* Get the choice corresponding to current index.
|
||||
* @return The choice. If index is out of range a null string is returned.
|
||||
* @throw if not attached.
|
||||
*/
|
||||
std::string getChoice();
|
||||
/**
|
||||
* Can choices be changed?
|
||||
* @return (false,true) if choices (can not, can) be changed.
|
||||
* @throw if not attached.
|
||||
*/
|
||||
bool choicesMutable();
|
||||
/**
|
||||
* Get the choices.
|
||||
* @return The current index.
|
||||
* @throw if not attached.
|
||||
*/
|
||||
inline PVStringArray::const_svector getChoices(){return pvChoices->view();}
|
||||
/**
|
||||
* Get the size of the choices array.
|
||||
* @return The size.
|
||||
* @throw if not attached.
|
||||
*/
|
||||
int32 getNumberChoices();
|
||||
/**
|
||||
* Get the choices.
|
||||
* @param choices The new value for choices.`
|
||||
* @return (false,true) if choices (was not was) replaced.
|
||||
* @throw if not attached.
|
||||
*/
|
||||
bool setChoices(const StringArray & choices);
|
||||
private:
|
||||
static std::string notFound;
|
||||
|
||||
@@ -30,11 +30,11 @@ bool PVTimeStamp::attach(PVFieldPtr const & pvField)
|
||||
PVStructurePtr xxx = static_pointer_cast<PVStructure>(pvField);
|
||||
PVStructure* pvStructure = xxx.get();
|
||||
while(true) {
|
||||
PVLongPtr pvLong = pvStructure->getLongField("secondsPastEpoch");
|
||||
PVLongPtr pvLong = pvStructure->getSubField<PVLong>("secondsPastEpoch");
|
||||
if(pvLong.get()!=NULL) {
|
||||
pvSecs = pvLong;
|
||||
pvNano = pvStructure->getIntField("nanoSeconds");
|
||||
pvUserTag = pvStructure->getIntField("userTag");
|
||||
pvNano = pvStructure->getSubField<PVInt>("nanoseconds");
|
||||
pvUserTag = pvStructure->getSubField<PVInt>("userTag");
|
||||
}
|
||||
if(pvSecs.get()!=NULL
|
||||
&& pvNano.get()!=NULL
|
||||
@@ -76,7 +76,7 @@ bool PVTimeStamp::set(TimeStamp const & timeStamp)
|
||||
if(pvSecs->isImmutable() || pvNano->isImmutable()) return false;
|
||||
pvSecs->put(timeStamp.getSecondsPastEpoch());
|
||||
pvUserTag->put(timeStamp.getUserTag());
|
||||
pvNano->put(timeStamp.getNanoSeconds());
|
||||
pvNano->put(timeStamp.getNanoseconds());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,19 +21,61 @@
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
/** @brief Methods for accessing a timeStamp structure.
|
||||
*
|
||||
* A timeStamp structure has the following fields:
|
||||
@code
|
||||
structure
|
||||
long secondsPastEpoch
|
||||
int nanoseconds
|
||||
int userTag
|
||||
@endcode
|
||||
* This class can be attached to a timeStamp structure field of any
|
||||
* PVData object.
|
||||
* The methods provide access to the fields in the attached structure,
|
||||
* via an instance of class TimeStamp.
|
||||
* This class should not be extended.
|
||||
*/
|
||||
class epicsShareClass PVTimeStamp {
|
||||
public:
|
||||
/**
|
||||
*
|
||||
* Constructor
|
||||
*/
|
||||
PVTimeStamp(){}
|
||||
//default constructors and destructor are OK
|
||||
//This class should not be extended
|
||||
|
||||
//returns (false,true) if pvField(isNot, is valid timeStamp structure
|
||||
//returns (false,true) if pvField(is not, is) a valid timeStamp structure
|
||||
/*
|
||||
* Attach to a field of a PVData object.
|
||||
* @param pvField The pvField.
|
||||
* @return (false,true) if the pvField (is not, is) an timeStamp structure.
|
||||
*/
|
||||
bool attach(PVFieldPtr const & pvField);
|
||||
/**
|
||||
* Detach for pvField.
|
||||
*/
|
||||
void detach();
|
||||
/**
|
||||
* Is the PVTimeStamp attached to a pvField?
|
||||
* @return (false,true) (is not,is) attached to a pvField.
|
||||
*/
|
||||
bool isAttached();
|
||||
// following throw logic_error is not attached to PVField
|
||||
// a set returns false if field is immutable
|
||||
void get(TimeStamp &) const;
|
||||
// following throw logic_error if not attached to PVField
|
||||
// set returns false if field is immutable
|
||||
/**
|
||||
* copy the timeStamp structure values to TimeStamp
|
||||
* @param timeStamp An instance of class TimeStamp
|
||||
* @throw If not attached to a pvField.
|
||||
*/
|
||||
void get(TimeStamp & timeStamp) const;
|
||||
/**
|
||||
* copy the values from TimeStamp to the timeStamp structure.
|
||||
* @param timeStamp An instance of class TimeStamp
|
||||
* @return (false,true) if pvField (immutable, mutable)
|
||||
* @throw If not attached to a pvField.
|
||||
*/
|
||||
bool set(TimeStamp const & timeStamp);
|
||||
private:
|
||||
static std::string noTimeStamp;
|
||||
|
||||
@@ -27,21 +27,21 @@ int32 microSecPerSec = milliSecPerSec*milliSecPerSec;
|
||||
int32 nanoSecPerSec = milliSecPerSec*microSecPerSec;
|
||||
int64 posixEpochAtEpicsEpoch = POSIX_TIME_AT_EPICS_EPOCH;
|
||||
|
||||
TimeStamp::TimeStamp(int64 secondsPastEpoch,int32 nanoSeconds,int32 userTag)
|
||||
: secondsPastEpoch(secondsPastEpoch),nanoSeconds(nanoSeconds),userTag(userTag)
|
||||
TimeStamp::TimeStamp(int64 secondsPastEpoch,int32 nanoseconds,int32 userTag)
|
||||
: secondsPastEpoch(secondsPastEpoch),nanoseconds(nanoseconds),userTag(userTag)
|
||||
{
|
||||
normalize();
|
||||
}
|
||||
|
||||
void TimeStamp::normalize()
|
||||
{
|
||||
if(nanoSeconds>=0 && nanoSeconds<nanoSecPerSec) return;
|
||||
while(nanoSeconds>=nanoSecPerSec) {
|
||||
nanoSeconds -= nanoSecPerSec;
|
||||
if(nanoseconds>=0 && nanoseconds<nanoSecPerSec) return;
|
||||
while(nanoseconds>=nanoSecPerSec) {
|
||||
nanoseconds -= nanoSecPerSec;
|
||||
secondsPastEpoch++;
|
||||
}
|
||||
while(nanoSeconds<0) {
|
||||
nanoSeconds += nanoSecPerSec;
|
||||
while(nanoseconds<0) {
|
||||
nanoseconds += nanoSecPerSec;
|
||||
secondsPastEpoch--;
|
||||
}
|
||||
}
|
||||
@@ -51,21 +51,21 @@ void TimeStamp::fromTime_t(const time_t & tt)
|
||||
epicsTimeStamp epicsTime;
|
||||
epicsTimeFromTime_t(&epicsTime,tt);
|
||||
secondsPastEpoch = epicsTime.secPastEpoch + posixEpochAtEpicsEpoch;
|
||||
nanoSeconds = epicsTime.nsec;
|
||||
nanoseconds = epicsTime.nsec;
|
||||
}
|
||||
|
||||
void TimeStamp::toTime_t(time_t &tt) const
|
||||
{
|
||||
epicsTimeStamp epicsTime;
|
||||
epicsTime.secPastEpoch = static_cast<epicsUInt32>(secondsPastEpoch-posixEpochAtEpicsEpoch);
|
||||
epicsTime.nsec = nanoSeconds;
|
||||
epicsTime.nsec = nanoseconds;
|
||||
epicsTimeToTime_t(&tt,&epicsTime);
|
||||
}
|
||||
|
||||
void TimeStamp::put(int64 milliseconds)
|
||||
{
|
||||
secondsPastEpoch = milliseconds/1000;
|
||||
nanoSeconds = (milliseconds%1000)*1000000;
|
||||
nanoseconds = (milliseconds%1000)*1000000;
|
||||
}
|
||||
|
||||
void TimeStamp::getCurrent()
|
||||
@@ -74,13 +74,13 @@ void TimeStamp::getCurrent()
|
||||
epicsTimeGetCurrent(&epicsTime);
|
||||
secondsPastEpoch = epicsTime.secPastEpoch;
|
||||
secondsPastEpoch += posixEpochAtEpicsEpoch;
|
||||
nanoSeconds = epicsTime.nsec;
|
||||
nanoseconds = epicsTime.nsec;
|
||||
}
|
||||
|
||||
double TimeStamp::toSeconds() const
|
||||
{
|
||||
double value = static_cast<double>(secondsPastEpoch);
|
||||
double nano = nanoSeconds;
|
||||
double nano = nanoseconds;
|
||||
value += nano/1e9;
|
||||
return value;
|
||||
}
|
||||
@@ -88,9 +88,9 @@ double TimeStamp::toSeconds() const
|
||||
int64 TimeStamp::diffInt(TimeStamp const & left,TimeStamp const&right )
|
||||
{
|
||||
int64 sl = left.secondsPastEpoch;
|
||||
int32 nl = left.nanoSeconds;
|
||||
int32 nl = left.nanoseconds;
|
||||
int64 sr = right.secondsPastEpoch;
|
||||
int32 nr = right.nanoSeconds;
|
||||
int32 nr = right.nanoseconds;
|
||||
int64 sdiff = sl - sr;
|
||||
sdiff *= nanoSecPerSec;
|
||||
sdiff += nl - nr;
|
||||
@@ -142,7 +142,7 @@ bool TimeStamp::operator>(TimeStamp const &right) const
|
||||
double TimeStamp::diff(TimeStamp const & a,TimeStamp const & b)
|
||||
{
|
||||
double result = static_cast<double>(a.secondsPastEpoch - b.secondsPastEpoch);
|
||||
result += (a.nanoSeconds - b.nanoSeconds)/1e9;
|
||||
result += (a.nanoseconds - b.nanoseconds)/1e9;
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -163,12 +163,12 @@ TimeStamp & TimeStamp::operator+=(double seconds)
|
||||
{
|
||||
int64 secs = static_cast<int64>(seconds);
|
||||
int64 nano = static_cast<int64>((seconds - secs)*1e9);
|
||||
nanoSeconds += static_cast<int32>(nano);
|
||||
if(nanoSeconds>nanoSecPerSec) {
|
||||
nanoSeconds -= nanoSecPerSec;
|
||||
nanoseconds += static_cast<int32>(nano);
|
||||
if(nanoseconds>nanoSecPerSec) {
|
||||
nanoseconds -= nanoSecPerSec;
|
||||
secondsPastEpoch += 1;
|
||||
} else if(nanoSeconds<-nanoSecPerSec) {
|
||||
nanoSeconds += -nanoSecPerSec;
|
||||
} else if(nanoseconds<-nanoSecPerSec) {
|
||||
nanoseconds += -nanoSecPerSec;
|
||||
secondsPastEpoch -= 1;
|
||||
}
|
||||
secondsPastEpoch += secs;
|
||||
@@ -182,7 +182,7 @@ TimeStamp & TimeStamp::operator-=(double seconds)
|
||||
|
||||
int64 TimeStamp::getMilliseconds()
|
||||
{
|
||||
return secondsPastEpoch*1000 + nanoSeconds/1000000;
|
||||
return secondsPastEpoch*1000 + nanoseconds/1000000;
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
@@ -35,47 +35,162 @@ epicsShareExtern int32 microSecPerSec;
|
||||
epicsShareExtern int32 nanoSecPerSec;
|
||||
epicsShareExtern int64 posixEpochAtEpicsEpoch;
|
||||
|
||||
/** @brief Methods for manipulating timeStamp.
|
||||
*
|
||||
* A timeStamp structure has the following fields:
|
||||
@code
|
||||
structure
|
||||
long secondsPastEpoch
|
||||
int nanoseconds
|
||||
int userTag
|
||||
@endcode
|
||||
* This is a class that holds values corresponding to the fields in
|
||||
* a timeStamp structure.
|
||||
* It is meant to be used together with pvTimeStamp
|
||||
* which allows values to be copied between an timeStamp structure
|
||||
* and this class.
|
||||
* This class should not be extended.
|
||||
*/
|
||||
class epicsShareClass TimeStamp {
|
||||
public:
|
||||
/**
|
||||
* Default constructor
|
||||
*/
|
||||
TimeStamp()
|
||||
:secondsPastEpoch(0), nanoSeconds(0), userTag(0) {}
|
||||
TimeStamp(int64 secondsPastEpoch,int32 nanoSeconds = 0,int32 userTag = 0);
|
||||
:secondsPastEpoch(0), nanoseconds(0), userTag(0) {}
|
||||
/**
|
||||
* Constructor
|
||||
* @param secondsPastEpoch seconds since 1970 UTC
|
||||
* @param nanoseconds nanoseconds since secondsPastEpoch
|
||||
* @param userTag application specific
|
||||
*/
|
||||
TimeStamp(int64 secondsPastEpoch,int32 nanoseconds = 0,int32 userTag = 0);
|
||||
//default constructors and destructor are OK
|
||||
//This class should not be extended
|
||||
/**
|
||||
* adjust secondsPastEpoch and nanoseconds so that
|
||||
* 0 <= nanoseconds < nanoSecPerSec
|
||||
*/
|
||||
void normalize();
|
||||
void fromTime_t(const time_t &);
|
||||
void toTime_t(time_t &) const;
|
||||
/**
|
||||
* Set timeStamp from standard C time
|
||||
* @param time time as returned by std::time
|
||||
*/
|
||||
void fromTime_t(const time_t & time);
|
||||
/**
|
||||
* Set time from timeStamp
|
||||
* @param time time as defined by std::time
|
||||
*/
|
||||
void toTime_t(time_t &time) const;
|
||||
/**
|
||||
* Get secondsPastEpoch.
|
||||
* @return The secondsPastEpoch.
|
||||
*/
|
||||
int64 getSecondsPastEpoch() const {return secondsPastEpoch;}
|
||||
/**
|
||||
* Get secondsPastEpoch for EPICS V3.
|
||||
* This is seconds since 1990 UTC.
|
||||
* @return The epics V3 secondsPastEpoch.
|
||||
*/
|
||||
int64 getEpicsSecondsPastEpoch() const {
|
||||
return secondsPastEpoch - posixEpochAtEpicsEpoch;
|
||||
}
|
||||
int32 getNanoSeconds() const {return nanoSeconds;}
|
||||
/**
|
||||
* Get nanoseconds.
|
||||
* @return nanoseconds within timeStamp.
|
||||
*/
|
||||
int32 getNanoseconds() const {return nanoseconds;}
|
||||
/**
|
||||
* Get userTag.
|
||||
* @return userTag.
|
||||
*/
|
||||
int32 getUserTag() const {return userTag;}
|
||||
/**
|
||||
* Set userTag.
|
||||
* @param userTag application specific.
|
||||
*/
|
||||
void setUserTag(int userTag) {this->userTag = userTag;}
|
||||
void put(int64 secondsPastEpoch,int32 nanoSeconds = 0) {
|
||||
/**
|
||||
* Set time fields in timeStamp.
|
||||
* Result will be normalized.
|
||||
* @param secondsPastEpoch seconds part of timeStamp.
|
||||
* @param nanoseconds nanoseconds part of timeStamp.
|
||||
*/
|
||||
void put(int64 secondsPastEpoch,int32 nanoseconds = 0) {
|
||||
this->secondsPastEpoch = secondsPastEpoch;
|
||||
this->nanoSeconds = nanoSeconds;
|
||||
this->nanoseconds = nanoseconds;
|
||||
normalize();
|
||||
}
|
||||
/**
|
||||
* Set time fields in timeStamp.
|
||||
* @param milliseconds The number of milliseconds since the epoch.
|
||||
*/
|
||||
void put(int64 milliseconds);
|
||||
/**
|
||||
* Set the timeStamp to the current time.
|
||||
*/
|
||||
void getCurrent();
|
||||
/**
|
||||
* Convert the timeStamp to a double value that is seconds past epoch.
|
||||
* @return seconds past 1970 UTC
|
||||
*/
|
||||
double toSeconds() const ;
|
||||
/**
|
||||
* Standard C++ operator.
|
||||
*/
|
||||
bool operator==(TimeStamp const &) const;
|
||||
/**
|
||||
* Standard C++ operator.
|
||||
*/
|
||||
bool operator!=(TimeStamp const &) const;
|
||||
/**
|
||||
* Standard C++ operator.
|
||||
*/
|
||||
bool operator<=(TimeStamp const &) const;
|
||||
/**
|
||||
* Standard C++ operator.
|
||||
*/
|
||||
bool operator< (TimeStamp const &) const;
|
||||
/**
|
||||
* Standard C++ operator.
|
||||
*/
|
||||
bool operator>=(TimeStamp const &) const;
|
||||
/**
|
||||
* Standard C++ operator.
|
||||
*/
|
||||
bool operator> (TimeStamp const &) const;
|
||||
/**
|
||||
* Return a-b as a double value with units of seconds.
|
||||
* @param a first timeStamp
|
||||
* @param b second timeStamp
|
||||
* @return time difference in seconds.
|
||||
*/
|
||||
static double diff(TimeStamp const & a,TimeStamp const & b);
|
||||
/**
|
||||
* Standard C++ operator.
|
||||
*/
|
||||
TimeStamp & operator+=(int64 seconds);
|
||||
/**
|
||||
* Standard C++ operator.
|
||||
*/
|
||||
TimeStamp & operator-=(int64 seconds);
|
||||
/**
|
||||
* Standard C++ operator.
|
||||
*/
|
||||
TimeStamp & operator+=(double seconds);
|
||||
/**
|
||||
* Standard C++ operator.
|
||||
*/
|
||||
TimeStamp & operator-=(double seconds);
|
||||
int64 getMilliseconds(); // milliseconds since epoch
|
||||
/**
|
||||
* Get number of milliseconds past epoch.
|
||||
* @return milliseconds past epoch.
|
||||
*/
|
||||
int64 getMilliseconds();
|
||||
private:
|
||||
static int64 diffInt(TimeStamp const &left,TimeStamp const &right );
|
||||
int64 secondsPastEpoch;
|
||||
int32 nanoSeconds;
|
||||
int32 nanoseconds;
|
||||
int32 userTag;
|
||||
};
|
||||
|
||||
|
||||
238
src/pv/convert.h
238
src/pv/convert.h
@@ -22,37 +22,12 @@
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
bool epicsShareExtern operator==(const PVField&, const PVField&);
|
||||
|
||||
static inline bool operator!=(const PVField& a, const PVField& b)
|
||||
{return !(a==b);}
|
||||
|
||||
|
||||
bool epicsShareExtern operator==(const Field&, const Field&);
|
||||
bool epicsShareExtern operator==(const Scalar&, const Scalar&);
|
||||
bool epicsShareExtern operator==(const ScalarArray&, const ScalarArray&);
|
||||
bool epicsShareExtern operator==(const Structure&, const Structure&);
|
||||
bool epicsShareExtern operator==(const StructureArray&, const StructureArray&);
|
||||
bool epicsShareExtern operator==(const Union&, const Union&);
|
||||
bool epicsShareExtern operator==(const UnionArray&, const UnionArray&);
|
||||
|
||||
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);}
|
||||
static inline bool operator!=(const Union& a, const Union& b)
|
||||
{return !(a==b);}
|
||||
static inline bool operator!=(const UnionArray& a, const UnionArray& b)
|
||||
{return !(a==b);}
|
||||
|
||||
class Convert;
|
||||
typedef std::tr1::shared_ptr<Convert> ConvertPtr;
|
||||
|
||||
/**
|
||||
* @brief Conversion and Copy facility for pvData.
|
||||
*
|
||||
* 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
|
||||
@@ -63,9 +38,7 @@ static inline bool operator!=(const UnionArray& a, const UnionArray& b)
|
||||
* pvUByte, pvUShort, pvUInt, pvULong,
|
||||
* pvFloat, or pvDouble.</p>
|
||||
*
|
||||
* <p>getString converts any supported type to a std::string.
|
||||
* Code that implements a PVField interface should implement
|
||||
* method toString by calling this method.</p>
|
||||
* <p>getString converts any supported type to a std::string.</p>
|
||||
*
|
||||
* <p>fromString converts a std::string to a scalar.
|
||||
* fromStringArray converts an array of std::strings
|
||||
@@ -73,85 +46,45 @@ static inline bool operator!=(const UnionArray& a, const UnionArray& b)
|
||||
* 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 epicsShareClass Convert {
|
||||
public:
|
||||
static ConvertPtr getConvert();
|
||||
/**
|
||||
* Get the full fieldName for the pvField.
|
||||
* @param builder The builder that will have the result.
|
||||
* @param pvField The pvField.
|
||||
*/
|
||||
void getFullName(std::string *buf,PVFieldPtr const & pvField)
|
||||
{
|
||||
*buf = pvField->getFullName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Do fields have the same definition.
|
||||
*
|
||||
* @param First field
|
||||
* @param Second field
|
||||
* @return (false, true) if the fields (are not, are) the same.
|
||||
* 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.
|
||||
* @deprecated use "to->copy[Unchecked](*from)" instead
|
||||
*/
|
||||
inline bool equals(PVFieldPtr const &a,PVFieldPtr const &b)
|
||||
{
|
||||
return *a==*b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do fields have the same definition.
|
||||
*
|
||||
* @param First field
|
||||
* @param Second field
|
||||
* @return (false, true) if the fields (are not, are) the same.
|
||||
*/
|
||||
inline bool equals(PVField &a,PVField &b)
|
||||
{
|
||||
return a==b;
|
||||
void copy(PVFieldPtr const & from, PVFieldPtr const & to) {
|
||||
to->copy(*from);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
inline void getString(std::string *buf,PVFieldPtr const & pvField,int indentLevel)
|
||||
{getString(buf, pvField.get(), 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.
|
||||
* @param buf string that will hold pvField converted to a string,
|
||||
* @param pvField The PVField to convert to a string.
|
||||
*/
|
||||
inline void getString(std::string * buf,PVFieldPtr const & pvField)
|
||||
{getString(buf, pvField.get(), 0);}
|
||||
/**
|
||||
* 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 buf string that will hold pvField converted to a string,
|
||||
* @param pvField The PVField to convert to a string.
|
||||
* @param indentLevel indentation level
|
||||
*/
|
||||
void getString(std::string * 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.
|
||||
*/
|
||||
inline void getString(std::string * buf,PVField const * pvField)
|
||||
{getString(buf, pvField, 0);}
|
||||
/**
|
||||
* Convert from an array of std::string to a PVScalar
|
||||
* Convert from an array of std::string to a PVStructure
|
||||
* @param pv The PV.
|
||||
* @param from The array of std::string value to convert and put into a PV.
|
||||
* @param fromStartIndex The first element if the array of strings.
|
||||
* @return The total number of fields that have been changed.
|
||||
* @throws std::logic_error if the array of std::string does not have a valid values.
|
||||
*/
|
||||
std::size_t fromString(
|
||||
@@ -211,129 +144,7 @@ public:
|
||||
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);
|
||||
/**
|
||||
* 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);
|
||||
/**
|
||||
* Are from and to valid arguments for copyUnion.
|
||||
* They are only compatible if they have the same Union description.
|
||||
* @param from from union.
|
||||
* @param to union.
|
||||
* @return (false,true) If the arguments (are not, are) compatible.
|
||||
*/
|
||||
bool isCopyUnionCompatible(
|
||||
UnionConstPtr const & from, UnionConstPtr const & to);
|
||||
/**
|
||||
* Copy from a union pv to another union pv.
|
||||
* NOTE: Only compatible nodes are copied.
|
||||
* @param from The source.
|
||||
* @param to The destination.
|
||||
* @throws std::invalid_argument if the arguments are not compatible.
|
||||
*/
|
||||
void copyUnion(PVUnionPtr const & from, PVUnionPtr const & to);
|
||||
/**
|
||||
* Are from and to valid for copyUnionArray.
|
||||
* @param from The from UnionArray.
|
||||
* @param to The to UnionArray.
|
||||
* @return (false,true) If the arguments (are not, are) compatible.
|
||||
*/
|
||||
bool isCopyUnionArrayCompatible(
|
||||
UnionArrayConstPtr const & from, UnionArrayConstPtr const & to);
|
||||
/**
|
||||
* Copy from a union array to another union array.
|
||||
* @param from The source array.
|
||||
* @param to The destination array.
|
||||
*/
|
||||
void copyUnionArray(
|
||||
PVUnionArrayPtr const & from, PVUnionArrayPtr const & to);
|
||||
/**
|
||||
* Convert a PV to a <byte>.
|
||||
* Convert a PV to a byte.
|
||||
* @param pv a PV
|
||||
* @return converted value
|
||||
*/
|
||||
@@ -477,13 +288,6 @@ public:
|
||||
*/
|
||||
inline void fromDouble(PVScalarPtr const & pv, double from) { pv->putFrom<double>(from); }
|
||||
|
||||
/**
|
||||
* Convenience method for implementing toString.
|
||||
* 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.
|
||||
*/
|
||||
void newLine(std::string * buf, int indentLevel);
|
||||
};
|
||||
|
||||
static inline ConvertPtr getConvert() { return Convert::getConvert(); }
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
#ifndef PRINTER_H
|
||||
#define PRINTER_H
|
||||
|
||||
#include <ostream>
|
||||
#include <shareLib.h>
|
||||
|
||||
#include "pvData.h"
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
class PrinterBase
|
||||
{
|
||||
public:
|
||||
virtual void setStream(std::ostream&);
|
||||
virtual void clearStream();
|
||||
|
||||
virtual void print(const PVField&);
|
||||
|
||||
protected:
|
||||
PrinterBase();
|
||||
virtual ~PrinterBase()=0;
|
||||
|
||||
virtual void beginStructure(const PVStructure&);
|
||||
virtual void endStructure(const PVStructure&);
|
||||
|
||||
virtual void beginStructureArray(const PVStructureArray&);
|
||||
virtual void endStructureArray(const PVStructureArray&);
|
||||
|
||||
virtual void beginUnion(const PVUnion&);
|
||||
virtual void endUnion(const PVUnion&);
|
||||
|
||||
virtual void beginUnionArray(const PVUnionArray&);
|
||||
virtual void endUnionArray(const PVUnionArray&);
|
||||
|
||||
virtual void encodeScalar(const PVScalar&);
|
||||
virtual void encodeArray(const PVScalarArray&);
|
||||
virtual void encodeNull();
|
||||
|
||||
inline std::ostream& S() { return *strm; }
|
||||
|
||||
void impl_print(const PVField&);
|
||||
private:
|
||||
std::ostream *strm;
|
||||
};
|
||||
|
||||
class PrinterPlain : public PrinterBase
|
||||
{
|
||||
size_t ilvl;
|
||||
protected:
|
||||
virtual void beginStructure(const PVStructure&);
|
||||
virtual void endStructure(const PVStructure&);
|
||||
|
||||
virtual void beginStructureArray(const PVStructureArray&);
|
||||
virtual void endStructureArray(const PVStructureArray&);
|
||||
|
||||
virtual void beginUnion(const PVUnion&);
|
||||
virtual void endUnion(const PVUnion&);
|
||||
|
||||
virtual void beginUnionArray(const PVUnionArray&);
|
||||
virtual void endUnionArray(const PVUnionArray&);
|
||||
|
||||
virtual void encodeScalar(const PVScalar&);
|
||||
virtual void encodeArray(const PVScalarArray&);
|
||||
virtual void encodeNull();
|
||||
|
||||
public:
|
||||
PrinterPlain();
|
||||
virtual ~PrinterPlain();
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif // PRINTER_H
|
||||
485
src/pv/pvData.h
485
src/pv/pvData.h
@@ -33,6 +33,14 @@
|
||||
typedef class std::ios std::ios_base;
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && !(defined(__vxworks) && !defined(_WRS_VXWORKS_MAJOR))
|
||||
#define USAGE_DEPRECATED __attribute__((deprecated))
|
||||
#define USAGE_ERROR(MSG) __attribute__((error(MSG)))
|
||||
#else
|
||||
#define USAGE_DEPRECATED
|
||||
#define USAGE_ERROR(MSG) { throw std::runtime_error(MSG); }
|
||||
#endif
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
class PostHandler;
|
||||
@@ -122,7 +130,8 @@ class PVDataCreate;
|
||||
typedef std::tr1::shared_ptr<PVDataCreate> PVDataCreatePtr;
|
||||
|
||||
/**
|
||||
* This class is implemented by code that calls setPostHander
|
||||
* @brief This class is implemented by code that calls setPostHander
|
||||
*
|
||||
*/
|
||||
class epicsShareClass PostHandler
|
||||
{
|
||||
@@ -133,13 +142,14 @@ public:
|
||||
*/
|
||||
virtual ~PostHandler(){}
|
||||
/**
|
||||
* This is called evertime postPut is called for this field.
|
||||
* This is called every time postPut is called for this field.
|
||||
*/
|
||||
virtual void postPut() = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* PVField is the base class for each PVData field.
|
||||
* @brief PVField is the base class for each PVData field.
|
||||
*
|
||||
* Each PVData field has an interface that extends PVField.
|
||||
*/
|
||||
class epicsShareClass PVField
|
||||
@@ -158,19 +168,19 @@ public:
|
||||
virtual ~PVField();
|
||||
/**
|
||||
* Get the fieldName for this field.
|
||||
* @return The name or empty string if top level field.
|
||||
* @return The name or empty string if top-level field.
|
||||
*/
|
||||
inline const std::string& getFieldName() const {return fieldName;}
|
||||
/**
|
||||
* Fully expand the name of this field using the
|
||||
* names of its parent fields with a dot '.' seperating
|
||||
* names of its parent fields with a dot '.' separating
|
||||
* each name.
|
||||
*/
|
||||
std::string getFullName() const;
|
||||
/**
|
||||
* Get offset of the PVField field within top level structure.
|
||||
* Get offset of the PVField field within top-level structure.
|
||||
* Every field within the PVStructure has a unique offset.
|
||||
* The top level structure has an offset of 0.
|
||||
* The top-level structure has an offset of 0.
|
||||
* The first field within the structure has offset equal to 1.
|
||||
* The other offsets are determined by recursively traversing each structure of the tree.
|
||||
* @return The offset.
|
||||
@@ -194,8 +204,8 @@ public:
|
||||
*/
|
||||
bool isImmutable() const;
|
||||
/**
|
||||
* Set the field to be immutable, i. e. it can no longer be modified.
|
||||
* This is permanent, i.e. once done the field can onot be made mutable.
|
||||
* Set the field to be immutable, i.e. it can no longer be modified.
|
||||
* This is permanent, i.e. once done the field cannot be made mutable.
|
||||
*/
|
||||
virtual void setImmutable();
|
||||
/**
|
||||
@@ -231,12 +241,15 @@ public:
|
||||
*/
|
||||
virtual std::ostream& dumpValue(std::ostream& o) const = 0;
|
||||
|
||||
void copy(const PVField& from);
|
||||
void copyUnchecked(const PVField& from);
|
||||
|
||||
protected:
|
||||
PVField::shared_pointer getPtrSelf()
|
||||
{
|
||||
return shared_from_this();
|
||||
}
|
||||
PVField(FieldConstPtr field);
|
||||
explicit PVField(FieldConstPtr field);
|
||||
void setParentAndName(PVStructure *parent, std::string const & fieldName);
|
||||
private:
|
||||
static void computeOffset(const PVField *pvField);
|
||||
@@ -256,7 +269,8 @@ private:
|
||||
epicsShareExtern std::ostream& operator<<(std::ostream& o, const PVField& f);
|
||||
|
||||
/**
|
||||
* PVScalar is the base class for each scalar field.
|
||||
* @brief PVScalar is the base class for each scalar field.
|
||||
*
|
||||
*/
|
||||
class epicsShareClass PVScalar : public PVField {
|
||||
// friend our child class(s) so that it
|
||||
@@ -317,12 +331,16 @@ public:
|
||||
|
||||
virtual void assign(const PVScalar&) = 0;
|
||||
|
||||
virtual void copy(const PVScalar& from) = 0;
|
||||
virtual void copyUnchecked(const PVScalar& from) = 0;
|
||||
|
||||
protected:
|
||||
PVScalar(ScalarConstPtr const & scalar);
|
||||
explicit PVScalar(ScalarConstPtr const & scalar);
|
||||
};
|
||||
|
||||
/**
|
||||
* Class that holds the data for each posssible scalar type.
|
||||
* @brief Class that holds the data for each possible scalar type.
|
||||
*
|
||||
*/
|
||||
template<typename T>
|
||||
class epicsShareClass PVScalarValue : public PVScalar {
|
||||
@@ -345,7 +363,7 @@ public:
|
||||
virtual T get() const = 0;
|
||||
/**
|
||||
* Put a new value into the PVScalar.
|
||||
* @param The value.
|
||||
* @param value The value.
|
||||
*/
|
||||
virtual void put(T value) = 0;
|
||||
|
||||
@@ -381,8 +399,27 @@ public:
|
||||
put(castUnsafe<T,T1>(val));
|
||||
}
|
||||
|
||||
virtual void assign(const PVScalar& scalar)
|
||||
{
|
||||
if(isImmutable())
|
||||
throw std::invalid_argument("destination is immutable");
|
||||
copyUnchecked(scalar);
|
||||
}
|
||||
virtual void copy(const PVScalar& from)
|
||||
{
|
||||
assign(from);
|
||||
}
|
||||
virtual void copyUnchecked(const PVScalar& from)
|
||||
{
|
||||
if(this==&from)
|
||||
return;
|
||||
T result;
|
||||
from.getAs((void*)&result, typeCode);
|
||||
put(result);
|
||||
}
|
||||
|
||||
protected:
|
||||
PVScalarValue(ScalarConstPtr const & scalar)
|
||||
explicit PVScalarValue(ScalarConstPtr const & scalar)
|
||||
: PVScalar(scalar) {}
|
||||
virtual void getAs(void * result, ScalarType rtype) const
|
||||
{
|
||||
@@ -395,16 +432,6 @@ protected:
|
||||
castUnsafeV(1, typeCode, (void*)&result, stype, src);
|
||||
put(result);
|
||||
}
|
||||
virtual void assign(const PVScalar& scalar)
|
||||
{
|
||||
if(this==&scalar)
|
||||
return;
|
||||
if(isImmutable())
|
||||
throw std::invalid_argument("Destination is immutable");
|
||||
T result;
|
||||
scalar.getAs((void*)&result, typeCode);
|
||||
put(result);
|
||||
}
|
||||
|
||||
private:
|
||||
friend class PVDataCreate;
|
||||
@@ -437,7 +464,8 @@ typedef std::tr1::shared_ptr<PVFloat> PVFloatPtr;
|
||||
typedef std::tr1::shared_ptr<PVDouble> PVDoublePtr;
|
||||
|
||||
/**
|
||||
* PVString is special case, since it implements SerializableArray
|
||||
* @brief PVString is special case, since it implements SerializableArray
|
||||
*
|
||||
*/
|
||||
class epicsShareClass PVString : public PVScalarValue<std::string>, SerializableArray {
|
||||
public:
|
||||
@@ -446,14 +474,18 @@ public:
|
||||
*/
|
||||
virtual ~PVString() {}
|
||||
protected:
|
||||
PVString(ScalarConstPtr const & scalar)
|
||||
explicit PVString(ScalarConstPtr const & scalar)
|
||||
: PVScalarValue<std::string>(scalar) {}
|
||||
};
|
||||
typedef std::tr1::shared_ptr<PVString> PVStringPtr;
|
||||
|
||||
|
||||
/**
|
||||
* PVArray is the base class for all array types, i.e. the scalarArray types and structureArray.
|
||||
* @brief PVArray is the base class for all array types.
|
||||
*
|
||||
* The array types are unionArray, strucrtureArray and scalarArray.
|
||||
* There is a scalarArray type for each scalarType.
|
||||
*
|
||||
*/
|
||||
class epicsShareClass PVArray : public PVField, public SerializableArray {
|
||||
public:
|
||||
@@ -472,8 +504,8 @@ public:
|
||||
*/
|
||||
virtual ArrayConstPtr getArray() const = 0;
|
||||
/**
|
||||
* Set the field to be immutable, i. e. it can no longer be modified.
|
||||
* This is permanent, i.e. once done the field can onot be made mutable.
|
||||
* Set the field to be immutable, i.e. it can no longer be modified.
|
||||
* This is permanent, i.e. once done the field cannot be made mutable.
|
||||
*/
|
||||
virtual void setImmutable();
|
||||
/**
|
||||
@@ -483,7 +515,7 @@ public:
|
||||
virtual std::size_t getLength() const = 0;
|
||||
/**
|
||||
* Set the array length.
|
||||
* @param The length.
|
||||
* @param length The length.
|
||||
*/
|
||||
virtual void setLength(std::size_t length) = 0;
|
||||
/**
|
||||
@@ -503,14 +535,16 @@ public:
|
||||
void setCapacityMutable(bool isMutable);
|
||||
/**
|
||||
* Set the array capacity.
|
||||
* @param The capacity.
|
||||
* @param capacity The capacity.
|
||||
*/
|
||||
virtual void setCapacity(std::size_t capacity) = 0;
|
||||
|
||||
using PVField::dumpValue;
|
||||
virtual std::ostream& dumpValue(std::ostream& o, std::size_t index) const = 0;
|
||||
|
||||
protected:
|
||||
PVArray(FieldConstPtr const & field);
|
||||
explicit PVArray(FieldConstPtr const & field);
|
||||
void checkLength(size_t length);
|
||||
private:
|
||||
bool capacityMutable;
|
||||
friend class PVDataCreate;
|
||||
@@ -518,9 +552,9 @@ private:
|
||||
|
||||
epicsShareExtern std::ostream& operator<<(format::array_at_internal const& manip, const PVArray& array);
|
||||
|
||||
|
||||
/**
|
||||
* Base class for a scalarArray.
|
||||
* @brief Base class for a scalarArray.
|
||||
*
|
||||
*/
|
||||
class epicsShareClass PVScalarArray : public PVArray {
|
||||
public:
|
||||
@@ -568,7 +602,7 @@ public:
|
||||
* A copy and element-wise conversion is performed unless
|
||||
* the element type of the PVScalarArray matches the
|
||||
* type of the provided data.
|
||||
* If the types do match then a new refernce to the provided
|
||||
* If the types do match then a new reference to the provided
|
||||
* data is kept.
|
||||
*
|
||||
* Calls postPut()
|
||||
@@ -586,22 +620,38 @@ public:
|
||||
* A copy and element-wise conversion is performed unless
|
||||
* the element type of the PVScalarArray matches the
|
||||
* type of the provided data.
|
||||
* If the types do match then a new refernce to the provided
|
||||
* If the types do match then a new reference to the provided
|
||||
* data is kept.
|
||||
*/
|
||||
void assign(PVScalarArray& pv) {
|
||||
void assign(const PVScalarArray& pv) {
|
||||
if (isImmutable())
|
||||
throw std::invalid_argument("destination is immutable");
|
||||
copyUnchecked(pv);
|
||||
}
|
||||
|
||||
void copy(const PVScalarArray& from) {
|
||||
assign(from);
|
||||
}
|
||||
|
||||
void copyUnchecked(const PVScalarArray& from) {
|
||||
if (this==&from)
|
||||
return;
|
||||
shared_vector<const void> temp;
|
||||
pv._getAsVoid(temp);
|
||||
from._getAsVoid(temp);
|
||||
_putFromVoid(temp);
|
||||
}
|
||||
|
||||
protected:
|
||||
PVScalarArray(ScalarArrayConstPtr const & scalarArray);
|
||||
explicit PVScalarArray(ScalarArrayConstPtr const & scalarArray);
|
||||
private:
|
||||
friend class PVDataCreate;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Data interface for a structure,
|
||||
*
|
||||
*/
|
||||
class epicsShareClass PVStructure : public PVField, public BitSetSerializable
|
||||
{
|
||||
public:
|
||||
@@ -613,8 +663,8 @@ public:
|
||||
typedef PVStructure & reference;
|
||||
typedef const PVStructure & const_reference;
|
||||
/**
|
||||
* Set the field to be immutable, i. e. it can no longer be modified.
|
||||
* This is permanent, i.e. once done the field can onot be made mutable.
|
||||
* Set the field to be immutable, i.e. it can no longer be modified.
|
||||
* This is permanent, i.e. once done the field cannot be made mutable.
|
||||
*/
|
||||
virtual void setImmutable();
|
||||
/**
|
||||
@@ -634,23 +684,42 @@ public:
|
||||
*/
|
||||
PVFieldPtr getSubField(std::string const &fieldName) const;
|
||||
|
||||
/**
|
||||
* Get a subfield with the specified name.
|
||||
* @param fieldName a '.' separated list of child field names (no whitespace allowed)
|
||||
* @returns A pointer to the sub-field or null if field does not exist or has a different type
|
||||
* @code
|
||||
* PVIntPtr ptr = pvStruct->getSubField<PVInt>("substruct.leaffield");
|
||||
* @endcode
|
||||
*/
|
||||
template<typename PVT>
|
||||
std::tr1::shared_ptr<PVT> getSubField(std::string const &fieldName) const
|
||||
FORCE_INLINE std::tr1::shared_ptr<PVT> getSubField(std::string const &fieldName) const
|
||||
{
|
||||
PVFieldPtr pvField = getSubField(fieldName);
|
||||
if (pvField.get())
|
||||
return std::tr1::dynamic_pointer_cast<PVT>(pvField);
|
||||
return this->getSubField<PVT>(fieldName.c_str());
|
||||
}
|
||||
|
||||
template<typename PVT>
|
||||
std::tr1::shared_ptr<PVT> getSubField(const char *name) const
|
||||
{
|
||||
PVField *raw = getSubFieldImpl(name, false);
|
||||
if (raw)
|
||||
return std::tr1::dynamic_pointer_cast<PVT>(raw->shared_from_this());
|
||||
else
|
||||
return std::tr1::shared_ptr<PVT>();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the subfield with the specified offset.
|
||||
* @param fieldOffset The offset.
|
||||
* @return Pointer to the field or null if field does not exist.
|
||||
*/
|
||||
PVFieldPtr getSubField(std::size_t fieldOffset) const;
|
||||
|
||||
|
||||
/**
|
||||
* Get the subfield with the specified offset.
|
||||
* @param fieldOffset The offset.
|
||||
* @return Pointer to the field or null if field does not exist.
|
||||
*/
|
||||
template<typename PVT>
|
||||
std::tr1::shared_ptr<PVT> getSubField(std::size_t fieldOffset) const
|
||||
{
|
||||
@@ -662,127 +731,51 @@ public:
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a boolean field with the specified name.
|
||||
* No longer needed. Use templete version of getSubField
|
||||
* @param fieldName The name of the field to get.
|
||||
* @return Pointer to the field of null if a field with that name and type does not exist.
|
||||
* Get a subfield with the specified name.
|
||||
* @param fieldName a '.' separated list of child field names (no whitespace allowed)
|
||||
* @returns A reference to the sub-field (never NULL)
|
||||
* @throws std::runtime_error if the requested sub-field doesn't exist, or has a different type
|
||||
*/
|
||||
PVBooleanPtr getBooleanField(std::string const &fieldName) ;
|
||||
FORCE_INLINE PVFieldPtr getSubFieldT(std::string const &fieldName) const
|
||||
{
|
||||
return getSubFieldImpl(fieldName.c_str())->shared_from_this();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a byte field with the specified name.
|
||||
* No longer needed. Use templete version of getSubField
|
||||
* @param fieldName The name of the field to get.
|
||||
* @return Pointer to the field of null if a field with that name and type does not exist.
|
||||
* Get a subfield with the specified name.
|
||||
* @param fieldName a '.' separated list of child field names (no whitespace allowed)
|
||||
* @returns A reference to the sub-field (never NULL)
|
||||
* @throws std::runtime_error if the requested sub-field doesn't exist, or has a different type
|
||||
* @code
|
||||
* PVIntPtr ptr = pvStruct->getSubFieldT<PVInt>("substruct.leaffield");
|
||||
* @endcode
|
||||
*/
|
||||
PVBytePtr getByteField(std::string const &fieldName) ;
|
||||
template<typename PVT>
|
||||
FORCE_INLINE std::tr1::shared_ptr<PVT> getSubFieldT(std::string const &fieldName) const
|
||||
{
|
||||
return this->getSubFieldT<PVT>(fieldName.c_str());
|
||||
}
|
||||
|
||||
template<typename PVT>
|
||||
std::tr1::shared_ptr<PVT> getSubFieldT(const char *name) const;
|
||||
|
||||
/**
|
||||
* Get a short field with the specified name.
|
||||
* No longer needed. Use templete version of getSubField
|
||||
* @param fieldName The name of the field to get.
|
||||
* @return Pointer to the field of null if a field with that name and type does not exist.
|
||||
* Get the subfield with the specified offset.
|
||||
* @param fieldOffset The offset.
|
||||
* @returns A reference to the sub-field (never NULL)
|
||||
* @throws std::runtime_error if the requested sub-field doesn't exist
|
||||
*/
|
||||
PVShortPtr getShortField(std::string const &fieldName) ;
|
||||
PVFieldPtr getSubFieldT(std::size_t fieldOffset) const;
|
||||
|
||||
/**
|
||||
* Get a int field with the specified name.
|
||||
* No longer needed. Use templete version of getSubField
|
||||
* @param fieldName The name of the field to get.
|
||||
* @return Pointer to the field of null if a field with that name and type does not exist.
|
||||
* Get the subfield with the specified offset.
|
||||
* @param fieldOffset The offset.
|
||||
* @returns A reference to the sub-field (never NULL)
|
||||
* @throws std::runtime_error if the requested sub-field doesn't exist, or has a different type
|
||||
*/
|
||||
PVIntPtr getIntField(std::string const &fieldName) ;
|
||||
/**
|
||||
* Get a long field with the specified name.
|
||||
* No longer needed. Use templete version of getSubField
|
||||
* @param fieldName The name of the field to get.
|
||||
* @return Pointer to the field of null if a field with that name and type does not exist.
|
||||
*/
|
||||
PVLongPtr getLongField(std::string const &fieldName) ;
|
||||
/**
|
||||
* Get an unsigned byte field with the specified name.
|
||||
* No longer needed. Use templete version of getSubField
|
||||
* @param fieldName The name of the field to get.
|
||||
* @return Pointer to the field of null if a field with that name and type does not exist.
|
||||
*/
|
||||
PVUBytePtr getUByteField(std::string const &fieldName) ;
|
||||
/**
|
||||
* Get an unsigned short field with the specified name.
|
||||
* No longer needed. Use templete version of getSubField
|
||||
* @param fieldName The name of the field to get.
|
||||
* @return Pointer to the field of null if a field with that name and type does not exist.
|
||||
*/
|
||||
PVUShortPtr getUShortField(std::string const &fieldName) ;
|
||||
/**
|
||||
* Get an unsigned int field with the specified name.
|
||||
* No longer needed. Use templete version of getSubField
|
||||
* @param fieldName The name of the field to get.
|
||||
* @return Pointer to the field of null if a field with that name and type does not exist.
|
||||
*/
|
||||
PVUIntPtr getUIntField(std::string const &fieldName) ;
|
||||
/**
|
||||
* Get an unsigned long field with the specified name.
|
||||
* No longer needed. Use templete version of getSubField
|
||||
* @param fieldName The name of the field to get.
|
||||
* @return Pointer to the field of null if a field with that name and type does not exist.
|
||||
*/
|
||||
PVULongPtr getULongField(std::string const &fieldName) ;
|
||||
/**
|
||||
* Get a float field with the specified name.
|
||||
* No longer needed. Use templete version of getSubField
|
||||
* @param fieldName The name of the field to get.
|
||||
* @return Pointer to the field of null if a field with that name and type does not exist.
|
||||
*/
|
||||
PVFloatPtr getFloatField(std::string const &fieldName) ;
|
||||
/**
|
||||
* Get a double field with the specified name.
|
||||
* No longer needed. Use templete version of getSubField
|
||||
* @param fieldName The name of the field to get.
|
||||
* @return Pointer to the field of null if a field with that name and type does not exist.
|
||||
*/
|
||||
PVDoublePtr getDoubleField(std::string const &fieldName) ;
|
||||
/**
|
||||
* Get a string field with the specified name.
|
||||
* No longer needed. Use templete version of getSubField
|
||||
* @param fieldName The name of the field to get.
|
||||
* @return Pointer to the field of null if a field with that name and type does not exist.
|
||||
*/
|
||||
PVStringPtr getStringField(std::string const &fieldName) ;
|
||||
|
||||
/**
|
||||
* Get a structure field with the specified name.
|
||||
* No longer needed. Use templete version of getSubField
|
||||
* @param fieldName The name of the field to get.
|
||||
* @return Pointer to the field of null if a field with that name and type does not exist.
|
||||
*/
|
||||
PVStructurePtr getStructureField(std::string const &fieldName) ;
|
||||
/**
|
||||
* Get a union field with the specified name.
|
||||
* No longer needed. Use templete version of getSubField
|
||||
* @param fieldName The name of the field to get.
|
||||
* @return Pointer to the field of null if a field with that name and type does not exist.
|
||||
*/
|
||||
PVUnionPtr getUnionField(std::string const &fieldName) ;
|
||||
/**
|
||||
* Get a scalarArray field with the specified name.
|
||||
* No longer needed. Use templete version of getSubField
|
||||
* @param fieldName The name of the field to get.
|
||||
* @param elementType The element type.
|
||||
* @return Pointer to the field of null if a field with that name and type does not exist.
|
||||
*/
|
||||
PVScalarArrayPtr getScalarArrayField(
|
||||
std::string const &fieldName,ScalarType elementType) ;
|
||||
/**
|
||||
* Get a structureArray field with the specified name.
|
||||
* No longer needed. Use templete version of getSubField
|
||||
* @param fieldName The name of the field to get.
|
||||
* @return Pointer to the field of null if a field with that name and type does not exist.
|
||||
*/
|
||||
PVStructureArrayPtr getStructureArrayField(std::string const &fieldName) ;
|
||||
/**
|
||||
* Get a unionArray field with the specified name.
|
||||
* No longer needed. Use templete version of getSubField
|
||||
* @param fieldName The name of the field to get.
|
||||
* @return Pointer to the field of null if a field with that name and type does not exist.
|
||||
*/
|
||||
PVUnionArrayPtr getUnionArrayField(std::string const &fieldName) ;
|
||||
template<typename PVT>
|
||||
std::tr1::shared_ptr<PVT> getSubFieldT(std::size_t fieldOffset) const;
|
||||
|
||||
/**
|
||||
* Serialize.
|
||||
* @param pbuffer The byte buffer.
|
||||
@@ -817,7 +810,7 @@ public:
|
||||
* Constructor
|
||||
* @param structure The introspection interface.
|
||||
*/
|
||||
PVStructure(StructureConstPtr const & structure);
|
||||
explicit PVStructure(StructureConstPtr const & structure);
|
||||
/**
|
||||
* Constructor
|
||||
* @param structure The introspection interface.
|
||||
@@ -827,7 +820,14 @@ public:
|
||||
|
||||
virtual std::ostream& dumpValue(std::ostream& o) const;
|
||||
|
||||
void copy(const PVStructure& from);
|
||||
|
||||
void copyUnchecked(const PVStructure& from);
|
||||
void copyUnchecked(const PVStructure& from, const BitSet& maskBitSet, bool inverse = false);
|
||||
|
||||
private:
|
||||
PVField *getSubFieldImpl(const char *name, bool throws = true) const;
|
||||
|
||||
static PVFieldPtr nullPVField;
|
||||
static PVBooleanPtr nullPVBoolean;
|
||||
static PVBytePtr nullPVByte;
|
||||
@@ -854,8 +854,43 @@ private:
|
||||
};
|
||||
|
||||
|
||||
template<typename PVT>
|
||||
std::tr1::shared_ptr<PVT> PVStructure::getSubFieldT(const char *name) const
|
||||
{
|
||||
std::tr1::shared_ptr<PVT> pvField = std::tr1::dynamic_pointer_cast<PVT>(
|
||||
getSubFieldImpl(name)->shared_from_this());
|
||||
|
||||
if (pvField.get())
|
||||
return pvField;
|
||||
else
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "Failed to get field: " << name << " (Field has wrong type)";
|
||||
throw std::runtime_error(ss.str());
|
||||
}
|
||||
}
|
||||
|
||||
template<typename PVT>
|
||||
std::tr1::shared_ptr<PVT> PVStructure::getSubFieldT(std::size_t fieldOffset) const
|
||||
{
|
||||
std::tr1::shared_ptr<PVT> pvField = std::tr1::dynamic_pointer_cast<PVT>(
|
||||
getSubFieldT(fieldOffset));
|
||||
if (pvField.get())
|
||||
return pvField;
|
||||
else
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "Failed to get field with offset "
|
||||
<< fieldOffset << " (Field has wrong type)";
|
||||
throw std::runtime_error(ss.str());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* PVUnion has a single subfield which has a type specified by a union introspection interface.
|
||||
* @brief PVUnion has a single subfield.
|
||||
*
|
||||
* The type for the subfield is specified by a union introspection interface.
|
||||
*
|
||||
*/
|
||||
class epicsShareClass PVUnion : public PVField
|
||||
{
|
||||
@@ -871,7 +906,7 @@ public:
|
||||
/**
|
||||
* Undefined index.
|
||||
* Default value upon PVUnion construction. Can be set by the user.
|
||||
* Corresponds to {@code null} value.
|
||||
* Corresponds to @c null value.
|
||||
*/
|
||||
static int32 UNDEFINED_INDEX;
|
||||
|
||||
@@ -882,8 +917,8 @@ public:
|
||||
UnionConstPtr getUnion() const;
|
||||
|
||||
/**
|
||||
* Get the {@code PVField} value stored in the field.
|
||||
* @return {@code PVField} value of field, {@code null} if {@code getSelectedIndex() == UNDEFINED_INDEX}.
|
||||
* Get the @c PVField value stored in the field.
|
||||
* @return @c PVField value of field, @c null if {@code getSelectedIndex() == UNDEFINED_INDEX}.
|
||||
*/
|
||||
PVFieldPtr get() const;
|
||||
|
||||
@@ -895,8 +930,8 @@ public:
|
||||
/**
|
||||
* Select field (set index) and get the field at the index.
|
||||
* @param index index of the field to select.
|
||||
* @return corresponding PVField (of undetermined value), {@code null} if {@code index == UNDEFINED_INDEX}.
|
||||
* @throws {@code std::invalid_argument} if index is invalid (out of range).
|
||||
* @return corresponding PVField (of undetermined value), @c null if {@code index == UNDEFINED_INDEX}.
|
||||
* @throws std::invalid_argument if index is invalid (out of range).
|
||||
*/
|
||||
PVFieldPtr select(int32 index);
|
||||
|
||||
@@ -909,7 +944,7 @@ public:
|
||||
* Select field (set index) and get the field by given name.
|
||||
* @param fieldName the name of the field to select.
|
||||
* @return corresponding PVField (of undetermined value).
|
||||
* @throws {@code std::invalid_argument} if field does not exist.
|
||||
* @throws std::invalid_argument if field does not exist.
|
||||
*/
|
||||
PVFieldPtr select(std::string const & fieldName);
|
||||
|
||||
@@ -931,27 +966,30 @@ public:
|
||||
std::string getSelectedFieldName() const;
|
||||
|
||||
/**
|
||||
* Set the {@code PVField} (by reference!) as selected field.
|
||||
* If a value is not a valid union field an {@code std::invalid_argument} exception is thrown.
|
||||
* Set the @c PVField (by reference!) as selected field.
|
||||
* If a value is not a valid union field an @c std::invalid_argument
|
||||
* exception is thrown.
|
||||
* @param value the field to set.
|
||||
*/
|
||||
void set(PVFieldPtr const & value);
|
||||
/**
|
||||
* Set the {@code PVField} (by reference!) as field at given index.
|
||||
* If a value is not a valid union field an {@code std::invalid_argument} exception is thrown.
|
||||
* Use {@code select(int)} to put by value.
|
||||
* Set the @c PVField (by reference!) as field at given index.
|
||||
* If a value is not a valid union field an @c std::invalid_argument
|
||||
* exception is thrown.
|
||||
* Use @c select(int32) to put by value.
|
||||
* @param index index of a field to put.
|
||||
* @param value the field to set.
|
||||
* @see #select(int)
|
||||
* @see #select(int32)
|
||||
*/
|
||||
void set(int32 index, PVFieldPtr const & value);
|
||||
/**
|
||||
* Set the {@code PVField} (by reference!) as field by given name.
|
||||
* If a value is not a valid union field an {@code std::invalid_argument} exception is thrown.
|
||||
* Use {@code select(std::string)} to put by value.
|
||||
* Set the @c PVField (by reference!) as field by given name.
|
||||
* If a value is not a valid union field an @c std::invalid_argument
|
||||
* exception is thrown.
|
||||
* Use @c select(std::string const &) to put by value.
|
||||
* @param fieldName Name of the field to put.
|
||||
* @param value the field to set.
|
||||
* @see #select(std::string)
|
||||
* @see #select(std::string const &)
|
||||
*/
|
||||
void set(std::string const & fieldName, PVFieldPtr const & value);
|
||||
|
||||
@@ -973,13 +1011,17 @@ public:
|
||||
* Constructor
|
||||
* @param punion The introspection interface.
|
||||
*/
|
||||
PVUnion(UnionConstPtr const & punion);
|
||||
explicit PVUnion(UnionConstPtr const & punion);
|
||||
|
||||
virtual std::ostream& dumpValue(std::ostream& o) const;
|
||||
|
||||
void copy(const PVUnion& from);
|
||||
void copyUnchecked(const PVUnion& from);
|
||||
|
||||
private:
|
||||
static PVDataCreatePtr pvDataCreate;
|
||||
|
||||
friend class PVDataCreate;
|
||||
|
||||
UnionConstPtr unionPtr;
|
||||
|
||||
int32 selector;
|
||||
@@ -1017,11 +1059,11 @@ namespace detail {
|
||||
PVVectorStorage() : Base() {}
|
||||
|
||||
template<typename A>
|
||||
PVVectorStorage(A a) : Base(a) {}
|
||||
explicit PVVectorStorage(A a) : Base(a) {}
|
||||
public:
|
||||
virtual ~PVVectorStorage(){};
|
||||
|
||||
// Primative array manipulations
|
||||
// Primitive array manipulations
|
||||
|
||||
//! Fetch a read-only view of the current array data
|
||||
virtual const_svector view() const = 0;
|
||||
@@ -1063,6 +1105,13 @@ namespace detail {
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
/**
|
||||
* @brief template class for all extensions of PVArray.
|
||||
*
|
||||
* The direct extensions are pvBooleanArray, pvByteArray, ..., pvStringArray.
|
||||
* There are specializations for PVStringArray, PVStructureArray, and PVUnionArray.
|
||||
*
|
||||
*/
|
||||
template<typename T>
|
||||
class epicsShareClass PVValueArray : public detail::PVVectorStorage<T,PVScalarArray> {
|
||||
typedef detail::PVVectorStorage<T,PVScalarArray> base_t;
|
||||
@@ -1084,6 +1133,9 @@ public:
|
||||
*/
|
||||
virtual ~PVValueArray() {}
|
||||
|
||||
/**
|
||||
* Get introspection interface.
|
||||
*/
|
||||
virtual ArrayConstPtr getArray() const
|
||||
{
|
||||
return std::tr1::static_pointer_cast<const Array>(this->getField());
|
||||
@@ -1121,14 +1173,15 @@ protected:
|
||||
this->replace(shared_vector_convert<const T>(in));
|
||||
}
|
||||
|
||||
PVValueArray(ScalarArrayConstPtr const & scalar)
|
||||
explicit PVValueArray(ScalarArrayConstPtr const & scalar)
|
||||
: base_t(scalar) {}
|
||||
friend class PVDataCreate;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Data class for a structureArray
|
||||
* @brief Data class for a structureArray
|
||||
*
|
||||
*/
|
||||
template<>
|
||||
class epicsShareClass PVValueArray<PVStructurePtr> : public detail::PVVectorStorage<PVStructurePtr,PVArray>
|
||||
@@ -1195,6 +1248,7 @@ public:
|
||||
virtual const_svector view() const { return value; }
|
||||
virtual void swap(const_svector &other);
|
||||
virtual void replace(const const_svector &other) {
|
||||
checkLength(other.size());
|
||||
value = other;
|
||||
PVField::postPut();
|
||||
}
|
||||
@@ -1209,8 +1263,11 @@ public:
|
||||
virtual std::ostream& dumpValue(std::ostream& o) const;
|
||||
virtual std::ostream& dumpValue(std::ostream& o, std::size_t index) const;
|
||||
|
||||
void copy(const PVStructureArray& from);
|
||||
void copyUnchecked(const PVStructureArray& from);
|
||||
|
||||
protected:
|
||||
PVValueArray(StructureArrayConstPtr const & structureArray)
|
||||
explicit PVValueArray(StructureArrayConstPtr const & structureArray)
|
||||
:base_t(structureArray)
|
||||
,structureArray(structureArray)
|
||||
{}
|
||||
@@ -1223,7 +1280,8 @@ private:
|
||||
|
||||
|
||||
/**
|
||||
* Data class for a unionArray
|
||||
* @brief Data class for a unionArray
|
||||
*
|
||||
*/
|
||||
template<>
|
||||
class epicsShareClass PVValueArray<PVUnionPtr> : public detail::PVVectorStorage<PVUnionPtr,PVArray>
|
||||
@@ -1290,6 +1348,7 @@ public:
|
||||
virtual const_svector view() const { return value; }
|
||||
virtual void swap(const_svector &other);
|
||||
virtual void replace(const const_svector &other) {
|
||||
checkLength(other.size());
|
||||
value = other;
|
||||
PVField::postPut();
|
||||
}
|
||||
@@ -1304,8 +1363,11 @@ public:
|
||||
virtual std::ostream& dumpValue(std::ostream& o) const;
|
||||
virtual std::ostream& dumpValue(std::ostream& o, std::size_t index) const;
|
||||
|
||||
void copy(const PVUnionArray& from);
|
||||
void copyUnchecked(const PVUnionArray& from);
|
||||
|
||||
protected:
|
||||
PVValueArray(UnionArrayConstPtr const & unionArray)
|
||||
explicit PVValueArray(UnionArrayConstPtr const & unionArray)
|
||||
:base_t(unionArray)
|
||||
,unionArray(unionArray)
|
||||
{}
|
||||
@@ -1356,7 +1418,8 @@ typedef PVValueArray<std::string> PVStringArray;
|
||||
typedef std::tr1::shared_ptr<PVStringArray> PVStringArrayPtr;
|
||||
|
||||
/**
|
||||
* This is a singlton class for creating data instances.
|
||||
* @brief This is a singleton class for creating data instances.
|
||||
*
|
||||
*/
|
||||
class epicsShareClass PVDataCreate {
|
||||
public:
|
||||
@@ -1387,7 +1450,7 @@ public:
|
||||
PVScalarPtr createPVScalar(ScalarConstPtr const & scalar);
|
||||
/**
|
||||
* Create an implementation of a scalar field. A Scalar introspection interface is created.
|
||||
* @param fieldType The field type.
|
||||
* @param scalarType The scalar type.
|
||||
* @return The PVScalar implementation.
|
||||
*/
|
||||
PVScalarPtr createPVScalar(ScalarType scalarType);
|
||||
@@ -1400,7 +1463,7 @@ public:
|
||||
PVScalarPtr createPVScalar(PVScalarPtr const & scalarToClone);
|
||||
/**
|
||||
* template version
|
||||
* @param PVT must ve a valid pvType
|
||||
* @tparam PVT must be a valid PVType
|
||||
* @return The PVScalar implementation.
|
||||
*/
|
||||
template<typename PVT>
|
||||
@@ -1432,7 +1495,7 @@ public:
|
||||
|
||||
/**
|
||||
* Create implementation for PVUnion.
|
||||
* @param union The introspection interface.
|
||||
* @param punion The introspection interface.
|
||||
* @return The PVUnion implementation
|
||||
*/
|
||||
PVUnionPtr createPVUnion(UnionConstPtr const & punion);
|
||||
@@ -1450,13 +1513,12 @@ public:
|
||||
|
||||
/**
|
||||
* Create an implementation of an array field reusing the Array introspection interface.
|
||||
* @param array The introspection interface.
|
||||
* @param scalarArray The introspection interface.
|
||||
* @return The PVScalarArray implementation.
|
||||
*/
|
||||
PVScalarArrayPtr createPVScalarArray(ScalarArrayConstPtr const & scalarArray);
|
||||
/**
|
||||
* Create an implementation for an array field. An Array introspection interface is created.
|
||||
* @param parent The parent interface.
|
||||
* @param elementType The element type.
|
||||
* @return The PVScalarArray implementation.
|
||||
*/
|
||||
@@ -1464,13 +1526,13 @@ public:
|
||||
/**
|
||||
* Create an implementation of an array field by cloning an existing PVArray.
|
||||
* The new PVArray will have the same value and auxInfo as the original.
|
||||
* @param arrayToClone The PVScalarArray to clone.
|
||||
* @param scalarArrayToClone The PVScalarArray to clone.
|
||||
* @return The PVScalarArray implementation.
|
||||
*/
|
||||
PVScalarArrayPtr createPVScalarArray(PVScalarArrayPtr const & scalarArrayToClone);
|
||||
/**
|
||||
* template version
|
||||
* @param PVT must ve a valid pvType
|
||||
* @tparam PVT must be a valid pvType
|
||||
* @return The PVScalarArray implementation.
|
||||
*/
|
||||
template<typename PVAT>
|
||||
@@ -1506,7 +1568,7 @@ public:
|
||||
PVUnionArrayPtr createPVUnionArray(UnionArrayConstPtr const & unionArray);
|
||||
/**
|
||||
* Create an implementation of an array with union elements.
|
||||
* @param punion The introspection interface tht is used to create UnionArrayConstPtr.
|
||||
* @param punion The introspection interface that is used to create UnionArrayConstPtr.
|
||||
* All elements share the same introspection interface.
|
||||
* @return The PVUnionArray implementation.
|
||||
*/
|
||||
@@ -1526,11 +1588,32 @@ private:
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the single class that implemnents PVDataCreate
|
||||
* @param The PVDataCreate factory.
|
||||
* Get the single class that implements PVDataCreate
|
||||
* @return The PVDataCreate factory.
|
||||
*/
|
||||
|
||||
epicsShareExtern PVDataCreatePtr getPVDataCreate();
|
||||
|
||||
bool epicsShareExtern operator==(const PVField&, const PVField&);
|
||||
|
||||
static inline bool operator!=(const PVField& a, const PVField& b)
|
||||
{return !(a==b);}
|
||||
|
||||
}}
|
||||
|
||||
/**
|
||||
* stream support for pvField
|
||||
*/
|
||||
namespace std{
|
||||
epicsShareExtern std::ostream& operator<<(std::ostream& o, const epics::pvData::PVField *ptr);
|
||||
}
|
||||
|
||||
#undef USAGE_DEPRECATED
|
||||
#undef USAGE_ERROR
|
||||
|
||||
#endif /* PVDATA_H */
|
||||
|
||||
/** @page Overview Documentation
|
||||
*
|
||||
* <a href = "pvDataCPP.html">pvData.html</a>
|
||||
*
|
||||
*/
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -71,7 +71,7 @@ epicsShareExtern void copy(
|
||||
PVStructureArray & pvFrom,
|
||||
size_t fromOffset,
|
||||
size_t fromStride,
|
||||
PVStructureArray & pvToo,
|
||||
PVStructureArray & pvTo,
|
||||
size_t toOffset,
|
||||
size_t toStride,
|
||||
size_t count);
|
||||
@@ -91,7 +91,7 @@ epicsShareExtern void copy(
|
||||
PVArray & pvFrom,
|
||||
size_t fromOffset,
|
||||
size_t fromStride,
|
||||
PVArray & pvToo,
|
||||
PVArray & pvTo,
|
||||
size_t toOffset,
|
||||
size_t toStride,
|
||||
size_t count);
|
||||
@@ -111,7 +111,7 @@ epicsShareExtern void copy(
|
||||
PVArray::shared_pointer const & pvFrom,
|
||||
size_t fromOffset,
|
||||
size_t fromStride,
|
||||
PVArray::shared_pointer & pvToo,
|
||||
PVArray::shared_pointer & pvTo,
|
||||
size_t toOffset,
|
||||
size_t toStride,
|
||||
size_t count);
|
||||
|
||||
@@ -29,7 +29,7 @@ typedef int intptr_t;
|
||||
typedef unsigned int uintptr_t;
|
||||
#ifndef INT64_MAX
|
||||
#define INT64_MAX (0x7fffffffffffffffLL)
|
||||
#define UINT64_MAX (0xffffffffffffffffLL)
|
||||
#define UINT64_MAX (0xffffffffffffffffULL)
|
||||
#endif
|
||||
#else
|
||||
#include <stdint.h>
|
||||
@@ -49,11 +49,11 @@ namespace detail {
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a set of typdefs used by pvData.
|
||||
* This is a set of typedefs used by pvData.
|
||||
*/
|
||||
|
||||
/**
|
||||
* boolean, i.e. can only have the values {@code false} or {@code true}
|
||||
* boolean, i.e. can only have the values @c false or @c true
|
||||
*/
|
||||
typedef detail::pick_type<int8_t, signed char,
|
||||
detail::pick_type<uint8_t, char, unsigned char>::type
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user