Compare commits
100 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 |
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\..*
|
||||
16
.hgtags
16
.hgtags
@@ -1,16 +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
|
||||
260f35b9c6cad113f242c83c89be9cdac802f610 3.1.0
|
||||
1348c22b125861ecb9da95b23f20314b167ee155 4.0.0
|
||||
1348c22b125861ecb9da95b23f20314b167ee155 4.0.0
|
||||
9c62aaa83b9db6ad69740a6bb46d6529e0e60b78 4.0.0
|
||||
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.
|
||||
|
||||
|
||||
|
||||
42
LICENSE
42
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-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.
|
||||
|
||||
________________________________________________________________________
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,4 +1,65 @@
|
||||
<h1>Release 4.0 IN DEVELOPMENT</h1>
|
||||
<h1>Release 4.1 IN DEVELOPMENT</h1>
|
||||
<p>The main changes since release 4.0 are:</p>
|
||||
<ul>
|
||||
<li>Convert copy methods and equals operators (re)moved</li>
|
||||
<li>Convert::copyUnion now always copies between subfields.</li>
|
||||
<li>CreateRequest prevents a possible SEGFAULT.</li>
|
||||
<li>New stream operators for Field and PVField are provided.</li>
|
||||
<li>New method getAs that is like getSubField except that it throws exception</li>
|
||||
</ul>
|
||||
<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>where 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 cppy, 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>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 provies an error.</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 struct, PVStructurePtr pv)
|
||||
{
|
||||
if(struct) {
|
||||
cout << *struct << endl;
|
||||
} else {
|
||||
cout << "nullptr\n"
|
||||
}
|
||||
if(pv) {
|
||||
cout << *.struct << endl;
|
||||
} else {
|
||||
cout << "nullptr\n"
|
||||
}
|
||||
}
|
||||
</code></pre>
|
||||
<p>Now it can be done as follows:</p>
|
||||
<pre><code> void print(StructureConstPtr struct, PVStructurePtr pv)
|
||||
{
|
||||
cout << struct << endl;
|
||||
cout << pv << endl;
|
||||
}
|
||||
</code></pre>
|
||||
<h2>New method getAs that is like getSubField except that it throws exception</h2>
|
||||
<p><b>PVStructure</b> has a new template member <b>getAs(const char *name)</b>
|
||||
that is like <b>getSubField</b> except that it throws a runtime_error
|
||||
instead of returning null.</p>
|
||||
<h1>Release 4.0</h1>
|
||||
<p>The main changes since release 3.0.2 are:</p>
|
||||
<ul>
|
||||
<li>array semantics now enforce Copy On Write.</li>
|
||||
@@ -55,4 +116,4 @@ only on pvData, i. e. it no longer has any knowledge of PVRecord.</p>
|
||||
<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>
|
||||
<p>This was the starting point for RELEASE_NOTES</p>
|
||||
@@ -1,4 +1,86 @@
|
||||
Release 4.0 IN DEVELOPMENT
|
||||
Release 4.1 IN DEVELOPMENT
|
||||
===========
|
||||
|
||||
The main changes since release 4.0 are:
|
||||
|
||||
* Convert copy methods and equals operators (re)moved
|
||||
* Convert::copyUnion now always copies between subfields.
|
||||
* CreateRequest prevents a possible SEGFAULT.
|
||||
* New stream operators for Field and PVField are provided.
|
||||
* New method getSubFieldT that is like getSubField except that it throws exception
|
||||
|
||||
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)
|
||||
|
||||
where 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 cppy, 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.
|
||||
|
||||
CreateRequest change
|
||||
--------------------
|
||||
|
||||
createRequest could cause a SEGFAULT if passed a bad argument.
|
||||
This has been changed so the it returns a null pvStructure
|
||||
and provies an error.
|
||||
|
||||
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 struct, PVStructurePtr pv)
|
||||
{
|
||||
if(struct) {
|
||||
cout << *struct << endl;
|
||||
} else {
|
||||
cout << "nullptr\n"
|
||||
}
|
||||
if(pv) {
|
||||
cout << *.struct << endl;
|
||||
} else {
|
||||
cout << "nullptr\n"
|
||||
}
|
||||
}
|
||||
|
||||
Now it can be done as follows:
|
||||
|
||||
void print(StructureConstPtr struct, PVStructurePtr pv)
|
||||
{
|
||||
cout << struct << endl;
|
||||
cout << pv << endl;
|
||||
}
|
||||
|
||||
New method getSubFieldT that is like getSubField except that it throws exception
|
||||
--------------------
|
||||
|
||||
<b>PVStructure</b> has a new template member <b>getSubFieldT(std::string const &fieldName)</b>
|
||||
that is like <b>getSubField</b> except that it throws a runtime_error
|
||||
instead of returning null.
|
||||
|
||||
Release 4.0
|
||||
===========
|
||||
|
||||
The main changes since release 3.0.2 are:
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
TODO
|
||||
===========
|
||||
|
||||
printer
|
||||
------------
|
||||
|
||||
pv/printer.h is not used.
|
||||
|
||||
doxygen
|
||||
-------
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
<h1>EPICS pvDataCPP</h1>
|
||||
<!-- Maturity: Working Draft or Request for Comments, or Recommendation, and date. -->
|
||||
|
||||
<h2 class="nocount">EPICS v4 Working Group, Working Draft, 08-Oct-2014</h2>
|
||||
<h2 class="nocount">EPICS v4 Working Group, Working Draft, 23-June-2015</h2>
|
||||
|
||||
<dl>
|
||||
<dt>Latest version:</dt>
|
||||
@@ -46,11 +46,11 @@
|
||||
</dd>
|
||||
<dt>This version:</dt>
|
||||
<dd><a
|
||||
href="pvDataCPP_20140723.html">pvDataCPP_20140723.html</a>
|
||||
href="pvDataCPP_20150623.html">pvDataCPP_20150623.html</a>
|
||||
</dd>
|
||||
<dt>Previous version:</dt>
|
||||
<dd><a
|
||||
href="pvDataCPP_20140708.html">pvDataCPP_20140708.html</a>
|
||||
href="pvDataCPP_20141110.html">pvDataCPP_20141110.html</a>
|
||||
</dd>
|
||||
<dt>Editors:</dt>
|
||||
<dd>Marty Kraimer, BNL</dd>
|
||||
@@ -79,7 +79,7 @@ V4 control system programming environment:<br />
|
||||
|
||||
<h2 class="nocount">Status of this Document</h2>
|
||||
|
||||
<p>This is the 08-Oct-2014 version of the C++ implementation of pvData.
|
||||
<p>This is the 23-June-2015 version of the C++ implementation of pvData.
|
||||
</p>
|
||||
|
||||
<p>RELEASE_NOTES.md provides changes since the last release.
|
||||
@@ -2309,6 +2309,16 @@ public:
|
||||
template<typename PVT>
|
||||
std::tr1::shared_ptr<PVT> getSubField(std::size_t fieldOffset) const
|
||||
|
||||
PVFieldPtr getSubFieldT(std::string const &fieldName) const;
|
||||
|
||||
template<typename PVT>
|
||||
std::tr1::shared_ptr<PVT> getSubFieldT(std::string const &fieldName) const
|
||||
|
||||
PVFieldPtr getSubFieldT(std::size_t fieldOffset) const;
|
||||
|
||||
template<typename PVT>
|
||||
std::tr1::shared_ptr<PVT> getSubFieldT(std::size_t fieldOffset) const
|
||||
|
||||
virtual void serialize(
|
||||
ByteBuffer *pbuffer,SerializableControl *pflusher) const ;
|
||||
virtual void deserialize(
|
||||
@@ -2329,7 +2339,7 @@ public:
|
||||
<dt>getPVFields</dt>
|
||||
<dd>Returns the array of subfields. The set of subfields must all have
|
||||
different field names.</dd>
|
||||
<dt>getSubField(std::string fieldName)</dt>
|
||||
<dt>getSubField(std::string const &fieldName)</dt>
|
||||
<dd>
|
||||
Get a subField of a field.d
|
||||
A non-null result is
|
||||
@@ -2344,9 +2354,13 @@ public:
|
||||
<dd>Get the field located a fieldOffset, where fieldOffset is relative to
|
||||
the top level structure. This returns null if the specified field is not
|
||||
located within this PVStructure.
|
||||
<br />
|
||||
<b>Note</b> The template version replaces getBooleanField, etc.<br/>
|
||||
</dd>
|
||||
<dt>getSubFieldT(std::string const &fieldName)</dt>
|
||||
<dd>Like getSubField except that it throws std::runtime_error if
|
||||
the field does not exists or has the wrong type.</dd>
|
||||
<dt>getSubFieldT(int fieldOffset)</dt>
|
||||
<dd>Like getSubField except that it throws std::runtime_error if
|
||||
the field does not exists or has the wrong type.</dd>
|
||||
<dt>dumpValue</dt>
|
||||
<dd>Method for streams I/O.</dd>
|
||||
</dl>
|
||||
@@ -2662,12 +2676,6 @@ objects:</p>
|
||||
</dl>
|
||||
<h3>convert.h</h3>
|
||||
|
||||
<p>NOTE about copying immutable array fields. If an entire immutable array
|
||||
field is copied to another array that has the same elementType, both offsets
|
||||
are 0, and the length is the length of the source array, then the shareData
|
||||
method of the target array is called and the target array is set immutable.
|
||||
Thus the source and target share the same primitive array.</p>
|
||||
|
||||
<p>This section describes the supported conversions between data types.</p>
|
||||
<ul>
|
||||
<li>All supported types can be converted to a string. If you ask for a 100
|
||||
@@ -2681,12 +2689,6 @@ Thus the source and target share the same primitive array.</p>
|
||||
<li>Either is a string</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>Copy between PVArrays that satisfy one of the following.
|
||||
<ul>
|
||||
<li>Both have the same type.</li>
|
||||
<li>Either is a string.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>Conversions between numeric scalar types.</li>
|
||||
<li>Conversion between compatible structures.</li>
|
||||
<li>A utility method the returns the full field name of a field</li>
|
||||
|
||||
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
@@ -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
|
||||
|
||||
46
jenkins/cloudbees_doc
Normal file
46
jenkins/cloudbees_doc
Normal file
@@ -0,0 +1,46 @@
|
||||
# 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.
|
||||
|
||||
###########################################
|
||||
# Determine EPICS Base version
|
||||
|
||||
DEFAULT_BASE=3.14.12.5
|
||||
|
||||
BASE=${1:-${DEFAULT_BASE}}
|
||||
|
||||
###########################################
|
||||
# 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
|
||||
|
||||
rsync -aqP --delete -e ssh documentation epics-jenkins@web.sourceforge.net:/home/project-web/epics-pvdata/htdocs/docbuild/pvDataCPP/tip
|
||||
@@ -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]
|
||||
236
pvDataCPP.files
236
pvDataCPP.files
@@ -1,236 +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/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/pvData.h
|
||||
pvDataApp/pv/pvIntrospect.h
|
||||
pvDataApp/pv/pvType.h
|
||||
pvDataApp/pv/standardField.h
|
||||
pvDataApp/pv/standardPVField.h
|
||||
pvDataApp/pvMisc/bitSetUtil.cpp
|
||||
pvDataApp/pvMisc/bitSetUtil.h
|
||||
testApp/capi/testc.cpp
|
||||
testApp/capi/testc.py
|
||||
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/testMonitor.cpp
|
||||
testApp/property/testProperty.cpp
|
||||
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
|
||||
src/copy/createRequest.cpp
|
||||
src/copy/createRequest.h
|
||||
src/copy/pvCopy.cpp
|
||||
src/copy/pvCopy.h
|
||||
src/factory/Compare.cpp
|
||||
src/factory/Convert.cpp
|
||||
src/factory/factory.h
|
||||
src/factory/FieldCreateFactory.cpp
|
||||
src/factory/printer.cpp
|
||||
src/factory/PVArray.cpp
|
||||
src/factory/PVDataCreateFactory.cpp
|
||||
src/factory/PVField.cpp
|
||||
src/factory/PVScalar.cpp
|
||||
src/factory/PVScalarArray.cpp
|
||||
src/factory/PVStructure.cpp
|
||||
src/factory/PVStructureArray.cpp
|
||||
src/factory/pvSubArrayCopy.cpp
|
||||
src/factory/PVUnion.cpp
|
||||
src/factory/PVUnionArray.cpp
|
||||
src/factory/StandardField.cpp
|
||||
src/factory/StandardPVField.cpp
|
||||
src/factory/TypeFunc.cpp
|
||||
src/misc/bitSet.cpp
|
||||
src/misc/bitSet.h
|
||||
src/misc/byteBuffer.cpp
|
||||
src/misc/byteBuffer.h
|
||||
src/misc/current_function.h
|
||||
src/misc/destroyable.h
|
||||
src/misc/epicsException.cpp
|
||||
src/misc/epicsException.h
|
||||
src/misc/event.cpp
|
||||
src/misc/event.h
|
||||
src/misc/executor.cpp
|
||||
src/misc/executor.h
|
||||
src/misc/localStaticLock.cpp
|
||||
src/misc/localStaticLock.h
|
||||
src/misc/lock.h
|
||||
src/misc/messageQueue.cpp
|
||||
src/misc/messageQueue.h
|
||||
src/misc/noDefaultMethods.h
|
||||
src/misc/parseToPOD.cpp
|
||||
src/misc/queue.h
|
||||
src/misc/requester.cpp
|
||||
src/misc/requester.h
|
||||
src/misc/serialize.h
|
||||
src/misc/serializeHelper.cpp
|
||||
src/misc/serializeHelper.h
|
||||
src/misc/sharedPtr.h
|
||||
src/misc/sharedVector.h
|
||||
src/misc/status.cpp
|
||||
src/misc/status.h
|
||||
src/misc/templateMeta.h
|
||||
src/misc/thread.h
|
||||
src/misc/timeFunction.cpp
|
||||
src/misc/timeFunction.h
|
||||
src/misc/timer.cpp
|
||||
src/misc/timer.h
|
||||
src/misc/typeCast.cpp
|
||||
src/misc/typeCast.h
|
||||
src/monitor/monitor.cpp
|
||||
src/monitor/monitor.h
|
||||
src/monitor/monitorPlugin.cpp
|
||||
src/monitor/monitorPlugin.h
|
||||
src/property/alarm.cpp
|
||||
src/property/alarm.h
|
||||
src/property/control.h
|
||||
src/property/display.h
|
||||
src/property/pvAlarm.cpp
|
||||
src/property/pvAlarm.h
|
||||
src/property/pvControl.cpp
|
||||
src/property/pvControl.h
|
||||
src/property/pvDisplay.cpp
|
||||
src/property/pvDisplay.h
|
||||
src/property/pvEnumerated.cpp
|
||||
src/property/pvEnumerated.h
|
||||
src/property/pvTimeStamp.cpp
|
||||
src/property/pvTimeStamp.h
|
||||
src/property/timeStamp.cpp
|
||||
src/property/timeStamp.h
|
||||
src/pv/convert.h
|
||||
src/pv/printer.h
|
||||
src/pv/pvData.h
|
||||
src/pv/pvIntrospect.h
|
||||
src/pv/pvSubArrayCopy.h
|
||||
src/pv/pvType.h
|
||||
src/pv/standardField.h
|
||||
src/pv/standardPVField.h
|
||||
src/pvMisc/bitSetUtil.cpp
|
||||
src/pvMisc/bitSetUtil.h
|
||||
testApp/copy/testCreateRequest.cpp
|
||||
testApp/copy/testPVCopy.cpp
|
||||
testApp/misc/testBaseException.cpp
|
||||
testApp/misc/testBitSet.cpp
|
||||
testApp/misc/testByteBuffer.cpp
|
||||
testApp/misc/testByteOrder.cpp
|
||||
testApp/misc/testMessageQueue.cpp
|
||||
testApp/misc/testOverrunBitSet.cpp
|
||||
testApp/misc/testQueue.cpp
|
||||
testApp/misc/testSerialization.cpp
|
||||
testApp/misc/testSharedVector.cpp
|
||||
testApp/misc/testThread.cpp
|
||||
testApp/misc/testTimer.cpp
|
||||
testApp/misc/testTimeStamp.cpp
|
||||
testApp/misc/testTypeCast.cpp
|
||||
testApp/property/testProperty.cpp
|
||||
testApp/pv/testBitSetUtil.cpp
|
||||
testApp/pv/testConvert.cpp
|
||||
testApp/pv/testFieldBuilder.cpp
|
||||
testApp/pv/testIntrospect.cpp
|
||||
testApp/pv/testOperators.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
|
||||
src/factory/printer.cpp
|
||||
@@ -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
|
||||
@@ -322,149 +322,157 @@ public:
|
||||
virtual PVStructurePtr createRequest(
|
||||
string const & crequest)
|
||||
{
|
||||
string request = crequest;
|
||||
if (!request.empty()) removeBlanks(request);
|
||||
if (request.empty())
|
||||
{
|
||||
return pvDataCreate->createPVStructure(fieldCreate->createStructure());
|
||||
}
|
||||
size_t offsetRecord = request.find("record[");
|
||||
size_t offsetField = request.find("field(");
|
||||
size_t offsetPutField = request.find("putField(");
|
||||
size_t offsetGetField = request.find("getField(");
|
||||
if(offsetRecord==string::npos
|
||||
&& offsetField==string::npos
|
||||
&& offsetPutField==string::npos
|
||||
&& offsetGetField==string::npos)
|
||||
{
|
||||
request = "field(" + request + ")";
|
||||
offsetField = request.find("field(");
|
||||
}
|
||||
int numParan = 0;
|
||||
int numBrace = 0;
|
||||
int numBracket = 0;
|
||||
for(size_t i=0; i< request.length() ; ++i) {
|
||||
char chr = request[i];
|
||||
if(chr=='(') numParan++;
|
||||
if(chr==')') numParan--;
|
||||
if(chr=='{') numBrace++;
|
||||
if(chr=='}') numBrace--;
|
||||
if(chr=='[') numBracket++;
|
||||
if(chr==']') numBracket--;
|
||||
}
|
||||
if(numParan!=0) {
|
||||
ostringstream oss;
|
||||
oss << "mismatched () " << numParan;
|
||||
message = oss.str();
|
||||
return PVStructurePtr();
|
||||
}
|
||||
if(numBrace!=0) {
|
||||
ostringstream oss;
|
||||
oss << "mismatched {} " << numBrace;
|
||||
message = oss.str();
|
||||
return PVStructurePtr();
|
||||
}
|
||||
if(numBracket!=0) {
|
||||
ostringstream oss;
|
||||
oss << "mismatched [] " << numBracket;
|
||||
message = oss.str();
|
||||
return PVStructurePtr();
|
||||
}
|
||||
vector<Node> top;
|
||||
try {
|
||||
if(offsetRecord!=string::npos) {
|
||||
fullFieldName = "record";
|
||||
size_t openBracket = request.find('[', offsetRecord);
|
||||
size_t closeBracket = request.find(']', openBracket);
|
||||
if(closeBracket==string::npos) {
|
||||
message = request.substr(offsetRecord) +
|
||||
"record[ does not have matching ]";
|
||||
return PVStructurePtr();
|
||||
string request = crequest;
|
||||
if (!request.empty()) removeBlanks(request);
|
||||
if (request.empty())
|
||||
{
|
||||
return pvDataCreate->createPVStructure(fieldCreate->createStructure());
|
||||
}
|
||||
size_t offsetRecord = request.find("record[");
|
||||
size_t offsetField = request.find("field(");
|
||||
size_t offsetPutField = request.find("putField(");
|
||||
size_t offsetGetField = request.find("getField(");
|
||||
if(offsetRecord==string::npos
|
||||
&& offsetField==string::npos
|
||||
&& offsetPutField==string::npos
|
||||
&& offsetGetField==string::npos)
|
||||
{
|
||||
request = "field(" + request + ")";
|
||||
offsetField = request.find("field(");
|
||||
}
|
||||
int numParan = 0;
|
||||
int numBrace = 0;
|
||||
int numBracket = 0;
|
||||
for(size_t i=0; i< request.length() ; ++i) {
|
||||
char chr = request[i];
|
||||
if(chr=='(') numParan++;
|
||||
if(chr==')') numParan--;
|
||||
if(chr=='{') numBrace++;
|
||||
if(chr=='}') numBrace--;
|
||||
if(chr=='[') numBracket++;
|
||||
if(chr==']') numBracket--;
|
||||
}
|
||||
if(numParan!=0) {
|
||||
ostringstream oss;
|
||||
oss << "mismatched () " << numParan;
|
||||
message = oss.str();
|
||||
return PVStructurePtr();
|
||||
}
|
||||
if(numBrace!=0) {
|
||||
ostringstream oss;
|
||||
oss << "mismatched {} " << numBrace;
|
||||
message = oss.str();
|
||||
return PVStructurePtr();
|
||||
}
|
||||
if(numBracket!=0) {
|
||||
ostringstream oss;
|
||||
oss << "mismatched [] " << numBracket;
|
||||
message = oss.str();
|
||||
return PVStructurePtr();
|
||||
}
|
||||
vector<Node> top;
|
||||
try {
|
||||
if(offsetRecord!=string::npos) {
|
||||
fullFieldName = "record";
|
||||
size_t openBracket = request.find('[', offsetRecord);
|
||||
size_t closeBracket = request.find(']', openBracket);
|
||||
if(closeBracket==string::npos) {
|
||||
message = request.substr(offsetRecord) +
|
||||
"record[ does not have matching ]";
|
||||
return PVStructurePtr();
|
||||
}
|
||||
if(closeBracket-openBracket > 3) {
|
||||
Node node("record");
|
||||
Node optNode = createRequestOptions(
|
||||
request.substr(openBracket+1,closeBracket-openBracket-1));
|
||||
node.nodes.push_back(optNode);
|
||||
top.push_back(node);
|
||||
}
|
||||
}
|
||||
if(closeBracket-openBracket > 3) {
|
||||
Node node("record");
|
||||
Node optNode = createRequestOptions(
|
||||
request.substr(openBracket+1,closeBracket-openBracket-1));
|
||||
node.nodes.push_back(optNode);
|
||||
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();
|
||||
}
|
||||
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();
|
||||
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);
|
||||
}
|
||||
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);
|
||||
StructureConstPtr structure = fieldCreate->createStructure(names, fields);
|
||||
if(!structure) throw std::invalid_argument("bad request " + crequest);
|
||||
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(structure);
|
||||
for(size_t i=0; i<optionList.size(); ++i) {
|
||||
OptionPair pair = optionList[i];
|
||||
string name = pair.name;
|
||||
string value = pair.value;
|
||||
PVStringPtr pvField = pvStructure->getSubField<PVString>(name);
|
||||
if(!pvField) throw std::invalid_argument("bad request " + crequest);
|
||||
pvField->put(value);
|
||||
}
|
||||
optionList.clear();
|
||||
return pvStructure;
|
||||
} catch (std::exception &e) {
|
||||
string xxx = e.what();
|
||||
message = "while creating Structure exception " + xxx;
|
||||
return PVStructurePtr();
|
||||
message = e.what();
|
||||
return PVStructurePtr();
|
||||
}
|
||||
size_t num = top.size();
|
||||
StringArray names(num);
|
||||
FieldConstPtrArray fields(num);
|
||||
for(size_t i=0; i<num; ++i) {
|
||||
Node node = top[i];
|
||||
names[i] = node.name;
|
||||
vector<Node> subNode = node.nodes;
|
||||
if(subNode.empty()) {
|
||||
fields[i] = fieldCreate->createStructure();
|
||||
} else {
|
||||
fields[i] = createSubStructure(subNode);
|
||||
}
|
||||
}
|
||||
StructureConstPtr structure = fieldCreate->createStructure(names, fields);
|
||||
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);
|
||||
pvField->put(value);
|
||||
}
|
||||
optionList.clear();
|
||||
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:
|
||||
|
||||
@@ -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);
|
||||
pvStructure = pvRequest->getSubField<PVStructure>(structureName);
|
||||
if(!pvStructure) return NULLPVCopy;
|
||||
}
|
||||
} else if(pvStructure->getSubField("field")) {
|
||||
pvStructure = pvRequest->getStructureField("field");
|
||||
pvStructure = pvRequest->getSubField<PVStructure>("field");
|
||||
}
|
||||
PVCopyPtr pvCopy = PVCopyPtr(new PVCopy(pvMaster));
|
||||
bool result = pvCopy->init(pvStructure);
|
||||
@@ -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,7 +302,7 @@ 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;
|
||||
@@ -300,14 +310,14 @@ void PVCopy::dump(string *builder,CopyNodePtr const &node,int indentLevel)
|
||||
*builder += ss.str();
|
||||
PVStructurePtr options = node->options;
|
||||
if(options) {
|
||||
getConvert()->newLine(builder,indentLevel +1);
|
||||
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();
|
||||
@@ -339,7 +349,7 @@ bool PVCopy::init(epics::pvData::PVStructurePtr const &pvRequest)
|
||||
if(len==0) entireMaster = true;
|
||||
PVStructurePtr pvOptions;
|
||||
if(len==1 && pvRequest->getSubField("_options")) {
|
||||
pvOptions = pvRequest->getStructureField("_options");
|
||||
pvOptions = pvRequest->getSubField<PVStructure>("_options");
|
||||
}
|
||||
if(entireMaster) {
|
||||
structure = pvMasterStructure->getStructure();
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
/**
|
||||
@@ -121,7 +124,7 @@ public:
|
||||
* 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(
|
||||
|
||||
@@ -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() );
|
||||
}
|
||||
|
||||
@@ -251,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;
|
||||
@@ -304,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;
|
||||
|
||||
@@ -52,9 +52,6 @@ void Convert::getString(string *buf,PVField const *pvField,int /*indentLevel*/)
|
||||
std::ostringstream strm;
|
||||
pvField->dumpValue(strm);
|
||||
strm << std::endl;
|
||||
// PrinterPlain p;
|
||||
// p.setStream(strm);
|
||||
// p.print(*pvField);
|
||||
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;
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/lock.h>
|
||||
#include <pv/pvIntrospect.h>
|
||||
#include <pv/convert.h>
|
||||
#include <pv/factory.h>
|
||||
#include <pv/serializeHelper.h>
|
||||
|
||||
@@ -52,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(){}
|
||||
@@ -137,7 +136,7 @@ BoundedString::BoundedString(std::size_t maxStringLength) :
|
||||
Scalar(pvString), maxLength(maxStringLength)
|
||||
{
|
||||
if (maxLength == 0)
|
||||
throw std::invalid_argument("maxLength == 0");
|
||||
THROW_EXCEPTION2(std::invalid_argument, "maxLength == 0");
|
||||
}
|
||||
|
||||
BoundedString::~BoundedString() {}
|
||||
@@ -400,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,
|
||||
@@ -412,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -497,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_:
|
||||
@@ -511,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;
|
||||
}
|
||||
}
|
||||
@@ -528,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,
|
||||
@@ -553,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -759,7 +778,7 @@ FieldBuilderPtr FieldBuilder::addArray(string const & name, FieldConstPtr const
|
||||
case scalar:
|
||||
|
||||
if (std::tr1::dynamic_pointer_cast<const BoundedString>(element).get())
|
||||
throw std::invalid_argument("bounded string arrays are not supported");
|
||||
THROW_EXCEPTION2(std::invalid_argument, "bounded string arrays are not supported");
|
||||
|
||||
fields.push_back(fieldCreate->createScalarArray(static_pointer_cast<const Scalar>(element)->getScalarType()));
|
||||
break;
|
||||
@@ -767,7 +786,7 @@ FieldBuilderPtr FieldBuilder::addArray(string const & name, FieldConstPtr const
|
||||
default:
|
||||
std::ostringstream msg("unsupported array element type: ");
|
||||
msg << element->getType();
|
||||
throw std::invalid_argument(msg.str());
|
||||
THROW_EXCEPTION2(std::invalid_argument, msg.str());
|
||||
}
|
||||
|
||||
fieldNames.push_back(name);
|
||||
@@ -796,7 +815,7 @@ FieldConstPtr FieldBuilder::createFieldInternal(Type type)
|
||||
{
|
||||
std::ostringstream msg("unsupported type: ");
|
||||
msg << type;
|
||||
throw std::invalid_argument(msg.str());
|
||||
THROW_EXCEPTION2(std::invalid_argument, msg.str());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -804,7 +823,7 @@ FieldConstPtr FieldBuilder::createFieldInternal(Type type)
|
||||
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();
|
||||
@@ -814,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();
|
||||
@@ -846,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)
|
||||
@@ -865,8 +884,11 @@ 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];
|
||||
}
|
||||
@@ -881,16 +903,22 @@ BoundedStringConstPtr FieldCreate::createBoundedString(std::size_t maxLength) co
|
||||
|
||||
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)
|
||||
throw std::invalid_argument("Can't construct ScalarArray from invalid ScalarType");
|
||||
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());
|
||||
@@ -900,8 +928,11 @@ ScalarArrayConstPtr FieldCreate::createFixedScalarArray(ScalarType elementType,
|
||||
|
||||
ScalarArrayConstPtr FieldCreate::createBoundedScalarArray(ScalarType elementType, size_t size) 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 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());
|
||||
@@ -989,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);
|
||||
@@ -1008,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);
|
||||
@@ -1230,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>
|
||||
|
||||
@@ -527,7 +526,7 @@ PVFieldPtr PVDataCreate::createPVField(PVFieldPtr const & fieldToClone)
|
||||
PVStructurePtr pvStructure
|
||||
= static_pointer_cast<PVStructure>(fieldToClone);
|
||||
StringArray const & fieldNames = pvStructure->getStructure()->getFieldNames();
|
||||
PVFieldPtrArray pvFieldPtrArray = pvStructure->getPVFields();
|
||||
PVFieldPtrArray const & pvFieldPtrArray = pvStructure->getPVFields();
|
||||
return createPVStructure(fieldNames,pvFieldPtrArray);
|
||||
}
|
||||
case structureArray:
|
||||
@@ -537,7 +536,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_:
|
||||
@@ -552,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;
|
||||
}
|
||||
}
|
||||
@@ -602,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;
|
||||
}
|
||||
|
||||
@@ -712,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;
|
||||
}
|
||||
|
||||
@@ -741,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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -179,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);
|
||||
@@ -232,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;
|
||||
}
|
||||
@@ -171,7 +172,7 @@ void PVUnion::deserialize(ByteBuffer *pbuffer, DeserializableControl *pcontrol)
|
||||
{
|
||||
// try to reuse existing field instance
|
||||
if (!value.get() || *value->getField() != *field)
|
||||
value = getPVDataCreate()->createPVField(field);
|
||||
value = pvDataCreate->createPVField(field);
|
||||
value->deserialize(pbuffer, pcontrol);
|
||||
}
|
||||
else
|
||||
@@ -188,7 +189,7 @@ void PVUnion::deserialize(ByteBuffer *pbuffer, DeserializableControl *pcontrol)
|
||||
FieldConstPtr field = unionPtr->getField(selector);
|
||||
// try to reuse existing field instance
|
||||
if (!value.get() || *value->getField() != *field)
|
||||
value = getPVDataCreate()->createPVField(field);
|
||||
value = pvDataCreate->createPVField(field);
|
||||
}
|
||||
value->deserialize(pbuffer, pcontrol);
|
||||
}
|
||||
@@ -217,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>
|
||||
|
||||
@@ -178,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);
|
||||
@@ -231,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];
|
||||
@@ -554,7 +554,7 @@ 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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -24,6 +24,8 @@ 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.
|
||||
@@ -206,7 +208,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,7 +206,8 @@ inline double swap(double val)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This class implements {@code Bytebuffer} that is like the {@code java.nio.ByteBuffer}.
|
||||
* @brief This class implements a Bytebuffer that is like the java.nio.ByteBuffer.
|
||||
*
|
||||
* <p>A {@code BitSet} is not safe for multithreaded use without
|
||||
* external synchronization.
|
||||
*
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -308,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)
|
||||
{
|
||||
@@ -350,7 +415,7 @@ noconvert:
|
||||
*endp = (char*)ptr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* do we need long long? */
|
||||
@@ -486,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,52 +25,185 @@ 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 field instance to be deserialized
|
||||
* @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.
|
||||
* ¶m 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.
|
||||
* ¶m bitSet The bitSet to deserialize.
|
||||
*/
|
||||
virtual void deserialize(ByteBuffer *buffer,
|
||||
DeserializableControl *flusher,BitSet *bitSet) = 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Class for serializing arrays.
|
||||
*
|
||||
*/
|
||||
class epicsShareClass SerializableArray : public virtual Serializable {
|
||||
public:
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
virtual ~SerializableArray(){}
|
||||
using Serializable::serialize;
|
||||
virtual void serialize(ByteBuffer *buffer,
|
||||
SerializableControl *flusher, std::size_t offset, std::size_t count) const = 0;
|
||||
/**
|
||||
* Serialize field into given buffer.
|
||||
* @param buffer serialization buffer.
|
||||
* @param flusher flush interface.
|
||||
* ¶m 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,6 +23,10 @@
|
||||
namespace epics {
|
||||
namespace pvData {
|
||||
|
||||
/**
|
||||
* @brief Serialization helper.
|
||||
*
|
||||
*/
|
||||
class epicsShareClass SerializeHelper : public NoDefaultMethods {
|
||||
public:
|
||||
|
||||
|
||||
@@ -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.
|
||||
* @parm 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
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
@@ -75,7 +68,7 @@ public:
|
||||
* 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 pvTop The top-level structure in which the field resides.
|
||||
* @param monitorElement The data for the client.
|
||||
* The plugin is allowed to change the data values.
|
||||
*/
|
||||
@@ -100,7 +93,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 +105,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 +125,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:
|
||||
/**
|
||||
* 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,14 +28,14 @@ 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("limitHigh");
|
||||
pvHigh = pvStructure->getSubField<PVDouble>("limitHigh");
|
||||
if(pvHigh.get()==NULL) {
|
||||
pvLow.reset();
|
||||
return false;
|
||||
}
|
||||
pvMinStep = pvStructure->getDoubleField("minStep");
|
||||
pvMinStep = pvStructure->getSubField<PVDouble>("minStep");
|
||||
if(pvMinStep.get()==NULL) {
|
||||
pvLow.reset();
|
||||
pvHigh.reset();
|
||||
|
||||
@@ -17,18 +17,60 @@
|
||||
|
||||
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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -35,43 +35,158 @@ 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) {}
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
/**
|
||||
* Get nanoseconds.
|
||||
* @return nanoseconds within timeStamp.
|
||||
*/
|
||||
int32 getNanoseconds() const {return nanoseconds;}
|
||||
/**
|
||||
* Get userTag.
|
||||
* @return userTag.
|
||||
*/
|
||||
int32 getUserTag() const {return userTag;}
|
||||
/**
|
||||
* Set userTag.
|
||||
* @param useTag application specific.
|
||||
*/
|
||||
void setUserTag(int userTag) {this->userTag = userTag;}
|
||||
/**
|
||||
* 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;
|
||||
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 n 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;
|
||||
|
||||
235
src/pv/convert.h
235
src/pv/convert.h
@@ -22,40 +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&);
|
||||
bool epicsShareExtern operator==(const BoundedString&, const BoundedString&);
|
||||
|
||||
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);}
|
||||
static inline bool operator!=(const BoundedString& a, const BoundedString& 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
|
||||
@@ -74,85 +46,45 @@ static inline bool operator!=(const BoundedString& a, const BoundedString& 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,128 +143,6 @@ public:
|
||||
std::size_t length,
|
||||
StringArray & to,
|
||||
std::size_t toOffset);
|
||||
/**
|
||||
* Are from and to valid arguments to copy.
|
||||
* This first checks of both arguments have the same Type.
|
||||
* Then calls one of isCopyScalarCompatible,
|
||||
* isCopyArrayCompatible, or isCopyStructureCompatible.
|
||||
* @param from The source.
|
||||
* @param to The destination.
|
||||
* @return (false,true) is the arguments (are not, are) compatible.
|
||||
*/
|
||||
bool isCopyCompatible(FieldConstPtr const & from, FieldConstPtr const & to);
|
||||
/**
|
||||
* Copy from a PVField to another PVField.
|
||||
* This calls one on copyScalar, copyArray, copyStructure.
|
||||
* The two arguments must be compatible.
|
||||
* @param from The source.
|
||||
* @param to The destination
|
||||
* @throws std::invalid_argument if the arguments are not compatible.
|
||||
*/
|
||||
void copy(PVFieldPtr const & from, PVFieldPtr const & to);
|
||||
/**
|
||||
* Are from and to valid arguments to copyScalar.
|
||||
* false will be returned if either argument is not a scalar as defined by Type.isScalar().
|
||||
* If both are scalars the return value is true if any of the following are true.
|
||||
* <ul>
|
||||
* <li>Both arguments are numeric.</li>
|
||||
* <li>Both arguments have the same type.</li>
|
||||
* <li>Either argument is a string.</li>
|
||||
* </ul>
|
||||
* @param from The introspection interface for the from data.
|
||||
* @param to The introspection interface for the to data..
|
||||
* @return (false,true) If the arguments (are not, are) compatible.
|
||||
*/
|
||||
bool isCopyScalarCompatible(
|
||||
ScalarConstPtr const & from,
|
||||
ScalarConstPtr const & to);
|
||||
/**
|
||||
* Copy from a scalar pv to another scalar pv.
|
||||
* @param from the source.
|
||||
* @param to the destination.
|
||||
* @throws std::invalid_argument if the arguments are not compatible.
|
||||
*/
|
||||
void copyScalar(PVScalarPtr const & from, PVScalarPtr const & to);
|
||||
/**
|
||||
* Are from and to valid arguments to copyArray.
|
||||
* The results are like isCopyScalarCompatible except that the tests are made on the elementType.
|
||||
* @param from The from array.
|
||||
* @param to The to array.
|
||||
* @return (false,true) If the arguments (are not, are) compatible.
|
||||
*/
|
||||
bool isCopyScalarArrayCompatible(
|
||||
ScalarArrayConstPtr const & from,
|
||||
ScalarArrayConstPtr const & to);
|
||||
/**
|
||||
* 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>.
|
||||
* @param pv a PV
|
||||
@@ -478,13 +288,6 @@ public:
|
||||
*/
|
||||
inline void fromDouble(PVScalarPtr const & pv, double from) { pv->putFrom<double>(from); }
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
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
|
||||
427
src/pv/pvData.h
427
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 {
|
||||
@@ -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();
|
||||
/**
|
||||
@@ -511,7 +543,7 @@ public:
|
||||
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;
|
||||
@@ -520,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:
|
||||
@@ -570,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()
|
||||
@@ -588,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:
|
||||
@@ -615,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();
|
||||
/**
|
||||
@@ -636,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
|
||||
{
|
||||
@@ -664,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.
|
||||
@@ -819,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.
|
||||
@@ -829,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;
|
||||
@@ -856,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
|
||||
{
|
||||
@@ -975,11 +1008,16 @@ 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;
|
||||
|
||||
@@ -1018,11 +1056,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;
|
||||
@@ -1064,6 +1102,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;
|
||||
@@ -1085,6 +1130,9 @@ public:
|
||||
*/
|
||||
virtual ~PVValueArray() {}
|
||||
|
||||
/**
|
||||
* Get introspection interface.
|
||||
*/
|
||||
virtual ArrayConstPtr getArray() const
|
||||
{
|
||||
return std::tr1::static_pointer_cast<const Array>(this->getField());
|
||||
@@ -1122,14 +1170,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>
|
||||
@@ -1211,8 +1260,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)
|
||||
{}
|
||||
@@ -1225,7 +1277,8 @@ private:
|
||||
|
||||
|
||||
/**
|
||||
* Data class for a unionArray
|
||||
* @brief Data class for a unionArray
|
||||
*
|
||||
*/
|
||||
template<>
|
||||
class epicsShareClass PVValueArray<PVUnionPtr> : public detail::PVVectorStorage<PVUnionPtr,PVArray>
|
||||
@@ -1307,8 +1360,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)
|
||||
{}
|
||||
@@ -1359,7 +1415,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:
|
||||
@@ -1403,7 +1460,7 @@ public:
|
||||
PVScalarPtr createPVScalar(PVScalarPtr const & scalarToClone);
|
||||
/**
|
||||
* template version
|
||||
* @param PVT must ve a valid pvType
|
||||
* @param PVT must be a valid pvType
|
||||
* @return The PVScalar implementation.
|
||||
*/
|
||||
template<typename PVT>
|
||||
@@ -1473,7 +1530,7 @@ public:
|
||||
PVScalarArrayPtr createPVScalarArray(PVScalarArrayPtr const & scalarArrayToClone);
|
||||
/**
|
||||
* template version
|
||||
* @param PVT must ve a valid pvType
|
||||
* @param PVT must be a valid pvType
|
||||
* @return The PVScalarArray implementation.
|
||||
*/
|
||||
template<typename PVAT>
|
||||
@@ -1509,7 +1566,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.
|
||||
*/
|
||||
@@ -1529,11 +1586,33 @@ private:
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the single class that implemnents PVDataCreate
|
||||
* Get the single class that implements PVDataCreate
|
||||
* @param 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>
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -32,11 +32,7 @@ struct indent_level
|
||||
indent_level(long l) : level(l) {}
|
||||
};
|
||||
|
||||
inline long& indent_value(std::ios_base& ios)
|
||||
{
|
||||
static int indent_index = std::ios_base::xalloc();
|
||||
return ios.iword(indent_index);
|
||||
}
|
||||
epicsShareExtern long& indent_value(std::ios_base& ios);
|
||||
|
||||
epicsShareExtern std::ostream& operator<<(std::ostream& os, indent_level const& indent);
|
||||
|
||||
@@ -167,7 +163,8 @@ enum Type {
|
||||
};
|
||||
|
||||
/**
|
||||
* Convenience functions for Type.
|
||||
* @brief Convenience functions for Type.
|
||||
*
|
||||
*/
|
||||
namespace TypeFunc {
|
||||
/**
|
||||
@@ -186,51 +183,51 @@ epicsShareExtern std::ostream& operator<<(std::ostream& o, const Type& type);
|
||||
*/
|
||||
enum ScalarType {
|
||||
/**
|
||||
* The type is boolean, i. e. value can be {@code false} or {@code true}
|
||||
* The type is boolean, i.e. value can be {@code false} or {@code true}
|
||||
*/
|
||||
pvBoolean,
|
||||
/**
|
||||
* The type is byte, i. e. a 8 bit signed integer.
|
||||
* The type is byte, i.e. a 8 bit signed integer.
|
||||
*/
|
||||
pvByte,
|
||||
/**
|
||||
* The type is short, i. e. a 16 bit signed integer.
|
||||
* The type is short, i.e. a 16 bit signed integer.
|
||||
*/
|
||||
pvShort,
|
||||
/**
|
||||
* The type is int, i. e. a 32 bit signed integer.
|
||||
* The type is int, i.e. a 32 bit signed integer.
|
||||
*/
|
||||
pvInt,
|
||||
/**
|
||||
* The type is long, i. e. a 64 bit signed integer.
|
||||
* The type is long, i.e. a 64 bit signed integer.
|
||||
*/
|
||||
pvLong,
|
||||
/**
|
||||
* The type is unsigned byte, i. e. a 8 bit unsigned integer.
|
||||
* The type is unsigned byte, i.e. a 8 bit unsigned integer.
|
||||
*/
|
||||
pvUByte,
|
||||
/**
|
||||
* The type is unsigned short, i. e. a 16 bit unsigned integer.
|
||||
* The type is unsigned short, i.e. a 16 bit unsigned integer.
|
||||
*/
|
||||
pvUShort,
|
||||
/**
|
||||
* The type is unsigned int, i. e. a 32 bit unsigned integer.
|
||||
* The type is unsigned int, i.e. a 32 bit unsigned integer.
|
||||
*/
|
||||
pvUInt,
|
||||
/**
|
||||
* The type is unsigned long, i. e. a 64 bit unsigned integer.
|
||||
* The type is unsigned long, i.e. a 64 bit unsigned integer.
|
||||
*/
|
||||
pvULong,
|
||||
/**
|
||||
* The type is float, i. e. 32 bit IEEE floating point,
|
||||
* The type is float, i.e. 32 bit IEEE floating point,
|
||||
*/
|
||||
pvFloat,
|
||||
/**
|
||||
* The type is float, i. e. 64 bit IEEE floating point,
|
||||
* The type is float, i.e. 64 bit IEEE floating point,
|
||||
*/
|
||||
pvDouble,
|
||||
/**
|
||||
* The type is string, i. e. a UTF8 character string.
|
||||
* The type is string, i.e. a UTF8 character string.
|
||||
*/
|
||||
pvString
|
||||
};
|
||||
@@ -238,29 +235,30 @@ enum ScalarType {
|
||||
#define MAX_SCALAR_TYPE pvString
|
||||
|
||||
/**
|
||||
* Convenience functions for ScalarType.
|
||||
* @brief Convenience functions for ScalarType.
|
||||
*
|
||||
*/
|
||||
namespace ScalarTypeFunc {
|
||||
/**
|
||||
* Is the type an integer, i. e. is it one of byte,...ulong
|
||||
* Is the type an integer, i.e. is it one of byte,...ulong
|
||||
* @param scalarType The type.
|
||||
* @return (false,true) if the scalarType is an integer.
|
||||
*/
|
||||
epicsShareExtern bool isInteger(ScalarType scalarType);
|
||||
/**
|
||||
* Is the type an unsigned integer, i. e. is it one of ubyte,...ulong
|
||||
* Is the type an unsigned integer, i.e. is it one of ubyte,...ulong
|
||||
* @param scalarType The type.
|
||||
* @return (false,true) if the scalarType is an integer.
|
||||
*/
|
||||
epicsShareExtern bool isUInteger(ScalarType scalarType);
|
||||
/**
|
||||
* Is the type numeric, i. e. is it one of byte,...,double
|
||||
* Is the type numeric, i.e. is it one of byte,...,double
|
||||
* @param scalarType The type.
|
||||
* @return (false,true) if the scalarType is a numeric
|
||||
*/
|
||||
epicsShareExtern bool isNumeric(ScalarType scalarType);
|
||||
/**
|
||||
* Is the type primitive, i. e. not string
|
||||
* Is the type primitive, i.e. not string
|
||||
* @param scalarType The type.
|
||||
* @return (false,true) if the scalarType is primitive.
|
||||
*/
|
||||
@@ -287,7 +285,8 @@ epicsShareExtern std::ostream& operator<<(std::ostream& o, const ScalarType& sca
|
||||
|
||||
|
||||
/**
|
||||
* This class implements introspection object for field.
|
||||
* @brief This class implements introspection object for field.
|
||||
*
|
||||
*/
|
||||
class epicsShareClass Field :
|
||||
virtual public Serializable,
|
||||
@@ -339,7 +338,8 @@ epicsShareExtern std::ostream& operator<<(std::ostream& o, const Field& field);
|
||||
|
||||
|
||||
/**
|
||||
* This class implements introspection object for Scalar.
|
||||
* @brief This class implements introspection object for Scalar.
|
||||
*
|
||||
*/
|
||||
class epicsShareClass Scalar : public Field{
|
||||
public:
|
||||
@@ -376,7 +376,8 @@ private:
|
||||
};
|
||||
|
||||
/**
|
||||
* This class implements introspection object for BoundedString.
|
||||
* @brief This class implements introspection object for BoundedString.
|
||||
*
|
||||
*/
|
||||
class epicsShareClass BoundedString : public Scalar{
|
||||
public:
|
||||
@@ -402,7 +403,8 @@ private:
|
||||
};
|
||||
|
||||
/**
|
||||
* This class implements introspection object for Array.
|
||||
* @brief This class implements introspection object for Array.
|
||||
*
|
||||
*/
|
||||
class epicsShareClass Array : public Field{
|
||||
public:
|
||||
@@ -437,14 +439,9 @@ protected:
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* This class implements introspection object for scalar array.
|
||||
* @brief This class implements introspection object for scalar array.
|
||||
*
|
||||
*/
|
||||
class epicsShareClass ScalarArray : public Array{
|
||||
public:
|
||||
@@ -488,7 +485,8 @@ private:
|
||||
|
||||
|
||||
/**
|
||||
* This class implements introspection object for bounded scalar array.
|
||||
* @brief This class implements introspection object for bounded scalar array.
|
||||
*
|
||||
*/
|
||||
class epicsShareClass BoundedScalarArray : public ScalarArray{
|
||||
public:
|
||||
@@ -522,7 +520,8 @@ private:
|
||||
};
|
||||
|
||||
/**
|
||||
* This class implements introspection object for bounded scalar array.
|
||||
* @brief This class implements introspection object for bounded scalar array.
|
||||
*
|
||||
*/
|
||||
class epicsShareClass FixedScalarArray : public ScalarArray{
|
||||
public:
|
||||
@@ -555,12 +554,9 @@ private:
|
||||
friend class FieldCreate;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* This class implements introspection object for a structureArray
|
||||
* @brief This class implements introspection object for a structureArray
|
||||
*
|
||||
*/
|
||||
class epicsShareClass StructureArray : public Array{
|
||||
public:
|
||||
@@ -601,7 +597,8 @@ private:
|
||||
};
|
||||
|
||||
/**
|
||||
* This class implements introspection object for a unionArray
|
||||
* @brief This class implements introspection object for a unionArray
|
||||
*
|
||||
*/
|
||||
class epicsShareClass UnionArray : public Array{
|
||||
public:
|
||||
@@ -642,7 +639,8 @@ private:
|
||||
};
|
||||
|
||||
/**
|
||||
* This class implements introspection object for a structure.
|
||||
* @brief This class implements introspection object for a structure.
|
||||
*
|
||||
*/
|
||||
class epicsShareClass Structure : public Field {
|
||||
public:
|
||||
@@ -651,7 +649,13 @@ public:
|
||||
/**
|
||||
* Default structure ID.
|
||||
*/
|
||||
static std::string DEFAULT_ID;
|
||||
static const std::string DEFAULT_ID;
|
||||
|
||||
/**
|
||||
* Get the default structure ID.
|
||||
* @return The default structure ID.
|
||||
*/
|
||||
static const std::string & defaultId();
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
@@ -672,13 +676,35 @@ public:
|
||||
* This will hold a null pointer if the field is not in the structure.
|
||||
*/
|
||||
FieldConstPtr getField(std::string const &fieldName) const;
|
||||
|
||||
template<typename FT>
|
||||
std::tr1::shared_ptr<const FT> getField(std::string const &fieldName) const
|
||||
{
|
||||
FieldConstPtr field = getField(fieldName);
|
||||
if (field.get())
|
||||
return std::tr1::dynamic_pointer_cast<const FT>(field);
|
||||
else
|
||||
return std::tr1::shared_ptr<const FT>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the field for the specified fieldName.
|
||||
* @param fieldName The index of the field to get;
|
||||
* @return The introspection interface.
|
||||
* This will hold a null pointer if the field is not in the structure.
|
||||
*/
|
||||
FieldConstPtr getField(std::size_t index) const {return fields[index];}
|
||||
FieldConstPtr getField(std::size_t index) const {return fields.at(index);}
|
||||
|
||||
template<typename FT>
|
||||
std::tr1::shared_ptr<const FT> getField(std::size_t index) const
|
||||
{
|
||||
FieldConstPtr field = getField(index);
|
||||
if (field.get())
|
||||
return std::tr1::dynamic_pointer_cast<const FT>(field);
|
||||
else
|
||||
return std::tr1::shared_ptr<const FT>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the field index for the specified fieldName.
|
||||
* @return The introspection interface.
|
||||
@@ -700,7 +726,7 @@ public:
|
||||
* @param fieldIndex The index of the desired field.
|
||||
* @return The fieldName.
|
||||
*/
|
||||
std::string getFieldName(std::size_t fieldIndex) const {return fieldNames[fieldIndex];}
|
||||
std::string getFieldName(std::size_t fieldIndex) const {return fieldNames.at(fieldIndex);}
|
||||
|
||||
virtual std::string getID() const;
|
||||
|
||||
@@ -710,7 +736,7 @@ public:
|
||||
virtual void deserialize(ByteBuffer *buffer, DeserializableControl *control);
|
||||
|
||||
protected:
|
||||
Structure(StringArray const & fieldNames, FieldConstPtrArray const & fields, std::string const & id = DEFAULT_ID);
|
||||
Structure(StringArray const & fieldNames, FieldConstPtrArray const & fields, std::string const & id = defaultId());
|
||||
private:
|
||||
StringArray fieldNames;
|
||||
FieldConstPtrArray fields;
|
||||
@@ -723,7 +749,8 @@ private:
|
||||
};
|
||||
|
||||
/**
|
||||
* This class implements introspection object for a union.
|
||||
* @brief This class implements introspection object for a union.
|
||||
*
|
||||
*/
|
||||
class epicsShareClass Union : public Field {
|
||||
public:
|
||||
@@ -732,12 +759,24 @@ public:
|
||||
/**
|
||||
* Default union ID.
|
||||
*/
|
||||
static std::string DEFAULT_ID;
|
||||
static const std::string DEFAULT_ID;
|
||||
|
||||
/**
|
||||
* Get the default union ID.
|
||||
* @return The default union ID.
|
||||
*/
|
||||
static const std::string & defaultId();
|
||||
|
||||
/**
|
||||
* Default variant union ID.
|
||||
*/
|
||||
static std::string ANY_ID;
|
||||
static const std::string ANY_ID;
|
||||
|
||||
/**
|
||||
* Get the default variant union ID.
|
||||
* @return The default variant union ID.
|
||||
*/
|
||||
static const std::string & anyId();
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
@@ -758,13 +797,35 @@ public:
|
||||
* This will hold a null pointer if the field is not in the union.
|
||||
*/
|
||||
FieldConstPtr getField(std::string const &fieldName) const;
|
||||
|
||||
template<typename FT>
|
||||
std::tr1::shared_ptr<const FT> getField(std::string const &fieldName) const
|
||||
{
|
||||
FieldConstPtr field = getField(fieldName);
|
||||
if (field.get())
|
||||
return std::tr1::dynamic_pointer_cast<const FT>(field);
|
||||
else
|
||||
return std::tr1::shared_ptr<const FT>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the field for the specified fieldName.
|
||||
* @param fieldName The index of the field to get;
|
||||
* @return The introspection interface.
|
||||
* This will hold a null pointer if the field is not in the union.
|
||||
*/
|
||||
FieldConstPtr getField(std::size_t index) const {return fields[index];}
|
||||
FieldConstPtr getField(std::size_t index) const {return fields.at(index);}
|
||||
|
||||
template<typename FT>
|
||||
std::tr1::shared_ptr<const FT> getField(std::size_t index) const
|
||||
{
|
||||
FieldConstPtr field = getField(index);
|
||||
if (field.get())
|
||||
return std::tr1::dynamic_pointer_cast<const FT>(field);
|
||||
else
|
||||
return std::tr1::shared_ptr<const FT>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the field index for the specified fieldName.
|
||||
* @return The introspection interface.
|
||||
@@ -786,7 +847,7 @@ public:
|
||||
* @param fieldIndex The index of the desired field.
|
||||
* @return The fieldName.
|
||||
*/
|
||||
std::string getFieldName(std::size_t fieldIndex) const {return fieldNames[fieldIndex];}
|
||||
std::string getFieldName(std::size_t fieldIndex) const {return fieldNames.at(fieldIndex);}
|
||||
/**
|
||||
* Check if this union is variant union (aka any type).
|
||||
* @return <code>true</code> if this union is variant union, otherwise <code>false</code>.
|
||||
@@ -802,7 +863,7 @@ public:
|
||||
|
||||
protected:
|
||||
Union();
|
||||
Union(StringArray const & fieldNames, FieldConstPtrArray const & fields, std::string const & id = DEFAULT_ID);
|
||||
Union(StringArray const & fieldNames, FieldConstPtrArray const & fields, std::string const & id = defaultId());
|
||||
private:
|
||||
StringArray fieldNames;
|
||||
FieldConstPtrArray fields;
|
||||
@@ -821,7 +882,8 @@ class FieldBuilder;
|
||||
typedef std::tr1::shared_ptr<FieldBuilder> FieldBuilderPtr;
|
||||
|
||||
/**
|
||||
* Interface for in-line creating of introspection interfaces.
|
||||
* @brief Interface for in-line creating of introspection interfaces.
|
||||
*
|
||||
* One instance can be used to create multiple {@code Field} instances.
|
||||
* An instance of this object must not be used concurrently (an object has a state).
|
||||
* @author mse
|
||||
@@ -985,7 +1047,8 @@ private:
|
||||
};
|
||||
|
||||
/**
|
||||
* This is a singleton class for creating introspection interfaces.
|
||||
* @brief This is a singleton class for creating introspection interfaces.
|
||||
*
|
||||
*/
|
||||
class epicsShareClass FieldCreate {
|
||||
public:
|
||||
@@ -1137,7 +1200,7 @@ private:
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the single class that implemnents FieldCreate,
|
||||
* Get the single class that implements FieldCreate,
|
||||
* @param The fieldCreate factory.
|
||||
*/
|
||||
epicsShareExtern FieldCreatePtr getFieldCreate();
|
||||
@@ -1153,7 +1216,7 @@ epicsShareExtern FieldCreatePtr getFieldCreate();
|
||||
* value (eg -1).
|
||||
*/
|
||||
template<typename T>
|
||||
struct ScalarTypeID { enum {value=-1}; };
|
||||
struct ScalarTypeID {};
|
||||
|
||||
/**
|
||||
* Static mapping from ScalarType enum to value type.
|
||||
@@ -1183,14 +1246,26 @@ OP(pvDouble, double)
|
||||
OP(pvString, std::string)
|
||||
#undef OP
|
||||
|
||||
/**
|
||||
* @brief Hash a Scalar
|
||||
*
|
||||
*/
|
||||
struct ScalarHashFunction {
|
||||
size_t operator() (const Scalar& scalar) const { return scalar.getScalarType(); }
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Hash a ScalarArray
|
||||
*
|
||||
*/
|
||||
struct ScalarArrayHashFunction {
|
||||
size_t operator() (const ScalarArray& scalarArray) const { return 0x10 | scalarArray.getElementType(); }
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Hash a Structure
|
||||
*
|
||||
*/
|
||||
struct StructureHashFunction {
|
||||
size_t operator() (const Structure& /*structure*/) const { return 0; }
|
||||
// TODO hash
|
||||
@@ -1198,9 +1273,47 @@ struct StructureHashFunction {
|
||||
// return PRIME * Arrays.hashCode(fieldNames) + Arrays.hashCode(fields);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Hash a StructureArray
|
||||
*
|
||||
*/
|
||||
struct StructureArrayHashFunction {
|
||||
size_t operator() (const StructureArray& structureArray) const { StructureHashFunction shf; return (0x10 | shf(*(structureArray.getStructure()))); }
|
||||
};
|
||||
|
||||
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&);
|
||||
bool epicsShareExtern operator==(const BoundedString&, const BoundedString&);
|
||||
|
||||
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);}
|
||||
static inline bool operator!=(const BoundedString& a, const BoundedString& b)
|
||||
{return !(a==b);}
|
||||
|
||||
}}
|
||||
|
||||
/**
|
||||
* stream support for Field
|
||||
*/
|
||||
namespace std{
|
||||
epicsShareExtern std::ostream& operator<<(std::ostream& o, const epics::pvData::Field *ptr);
|
||||
}
|
||||
|
||||
#endif /* PVINTROSPECT_H */
|
||||
|
||||
@@ -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,7 +49,7 @@ namespace detail {
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a set of typdefs used by pvData.
|
||||
* This is a set of typedefs used by pvData.
|
||||
*/
|
||||
|
||||
/**
|
||||
|
||||
@@ -25,7 +25,8 @@ class StandardField;
|
||||
typedef std::tr1::shared_ptr<StandardField> StandardFieldPtr;
|
||||
|
||||
/**
|
||||
* Standard Fields is a class or creating or sharing Field objects for standard fields.
|
||||
* @brief Standard Fields is a class or creating or sharing Field objects for standard fields.
|
||||
*
|
||||
* For each type of standard object two methods are defined:s
|
||||
* one with no properties and with properties
|
||||
* The property field is a comma separated string of property names of the following:
|
||||
@@ -85,7 +86,7 @@ public:
|
||||
StructureConstPtr regUnion(
|
||||
UnionConstPtr const & punion,
|
||||
std::string const & properties);
|
||||
/** Create a structure that has a varient union value field.
|
||||
/** Create a structure that has a variant union value field.
|
||||
* @param properties A comma separated list of properties.
|
||||
* This is some combination of "alarm,timeStamp,display,control,valueAlarm".
|
||||
* @return The const shared pointer to the structure.
|
||||
|
||||
@@ -25,7 +25,8 @@ class StandardPVField;
|
||||
typedef std::tr1::shared_ptr<StandardPVField> StandardPVFieldPtr;
|
||||
|
||||
/**
|
||||
* StandardPVField is a class or creating standard data fields.
|
||||
* @brief StandardPVField is a class or creating standard data fields.
|
||||
*
|
||||
* Like class StandardField it has two forms of the methods which create a fields:
|
||||
* one without properties and one with properties.
|
||||
* The properties are some combination of alarm, timeStamp, control, display, and valueAlarm.
|
||||
|
||||
@@ -18,8 +18,20 @@
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
/**
|
||||
* @brief Compress a bitSet.
|
||||
*
|
||||
*/
|
||||
class epicsShareClass BitSetUtil : private NoDefaultMethods {
|
||||
public:
|
||||
/**
|
||||
* compress the bitSet for a pvStructure.
|
||||
* In all subfields of a structure have been modified then
|
||||
* the bit for the structure is set and all the subfield bits
|
||||
* are cleared.
|
||||
* @param bitSet this must be a valid bitSet for pvStructure.
|
||||
* @param pvStructure the structure.
|
||||
*/
|
||||
static bool compress(BitSetPtr const &bitSet,PVStructurePtr const &pvStructure);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,8 +1,31 @@
|
||||
# Makefile for the pvData tests
|
||||
|
||||
TOP = ..
|
||||
include $(TOP)/configure/CONFIG
|
||||
DIRS += misc
|
||||
DIRS += pv
|
||||
DIRS += property
|
||||
DIRS += copy
|
||||
include $(TOP)/configure/RULES_DIRS
|
||||
|
||||
PVDATA_TEST = $(TOP)/testApp
|
||||
|
||||
PROD_LIBS += pvData Com
|
||||
|
||||
include $(PVDATA_TEST)/misc/Makefile
|
||||
include $(PVDATA_TEST)/pv/Makefile
|
||||
include $(PVDATA_TEST)/property/Makefile
|
||||
include $(PVDATA_TEST)/copy/Makefile
|
||||
|
||||
# The testHarness runs all the test programs in a known working order.
|
||||
testHarness_SRCS += pvDataAllTests.c
|
||||
|
||||
PROD_vxWorks = vxTestHarness
|
||||
vxTestHarness_SRCS += $(testHarness_SRCS)
|
||||
TESTSPEC_vxWorks = vxTestHarness.$(MUNCH_SUFFIX); pvDataAllTests
|
||||
|
||||
PROD_RTEMS += rtemsTestHarness
|
||||
rtemsTestHarness_SRCS += rtemsTestHarness.c rtemsConfig.c
|
||||
rtemsTestHarness_SRCS += $(testHarness_SRCS)
|
||||
TESTSPEC_RTEMS = rtemsTestHarness.$(MUNCH_SUFFIX); pvDataAllTests
|
||||
|
||||
TESTSCRIPTS_HOST += $(TESTS:%=%.t)
|
||||
|
||||
include $(TOP)/configure/RULES
|
||||
|
||||
|
||||
|
||||
@@ -1,22 +1,13 @@
|
||||
TOP=../..
|
||||
# This is a Makefile fragment, see ../Makefile
|
||||
|
||||
include $(TOP)/configure/CONFIG
|
||||
SRC_DIRS += $(PVDATA_TEST)/copy
|
||||
|
||||
PROD_HOST += testCreateRequest
|
||||
TESTPROD_HOST += testCreateRequest
|
||||
testCreateRequest_SRCS = testCreateRequest.cpp
|
||||
testCreateRequest_LIBS = pvData Com
|
||||
testHarness_SRCS += testCreateRequest.cpp
|
||||
TESTS += testCreateRequest
|
||||
|
||||
PROD_HOST += testPVCopy
|
||||
TESTPROD_HOST += testPVCopy
|
||||
testPVCopy_SRCS += testPVCopy.cpp
|
||||
testPVCopy_LIBS += pvData Com
|
||||
testHarness_SRCS += testPVCopy.cpp
|
||||
TESTS += testPVCopy
|
||||
|
||||
TESTSCRIPTS_HOST += $(TESTS:%=%.t)
|
||||
|
||||
|
||||
|
||||
include $(TOP)/configure/RULES
|
||||
#----------------------------------------
|
||||
# ADD RULES AFTER THIS LINE
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ using std::endl;
|
||||
|
||||
static bool debug = false;
|
||||
|
||||
static void testCreateRequest() {
|
||||
static void testCreateRequestInternal() {
|
||||
printf("testCreateRequest... \n");
|
||||
CreateRequest::shared_pointer createRequest = CreateRequest::create();
|
||||
PVStringPtr pvString;
|
||||
@@ -30,8 +30,8 @@ static void testCreateRequest() {
|
||||
string request = "";
|
||||
if(debug) { cout << "request " << request <<endl;}
|
||||
PVStructurePtr pvRequest = createRequest->createRequest(request);
|
||||
if(pvRequest.get()==NULL) { cout<< createRequest->getMessage() << endl;}
|
||||
if(debug) { cout << *pvRequest << endl;}
|
||||
if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
|
||||
if(debug) { cout << pvRequest << endl;}
|
||||
testOk1(pvRequest.get()!=NULL);
|
||||
testOk1(pvRequest->getStructure()->getNumberFields()==0);
|
||||
testPass("request %s",request.c_str());
|
||||
@@ -39,8 +39,8 @@ static void testCreateRequest() {
|
||||
request = "record[]field()getField()putField()";
|
||||
if(debug) { cout << "request " << request <<endl;}
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
if(pvRequest.get()==NULL) { cout<< createRequest->getMessage() << endl;}
|
||||
if(debug) { cout << *pvRequest << endl;}
|
||||
if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
|
||||
if(debug) { cout << pvRequest << endl;}
|
||||
testOk1(pvRequest.get()!=NULL);
|
||||
testOk1(pvRequest->getSubField("field").get()!=NULL);
|
||||
testOk1(pvRequest->getSubField("putField").get()!=NULL);
|
||||
@@ -50,8 +50,8 @@ static void testCreateRequest() {
|
||||
request = "record[a=b,x=y]field(a) putField(a),getField(a)";
|
||||
if(debug) { cout << "request " << request <<endl;}
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
if(pvRequest.get()==NULL) { cout<< createRequest->getMessage() << endl;}
|
||||
if(debug) { cout << *pvRequest << endl;}
|
||||
if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
|
||||
if(debug) { cout << pvRequest << endl;}
|
||||
testOk1(pvRequest.get()!=NULL);
|
||||
pvString = pvRequest->getSubField<PVString>("record._options.a");
|
||||
sval = pvString->get();
|
||||
@@ -67,8 +67,8 @@ static void testCreateRequest() {
|
||||
request = "field(a.b[x=y])";
|
||||
if(debug) { cout << "request " << request <<endl;}
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
if(pvRequest.get()==NULL) { cout<< createRequest->getMessage() << endl;}
|
||||
if(debug) { cout << *pvRequest << endl;}
|
||||
if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
|
||||
if(debug) { cout << pvRequest << endl;}
|
||||
testOk1(pvRequest.get()!=NULL);
|
||||
pvString = pvRequest->getSubField<PVString>("field.a.b._options.x");
|
||||
sval = pvString->get();
|
||||
@@ -78,8 +78,8 @@ static void testCreateRequest() {
|
||||
request = "field(a.b{c.d})";
|
||||
if(debug) { cout << "request " << request <<endl;}
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
if(pvRequest.get()==NULL) { cout<< createRequest->getMessage() << endl;}
|
||||
if(debug) { cout << *pvRequest << endl;}
|
||||
if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
|
||||
if(debug) { cout << pvRequest << endl;}
|
||||
testOk1(pvRequest.get()!=NULL);
|
||||
testOk1(pvRequest->getSubField("field.a.b.c.d").get()!=NULL);
|
||||
testPass("request %s",request.c_str());
|
||||
@@ -87,8 +87,8 @@ static void testCreateRequest() {
|
||||
request = "field(a.b[x=y]{c.d})";
|
||||
if(debug) { cout << "request " << request <<endl;}
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
if(pvRequest.get()==NULL) { cout<< createRequest->getMessage() << endl;}
|
||||
if(debug) { cout << *pvRequest << endl;}
|
||||
if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
|
||||
if(debug) { cout << pvRequest << endl;}
|
||||
testOk1(pvRequest.get()!=NULL);
|
||||
pvString = pvRequest->getSubField<PVString>("field.a.b._options.x");
|
||||
sval = pvString->get();
|
||||
@@ -99,8 +99,8 @@ static void testCreateRequest() {
|
||||
request = "field(a.b[x=y]{c.d[x=y]})";
|
||||
if(debug) { cout << "request " << request <<endl;}
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
if(pvRequest.get()==NULL) { cout<< createRequest->getMessage() << endl;}
|
||||
if(debug) { cout << *pvRequest << endl;}
|
||||
if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
|
||||
if(debug) { cout << pvRequest << endl;}
|
||||
testOk1(pvRequest.get()!=NULL);
|
||||
pvString = pvRequest->getSubField<PVString>("field.a.b._options.x");
|
||||
sval = pvString->get();
|
||||
@@ -113,8 +113,8 @@ static void testCreateRequest() {
|
||||
request = "record[a=b,c=d] field(a.a[a=b]{a.a[a=b]},b.a[a=b]{a,b})";
|
||||
if(debug) { cout << "request " << request <<endl;}
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
if(pvRequest.get()==NULL) { cout<< createRequest->getMessage() << endl;}
|
||||
if(debug) { cout << *pvRequest << endl;}
|
||||
if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
|
||||
if(debug) { cout << pvRequest << endl;}
|
||||
testOk1(pvRequest.get()!=NULL);
|
||||
pvString = pvRequest->getSubField<PVString>("field.a.a._options.a");
|
||||
sval = pvString->get();
|
||||
@@ -133,8 +133,8 @@ static void testCreateRequest() {
|
||||
request = "alarm,timeStamp,power.value";
|
||||
if(debug) { cout << "request " << request <<endl;}
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
if(pvRequest.get()==NULL) { cout<< createRequest->getMessage() << endl;}
|
||||
if(debug) { cout << *pvRequest << endl;}
|
||||
if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
|
||||
if(debug) { cout << pvRequest << endl;}
|
||||
testOk1(pvRequest.get()!=NULL);
|
||||
testOk1(pvRequest->getSubField("field.alarm").get()!=NULL);
|
||||
testOk1(pvRequest->getSubField("field.timeStamp").get()!=NULL);
|
||||
@@ -144,8 +144,8 @@ static void testCreateRequest() {
|
||||
request = "record[process=true]field(alarm,timeStamp,power.value)";
|
||||
if(debug) { cout << "request " << request <<endl;}
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
if(pvRequest.get()==NULL) { cout<< createRequest->getMessage() << endl;}
|
||||
if(debug) { cout << *pvRequest << endl;}
|
||||
if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
|
||||
if(debug) { cout << pvRequest << endl;}
|
||||
testOk1(pvRequest.get()!=NULL);
|
||||
pvString = pvRequest->getSubField<PVString>("record._options.process");
|
||||
sval = pvString->get();
|
||||
@@ -158,8 +158,8 @@ static void testCreateRequest() {
|
||||
request = "record[process=true]field(alarm,timeStamp[algorithm=onChange,causeMonitor=false],power{value,alarm})";
|
||||
if(debug) { cout << "request " << request <<endl;}
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
if(pvRequest.get()==NULL) { cout<< createRequest->getMessage() << endl;}
|
||||
if(debug) { cout << *pvRequest << endl;}
|
||||
if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
|
||||
if(debug) { cout << pvRequest << endl;}
|
||||
testOk1(pvRequest.get()!=NULL);
|
||||
pvString = pvRequest->getSubField<PVString>("record._options.process");
|
||||
sval = pvString->get();
|
||||
@@ -179,8 +179,8 @@ static void testCreateRequest() {
|
||||
request = "record[int=2,float=3.14159]field(alarm,timeStamp[shareData=true],power.value)";
|
||||
if(debug) { cout << "request " << request <<endl;}
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
if(pvRequest.get()==NULL) { cout<< createRequest->getMessage() << endl;}
|
||||
if(debug) { cout << *pvRequest << endl;}
|
||||
if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
|
||||
if(debug) { cout << pvRequest << endl;}
|
||||
testOk1(pvRequest.get()!=NULL);
|
||||
pvString = pvRequest->getSubField<PVString>("record._options.int");
|
||||
sval = pvString->get();
|
||||
@@ -201,8 +201,8 @@ static void testCreateRequest() {
|
||||
+ "current{value,alarm},voltage{value,alarm})";
|
||||
if(debug) { cout << "request " << request <<endl;}
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
if(pvRequest.get()==NULL) { cout<< createRequest->getMessage() << endl;}
|
||||
if(debug) { cout << *pvRequest << endl;}
|
||||
if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
|
||||
if(debug) { cout << pvRequest << endl;}
|
||||
testOk1(pvRequest.get()!=NULL);
|
||||
testOk1(pvRequest->getSubField("putField.power.value").get()!=NULL);
|
||||
testOk1(pvRequest->getSubField("getField.alarm").get()!=NULL);
|
||||
@@ -221,8 +221,8 @@ static void testCreateRequest() {
|
||||
+ "})";
|
||||
if(debug) { cout << "request " << request <<endl;}
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
if(pvRequest.get()==NULL) { cout<< createRequest->getMessage() << endl;}
|
||||
if(debug) { cout << *pvRequest << endl;}
|
||||
if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
|
||||
if(debug) { cout << pvRequest << endl;}
|
||||
testOk1(pvRequest.get()!=NULL);
|
||||
testOk1(pvRequest->getSubField("field.alarm").get()!=NULL);
|
||||
testOk1(pvRequest->getSubField("field.timeStamp").get()!=NULL);
|
||||
@@ -243,8 +243,8 @@ static void testCreateRequest() {
|
||||
+ ")";
|
||||
if(debug) { cout << "request " << request <<endl;}
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
if(pvRequest.get()==NULL) { cout<< createRequest->getMessage() << endl;}
|
||||
if(debug) { cout << *pvRequest << endl;}
|
||||
if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
|
||||
if(debug) { cout << pvRequest << endl;}
|
||||
testOk1(pvRequest.get()!=NULL);
|
||||
testOk1(pvRequest->getSubField("putField.power.value").get()!=NULL);
|
||||
testOk1(pvRequest->getSubField("getField.alarm").get()!=NULL);
|
||||
@@ -276,8 +276,8 @@ static void testCreateRequest() {
|
||||
request = "a{b{c{d}}}";
|
||||
if(debug) { cout << "request " << request <<endl;}
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
if(pvRequest.get()==NULL) { cout<< createRequest->getMessage() << endl;}
|
||||
if(debug) { cout << *pvRequest << endl;}
|
||||
if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
|
||||
if(debug) { cout << pvRequest << endl;}
|
||||
testOk1(pvRequest.get()!=NULL);
|
||||
testOk1(pvRequest->getSubField("field.a.b.c.d").get()!=NULL);
|
||||
testPass("request %s",request.c_str());
|
||||
@@ -302,12 +302,28 @@ static void testCreateRequest() {
|
||||
cout << "reason " << createRequest->getMessage() << endl;
|
||||
testOk1(pvRequest.get()==NULL);
|
||||
testPass("request %s",request.c_str());
|
||||
|
||||
request = "field(alarm.status,alarm.severity)";
|
||||
if(debug) { cout << "request " << request <<endl;}
|
||||
cout << endl << "Error Expected for next call!!" << endl;
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
cout << "reason " << createRequest->getMessage() << endl;
|
||||
testOk1(pvRequest.get()==NULL);
|
||||
testPass("request %s",request.c_str());
|
||||
|
||||
request = ":field(record[process=false]power.value)";
|
||||
if(debug) { cout << "request " << request <<endl;}
|
||||
cout << endl << "Error Expected for next call!!" << endl;
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
cout << "reason " << createRequest->getMessage() << endl;
|
||||
testOk1(pvRequest.get()==NULL);
|
||||
testPass("request %s",request.c_str());
|
||||
}
|
||||
|
||||
MAIN(testCreateRequest)
|
||||
{
|
||||
testPlan(117);
|
||||
testCreateRequest();
|
||||
testPlan(121);
|
||||
testCreateRequestInternal();
|
||||
return testDone();
|
||||
}
|
||||
|
||||
|
||||
@@ -108,7 +108,6 @@ static void testPVScalar(
|
||||
}
|
||||
|
||||
static void testPVScalarArray(
|
||||
ScalarType scalarType,
|
||||
string const & valueNameMaster,
|
||||
string const & valueNameCopy,
|
||||
PVStructurePtr const & pvMaster,
|
||||
@@ -123,14 +122,14 @@ static void testPVScalarArray(
|
||||
shared_vector<double> values(n);
|
||||
shared_vector<const double> cvalues;
|
||||
|
||||
pvValueMaster = pvMaster->getScalarArrayField(valueNameMaster,scalarType);
|
||||
pvValueMaster = pvMaster->getSubField<PVScalarArray>(valueNameMaster);
|
||||
for(size_t i=0; i<n; i++) values[i] = i;
|
||||
const shared_vector<const double> xxx(freeze(values));
|
||||
pvValueMaster->putFrom(xxx);
|
||||
StructureConstPtr structure = pvCopy->getStructure();
|
||||
if(debug) { cout << "structure from copy" << endl << *structure << endl;}
|
||||
pvStructureCopy = pvCopy->createPVStructure();
|
||||
pvValueCopy = pvStructureCopy->getScalarArrayField(valueNameCopy,scalarType);
|
||||
pvValueCopy = pvStructureCopy->getSubField<PVScalarArray>(valueNameCopy);
|
||||
bitSet = BitSetPtr(new BitSet(pvStructureCopy->getNumberFields()));
|
||||
pvCopy->initCopy(pvStructureCopy, bitSet);
|
||||
if(debug) { cout << "after initCopy pvValueCopy " << *pvValueCopy << endl; }
|
||||
@@ -256,7 +255,7 @@ static void arrayTest()
|
||||
if(debug) { cout << "pvRequest\n" << *pvRequest << endl; }
|
||||
pvCopy = PVCopy::create(pvMaster,pvRequest,"");
|
||||
valueNameCopy = "value";
|
||||
testPVScalarArray(pvDouble,valueNameMaster,valueNameCopy,pvMaster,pvCopy);
|
||||
testPVScalarArray(valueNameMaster,valueNameCopy,pvMaster,pvCopy);
|
||||
request = "";
|
||||
valueNameMaster = "value";
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
@@ -264,7 +263,7 @@ static void arrayTest()
|
||||
if(debug) { cout << "pvRequest\n" << *pvRequest << endl; }
|
||||
pvCopy = PVCopy::create(pvMaster,pvRequest,"");
|
||||
valueNameCopy = "value";
|
||||
testPVScalarArray(pvDouble,valueNameMaster,valueNameCopy,pvMaster,pvCopy);
|
||||
testPVScalarArray(valueNameMaster,valueNameCopy,pvMaster,pvCopy);
|
||||
request = "alarm,timeStamp,value";
|
||||
valueNameMaster = "value";
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
@@ -272,7 +271,7 @@ static void arrayTest()
|
||||
if(debug) { cout << "pvRequest\n" << *pvRequest << endl; }
|
||||
pvCopy = PVCopy::create(pvMaster,pvRequest,"");
|
||||
valueNameCopy = "value";
|
||||
testPVScalarArray(pvDouble,valueNameMaster,valueNameCopy,pvMaster,pvCopy);
|
||||
testPVScalarArray(valueNameMaster,valueNameCopy,pvMaster,pvCopy);
|
||||
}
|
||||
|
||||
static PVStructurePtr createPowerSupply()
|
||||
|
||||
@@ -1,63 +1,71 @@
|
||||
TOP=../..
|
||||
# This is a Makefile fragment, see ../Makefile
|
||||
|
||||
include $(TOP)/configure/CONFIG
|
||||
SRC_DIRS += $(PVDATA_TEST)/misc
|
||||
|
||||
PROD_LIBS += pvData Com
|
||||
|
||||
PROD_HOST += testThread
|
||||
TESTPROD_HOST += testThread
|
||||
testThread_SRCS += testThread.cpp
|
||||
testHarness_SRCS += testThread.cpp
|
||||
TESTS += testThread
|
||||
|
||||
PROD_HOST += testTimer
|
||||
TESTPROD_HOST += testEvent
|
||||
testEvent_SRCS += testEvent.cpp
|
||||
testHarness_SRCS += testEvent.cpp
|
||||
TESTS += testEvent
|
||||
|
||||
TESTPROD_HOST += testTimer
|
||||
testTimer_SRCS += testTimer.cpp
|
||||
testHarness_SRCS += testTimer.cpp
|
||||
TESTS += testTimer
|
||||
|
||||
PROD_HOST += testBitSet
|
||||
TESTPROD_HOST += testBitSet
|
||||
testBitSet_SRCS += testBitSet.cpp
|
||||
testHarness_SRCS += testBitSet.cpp
|
||||
TESTS += testBitSet
|
||||
|
||||
PROD_HOST += testOverrunBitSet
|
||||
TESTPROD_HOST += testOverrunBitSet
|
||||
testOverrunBitSet_SRCS += testOverrunBitSet.cpp
|
||||
testHarness_SRCS += testOverrunBitSet.cpp
|
||||
TESTS += testOverrunBitSet
|
||||
|
||||
PROD_HOST += testByteOrder
|
||||
TESTPROD_HOST += testByteOrder
|
||||
testByteOrder_SRCS += testByteOrder.cpp
|
||||
|
||||
PROD_HOST += testByteBuffer
|
||||
TESTPROD_HOST += testByteBuffer
|
||||
testByteBuffer_SRCS += testByteBuffer.cpp
|
||||
testHarness_SRCS += testByteBuffer.cpp
|
||||
TESTS += testByteBuffer
|
||||
|
||||
PROD_HOST += testBaseException
|
||||
TESTPROD_HOST += testBaseException
|
||||
testBaseException_SRCS += testBaseException.cpp
|
||||
testHarness_SRCS += testBaseException.cpp
|
||||
TESTS += testBaseException
|
||||
|
||||
PROD_HOST += testSharedVector
|
||||
TESTPROD_HOST += testSharedVector
|
||||
testSharedVector_SRCS += testSharedVector.cpp
|
||||
testHarness_SRCS += testSharedVector.cpp
|
||||
TESTS += testSharedVector
|
||||
|
||||
PROD_HOST += testSerialization
|
||||
TESTPROD_HOST += testSerialization
|
||||
testSerialization_SRCS += testSerialization.cpp
|
||||
testHarness_SRCS += testSerialization.cpp
|
||||
TESTS += testSerialization
|
||||
|
||||
PROD_HOST += testTimeStamp
|
||||
TESTPROD_HOST += testTimeStamp
|
||||
testTimeStamp_SRCS += testTimeStamp.cpp
|
||||
testHarness_SRCS += testTimeStamp.cpp
|
||||
TESTS += testTimeStamp
|
||||
|
||||
PROD_HOST += testQueue
|
||||
TESTPROD_HOST += testQueue
|
||||
testQueue_SRCS += testQueue.cpp
|
||||
testHarness_SRCS += testQueue.cpp
|
||||
TESTS += testQueue
|
||||
|
||||
PROD_HOST += testMessageQueue
|
||||
TESTPROD_HOST += testMessageQueue
|
||||
testMessageQueue_SRCS += testMessageQueue.cpp
|
||||
testHarness_SRCS += testMessageQueue.cpp
|
||||
TESTS += testMessageQueue
|
||||
|
||||
PROD_HOST += testTypeCast
|
||||
TESTPROD_HOST += testTypeCast
|
||||
testTypeCast_SRCS += testTypeCast.cpp
|
||||
testHarness_SRCS += testTypeCast.cpp
|
||||
TESTS += testTypeCast
|
||||
|
||||
TESTSCRIPTS_HOST += $(TESTS:%=%.t)
|
||||
|
||||
include $(TOP)/configure/RULES
|
||||
#----------------------------------------
|
||||
# ADD RULES AFTER THIS LINE
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ void internalTestBaseException(int /*unused*/ = 0)
|
||||
}
|
||||
}
|
||||
|
||||
void testBaseException() {
|
||||
void testBaseExceptionTest() {
|
||||
printf("testBaseException... ");
|
||||
|
||||
try {
|
||||
@@ -86,7 +86,7 @@ MAIN(testBaseException)
|
||||
testPlan(2);
|
||||
testDiag("Tests base exception");
|
||||
testLogicException();
|
||||
testBaseException();
|
||||
testBaseExceptionTest();
|
||||
return testDone();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
#include <testMain.h>
|
||||
#include <epicsEndian.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main()
|
||||
MAIN(testByteOrder)
|
||||
{
|
||||
printf("EPICS_BYTE_ORDER: %s\n", (EPICS_BYTE_ORDER == EPICS_ENDIAN_LITTLE) ? "little" : "big");
|
||||
printf("EPICS_FLOAT_WORD_ORDER: %s\n", (EPICS_FLOAT_WORD_ORDER == EPICS_ENDIAN_LITTLE) ? "little" : "big");
|
||||
|
||||
51
testApp/misc/testEvent.cpp
Normal file
51
testApp/misc/testEvent.cpp
Normal file
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
|
||||
#include <epicsUnitTest.h>
|
||||
#include <testMain.h>
|
||||
|
||||
#include <pv/event.h>
|
||||
|
||||
using namespace epics::pvData;
|
||||
|
||||
static void testBasicEvent()
|
||||
{
|
||||
testDiag("testBasicEvent");
|
||||
|
||||
Event e;
|
||||
|
||||
// 0 signals, 2 waits
|
||||
testOk1(!e.tryWait());
|
||||
testOk1(!e.tryWait());
|
||||
|
||||
// signal, wait, signal, wait
|
||||
e.signal();
|
||||
testOk1(e.tryWait());
|
||||
e.signal();
|
||||
testOk1(e.tryWait());
|
||||
|
||||
// 1 signal, 2 waits
|
||||
e.signal();
|
||||
testOk1(e.tryWait());
|
||||
testOk1(!e.tryWait());
|
||||
|
||||
// 2 signals, 2 waits
|
||||
e.signal();
|
||||
e.signal();
|
||||
testOk1(e.tryWait());
|
||||
testOk1(!e.tryWait());
|
||||
|
||||
// 0 signals, 1 wait
|
||||
testOk1(!e.tryWait());
|
||||
}
|
||||
|
||||
MAIN(testEvent)
|
||||
{
|
||||
testPlan(9);
|
||||
testBasicEvent();
|
||||
return testDone();
|
||||
}
|
||||
|
||||
@@ -32,17 +32,17 @@ void test()
|
||||
string buffer;
|
||||
string properties("alarm,timeStamp,display");
|
||||
PVStructurePtr pvStructure = standardPVField->scalar(pvDouble,properties);
|
||||
PVDoublePtr pvValue = pvStructure->getDoubleField("value");
|
||||
PVDoublePtr pvValue = pvStructure->getSubField<PVDouble>("value");
|
||||
uint32 valueOffset = (uint32) pvValue->getFieldOffset();
|
||||
PVStructurePtr pvAlarm = pvStructure->getStructureField("alarm");
|
||||
PVIntPtr pvSeverity = pvAlarm->getIntField("severity");
|
||||
PVStringPtr pvMessage = pvAlarm->getStringField("message");
|
||||
PVStructurePtr pvAlarm = pvStructure->getSubField<PVStructure>("alarm");
|
||||
PVIntPtr pvSeverity = pvAlarm->getSubField<PVInt>("severity");
|
||||
PVStringPtr pvMessage = pvAlarm->getSubField<PVString>("message");
|
||||
uint32 severityOffset = (uint32) pvSeverity->getFieldOffset();
|
||||
uint32 messageOffset = (uint32) pvMessage->getFieldOffset();
|
||||
PVStructurePtr pvTimeStamp = pvStructure->getStructureField("timeStamp");
|
||||
PVLongPtr pvSeconds = pvTimeStamp->getLongField("secondsPastEpoch");
|
||||
PVIntPtr pvNanoseconds = pvTimeStamp->getIntField("nanoseconds");
|
||||
PVIntPtr pvUserTag = pvTimeStamp->getIntField("userTag");
|
||||
PVStructurePtr pvTimeStamp = pvStructure->getSubField<PVStructure>("timeStamp");
|
||||
PVLongPtr pvSeconds = pvTimeStamp->getSubField<PVLong>("secondsPastEpoch");
|
||||
PVIntPtr pvNanoseconds = pvTimeStamp->getSubField<PVInt>("nanoseconds");
|
||||
PVIntPtr pvUserTag = pvTimeStamp->getSubField<PVInt>("userTag");
|
||||
uint32 timeStampOffset = (uint32) pvTimeStamp->getFieldOffset();
|
||||
uint32 secondsOffset = (uint32) pvSeconds->getFieldOffset();
|
||||
uint32 nanosecondsOffset = (uint32) pvNanoseconds->getFieldOffset();
|
||||
@@ -132,7 +132,7 @@ void test()
|
||||
}
|
||||
|
||||
|
||||
MAIN(testOverrunBitSet`)
|
||||
MAIN(testOverrunBitSet)
|
||||
{
|
||||
testPlan(41);
|
||||
testDiag("Tests for changeBitSet and overrunBitSet");
|
||||
|
||||
@@ -385,9 +385,9 @@ void testStructure() {
|
||||
|
||||
testDiag("\tSimple structure serialization");
|
||||
PVStructurePtr pvStructure = factory->createPVStructure(getStandardField()->timeStamp());
|
||||
pvStructure->getLongField("secondsPastEpoch")->put(123);
|
||||
pvStructure->getIntField("nanoseconds")->put(456);
|
||||
pvStructure->getIntField("userTag")->put(789);
|
||||
pvStructure->getSubField<PVLong>("secondsPastEpoch")->put(123);
|
||||
pvStructure->getSubField<PVInt>("nanoseconds")->put(456);
|
||||
pvStructure->getSubField<PVInt>("userTag")->put(789);
|
||||
|
||||
serializationTest(pvStructure);
|
||||
|
||||
@@ -716,7 +716,9 @@ void testArraySizeType() {
|
||||
serializationFieldTest(s);
|
||||
|
||||
PVStructurePtr pvs = getPVDataCreate()->createPVStructure(s);
|
||||
pvs->getSubField<PVArray>("fixedArray")->setLength(10);
|
||||
PVDoubleArray::shared_pointer pvDA = pvs->getSubField<PVDoubleArray>("fixedArray");
|
||||
PVDoubleArray::svector vec(10, 42);
|
||||
pvDA->replace(freeze(vec));
|
||||
serializationTest(pvs);
|
||||
}
|
||||
|
||||
@@ -790,7 +792,6 @@ MAIN(testSerialization) {
|
||||
delete control;
|
||||
delete flusher;
|
||||
|
||||
epicsExitCallAtExits();
|
||||
return testDone();
|
||||
}
|
||||
|
||||
|
||||
@@ -19,11 +19,12 @@
|
||||
#include "pv/sharedVector.h"
|
||||
|
||||
using std::string;
|
||||
using namespace epics::pvData;
|
||||
|
||||
static void testEmpty()
|
||||
{
|
||||
testDiag("Test empty vector");
|
||||
epics::pvData::shared_vector<int> empty, empty2;
|
||||
epics::pvData::shared_vector<int32> empty, empty2;
|
||||
|
||||
testOk1(empty.size()==0);
|
||||
testOk1(empty.empty());
|
||||
@@ -42,7 +43,7 @@ static void testInternalAlloc()
|
||||
{
|
||||
testDiag("Test vector alloc w/ new[]");
|
||||
|
||||
epics::pvData::shared_vector<int> internal(5);
|
||||
epics::pvData::shared_vector<int32> internal(5);
|
||||
|
||||
testOk1(internal.size()==5);
|
||||
testOk1(!internal.empty());
|
||||
@@ -57,7 +58,7 @@ static void testInternalAlloc()
|
||||
internal[2] = 42;
|
||||
testOk1(internal[2]==42);
|
||||
|
||||
epics::pvData::shared_vector<int> internal2(15, 500);
|
||||
epics::pvData::shared_vector<int32> internal2(15, 500);
|
||||
|
||||
testOk1(internal2.size()==15);
|
||||
testOk1(internal2[1]==500);
|
||||
@@ -79,8 +80,8 @@ namespace {
|
||||
//Note: STL shared_ptr requires that deletors be copy constructable
|
||||
template<typename E>
|
||||
struct callCounter {
|
||||
std::tr1::shared_ptr<int> count;
|
||||
callCounter():count(new int){*count=0;}
|
||||
std::tr1::shared_ptr<int32> count;
|
||||
callCounter():count(new int32){*count=0;}
|
||||
callCounter(const callCounter& o):count(o.count) {};
|
||||
callCounter& operator=(const callCounter& o){count=o.count;}
|
||||
void operator()(E){*count=1;}
|
||||
@@ -92,8 +93,8 @@ static void testExternalAlloc()
|
||||
testDiag("Test vector external alloc");
|
||||
|
||||
// Simulate a failed malloc() or similar
|
||||
int *oops=0;
|
||||
epics::pvData::shared_vector<int> nullPtr(oops, 42, 100);
|
||||
int32 *oops=0;
|
||||
epics::pvData::shared_vector<int32> nullPtr(oops, 42, 100);
|
||||
|
||||
testOk1(nullPtr.size()==0);
|
||||
testOk1(nullPtr.empty());
|
||||
@@ -102,8 +103,8 @@ static void testExternalAlloc()
|
||||
|
||||
testOk1(nullPtr.data()==NULL);
|
||||
|
||||
int *raw=new int[5];
|
||||
epics::pvData::shared_vector<int> newData(raw, 1, 4);
|
||||
int32 *raw=new int32[5];
|
||||
epics::pvData::shared_vector<int32> newData(raw, 1, 4);
|
||||
|
||||
testOk1(newData.size()==4);
|
||||
testOk1(!newData.empty());
|
||||
@@ -113,11 +114,11 @@ static void testExternalAlloc()
|
||||
testOk1(newData[0]==14);
|
||||
|
||||
// Check use of custom deleter
|
||||
int localVar[4] = {1,2,3,4};
|
||||
callCounter<int*> tracker;
|
||||
int32 localVar[4] = {1,2,3,4};
|
||||
callCounter<int32*> tracker;
|
||||
testOk1(*tracker.count==0);
|
||||
|
||||
epics::pvData::shared_vector<int> locvar(localVar,
|
||||
epics::pvData::shared_vector<int32> locvar(localVar,
|
||||
tracker,
|
||||
0, 4);
|
||||
|
||||
@@ -137,8 +138,8 @@ static void testShare()
|
||||
{
|
||||
testDiag("Test vector Sharing");
|
||||
|
||||
epics::pvData::shared_vector<int> one, two(15);
|
||||
epics::pvData::shared_vector<int> three(two);
|
||||
epics::pvData::shared_vector<int32> one, two(15);
|
||||
epics::pvData::shared_vector<int32> three(two);
|
||||
|
||||
testOk1(one.unique());
|
||||
testOk1(!two.unique());
|
||||
@@ -199,22 +200,22 @@ static void testConst()
|
||||
{
|
||||
testDiag("Test constant vector");
|
||||
|
||||
epics::pvData::shared_vector<int> writable(15, 100);
|
||||
epics::pvData::shared_vector<int32> writable(15, 100);
|
||||
|
||||
epics::pvData::shared_vector<int>::reference wr = writable[0];
|
||||
epics::pvData::shared_vector<int>::const_reference ror = writable[0];
|
||||
epics::pvData::shared_vector<int32>::reference wr = writable[0];
|
||||
epics::pvData::shared_vector<int32>::const_reference ror = writable[0];
|
||||
|
||||
testOk1(wr==ror);
|
||||
|
||||
int *compare = writable.data();
|
||||
int32 *compare = writable.data();
|
||||
|
||||
testOk1(writable.unique());
|
||||
|
||||
// can re-target container, but data is R/O
|
||||
epics::pvData::shared_vector<const int> rodata(freeze(writable));
|
||||
epics::pvData::shared_vector<const int32> rodata(freeze(writable));
|
||||
|
||||
epics::pvData::shared_vector<const int>::reference wcr = rodata[0];
|
||||
epics::pvData::shared_vector<const int>::const_reference rocr = rodata[0];
|
||||
epics::pvData::shared_vector<const int32>::reference wcr = rodata[0];
|
||||
epics::pvData::shared_vector<const int32>::const_reference rocr = rodata[0];
|
||||
|
||||
testOk1(wcr==rocr);
|
||||
|
||||
@@ -227,7 +228,7 @@ static void testConst()
|
||||
|
||||
testOk1(rodata.data()==compare);
|
||||
|
||||
epics::pvData::shared_vector<const int> rodata2(rodata);
|
||||
epics::pvData::shared_vector<const int32> rodata2(rodata);
|
||||
|
||||
testOk1(rodata.data()==rodata2.data());
|
||||
|
||||
@@ -240,9 +241,9 @@ static void testSlice()
|
||||
{
|
||||
testDiag("Test vector slicing");
|
||||
|
||||
epics::pvData::shared_vector<int> original(10, 100);
|
||||
epics::pvData::shared_vector<int32> original(10, 100);
|
||||
|
||||
epics::pvData::shared_vector<int> half1(original), half2(original), half2a(original);
|
||||
epics::pvData::shared_vector<int32> half1(original), half2(original), half2a(original);
|
||||
|
||||
half1.slice(0, 5);
|
||||
half2.slice(5, 5);
|
||||
@@ -290,9 +291,9 @@ static void testCapacity()
|
||||
{
|
||||
testDiag("Test vector capacity");
|
||||
|
||||
epics::pvData::shared_vector<int> vect(10, 100);
|
||||
epics::pvData::shared_vector<int32> vect(10, 100);
|
||||
|
||||
int *peek = vect.dataPtr().get();
|
||||
int32 *peek = vect.dataPtr().get();
|
||||
|
||||
vect.slice(0, 5);
|
||||
|
||||
@@ -330,7 +331,7 @@ static void testCapacity()
|
||||
|
||||
static void testPush()
|
||||
{
|
||||
epics::pvData::shared_vector<int> vect;
|
||||
epics::pvData::shared_vector<int32> vect;
|
||||
|
||||
testDiag("Test push_back optimizations");
|
||||
|
||||
@@ -355,9 +356,9 @@ static void testPush()
|
||||
|
||||
static void testVoid()
|
||||
{
|
||||
testDiag("Test vecter cast to/from void");
|
||||
testDiag("Test vector cast to/from void");
|
||||
|
||||
epics::pvData::shared_vector<int> typed(4);
|
||||
epics::pvData::shared_vector<int32> typed(4);
|
||||
|
||||
epics::pvData::shared_vector<void> untyped2(epics::pvData::static_shared_vector_cast<void>(typed));
|
||||
|
||||
@@ -366,7 +367,7 @@ static void testVoid()
|
||||
|
||||
untyped2.slice(sizeof(int), 2*sizeof(int));
|
||||
|
||||
typed = epics::pvData::static_shared_vector_cast<int>(untyped2);
|
||||
typed = epics::pvData::static_shared_vector_cast<int32>(untyped2);
|
||||
|
||||
testOk1(typed.dataOffset()==1);
|
||||
testOk1(typed.size()==2);
|
||||
@@ -406,7 +407,7 @@ static void testVectorConvert()
|
||||
{
|
||||
testDiag("Test shared_vector_convert");
|
||||
|
||||
epics::pvData::shared_vector<int> ints(6, 42), moreints;
|
||||
epics::pvData::shared_vector<int32> ints(6, 42), moreints;
|
||||
epics::pvData::shared_vector<float> floats;
|
||||
epics::pvData::shared_vector<string> strings;
|
||||
epics::pvData::shared_vector<void> voids;
|
||||
@@ -414,7 +415,7 @@ static void testVectorConvert()
|
||||
testOk1(ints.unique());
|
||||
|
||||
// no-op convert. Just returns another reference
|
||||
moreints = epics::pvData::shared_vector_convert<int>(ints);
|
||||
moreints = epics::pvData::shared_vector_convert<int32>(ints);
|
||||
|
||||
testOk1(!ints.unique());
|
||||
moreints.clear();
|
||||
@@ -432,11 +433,12 @@ static void testVectorConvert()
|
||||
voids = epics::pvData::shared_vector_convert<void>(ints);
|
||||
|
||||
testOk1(!ints.unique());
|
||||
testOk1(voids.size()==ints.size()*sizeof(int));
|
||||
testOk1(voids.size()==ints.size()*sizeof(int32));
|
||||
|
||||
// convert from void uses shared_vector<void>::original_type()
|
||||
// to find that the actual type is 'int'.
|
||||
// to find that the actual type is 'int32'.
|
||||
// returns a new vector
|
||||
testOk1(voids.original_type()==epics::pvData::pvInt);
|
||||
strings = epics::pvData::shared_vector_convert<string>(voids);
|
||||
|
||||
voids.clear();
|
||||
@@ -450,11 +452,11 @@ static void testWeak()
|
||||
{
|
||||
testDiag("Test weak_ptr counting");
|
||||
|
||||
epics::pvData::shared_vector<int> data(6);
|
||||
epics::pvData::shared_vector<int32> data(6);
|
||||
|
||||
testOk1(data.unique());
|
||||
|
||||
std::tr1::shared_ptr<int> pdata(data.dataPtr());
|
||||
std::tr1::shared_ptr<int32> pdata(data.dataPtr());
|
||||
|
||||
testOk1(!data.unique());
|
||||
|
||||
@@ -462,7 +464,7 @@ static void testWeak()
|
||||
|
||||
testOk1(data.unique());
|
||||
|
||||
std::tr1::weak_ptr<int> wdata(data.dataPtr());
|
||||
std::tr1::weak_ptr<int32> wdata(data.dataPtr());
|
||||
|
||||
testOk1(data.unique()); // True, but I wish it wasn't!!!
|
||||
|
||||
@@ -475,10 +477,10 @@ static void testICE()
|
||||
{
|
||||
testDiag("Test freeze and thaw");
|
||||
|
||||
epics::pvData::shared_vector<int> A(6, 42), C;
|
||||
epics::pvData::shared_vector<const int> B, D;
|
||||
epics::pvData::shared_vector<int32> A(6, 42), C;
|
||||
epics::pvData::shared_vector<const int32> B, D;
|
||||
|
||||
int *check = A.data();
|
||||
int32 *check = A.data();
|
||||
|
||||
// check freeze w/ unique reference
|
||||
|
||||
@@ -495,8 +497,8 @@ static void testICE()
|
||||
|
||||
D = B; // create second const reference
|
||||
|
||||
// clears D, but reference to B refrence
|
||||
// to B remains, so a copy is made
|
||||
// clears D, but reference to B
|
||||
// remains, so a copy is made
|
||||
C = epics::pvData::thaw(D);
|
||||
|
||||
testOk1(B.unique());
|
||||
@@ -537,11 +539,11 @@ static void testICE()
|
||||
|
||||
MAIN(testSharedVector)
|
||||
{
|
||||
testPlan(162);
|
||||
testPlan(163);
|
||||
testDiag("Tests for shared_vector");
|
||||
|
||||
testDiag("sizeof(shared_vector<int>)=%lu",
|
||||
(unsigned long)sizeof(epics::pvData::shared_vector<int>));
|
||||
testDiag("sizeof(shared_vector<int32>)=%lu",
|
||||
(unsigned long)sizeof(epics::pvData::shared_vector<int32>));
|
||||
|
||||
testEmpty();
|
||||
testInternalAlloc();
|
||||
|
||||
@@ -28,14 +28,14 @@ using namespace epics::pvData;
|
||||
|
||||
static bool debug = false;
|
||||
|
||||
void testTimeStamp()
|
||||
void testTimeStampInternal()
|
||||
{
|
||||
testOk1(nanoSecPerSec==1000000000);
|
||||
TimeStamp current;
|
||||
current.getCurrent();
|
||||
printf("current %lli %i milliSec %lli\n",
|
||||
(long long)current.getSecondsPastEpoch(),
|
||||
current.getNanoseconds(),
|
||||
(int)current.getNanoseconds(),
|
||||
(long long)current.getMilliseconds());
|
||||
time_t tt;
|
||||
current.toTime_t(tt);
|
||||
@@ -45,13 +45,13 @@ void testTimeStamp()
|
||||
"%4.4d.%2.2d.%2.2d %2.2d:%2.2d:%2.2d %d isDst %s\n",
|
||||
ctm.tm_year+1900,ctm.tm_mon + 1,ctm.tm_mday,
|
||||
ctm.tm_hour,ctm.tm_min,ctm.tm_sec,
|
||||
current.getNanoseconds(),
|
||||
(int)current.getNanoseconds(),
|
||||
(ctm.tm_isdst==0) ? "false" : "true");
|
||||
tt = time(&tt);
|
||||
current.fromTime_t(tt);
|
||||
printf("fromTime_t\ncurrent %lli %i milliSec %lli\n",
|
||||
(long long)current.getSecondsPastEpoch(),
|
||||
current.getNanoseconds(),
|
||||
(int)current.getNanoseconds(),
|
||||
(long long)current.getMilliseconds());
|
||||
current.toTime_t(tt);
|
||||
memcpy(&ctm,localtime(&tt),sizeof(struct tm));
|
||||
@@ -59,7 +59,7 @@ void testTimeStamp()
|
||||
"%4.4d.%2.2d.%2.2d %2.2d:%2.2d:%2.2d %d isDst %s\n",
|
||||
ctm.tm_year+1900,ctm.tm_mon + 1,ctm.tm_mday,
|
||||
ctm.tm_hour,ctm.tm_min,ctm.tm_sec,
|
||||
current.getNanoseconds(),
|
||||
(int)current.getNanoseconds(),
|
||||
(ctm.tm_isdst==0) ? "false" : "true");
|
||||
TimeStamp right;
|
||||
TimeStamp left;
|
||||
@@ -131,6 +131,6 @@ MAIN(testTimeStamp)
|
||||
{
|
||||
testPlan(37);
|
||||
testDiag("Tests timeStamp");
|
||||
testTimeStamp();
|
||||
testTimeStampInternal();
|
||||
return testDone();
|
||||
}
|
||||
|
||||
@@ -37,11 +37,11 @@ namespace {
|
||||
};
|
||||
template<>
|
||||
struct testequal<double> {
|
||||
static bool op(double A, double B) {return fabs(A-B)<1e-300; }
|
||||
static bool op(double A, double B) {return fabs(A-B)<1e-15; }
|
||||
};
|
||||
template<>
|
||||
struct testequal<float> {
|
||||
static bool op(float A, float B) {return fabs(A-B)<1e-30; }
|
||||
static bool op(float A, float B) {return fabs(A-B)<1e-7; }
|
||||
};
|
||||
|
||||
template<typename TO, typename FROM>
|
||||
@@ -117,7 +117,7 @@ namespace {
|
||||
|
||||
MAIN(testTypeCast)
|
||||
{
|
||||
testPlan(122);
|
||||
testPlan(123);
|
||||
|
||||
try {
|
||||
|
||||
@@ -387,7 +387,8 @@ try {
|
||||
FAIL(int8_t, string, "1000");
|
||||
FAIL(int8_t, string, "-1000");
|
||||
|
||||
FAIL(double, string, "1e+10000000");
|
||||
FAIL(double, string, "1e+1000");
|
||||
FAIL(double, string, "-1e+1000");
|
||||
|
||||
FAIL(epics::pvData::boolean, string, "hello");
|
||||
FAIL(epics::pvData::boolean, string, "1");
|
||||
|
||||
@@ -1,16 +1,8 @@
|
||||
TOP=../..
|
||||
# This is a Makefile fragment, see ../Makefile
|
||||
|
||||
include $(TOP)/configure/CONFIG
|
||||
SRC_DIRS += $(PVDATA_TEST)/property
|
||||
|
||||
TESTPROD_HOST += testProperty
|
||||
testProperty_SRCS += testProperty.cpp
|
||||
testHarness_SRCS += testProperty.cpp
|
||||
TESTS += testProperty
|
||||
|
||||
testProperty_LIBS += pvData Com
|
||||
|
||||
TESTSCRIPTS_HOST += $(TESTS:%=%.t)
|
||||
|
||||
include $(TOP)/configure/RULES
|
||||
#----------------------------------------
|
||||
# ADD RULES AFTER THIS LINE
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user