100 Commits
4.0.0 ... 5.0.0

Author SHA1 Message Date
Dave Hickin
d3853bd4e9 Ignore target-specific RELEASE and CONFIG_SITE in git
Tell gir to ignore configuration files such as RELEASE.win32-x86.Common
or CONFIG_SITE.linux-x86_64.Common.
2015-09-02 16:36:26 +01:00
Dave Hickin
7253bac48a Updated copyright notice and license
Updated copyright notice using the one in normativeTypesCPP. Added
Diamond and BNL. Added legal discalimers for Diamond and BNL to license.
Added dates to copyright notice. "All rights reserved" added to
copyright.
2015-09-02 14:04:29 +01:00
dhickin
973fbeeba5 Merge pull request #8 from dhickin/move_getSubFieldT_def_from_class_body
Move getSubFieldT definitions out of class body
2015-09-01 17:03:14 +01:00
dhickin
f22cefba97 Merge pull request #11 from anjohnson/fix-mac-build
Fix build problem on Mac
2015-09-01 17:00:58 +01:00
Ralph Lange
a5abc37b17 Add QtCreator pattern to .gitignore 2015-08-18 16:11:33 +02:00
Ralph Lange
b95fa7be56 jenkins: remove hgweb job; split doc and build jobs; update EPICS Base version 2015-08-18 16:11:05 +02:00
Andrew Johnson
f6cf87a52d Fix build problem on Mac
../../testApp/pv/testPVData.cpp:549:14: error: use of overloaded operator '!='
      is ambiguous (with operand types 'PVIntPtr' (aka 'shared_ptr<PVInt>') and
      'long')
    testOk1(a!=NULL);
            ~^ ~~~~
2015-08-12 15:06:46 -05:00
dhickin
51f36b2281 Merge pull request #10 from dhickin/remove_deprecated_getDerivedTypeField
Remove deprecated PVStructure::get*Field Functions
2015-07-29 12:29:08 +01:00
Dave Hickin
ddebd494c6 Remove deprecated PVStructure::get*Field Functions
Remove the deprecated functions such as getIntField in PVStructure,
whose usage has been replaced by that of the template getSubField
function and which are now no longer called anywhere.
2015-07-28 17:45:26 +01:00
dhickin
d0a8d2b1cd Merge pull request #9 from dhickin/replace_calls_getScalarArrayField
Replace calls of deprecated PVStructure::getScalarArrayField
2015-07-28 17:07:50 +01:00
Dave Hickin
1731a0daf6 USAGE_DEPRECATED macro used for getScalarArrayField 2015-07-24 16:56:49 +01:00
Dave Hickin
3487b3ee9e Remove unused argument in testPVScalarArray 2015-07-24 11:22:50 +01:00
Dave Hickin
5834efb709 Remove calls of deprecated getScalarArrayField 2015-07-24 11:21:58 +01:00
Dave Hickin
52bc6d060d Move getSubFieldT definitions out of class body
Move definitions of 2 getSubFieldT overloads:
shared_ptr<PVT> PVStructure::getSubFieldT(const char *name) const
shared_ptr<PVT> PVStructure::getSubFieldT(size_t fieldOffset) const
out of class body so not implicitly inlined.
2015-07-15 11:34:44 +01:00
dhickin
35ca5f3aed Merge pull request #7 from dhickin/getSubFieldT
GetSubFieldT
2015-07-14 16:19:38 +01:00
Dave Hickin
ac2b6ea8db Make getSubFieldT return shared pointer
Signed-off-by: Dave Hickin <david.hickin@diamond.ac.uk>
2015-07-13 12:48:05 +01:00
Dave Hickin
9827caa3e3 Make overloads of getSubField and getSubFieldT match
For each getSubField overload a throwing getSubFieldT has been added and
vice versa. These have been documented in doxygen and in the module
documentation.

Signed-off-by: Dave Hickin <david.hickin@diamond.ac.uk>
2015-07-13 12:41:47 +01:00
Dave Hickin
ebe2d6196c Rename getAs getSubFieldT
Signed-off-by: Dave Hickin <david.hickin@diamond.ac.uk>
2015-07-13 12:34:15 +01:00
Dave Hickin
e4689dd3f8 Added unit tests for functions for getting subfields
Signed-off-by: Dave Hickin <david.hickin@diamond.ac.uk>
2015-07-13 12:07:54 +01:00
Dave Hickin
1dba611b8e Improve exception messages when getting PVStructure subfield
Signed-off-by: Dave Hickin <david.hickin@diamond.ac.uk>
2015-07-13 11:47:21 +01:00
Dave Hickin
97cbea6f4d Implement getSubField functions without using exceptions
Implementation of getSubField (and getScalarArrayField) introduced in
the getAs pull request throws an exception then catches it to return a
null pointer. Implement without throwing.

Signed-off-by: Dave Hickin <david.hickin@diamond.ac.uk>
2015-07-13 02:16:08 +01:00
Dave Hickin
d9963b0631 Add test for getAs when mid-field not structure
Signed-off-by: Dave Hickin <david.hickin@diamond.ac.uk>
2015-07-09 13:22:42 +01:00
Dave Hickin
8418303ce2 Fix bug in new PVStructure::getAs function
Fix seg fault when getAs is called with a string of the form x.y (or
x_1. ... x_n.y) where x or (x1. ... .x_i) is not a structure field.

Signed-off-by: Dave Hickin <david.hickin@diamond.ac.uk>
2015-07-09 13:21:45 +01:00
Dave Hickin
40952df965 Corrected spelling in test and exception messages
Signed-off-by: Dave Hickin <david.hickin@diamond.ac.uk>
2015-07-08 18:19:53 +01:00
Dave Hickin
4f2c51c480 Correct spelling and typos in doxygen and comments
Signed-off-by: Dave Hickin <david.hickin@diamond.ac.uk>
2015-07-08 18:18:37 +01:00
Marty Kraimer
fd31a0d6b0 Merge pull request #6 from mdavidsaver/dropprinter
remove unused PrinterPlain
2015-06-27 07:00:15 -04:00
Michael Davidsaver
9ad725a272 remove unused PrinterPlain 2015-06-25 16:51:04 -04:00
Marty Kraimer
2b6172ba63 Merge pull request #5 from mrkraimer/master
document new PVStructure::getAs method
2015-06-23 10:12:10 -04:00
Marty Kraimer
c521f9299d document new PVStructure::getAs method 2015-06-23 08:24:54 -04:00
Marty Kraimer
1e646f8df1 Merge pull request #4 from mdavidsaver/getasfield
Add PVStructure::getAs<>()
2015-06-23 07:24:30 -04:00
Marty Kraimer
b5a436c1b7 Merge pull request #3 from mdavidsaver/getdeprecate
Deprecated PVStructure::get*Field methods trigger a warning
2015-06-23 07:17:38 -04:00
Michael Davidsaver
4f25c7a3ea remove findSubField 2015-06-22 18:14:23 -04:00
Michael Davidsaver
eadb8ff65b add PVStructure::getAs<>() for field access w/o NULL 2015-06-22 18:14:23 -04:00
Michael Davidsaver
6a80e941a0 replace use of depercated methods 2015-06-22 14:36:27 -04:00
Michael Davidsaver
7fc9b42b3a PVStructure: compiler warning when deprecated methods are used 2015-06-22 14:27:44 -04:00
Dave Hickin
0d857999bf Make default type ID strings const.
Signed-off-by: Dave Hickin <david.hickin@diamond.ac.uk>
2015-06-17 14:51:07 +01:00
Marty Kraimer
8ba71b048e Merge pull request #1 from mdavidsaver/errmsg
Friendlier exception messages w/ stack trace during Field creation
2015-06-15 06:41:34 -04:00
Michael Davidsaver
e07f6c1703 Friendlier exception messages w/ stack trace during Field creation 2015-06-12 13:54:03 -04:00
Marty Kraimer
e4f38121d2 remove qtcreator file 2015-06-10 10:31:08 -04:00
Marty Kraimer
255ee3f151 clean up conversion from hg to got; remove qtcreator files 2015-06-09 08:43:41 -04:00
dhickin
e72dbaabe1 Add some doxygen 2015-06-08 10:06:06 +01:00
dhickin
b39662450f Fix for windows static build static initialisation errors. 2015-06-08 04:58:04 +01:00
dhickin
98da0c0bec Add template getField member functions which return specific field types to Structure and Union. 2015-03-30 09:05:59 +01:00
dhickin
45dde325fd Change the printing of structure array and union array fields of structure introspection objects. Removes superfluous information and brings it in line with pvData meta language. 2015-03-20 17:23:32 +00:00
dhickin
2967a8f798 Declare the one argument constructors of PVField and its derived classes explicit. 2015-03-06 21:05:50 +00:00
Matej Sekoranja
d4bdc73948 documentation/RELEASE_NOTES.md updated 2015-02-18 14:26:19 +01:00
Matej Sekoranja
37c2f6bb17 merge 2015-02-18 10:11:15 +01:00
Matej Sekoranja
a8e4d749e3 flow: Merged <feature> 'copy_refactoring' to <develop> ('default'). 2015-02-18 10:02:17 +01:00
Matej Sekoranja
3df16ee449 flow: Closed <feature> 'copy_refactoring'. 2015-02-18 10:02:17 +01:00
Matej Sekoranja
332c2f959b added copy() method back to convert, since it is usually used by external modules; marked as DEPRECATED 2015-02-17 22:36:28 +01:00
Matej Sekoranja
a1b89c9a3b PVScalar::copy made public; copy tests 2015-02-17 21:54:35 +01:00
Matej Sekoranja
d6921fdac0 removal of some methods from convert 2015-02-17 20:22:37 +01:00
Matej Sekoranja
4cb3c22221 update code to the new method, removed copy from convert 2015-02-17 18:56:56 +01:00
Matej Sekoranja
cc1536b6e1 moved operators to pvData/pvIntrospect, added copy/copyUnchecked methods 2015-02-17 13:59:15 +01:00
Matej Sekoranja
92a178cbf9 flow: Created branch 'feature/copy_refactoring'. 2015-02-17 09:36:44 +01:00
dhickin
fbebce0a49 Make sure postPut is called precisely once and after put in Convert::copyUnion. 2015-02-11 22:17:45 +00:00
Matej Sekoranja
b13bb9819a updated testPlan(0) to actual value 2015-02-11 20:56:38 +01:00
Matej Sekoranja
bb505b8ed9 win32: new operators were missing exports 2015-02-11 15:41:12 +01:00
dhickin
cf030bc711 Call postPut() in Convert::copyUnion(). 2015-02-11 14:04:15 +00:00
Marty Kraimer
6cb95c5cfc fixed possible SEGFAULT in ceateRequest; new stream operator for Field and PVField 2015-02-11 07:26:04 -05:00
Matej Sekoranja
a277a4fdd5 copy schematic 2015-02-11 11:30:39 +01:00
Matej Sekoranja
388799d39d monitors: minor monitor API doc update 2015-02-01 00:46:55 +01:00
Matej Sekoranja
4acf7edf95 non-copy (by reference) retrival of getFields()/getPVFields()/getFieldNames() 2015-01-30 11:35:43 +01:00
Matej Sekoranja
e39346d51e missing swap templates for unsigned types 2015-01-21 20:19:23 +01:00
Ralph Lange
5ae6de4f1d jenkins: fix cloudbees script (commands must return 0) 2014-12-19 14:01:13 +01:00
Ralph Lange
e0f1427af7 jenkins: create and update documentation in only one build configuration 2014-12-19 13:18:52 +01:00
Ralph Lange
69297bdb58 jenkins: make EPICS base a parameter in jenkins job 2014-12-12 09:49:01 +01:00
Marty Kraimer
0fa2f2c2ff merge branch release/4.0 2014-12-11 14:11:54 -05:00
Marty Kraimer
9efce46fff work on doxygen 2014-12-11 09:47:20 -05:00
dhickin
c356ecb402 make local RELEASE.local files take precedence over those in TOP/.. 2014-12-09 13:45:56 +00:00
dhickin
4c6887e7ec Added tag 4.0.3 for changeset 8543734dbf6e 2014-12-05 11:30:03 +00:00
Marty Kraimer
6d338cab15 merge branch release/4.0 2014-12-04 08:30:26 -05:00
dhickin
354fdd412f make "local" *.local files take precedence over those in TOP/.. 2014-12-03 16:55:27 +00:00
dhickin
f3f6141e6a include CONFIG_SITE.local instead of CONFIG.local at top-level. 2014-12-03 16:10:25 +00:00
Matej Sekoranja
f2b43b704c rtems compilation warnings (int32 != int) 2014-11-26 14:12:09 +01:00
Matej Sekoranja
de1478d7ba Event test added 2014-11-25 10:43:07 +01:00
Marty Kraimer
b9592eeb8c Added tag 4.0.2 for changeset af82285f71aa 2014-11-24 06:55:18 -05:00
Marty Kraimer
6a62f9c082 catch std::exception and return NULL PVStructurePtr 2014-11-24 06:54:28 -05:00
Matej Sekoranja
2e4a8b2e23 Structure/Union: bound check access for getFieldName(int)/getField(int) 2014-11-13 18:32:50 +01:00
Marty Kraimer
c5112ffa11 Added tag 4.0.1 for changeset b0d39d12d743 2014-11-11 07:05:19 -05:00
Matej Sekoranja
7b9fda4e81 merge 2014-11-10 21:33:47 +01:00
Matej Sekoranja
278e531806 PVUnion copy allways shallow 2014-11-10 21:30:48 +01:00
Marty Kraimer
047de40642 change date, this version, and previous version 2014-11-10 09:06:35 -05:00
Matej Sekoranja
4e671a1c21 win32 indent problem: local static DLL saga 2014-11-06 22:18:58 +01:00
Matej Sekoranja
f36c8ce280 testByteOrder: use MAIN instead of main 2014-11-06 14:28:49 +01:00
Matej Sekoranja
e77f2c91d7 fixed undeterministic serialization test on clang 2014-11-06 13:03:59 +01:00
Matej Sekoranja
82b0d5ce5f merge 2014-11-06 12:50:04 +01:00
Matej Sekoranja
6117035863 null element handling for structure/union array 2014-11-06 12:48:57 +01:00
Matej Sekoranja
c86e31ad99 vxWorks: type cast fixes 2014-11-06 12:38:01 +01:00
Matej Sekoranja
f506fe1c0e int/int32 compilation fix; now all test spass on RTEMS-i386 2014-11-05 14:05:28 +01:00
Matej Sekoranja
554dc06eda ScalarTypeID mapping fixed in case 'int' == 'long', e.g. RTEMS-i386 2014-11-05 13:52:10 +01:00
Matej Sekoranja
80e1dfd142 removed forces NE2K card or non i386 builds 2014-11-03 13:51:21 +01:00
Matej Sekoranja
6db5cf60dc removing file should not have been commited 2014-11-03 12:41:09 +01:00
Matej Sekoranja
63d181a0ac RTEMS QEMU tests 2014-11-03 12:37:12 +01:00
Matej Sekoranja
73c4896cce tests: VxWorks tests are now ready to be run 2014-10-31 17:49:10 -04:00
Matej Sekoranja
5b1b5ab904 tests: refactored test building so that one test object can be created for VxWorks and RTEMS 2014-10-31 18:29:55 +01:00
Matej Sekoranja
80a537bc4c vxWork tests for all subtests; still need to combine them all to one 2014-10-31 07:57:20 -04:00
Matej Sekoranja
2a8a1d3736 tests: PROD_HOST to TESTPROD_HOST; VxWorks tests for testApp/pv PASSES 2014-10-31 06:42:52 -04:00
Matej Sekoranja
61fbfa0684 Added tag 4.0.0 for changeset f9f187685032 2014-10-29 12:59:39 +01:00
Matej Sekoranja
f06a6bfe7b merge to default branch 2014-10-28 19:37:34 +01:00
117 changed files with 16216 additions and 3164 deletions

15
.gitignore vendored Normal file
View 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-*

View File

@@ -1,8 +0,0 @@
[branchname]
master = master
develop = default
feature = feature/
release = release/
hotfix = hotfix/
support = support/

View File

@@ -1,12 +0,0 @@
QtC-
bin/
lib/
doc/
include/
db/
dbd/
documentation/html
documentation/*.tag
envPaths
configure/.*\.local
/O\..*

16
.hgtags
View File

@@ -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

View File

@@ -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.

2343
Doxyfile

File diff suppressed because it is too large Load Diff

42
LICENSE
View File

@@ -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.
________________________________________________________________________

View File

@@ -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

View File

@@ -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

View File

@@ -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&amp; from)
</code></pre>
<p>Methods</p>
<pre><code>PVField::copyUnchecked(const PVField&amp; 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 &lt;&lt; *struct &lt;&lt; endl;
} else {
cout &lt;&lt; "nullptr\n"
}
if(pv) {
cout &lt;&lt; *.struct &lt;&lt; endl;
} else {
cout &lt;&lt; "nullptr\n"
}
}
</code></pre>
<p>Now it can be done as follows:</p>
<pre><code> void print(StructureConstPtr struct, PVStructurePtr pv)
{
cout &lt;&lt; struct &lt;&lt; endl;
cout &lt;&lt; pv &lt;&lt; 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>

View File

@@ -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:

View File

@@ -1,11 +1,6 @@
TODO
===========
printer
------------
pv/printer.h is not used.
doxygen
-------

View File

@@ -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&lt;typename PVT&gt;
std::tr1::shared_ptr&lt;PVT&gt; getSubField(std::size_t fieldOffset) const
PVFieldPtr getSubFieldT(std::string const &amp;fieldName) const;
template&lt;typename PVT&gt;
std::tr1::shared_ptr&lt;PVT&gt; getSubFieldT(std::string const &amp;fieldName) const
PVFieldPtr getSubFieldT(std::size_t fieldOffset) const;
template&lt;typename PVT&gt;
std::tr1::shared_ptr&lt;PVT&gt; 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 &amp;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 &amp;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>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -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
View 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

View File

@@ -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

View File

@@ -1 +0,0 @@
// ADD PREDEFINED MACROS HERE!

View File

@@ -1 +0,0 @@
[General]

View File

@@ -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

View File

@@ -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

View File

@@ -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()

View File

@@ -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:

View File

@@ -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);
}
}
}

View File

@@ -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(

View File

@@ -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;

View File

@@ -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;

View File

@@ -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";
}
}

View File

@@ -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";
}
}

View File

@@ -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");
}
}
}
}}

View File

@@ -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);
}
}
}
}}

View File

@@ -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());
}
}}

View File

@@ -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();
}
}
}}

View File

@@ -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());
}
}}

View File

@@ -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)

View File

@@ -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;
}

View File

@@ -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*)&marker;
/* 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;
}
}}

View File

@@ -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

View File

@@ -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);

View File

@@ -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++)

View File

@@ -18,7 +18,8 @@ namespace epics { namespace pvData {
/**
* Instance declaring destroy method.
* @brief Instance declaring destroy method.
*
* @author mse
*/
class epicsShareClass Destroyable {

View File

@@ -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:

View File

@@ -38,8 +38,7 @@ Event::~Event() {
Event::Event(bool full)
: id(epicsEventCreate(full?epicsEventFull : epicsEventEmpty)),
alreadyOn("already on list")
: id(epicsEventCreate(full?epicsEventFull : epicsEventEmpty))
{
}

View File

@@ -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;
};
}}

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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 */

View File

@@ -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
}
}}}

View File

@@ -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;

View File

@@ -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;
};

View File

@@ -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.
* &param bitSet The bitSet to serialize.
*/
virtual void serialize(ByteBuffer *buffer,
SerializableControl *flusher,BitSet *bitSet) const = 0;
/**
* Deserialize buffer.
* @param buffer serialization buffer.
* @param flusher deserialization control.
* &param bitSet The bitSet to deserialize.
*/
virtual void deserialize(ByteBuffer *buffer,
DeserializableControl *flusher,BitSet *bitSet) = 0;
};
/**
* @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.
* &param offset offset in elements.
* @param count number of elements
*/
virtual void serialize(
ByteBuffer *buffer,
SerializableControl *flusher,
std::size_t offset,
std::size_t count) const = 0;
};
}}

View File

@@ -7,7 +7,7 @@
* serializeHelper.cpp
*
* Created on: Oct 22, 2010
* Author: Miha vitorovic
* Author: Miha Vitorovic
*/
#include <algorithm>

View File

@@ -23,6 +23,10 @@
namespace epics {
namespace pvData {
/**
* @brief Serialization helper.
*
*/
class epicsShareClass SerializeHelper : public NoDefaultMethods {
public:

View File

@@ -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.

View File

@@ -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 {

View File

@@ -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();

View File

@@ -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;

View File

@@ -14,9 +14,9 @@
#include <stdexcept>
#include <string>
#include <iostream>
#define epicsExportSharedSymbols
#include <pv/convert.h>
#include <pv/timer.h>
using std::string;

View File

@@ -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:

View File

@@ -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

View File

@@ -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
*/

View File

@@ -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
*/

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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();

View File

@@ -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;

View File

@@ -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();

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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];
}

View File

@@ -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;

View File

@@ -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

View File

@@ -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;

View File

@@ -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;

View File

@@ -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(); }

View File

@@ -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

View File

@@ -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>
*
*/

View File

@@ -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 */

View File

@@ -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.
*/
/**

View File

@@ -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.

View File

@@ -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.

View File

@@ -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);
};

View File

@@ -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

View File

@@ -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

View File

@@ -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();
}

View File

@@ -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()

View File

@@ -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

View File

@@ -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();
}

View File

@@ -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");

View 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();
}

View File

@@ -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");

View File

@@ -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();
}

View File

@@ -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();

View File

@@ -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();
}

View File

@@ -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");

View File

@@ -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