113 Commits
4.0.0 ... 5.0.2

Author SHA1 Message Date
Dave Hickin
7fc3f50ae9 Merge branch 'master' into release/5.0 2015-10-15 10:37:46 +01:00
Dave Hickin
05d41f81e4 Minor correction to README 2015-10-15 10:37:12 +01:00
Dave Hickin
d400e8eaf5 Merge branch 'master' into release/5.0 2015-10-15 09:39:53 +01:00
Dave Hickin
fdc289d888 Add new README
Replace out of date HTML README with a new markdown one
2015-10-15 09:16:20 +01:00
Dave Hickin
0a2243e033 Update TODO 2015-10-15 07:46:40 +01:00
Dave Hickin
9d877d764f Doxgen fixes and enhancements
Change &param to @param. Add missing parameter.
Add more doxygen comments in SerializeHelper.
2015-10-15 07:12:42 +01:00
Dave Hickin
f5df29cf34 Doxygen: remove @code when code block not wanted
@code produces a separate code block, rather than just displaying
contents as code.

Mostly replaced use with @c tag when block not wanted.
2015-10-15 06:50:26 +01:00
Dave Hickin
8008823ea5 Fix doxygen warnings 2015-10-14 23:01:28 +01:00
Dave Hickin
6515de4bc0 Add release notes for 5.0 2015-10-08 15:24:14 +01:00
Ralph Lange
8c5f535b79 jenkins: fix CloudBees doc job 2015-09-28 15:29:39 +02:00
Ralph Lange
de2fac122c jenkins: fix CloudBees doc job 2015-09-28 15:29:17 +02:00
Ralph Lange
7707da0b45 jenkins: adapt doc script to new CloudBees jenkins job 2015-09-14 16:48:33 +02:00
Ralph Lange
036186fc12 jenkins: adapt doc script to new CloudBees jenkins job 2015-09-14 16:48:15 +02:00
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
121 changed files with 16648 additions and 3487 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 @@
/**************************************************** This software is in part copyrighted by the various organizations and
Copyright (c) 2008 All rights reserved individuals listed below. Permission to use it is set out in the file
Copyright (c) 2008 Martin R. Kraimer LICENSE that accompanies the software.
Copyright (c) 2006 The University of Chicago, as Operator of Argonne
National Laboratory. 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, Deutsches Elektronen-Synchroton, Member of the Helmholtz Association,
(DESY), HAMBURG, GERMANY, (DESY), HAMBURG, GERMANY,
BERLINER SPEICHERRING GESELLSCHAFT FUER SYNCHROTRONSTRAHLUNG M.B.H. BERLINER SPEICHERRING GESELLSCHAFT FUER SYNCHROTRONSTRAHLUNG M.B.H.
(BESSY), BERLIN, GERMANY. (BESSY), BERLIN, GERMANY.
COSYLAB (Control System Laboratory) COSYLAB (Control System Laboratory), Ljubljana, Slovenia.
(Cosylab) 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 Copyright (c) 2006 The University of Chicago, as Operator of Argonne
National Laboratory. National Laboratory.
Copyright (c) 2006 Deutsches Elektronen-Synchrotron, Copyright (c) 2006 Deutsches Elektronen-Synchrotron,
Member of the Helmholtz Association, (DESY), HAMBURG, GERMANY. Member of the Helmholtz Association, (DESY), HAMBURG, GERMANY.
Copyright (c) 2007 Control System Laboratory, Copyright (c) 2007-2015 Control System Laboratory,
(COSYLAB) Ljubljana Slovenia (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 Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation 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" purpose, and non-infringement. This software is provided on an "as is"
basis, and DESY has no obligation to provide maintenance, support, basis, and DESY has no obligation to provide maintenance, support,
updates, enhancements, or modifications. 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

@@ -1,82 +0,0 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
<title>EPICS pvData C++</title>
</head>
<body>
<h1 style="text-align: center">EPICS pvData C++<br />
Overview<br />
2010.08.10</h1>
CONTENTS
<hr />
<h2 style="text-align: center">Introduction</h2>
<hr />
<p>This project has the begining of the C++ implementation of pvData. The
following is done:</p>
<dl>
<dt>introspection interfaces</dt>
<dd>The introspection interfaces for clients are described.</dd>
<dt>introspection implementation</dt>
<dd>The following have been implemented: Type, ScalarType, Field,
Scalar</dd>
<dt>test</dt>
<dd>A test of Scalar.</dd>
<dt>As mentioned below there are problems with the current
implementation.</dt>
</dl>
<hr />
<h2 style="text-align: center">Building</h2>
<hr />
<p>The project is structured as an epics base client application. Edit
configure/RELEASE so that it references your EPICS base and then just
type:</p>
<pre> make</pre>
<p>At the top. Then execute the test in the bin directory.</p>
<p>pvDataApp has the following sub directories:</p>
<dl>
<dt>pv</dt>
<dd>pvData.h has the interface descriptions for client code.</dd>
<dt>factory</dt>
<dd>FieldCreateFactory.cpp has the current implementation</dd>
<dt>test</dt>
<dd>Has a test for the current implementation.</dd>
</dl>
<hr />
<h2 style="text-align: center">Questions about Classes</h2>
<hr />
<p>The pure virtual classes defined in pvData.h now work. But there are still
some things that are not so nice. Amoung these are:</p>
<ul>
<li>In FieldCreateFactory.cpp look for "WHY DO I". It asks why the derived
class must also define methods defined in the base class. If it does not
then a compilation error occurs. WHY??? </li>
<li>The toString methods have an argument of "std::string &amp;buf" instead
of "std::string *". Does this seem correct?</li>
<li>Can arguments and return descriptions be defined better?</li>
<li>Is const present everywhere it should be? Remember that introspection
classes are immutable.</li>
<li>The code is NOT thread safe. When we decide for sure what thread/lock
support to choose I will fix this.</li>
</ul>
<p>HELP WILL BE GREATLY APPRECIATED. because I am still coming up to speed
with c++</p>
<hr />
<h2 style="text-align: center">Garbage Collection</h2>
<hr />
<p>Not yet implemented. Lets get class structure correct first.</p>
</body>
</html>

57
README.md Normal file
View File

@@ -0,0 +1,57 @@
pvaDataCPP
==========
pvDataCPP is a set of data types and utilities that form part of the EPICS V4 project.
Further Info
------------
Consult the documents in the documentation directory, in particular
* pvDataCPP.html
* RELEASE_NOTES.md
Also see the [EPICS Version 4 website](http://epics-pvdata.sourceforge.net)
Prerequisites
-------------
The pvDataCPP requires recent versions of the following software:
1. EPICS Base (v3.14.12.3 or later)
2. EPICS4 pvCommonCPP (4.1.0 or later)
(pvCommonCPP may not be needed depending on host/compiler.)
Building
--------
Building uses the make utility and the EPICS base build system.
The build system needs the location of the prerequisites, e.g. by placing the
lines of the form
PVCOMMON = /home/install/epicsV4/pvCommonCPP
EPICS_BASE = /home/install/epics/base
pointing to the locations in a file called RELEASE.local
in the configure directory or the parent directory of pvDataCPP.
With this in place, to build type make
make
To perform a clean build type
make clean uninstall
To run the unit tests type
make runtests
For more information on the EPICS build system consult the
[Application Development guide](http://www.aps.anl.gov/epics/base/R3-14/12-docs/AppDevGuide.pdf).

View File

@@ -20,8 +20,8 @@ CHECK_RELEASE = YES
# INSTALL_LOCATION here. # INSTALL_LOCATION here.
#INSTALL_LOCATION=</path/name/to/install/top> #INSTALL_LOCATION=</path/name/to/install/top>
-include $(TOP)/../CONFIG_SITE.local
-include $(TOP)/configure/CONFIG_SITE.local -include $(TOP)/configure/CONFIG_SITE.local
-include $(TOP)/../CONFIG.local
ifdef WITH_COVERAGE ifdef WITH_COVERAGE
USR_CPPFLAGS += --coverage USR_CPPFLAGS += --coverage

View File

@@ -21,5 +21,5 @@
# PVCOMMON = /home/install/epicsV4/pvCommonCPP # PVCOMMON = /home/install/epicsV4/pvCommonCPP
# EPICS_BASE = /home/install/epics/base # EPICS_BASE = /home/install/epics/base
-include $(TOP)/configure/RELEASE.local
-include $(TOP)/../RELEASE.local -include $(TOP)/../RELEASE.local
-include $(TOP)/configure/RELEASE.local

View File

@@ -1,5 +1,142 @@
<h1>Release 4.0 IN DEVELOPMENT</h1> <h1>Release 5.0</h1>
<p>The main changes since release 4.0 are:</p>
<ul>
<li>Deprecated getXXXField() methods have been removed from PVStructure</li>
<li>Convert copy methods and equals operators (re)moved</li>
<li>Convert::copyUnion now always copies between subfields.</li>
<li>New method getSubFieldT, like getSubField except it throws an exception</li>
<li>findSubField method removed from PVStructure</li>
<li>New stream operators for Field and PVField are provided</li>
<li>New template versions of Structure::getField</li>
<li>Fixes for static initialisation order issues</li>
<li>CreateRequest prevents a possible SEGFAULT</li>
</ul>
<h2>Deprecated getXXXField methods have been removed from PVStructure</h2>
<p>The following methods have been removed from PVStructure</p>
<ul>
<li>getBooleanField</li>
<li>getByteField, getShortField, getIntField, getLongField</li>
<li>getUByteField, getUShortField, getUIntField, getULongField</li>
<li>getStringField</li>
<li>getStructureField, getUnionField</li>
<li>getScalarArrayField, getStructureArrayField, getUnionArrayField</li>
</ul>
<p>Use template getSubField instead, e.g. use</p>
<pre><code>getSubField&lt; PVInt &gt;(fieldName)
</code></pre>
<p>in place of</p>
<pre><code>getIntField(fieldName)
</code></pre>
<h2>Convert copy methods and equals operators</h2>
<p>Convert copy methods where moved and replaced with methods
on PVField classes, i.e.</p>
<pre><code>PVField::copy(const PVField&amp; from)
</code></pre>
<p>Methods</p>
<pre><code>PVField::copyUnchecked(const PVField&amp; from)
</code></pre>
<p>were added to allow unchecked copies, to gain performance
where checked are not needed (anymore).</p>
<p>In addition:
- isCompatibleXXX methods were removed in favour of Field::operator==.
- equals methods were remove in favour of PVField::operator==.
- operator== methods where moved to pvIntrospect.h and pvData.h</p>
<h2>Convert::copyUnion</h2>
<p>Before this method, depending on types for to and from,
sometimes did a shallow copy, i.e. just made to shared_ptr for to
share the same data as from.
Now it always copies between the subfield of to and from.</p>
<h2>New method getSubFieldT, like getSubField except it throws an exception</h2>
<p>PVStructure has a new template member</p>
<pre><code>getSubFieldT(std::string const &amp;fieldName)
</code></pre>
<p>that is like <b>getSubField</b> except that it throws a runtime_error
instead of returning null.</p>
<h2>findSubField method removed from PVStructure</h2>
<p>This was mainly used in the implementation of getSubField. With a change to
the latter, findSubField was removed.</p>
<h2>New stream operators</h2>
<p>New steam operators are available for Field and PVField.
Before to print a Field (or any extension) or a PVField (or any extension)
it was necessary to have code like:</p>
<pre><code> void print(StructureConstPtr struc, PVStructurePtr pv)
{
if(struc) {
cout &lt;&lt; *struc &lt;&lt; endl;
} else {
cout &lt;&lt; "nullptr\n"
}
if(pv) {
cout &lt;&lt; *.struc &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 struc, PVStructurePtr pv)
{
cout &lt;&lt; struc &lt;&lt; endl;
cout &lt;&lt; pv &lt;&lt; endl;
}
</code></pre>
<h2>New template version of Structure::getField</h2>
<p>A new template getField method has been added to Structure</p>
<p>template<typename FT >
std::tr1::shared_ptr&lt; const FT > getField(std::string const &amp;fieldName) const </p>
<p>Can be used, for example, as follows:</p>
<pre><code>StructurePtr tsStruc = struc-&gt;getField&lt;Structure&gt;("timeStamp");
</code></pre>
<h2>Fixes for static initialisation order issues</h2>
<p>Certain static builds (in particular Windows builds) of applications using
pvData had issues due to PVStructure::DEFAULT_ID being used before being initialised. This has been fixed.</p>
<h2>CreateRequest change</h2>
<p>createRequest could cause a SEGFAULT if passed a bad argument.
This has been changed so the it returns a null pvStructure
and provides an error.</p>
<h1>Release 4.0</h1>
<p>The main changes since release 3.0.2 are:</p> <p>The main changes since release 3.0.2 are:</p>
<ul> <ul>
<li>array semantics now enforce Copy On Write.</li> <li>array semantics now enforce Copy On Write.</li>
<li>String no longer defined.</li> <li>String no longer defined.</li>
@@ -9,21 +146,31 @@
<li>copy is new.</li> <li>copy is new.</li>
<li>monitorPlugin is new.</li> <li>monitorPlugin is new.</li>
</ul> </ul>
<h2>New Semantics for Arrays</h2> <h2>New Semantics for Arrays</h2>
<p>PVScalarArray, PVStructureArray, and PVUnionArray all enforce COW (Copy On Write) Semantics. <p>PVScalarArray, PVStructureArray, and PVUnionArray all enforce COW (Copy On Write) Semantics.
In order to limit memory usage the storage for raw data is managed via a new shared_vector facility. In order to limit memory usage the storage for raw data is managed via a new shared<em>vector facility.
This allows multiple instances of array data to use the shared raw data. This allows multiple instances of array data to use the shared raw data.
COW is implemented via shared_vectors of const data, i. e. data that can not be modified.</p> COW is implemented via shared</em>vectors of const data, i. e. data that can not be modified.</p>
<h2>String no longer defined</h2> <h2>String no longer defined</h2>
<p>This is replaced by std::string.</p> <p>This is replaced by std::string.</p>
<h2>timeStamp and valueAlarm name changes</h2> <h2>timeStamp and valueAlarm name changes</h2>
<p>In timeStamp nanoSeconds is changed to nanoseconds.</p> <p>In timeStamp nanoSeconds is changed to nanoseconds.</p>
<p>In valueAlarm hystersis is changed to hysteresis</p>
<p>In valueAlarm hysteresis is changed to hysteresis</p>
<h2>toString replaced by stream I/O</h2> <h2>toString replaced by stream I/O</h2>
<p>pvData.h and pvIntrospect no longer defines toString <p>pvData.h and pvIntrospect no longer defines toString
Instead they have stream support. Instead they have stream support.
pvIntrospect uses method dump and pvData uses dumpValue. pvIntrospect uses method dump and pvData uses dumpValue.
For example:</p> For example:</p>
<pre><code> PVDoublePtr pvValue; <pre><code> PVDoublePtr pvValue;
String buffer; String buffer;
pvValue-&gt;toString(&amp;buffer); pvValue-&gt;toString(&amp;buffer);
@@ -32,27 +179,40 @@ For example:</p>
pvValue-&gt;getField()-&gt;toString(&amp;buffer); pvValue-&gt;getField()-&gt;toString(&amp;buffer);
cout &lt;&lt; buffer &lt;&lt; evdl; cout &lt;&lt; buffer &lt;&lt; evdl;
</code></pre> </code></pre>
<p>is replaced by</p> <p>is replaced by</p>
<pre><code> PVDoublePtr pvValue; <pre><code> PVDoublePtr pvValue;
cout &lt;&lt; *pvValue &lt;&lt; endl cout &lt;&lt; *pvValue &lt;&lt; endl
cout &lt;&lt; *pvValue-&gt;getField() &lt;&lt; endl; cout &lt;&lt; *pvValue-&gt;getField() &lt;&lt; endl;
</code></pre> </code></pre>
<h2>union is a new basic type.</h2> <h2>union is a new basic type.</h2>
<p>There are two new basic types: union_t and unionArray.</p> <p>There are two new basic types: union_t and unionArray.</p>
<p>A union is like a structure that has a single subfield. <p>A union is like a structure that has a single subfield.
There are two flavors:</p> There are two flavors:</p>
<ul> <ul>
<li><b>varient union</b> The field can have any type.</li> <li><b>variant union</b> The field can have any type.</li>
<li><b>union</b> The field can any of specified set of types.</li> <li><b>union</b> The field can any of specified set of types.</li>
</ul> </ul>
<p>The field type can be dynamically changed.</p> <p>The field type can be dynamically changed.</p>
<h2>copy</h2>
<h2>copy </h2>
<p>This consists of createRequest and pvCopy. <p>This consists of createRequest and pvCopy.
createRequest was moved from pvAccess to here. createRequest was moved from pvAccess to here.
pvCopy is moved from pvDatabaseCPP and now depends pvCopy is moved from pvDatabaseCPP and now depends
only on pvData, i. e. it no longer has any knowledge of PVRecord.</p> only on pvData, i.e. it no longer has any knowledge of PVRecord.</p>
<h2>monitorPlugin</h2> <h2>monitorPlugin</h2>
<p>This is for is for use by code that implements pvAccess monitors. <p>This is for is for use by code that implements pvAccess monitors.
This is prototype and is subject to debate.</p> This is prototype and is subject to debate.</p>
<h1>Release 3.0.2</h1> <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,147 @@
Release 4.0 IN DEVELOPMENT Release 5.0
===========
The main changes since release 4.0 are:
* Deprecated getXXXField() methods have been removed from PVStructure
* Convert copy methods and equals operators (re)moved
* Convert::copyUnion now always copies between subfields.
* New method getSubFieldT, like getSubField except it throws an exception
* findSubField method removed from PVStructure
* New stream operators for Field and PVField are provided
* New template versions of Structure::getField
* Fixes for static initialisation order issues
* CreateRequest prevents a possible SEGFAULT
Deprecated getXXXField methods have been removed from PVStructure
-------------------------------------------------------------------
The following methods have been removed from PVStructure
* getBooleanField
* getByteField, getShortField, getIntField, getLongField
* getUByteField, getUShortField, getUIntField, getULongField
* getStringField
* getStructureField, getUnionField
* getScalarArrayField, getStructureArrayField, getUnionArrayField
Use template getSubField instead, e.g. use
getSubField< PVInt >(fieldName)
in place of
getIntField(fieldName)
Convert copy methods and equals operators
-----------------------------------------
Convert copy methods where moved and replaced with methods
on PVField classes, i.e.
PVField::copy(const PVField& from)
Methods
PVField::copyUnchecked(const PVField& from)
were added to allow unchecked copies, to gain performance
where checked are not needed (anymore).
In addition:
- isCompatibleXXX methods were removed in favour of Field::operator==.
- equals methods were remove in favour of PVField::operator==.
- operator== methods where moved to pvIntrospect.h and pvData.h
Convert::copyUnion
-----------------
Before this method, depending on types for to and from,
sometimes did a shallow copy, i.e. just made to shared_ptr for to
share the same data as from.
Now it always copies between the subfield of to and from.
New method getSubFieldT, like getSubField except it throws an exception
--------------------
PVStructure has a new template member
getSubFieldT(std::string const &fieldName)
that is like <b>getSubField</b> except that it throws a runtime_error
instead of returning null.
findSubField method removed from PVStructure
--------------------------------------------
This was mainly used in the implementation of getSubField. With a change to
the latter, findSubField was removed.
New stream operators
--------------------
New steam operators are available for Field and PVField.
Before to print a Field (or any extension) or a PVField (or any extension)
it was necessary to have code like:
void print(StructureConstPtr struc, PVStructurePtr pv)
{
if(struc) {
cout << *struc << endl;
} else {
cout << "nullptr\n"
}
if(pv) {
cout << *.struc << endl;
} else {
cout << "nullptr\n"
}
}
Now it can be done as follows:
void print(StructureConstPtr struc, PVStructurePtr pv)
{
cout << struc << endl;
cout << pv << endl;
}
New template version of Structure::getField
--------------------------------------------
A new template getField method has been added to Structure
template<typename FT >
std::tr1::shared_ptr< const FT > getField(std::string const &fieldName) const
Can be used, for example, as follows:
StructurePtr tsStruc = struc->getField<Structure>("timeStamp");
Fixes for static initialisation order issues
--------------------------------------------
Certain static builds (in particular Windows builds) of applications using
pvData had issues due to PVStructure::DEFAULT_ID being used before being initialised. This has been fixed.
CreateRequest change
--------------------
createRequest could cause a SEGFAULT if passed a bad argument.
This has been changed so the it returns a null pvStructure
and provides an error.
Release 4.0
=========== ===========
The main changes since release 3.0.2 are: The main changes since release 3.0.2 are:
@@ -31,7 +174,7 @@ timeStamp and valueAlarm name changes
In timeStamp nanoSeconds is changed to nanoseconds. In timeStamp nanoSeconds is changed to nanoseconds.
In valueAlarm hystersis is changed to hysteresis In valueAlarm hysteresis is changed to hysteresis
toString replaced by stream I/O toString replaced by stream I/O
@@ -65,7 +208,7 @@ There are two new basic types: union_t and unionArray.
A union is like a structure that has a single subfield. A union is like a structure that has a single subfield.
There are two flavors: There are two flavors:
* <b>varient union</b> The field can have any type. * <b>variant union</b> The field can have any type.
* <b>union</b> The field can any of specified set of types. * <b>union</b> The field can any of specified set of types.
The field type can be dynamically changed. The field type can be dynamically changed.
@@ -76,7 +219,7 @@ copy
This consists of createRequest and pvCopy. This consists of createRequest and pvCopy.
createRequest was moved from pvAccess to here. createRequest was moved from pvAccess to here.
pvCopy is moved from pvDatabaseCPP and now depends pvCopy is moved from pvDatabaseCPP and now depends
only on pvData, i. e. it no longer has any knowledge of PVRecord. only on pvData, i.e. it no longer has any knowledge of PVRecord.
monitorPlugin monitorPlugin
------------- -------------

View File

@@ -1,17 +0,0 @@
<h1>TODO</h1>
<h2>printer</h2>
<p>pv/printer.h is not used.</p>
<h2>doxygen</h2>
<p>There is a lot of public code that does not have doxygen tags.</p>
<h2>postMonitor: PVUnion, PVUnionArray, and PVStructureArray</h2>
<p>PVUnion, PVUnionArray, and PVStructureArray all have elements
that are treated like a top level field.</p>
<p>Currently if a subField of any of these is changed postMonitor is not called for the field itself.</p>
<p>David asked if this could be changed so that it is called.
Marty thinks this may not be a good idea.</p>
<h2>valueAlarm</h2>
<p>normativeTypes.html describes valueAlarm only for a value field that has type
double.
The implementation also supports all the numeric scalar types.</p>
<h2>monitorPlugin</h2>
<p>A debate is on-going about what semantics should be.</p>

View File

@@ -1,29 +1,11 @@
TODO TODO
=========== ===========
printer
------------
pv/printer.h is not used.
doxygen doxygen
------- -------
There is a lot of public code that does not have doxygen tags. There is a lot of public code that does not have doxygen tags.
postMonitor: PVUnion, PVUnionArray, and PVStructureArray
--------
PVUnion, PVUnionArray, and PVStructureArray all have elements
that are treated like a top level field.
Currently if a subField of any of these is changed postMonitor is not called for the field itself.
David asked if this could be changed so that it is called.
Marty thinks this may not be a good idea.
valueAlarm valueAlarm
--------- ---------

View File

@@ -37,7 +37,7 @@
<h1>EPICS pvDataCPP</h1> <h1>EPICS pvDataCPP</h1>
<!-- Maturity: Working Draft or Request for Comments, or Recommendation, and date. --> <!-- 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> <dl>
<dt>Latest version:</dt> <dt>Latest version:</dt>
@@ -46,11 +46,11 @@
</dd> </dd>
<dt>This version:</dt> <dt>This version:</dt>
<dd><a <dd><a
href="pvDataCPP_20140723.html">pvDataCPP_20140723.html</a> href="pvDataCPP_20150623.html">pvDataCPP_20150623.html</a>
</dd> </dd>
<dt>Previous version:</dt> <dt>Previous version:</dt>
<dd><a <dd><a
href="pvDataCPP_20140708.html">pvDataCPP_20140708.html</a> href="pvDataCPP_20141110.html">pvDataCPP_20141110.html</a>
</dd> </dd>
<dt>Editors:</dt> <dt>Editors:</dt>
<dd>Marty Kraimer, BNL</dd> <dd>Marty Kraimer, BNL</dd>
@@ -79,7 +79,7 @@ V4 control system programming environment:<br />
<h2 class="nocount">Status of this Document</h2> <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>
<p>RELEASE_NOTES.md provides changes since the last release. <p>RELEASE_NOTES.md provides changes since the last release.
@@ -2309,6 +2309,16 @@ public:
template&lt;typename PVT&gt; template&lt;typename PVT&gt;
std::tr1::shared_ptr&lt;PVT&gt; getSubField(std::size_t fieldOffset) const 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( virtual void serialize(
ByteBuffer *pbuffer,SerializableControl *pflusher) const ; ByteBuffer *pbuffer,SerializableControl *pflusher) const ;
virtual void deserialize( virtual void deserialize(
@@ -2329,7 +2339,7 @@ public:
<dt>getPVFields</dt> <dt>getPVFields</dt>
<dd>Returns the array of subfields. The set of subfields must all have <dd>Returns the array of subfields. The set of subfields must all have
different field names.</dd> different field names.</dd>
<dt>getSubField(std::string fieldName)</dt> <dt>getSubField(std::string const &amp;fieldName)</dt>
<dd> <dd>
Get a subField of a field.d Get a subField of a field.d
A non-null result is A non-null result is
@@ -2344,9 +2354,13 @@ public:
<dd>Get the field located a fieldOffset, where fieldOffset is relative to <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 the top level structure. This returns null if the specified field is not
located within this PVStructure. located within this PVStructure.
<br />
<b>Note</b> The template version replaces getBooleanField, etc.<br/>
</dd> </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> <dt>dumpValue</dt>
<dd>Method for streams I/O.</dd> <dd>Method for streams I/O.</dd>
</dl> </dl>
@@ -2662,12 +2676,6 @@ objects:</p>
</dl> </dl>
<h3>convert.h</h3> <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> <p>This section describes the supported conversions between data types.</p>
<ul> <ul>
<li>All supported types can be converted to a string. If you ask for a 100 <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> <li>Either is a string</li>
</ul> </ul>
</li> </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>Conversions between numeric scalar types.</li>
<li>Conversion between compatible structures.</li> <li>Conversion between compatible structures.</li>
<li>A utility method the returns the full field name of a field</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 # 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. # 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) 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. # 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 # Fetch and unpack dependencies
@@ -17,10 +26,8 @@ rm -fr ${STUFF}
mkdir -p ${STUFF} mkdir -p ${STUFF}
cd ${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/Base-${BASE}_Build/lastSuccessfulBuild/artifact/base-${BASE}.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 base-${BASE}.CB-dist.tar.gz
tar -xzf baseR3.14.12.3.CB-dist.tar.gz
tar -xzf doxygen-1.8.3.CB-dist.tar.gz
########################################### ###########################################
# Build # Build
@@ -37,20 +44,13 @@ EPICS_BASE=${EPICS_BASE}
EOF EOF
make distclean all make distclean all
doxygen
########################################### ###########################################
# Test # Test
# EPICS Test Harness tests
make runtests make runtests
########################################### ###########################################
# Create distribution # Create distribution
tar czf pvData.CB-dist.tar.gz lib include COPYRIGHT LICENSE tar czf pvData.CB-dist.tar.gz lib include COPYRIGHT LICENSE
###########################################
# Publish documentation
rsync -aP --delete -e ssh documentation epics-jenkins@web.sourceforge.net:/home/project-web/epics-pvdata/htdocs/docbuild/pvDataCPP/tip

51
jenkins/cloudbees_doc Normal file
View File

@@ -0,0 +1,51 @@
# pvData C++ implementation
# Jenkins @ Cloudbees documentation generation and deployment
#
# Jenkins invokes scripts with the "-ex" option. So the build is considered a failure
# if any of the commands exits with a non-zero exit code.
#
# Author: Ralph Lange <ralph.lange@gmx.de>
# Copyright (C) 2013 Helmholtz-Zentrum Berlin für Materialien und Energie GmbH
# Copyright (C) 2014-2015 ITER Organization.
# All rights reserved. Use is subject to license terms.
###########################################
# Set EPICS Base version and upload target
BASE=3.15.2
PUBLISH=${1:-DONT}
###########################################
# Fetch and unpack dependencies
export STUFF=/tmp/stuff
rm -fr ${STUFF}
mkdir -p ${STUFF}
cd ${STUFF}
wget -nv https://openepics.ci.cloudbees.com/job/Doxygen-1.8.3_Build/lastSuccessfulBuild/artifact/doxygen-1.8.3.CB-dist.tar.gz
tar -xzf doxygen-1.8.3.CB-dist.tar.gz
###########################################
# Generate
cd ${WORKSPACE}
wget -nv https://openepics.ci.cloudbees.com/job/pvDataCPP_Build/BASE=${BASE},USE_MB=MB_NO/lastSuccessfulBuild/artifact/pvData.CB-dist.tar.gz
tar -xzf pvData.CB-dist.tar.gz
export PATH=${STUFF}/bin:${PATH}
doxygen
###########################################
# Publish
if [ "${PUBLISH}" != "DONT" ]; then
# Upload explicit dummy to ensure target directory exists
echo "Created by CloudBees Jenkins upload job. Should be deleted as part of the job." > DUMMY
rsync -q -e ssh DUMMY epics-jenkins@web.sourceforge.net:/home/project-web/epics-pvdata/htdocs/docbuild/pvDataCPP/${PUBLISH}/
rsync -aqP --delete -e ssh documentation epics-jenkins@web.sourceforge.net:/home/project-web/epics-pvdata/htdocs/docbuild/pvDataCPP/${PUBLISH}/
fi

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( virtual PVStructurePtr createRequest(
string const & crequest) 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 { try {
if(offsetRecord!=string::npos) { string request = crequest;
fullFieldName = "record"; if (!request.empty()) removeBlanks(request);
size_t openBracket = request.find('[', offsetRecord); if (request.empty())
size_t closeBracket = request.find(']', openBracket); {
if(closeBracket==string::npos) { return pvDataCreate->createPVStructure(fieldCreate->createStructure());
message = request.substr(offsetRecord) + }
"record[ does not have matching ]"; size_t offsetRecord = request.find("record[");
return PVStructurePtr(); 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) { if(offsetField!=string::npos) {
Node node("record"); fullFieldName = "field";
Node optNode = createRequestOptions( Node node("field");
request.substr(openBracket+1,closeBracket-openBracket-1)); size_t openParan = request.find('(', offsetField);
node.nodes.push_back(optNode); 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); 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) { size_t num = top.size();
fullFieldName = "field"; StringArray names(num);
Node node("field"); FieldConstPtrArray fields(num);
size_t openParan = request.find('(', offsetField); for(size_t i=0; i<num; ++i) {
size_t closeParan = request.find(')', openParan); Node node = top[i];
if(closeParan==string::npos) { names[i] = node.name;
message = request.substr(offsetField) vector<Node> subNode = node.nodes;
+ " field( does not have matching )"; if(subNode.empty()) {
return PVStructurePtr(); 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) { StructureConstPtr structure = fieldCreate->createStructure(names, fields);
fullFieldName = "getField"; if(!structure) throw std::invalid_argument("bad request " + crequest);
Node node("getField"); PVStructurePtr pvStructure = pvDataCreate->createPVStructure(structure);
size_t openParan = request.find('(', offsetGetField); for(size_t i=0; i<optionList.size(); ++i) {
size_t closeParan = request.find(')', openParan); OptionPair pair = optionList[i];
if(closeParan==string::npos) { string name = pair.name;
message = request.substr(offsetField) string value = pair.value;
+ " getField( does not have matching )"; PVStringPtr pvField = pvStructure->getSubField<PVString>(name);
return PVStructurePtr(); if(!pvField) throw std::invalid_argument("bad request " + crequest);
} pvField->put(value);
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);
} }
optionList.clear();
return pvStructure;
} catch (std::exception &e) { } catch (std::exception &e) {
string xxx = e.what(); message = e.what();
message = "while creating Structure exception " + xxx; return PVStructurePtr();
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() CreateRequest::shared_pointer CreateRequest::create()

View File

@@ -18,7 +18,12 @@
namespace epics { namespace pvData { 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 { class epicsShareClass CreateRequest {
public: public:
@@ -33,7 +38,6 @@ class epicsShareClass CreateRequest {
* Create a request structure for the create calls in Channel. * Create a request structure for the create calls in Channel.
* See the package overview documentation for details. * See the package overview documentation for details.
* @param request The field request. See the package overview documentation for details. * @param request The field request. See the package overview documentation for details.
* @param requester The requester;
* @return The request PVStructure if a valid request was given. * @return The request PVStructure if a valid request was given.
* If a NULL PVStructure is returned then getMessage will return * If a NULL PVStructure is returned then getMessage will return
* the reason. * the reason.

View File

@@ -18,7 +18,6 @@
#include <pv/thread.h> #include <pv/thread.h>
#include <pv/pvCopy.h> #include <pv/pvCopy.h>
#include <pv/convert.h>
using std::tr1::static_pointer_cast; using std::tr1::static_pointer_cast;
using std::tr1::dynamic_pointer_cast; using std::tr1::dynamic_pointer_cast;
@@ -29,6 +28,18 @@ using std::endl;
namespace epics { namespace pvData { 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 PVCopyPtr NULLPVCopy;
static FieldConstPtr NULLField; static FieldConstPtr NULLField;
static StructureConstPtr NULLStructure; static StructureConstPtr NULLStructure;
@@ -67,11 +78,11 @@ PVCopyPtr PVCopy::create(
PVStructurePtr pvStructure(pvRequest); PVStructurePtr pvStructure(pvRequest);
if(structureName.size()>0) { if(structureName.size()>0) {
if(pvRequest->getStructure()->getNumberFields()>0) { if(pvRequest->getStructure()->getNumberFields()>0) {
pvStructure = pvRequest->getStructureField(structureName); pvStructure = pvRequest->getSubField<PVStructure>(structureName);
if(!pvStructure) return NULLPVCopy; if(!pvStructure) return NULLPVCopy;
} }
} else if(pvStructure->getSubField("field")) { } else if(pvStructure->getSubField("field")) {
pvStructure = pvRequest->getStructureField("field"); pvStructure = pvRequest->getSubField<PVStructure>("field");
} }
PVCopyPtr pvCopy = PVCopyPtr(new PVCopy(pvMaster)); PVCopyPtr pvCopy = PVCopyPtr(new PVCopy(pvMaster));
bool result = pvCopy->init(pvStructure); bool result = pvCopy->init(pvStructure);
@@ -243,10 +254,9 @@ void PVCopy::updateCopySetBitSet(
updateSubFieldSetBitSet(copyPVField,pvMasterField,bitSet); updateSubFieldSetBitSet(copyPVField,pvMasterField,bitSet);
return; return;
} }
ConvertPtr convert = getConvert(); bool isEqual = (*copyPVField == *pvField);
bool isEqual = convert->equals(copyPVField,pvField);
if(!isEqual) { if(!isEqual) {
convert->copy(pvField, copyPVField); copyPVField->copyUnchecked(*pvField);
bitSet->set(copyPVField->getFieldOffset()); bitSet->set(copyPVField->getFieldOffset());
} }
} }
@@ -292,7 +302,7 @@ string PVCopy::dump()
void PVCopy::dump(string *builder,CopyNodePtr const &node,int indentLevel) void PVCopy::dump(string *builder,CopyNodePtr const &node,int indentLevel)
{ {
getConvert()->newLine(builder,indentLevel); newLine(builder,indentLevel);
std::stringstream ss; std::stringstream ss;
ss << (node->isStructure ? "structureNode" : "masterNode"); ss << (node->isStructure ? "structureNode" : "masterNode");
ss << " structureOffset " << node->structureOffset; ss << " structureOffset " << node->structureOffset;
@@ -300,14 +310,14 @@ void PVCopy::dump(string *builder,CopyNodePtr const &node,int indentLevel)
*builder += ss.str(); *builder += ss.str();
PVStructurePtr options = node->options; PVStructurePtr options = node->options;
if(options) { if(options) {
getConvert()->newLine(builder,indentLevel +1); newLine(builder,indentLevel +1);
// TODO !!! ugly // TODO !!! ugly
std::ostringstream oss; std::ostringstream oss;
oss << *options; oss << *options;
*builder += oss.str(); *builder += oss.str();
getConvert()->newLine(builder,indentLevel); newLine(builder,indentLevel);
} }
if(!node->isStructure) { if(!node->isStructure) {
CopyMasterNodePtr masterNode = static_pointer_cast<CopyMasterNode>(node); 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; CopyNodePtrArrayPtr nodes = structureNode->nodes;
for(size_t i=0; i<nodes->size(); ++i) { for(size_t i=0; i<nodes->size(); ++i) {
if((*nodes)[i].get()==NULL) { if((*nodes)[i].get()==NULL) {
getConvert()->newLine(builder,indentLevel +1); newLine(builder,indentLevel +1);
ss.str(""); ss.str("");
ss << "node[" << i << "] is null"; ss << "node[" << i << "] is null";
*builder += ss.str(); *builder += ss.str();
@@ -339,7 +349,7 @@ bool PVCopy::init(epics::pvData::PVStructurePtr const &pvRequest)
if(len==0) entireMaster = true; if(len==0) entireMaster = true;
PVStructurePtr pvOptions; PVStructurePtr pvOptions;
if(len==1 && pvRequest->getSubField("_options")) { if(len==1 && pvRequest->getSubField("_options")) {
pvOptions = pvRequest->getStructureField("_options"); pvOptions = pvRequest->getSubField<PVStructure>("_options");
} }
if(entireMaster) { if(entireMaster) {
structure = pvMasterStructure->getStructure(); structure = pvMasterStructure->getStructure();
@@ -499,17 +509,16 @@ void PVCopy::updateSubFieldSetBitSet(
FieldConstPtr field = pvCopy->getField(); FieldConstPtr field = pvCopy->getField();
Type type = field->getType(); Type type = field->getType();
if(type!=epics::pvData::structure) { if(type!=epics::pvData::structure) {
ConvertPtr convert = getConvert(); bool isEqual = (*pvCopy == *pvMaster);
bool isEqual = convert->equals(pvCopy,pvMaster);
if(isEqual) { if(isEqual) {
if(type==structureArray) { if(type==structureArray) {
// always act as though a change occurred. // always act as though a change occurred.
// Note that array elements are shared. // Note that array elements are shared.
bitSet->set(pvCopy->getFieldOffset()); bitSet->set(pvCopy->getFieldOffset());
} }
} }
if(isEqual) return; if(isEqual) return;
convert->copy(pvMaster, pvCopy); pvCopy->copyUnchecked(*pvMaster);
bitSet->set(pvCopy->getFieldOffset()); bitSet->set(pvCopy->getFieldOffset());
return; return;
} }
@@ -574,7 +583,6 @@ void PVCopy::updateSubFieldFromBitSet(
if(nextSet==string::npos) return; if(nextSet==string::npos) return;
if(nextSet>=pvCopy->getNextFieldOffset()) return; if(nextSet>=pvCopy->getNextFieldOffset()) return;
} }
ConvertPtr convert = getConvert();
if(pvCopy->getField()->getType()==epics::pvData::structure) { if(pvCopy->getField()->getType()==epics::pvData::structure) {
PVStructurePtr pvCopyStructure = PVStructurePtr pvCopyStructure =
static_pointer_cast<PVStructure>(pvCopy); static_pointer_cast<PVStructure>(pvCopy);
@@ -595,9 +603,9 @@ void PVCopy::updateSubFieldFromBitSet(
} }
} else { } else {
if(toCopy) { if(toCopy) {
convert->copy(pvMasterField, pvCopy); pvCopy->copyUnchecked(*pvMasterField);
} else { } else {
convert->copy(pvCopy, pvMasterField); pvMasterField->copyUnchecked(*pvCopy);
} }
} }
} }

View File

@@ -25,7 +25,8 @@ class PVCopyTraverseMasterCallback;
typedef std::tr1::shared_ptr<PVCopyTraverseMasterCallback> PVCopyTraverseMasterCallbackPtr; 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. * Must be implemented by code that creates pvCopy.
*/ */
class epicsShareClass PVCopyTraverseMasterCallback 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 * Class that manages one or more PVStructures that holds an arbitrary subset of the fields
* in another PVStructure called master. * in another PVStructure called master.
*/ */
@@ -63,8 +66,8 @@ public:
POINTER_DEFINITIONS(PVCopy); POINTER_DEFINITIONS(PVCopy);
/** /**
* Create a new pvCopy * Create a new pvCopy
* @param pvMaster The top level sructure for which a copy of * @param pvMaster The top-level structure for which a copy of
* an arbritary subset of the fields in master will be created and managed. * 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 pvRequest Selects the set of subfields desired and options for each field.
* @param structureName The name for the top level of any PVStructure created. * @param structureName The name for the top level of any PVStructure created.
*/ */
@@ -75,8 +78,8 @@ public:
virtual ~PVCopy(){} virtual ~PVCopy(){}
virtual void destroy(); virtual void destroy();
/** /**
* Get the top level structure of master * Get the top-level structure of master
* @returns The master top level structure. * @returns The master top-level structure.
* This should not be modified. * This should not be modified.
*/ */
PVStructurePtr getPVMaster(); PVStructurePtr getPVMaster();
@@ -94,7 +97,7 @@ public:
StructureConstPtr getStructure(); StructureConstPtr getStructure();
/** /**
* Create a copy instance. Monitors keep a queue of monitor elements. * 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(); PVStructurePtr createPVStructure();
/** /**
@@ -113,15 +116,15 @@ public:
PVStructurePtr const &masterPVStructure, PVStructurePtr const &masterPVStructure,
PVFieldPtr const &masterPVField); PVFieldPtr const &masterPVField);
/** /**
* Given a offset in the copy get the corresponding field in pvMaster. * Given an offset in the copy get the corresponding field in pvMaster.
* @param offset The offset in the copy. * @param structureOffset The offset in the copy.
*/ */
PVFieldPtr getMasterPVField(std::size_t structureOffset); PVFieldPtr getMasterPVField(std::size_t structureOffset);
/** /**
* Initialize the fields in copyPVStructure by giving each field * Initialize the fields in copyPVStructure by giving each field
* the value from the corresponding field in pvMaster. * the value from the corresponding field in pvMaster.
* bitSet will be set to show that all fields are changed. * 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. * @param bitSet A bitSet for copyPVStructure.
*/ */
void initCopy( void initCopy(
@@ -130,7 +133,7 @@ public:
/** /**
* Set all fields in copyPVStructure to the value of the corresponding field in pvMaster. * 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. * 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. * @param bitSet A bitSet for copyPVStructure.
*/ */
void updateCopySetBitSet( void updateCopySetBitSet(
@@ -138,8 +141,8 @@ public:
BitSetPtr const &bitSet); BitSetPtr const &bitSet);
/** /**
* For each set bit in bitSet * For each set bit in bitSet
* set the field in copyPVStructure to the value of the corrseponding field in pvMaster. * set the field in copyPVStructure to the value of the corresponding field in pvMaster.
* @param copyPVStructure A copy top level structure. * @param copyPVStructure A copy top-level structure.
* @param bitSet A bitSet for copyPVStructure. * @param bitSet A bitSet for copyPVStructure.
*/ */
void updateCopyFromBitSet( void updateCopyFromBitSet(
@@ -147,8 +150,8 @@ public:
BitSetPtr const &bitSet); BitSetPtr const &bitSet);
/** /**
* For each set bit in bitSet * For each set bit in bitSet
* set the field in pvMaster to the value of the corrseponding field in copyPVStructure * set the field in pvMaster to the value of the corresponding field in copyPVStructure
* @param copyPVStructure A copy top level structure. * @param copyPVStructure A copy top-level structure.
* @param bitSet A bitSet for copyPVStructure. * @param bitSet A bitSet for copyPVStructure.
*/ */
void updateMaster( void updateMaster(
@@ -156,7 +159,7 @@ public:
BitSetPtr const &bitSet); BitSetPtr const &bitSet);
/** /**
* Get the options for the field at the specified offset. * Get the options for the field at the specified offset.
* @param offset the offset in copy. * @param fieldOffset the offset in copy.
* @returns A NULL is returned if no options were specified for the field. * @returns A NULL is returned if no options were specified for the field.
* If options were specified,PVStructurePtr is a structures * If options were specified,PVStructurePtr is a structures
* with a set of PVString subfields that specify name,value pairs.s * with a set of PVString subfields that specify name,value pairs.s

View File

@@ -12,13 +12,13 @@
#include <sstream> #include <sstream>
#define epicsExportSharedSymbols #define epicsExportSharedSymbols
#include <pv/convert.h> #include <pv/pvData.h>
using std::string; using std::string;
namespace epics { namespace pvData { namespace epics { namespace pvData {
// Introspection object comparision // Introspection object comparison
/** Field equality conditions: /** Field equality conditions:
* 1) same instance * 1) same instance
@@ -62,7 +62,7 @@ bool operator==(const Field& a, const Field& b)
return A==B; return A==B;
} }
default: 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; return false;
// std::equals does not work, since FieldConstPtrArray is an array of shared_pointers // std::equals does not work, since FieldConstPtrArray is an array of shared_pointers
FieldConstPtrArray af = a.getFields(); FieldConstPtrArray const & af = a.getFields();
FieldConstPtrArray bf = b.getFields(); FieldConstPtrArray const & bf = b.getFields();
for (size_t i = 0; i < nflds; i++) for (size_t i = 0; i < nflds; i++)
if (*(af[i].get()) != *(bf[i].get())) if (*(af[i].get()) != *(bf[i].get()))
return false; return false;
StringArray an = a.getFieldNames(); StringArray const & an = a.getFieldNames();
StringArray bn = b.getFieldNames(); StringArray const & bn = b.getFieldNames();
return std::equal( an.begin(), an.end(), bn.begin() ); return std::equal( an.begin(), an.end(), bn.begin() );
} }
@@ -118,14 +118,14 @@ bool operator==(const Union& a, const Union& b)
return false; return false;
// std::equals does not work, since FieldConstPtrArray is an array of shared_pointers // std::equals does not work, since FieldConstPtrArray is an array of shared_pointers
FieldConstPtrArray af = a.getFields(); FieldConstPtrArray const & af = a.getFields();
FieldConstPtrArray bf = b.getFields(); FieldConstPtrArray const & bf = b.getFields();
for (size_t i = 0; i < nflds; i++) for (size_t i = 0; i < nflds; i++)
if (*(af[i].get()) != *(bf[i].get())) if (*(af[i].get()) != *(bf[i].get()))
return false; return false;
StringArray an = a.getFieldNames(); StringArray const & an = a.getFieldNames();
StringArray bn = b.getFieldNames(); StringArray const & bn = b.getFieldNames();
return std::equal( an.begin(), an.end(), bn.begin() ); return std::equal( an.begin(), an.end(), bn.begin() );
} }
@@ -251,7 +251,13 @@ bool compareField(const PVStructureArray* left, const PVStructureArray* right)
lit!=lend; lit!=lend;
++lit, ++rit) ++lit, ++rit)
{ {
if(**lit != **rit) // element can be null
if (!(*lit) || !(*rit))
{
if (*lit || *rit)
return false;
}
else if (**lit != **rit)
return false; return false;
} }
return true; return true;
@@ -304,7 +310,13 @@ bool compareField(const PVUnionArray* left, const PVUnionArray* right)
lit!=lend; lit!=lend;
++lit, ++rit) ++lit, ++rit)
{ {
if(**lit != **rit) // element can be null
if (!(*lit) || !(*rit))
{
if (*lit || *rit)
return false;
}
else if (**lit != **rit)
return false; return false;
} }
return true; return true;

View File

@@ -52,9 +52,6 @@ void Convert::getString(string *buf,PVField const *pvField,int /*indentLevel*/)
std::ostringstream strm; std::ostringstream strm;
pvField->dumpValue(strm); pvField->dumpValue(strm);
strm << std::endl; strm << std::endl;
// PrinterPlain p;
// p.setStream(strm);
// p.print(*pvField);
strm.str().swap(*buf); strm.str().swap(*buf);
} }
@@ -152,374 +149,6 @@ size_t Convert::toStringArray(PVScalarArrayPtr const & pv,
return data.size(); 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() ConvertPtr Convert::getConvert()
{ {
static ConvertPtr convert; static ConvertPtr convert;

View File

@@ -22,7 +22,6 @@
#define epicsExportSharedSymbols #define epicsExportSharedSymbols
#include <pv/lock.h> #include <pv/lock.h>
#include <pv/pvIntrospect.h> #include <pv/pvIntrospect.h>
#include <pv/convert.h>
#include <pv/factory.h> #include <pv/factory.h>
#include <pv/serializeHelper.h> #include <pv/serializeHelper.h>
@@ -52,7 +51,7 @@ Scalar::Scalar(ScalarType scalarType)
: Field(scalar),scalarType(scalarType) : Field(scalar),scalarType(scalarType)
{ {
if(scalarType<0 || scalarType>MAX_SCALAR_TYPE) 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(){} Scalar::~Scalar(){}
@@ -137,7 +136,7 @@ BoundedString::BoundedString(std::size_t maxStringLength) :
Scalar(pvString), maxLength(maxStringLength) Scalar(pvString), maxLength(maxStringLength)
{ {
if (maxLength == 0) if (maxLength == 0)
throw std::invalid_argument("maxLength == 0"); THROW_EXCEPTION2(std::invalid_argument, "maxLength == 0");
} }
BoundedString::~BoundedString() {} BoundedString::~BoundedString() {}
@@ -400,7 +399,13 @@ void UnionArray::deserialize(ByteBuffer* /*buffer*/, DeserializableControl* /*co
throw std::runtime_error("not valid operation, use FieldCreate::deserialize instead"); 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 ( Structure::Structure (
StringArray const & fieldNames, StringArray const & fieldNames,
@@ -412,27 +417,27 @@ Structure::Structure (
id(inid) id(inid)
{ {
if(inid.empty()) { 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()) { 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(); size_t number = fields.size();
for(size_t i=0; i<number; i++) { for(size_t i=0; i<number; i++) {
const string& name = fieldNames[i]; const string& name = fieldNames[i];
if(name.empty()) { 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) 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 // look for duplicates
for(size_t j=i+1; j<number; j++) { for(size_t j=i+1; j<number; j++) {
string otherName = fieldNames[j]; string otherName = fieldNames[j];
int result = name.compare(otherName); int result = name.compare(otherName);
if(result==0) { if(result==0) {
string message("duplicate fieldName "); string message("Can't construct Structure, duplicate fieldName ");
message += name; 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: case structureArray:
{ {
format::indent_scope s(o); format::indent_scope s(o);
o << *pfield; Field const *xxx = pfield.get();
StructureArray const *pstructureArray = static_cast<StructureArray const*>(xxx);
o << *pstructureArray->getStructure();
break; break;
} }
case union_: case union_:
@@ -511,7 +518,9 @@ void Structure::dumpFields(std::ostream& o) const
case unionArray: case unionArray:
{ {
format::indent_scope s(o); format::indent_scope s(o);
o << *pfield; Field const *xxx = pfield.get();
UnionArray const *punionArray = static_cast<UnionArray const*>(xxx);
o << *punionArray->getUnion();
break; break;
} }
} }
@@ -528,20 +537,30 @@ void Structure::deserialize(ByteBuffer* /*buffer*/, DeserializableControl* /*con
throw std::runtime_error("not valid operation, use FieldCreate::deserialize instead"); 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" const string & Union::defaultId()
string Union::ANY_ID = UNION_ANY_ID; {
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 () Union::Union ()
: Field(union_), : Field(union_),
fieldNames(), fieldNames(),
fields(), fields(),
id(UNION_ANY_ID) id(anyId())
{ {
} }
#undef UNION_ANY_ID
Union::Union ( Union::Union (
StringArray const & fieldNames, StringArray const & fieldNames,
@@ -553,31 +572,31 @@ Union::Union (
id(inid) id(inid)
{ {
if(inid.empty()) { 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()) { 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) { 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(); size_t number = fields.size();
for(size_t i=0; i<number; i++) { for(size_t i=0; i<number; i++) {
const string& name = fieldNames[i]; const string& name = fieldNames[i];
if(name.empty()) { 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) 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 // look for duplicates
for(size_t j=i+1; j<number; j++) { for(size_t j=i+1; j<number; j++) {
string otherName = fieldNames[j]; string otherName = fieldNames[j];
int result = name.compare(otherName); int result = name.compare(otherName);
if(result==0) { if(result==0) {
string message("duplicate fieldName "); string message("Can't construct Union, duplicate fieldName ");
message += name; 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: case scalar:
if (std::tr1::dynamic_pointer_cast<const BoundedString>(element).get()) 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())); fields.push_back(fieldCreate->createScalarArray(static_pointer_cast<const Scalar>(element)->getScalarType()));
break; break;
@@ -767,7 +786,7 @@ FieldBuilderPtr FieldBuilder::addArray(string const & name, FieldConstPtr const
default: default:
std::ostringstream msg("unsupported array element type: "); std::ostringstream msg("unsupported array element type: ");
msg << element->getType(); msg << element->getType();
throw std::invalid_argument(msg.str()); THROW_EXCEPTION2(std::invalid_argument, msg.str());
} }
fieldNames.push_back(name); fieldNames.push_back(name);
@@ -796,7 +815,7 @@ FieldConstPtr FieldBuilder::createFieldInternal(Type type)
{ {
std::ostringstream msg("unsupported type: "); std::ostringstream msg("unsupported type: ");
msg << 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() StructureConstPtr FieldBuilder::createStructure()
{ {
if (parentBuilder.get()) 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))); StructureConstPtr field(static_pointer_cast<const Structure>(createFieldInternal(structure)));
reset(); reset();
@@ -814,7 +833,7 @@ StructureConstPtr FieldBuilder::createStructure()
UnionConstPtr FieldBuilder::createUnion() UnionConstPtr FieldBuilder::createUnion()
{ {
if (parentBuilder.get()) 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_))); UnionConstPtr field(static_pointer_cast<const Union>(createFieldInternal(union_)));
reset(); reset();
@@ -846,7 +865,7 @@ FieldBuilderPtr FieldBuilder::addNestedUnionArray(string const & name)
FieldBuilderPtr FieldBuilder::endNested() FieldBuilderPtr FieldBuilder::endNested()
{ {
if (!parentBuilder.get()) 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); FieldConstPtr nestedField = createFieldInternal(nestedClassToBuild);
if (nestedArray) if (nestedArray)
@@ -865,8 +884,11 @@ FieldBuilderPtr FieldCreate::createFieldBuilder() const
ScalarConstPtr FieldCreate::createScalar(ScalarType scalarType) const ScalarConstPtr FieldCreate::createScalar(ScalarType scalarType) const
{ {
if(scalarType<0 || scalarType>MAX_SCALAR_TYPE) if(scalarType<0 || scalarType>MAX_SCALAR_TYPE) {
throw std::invalid_argument("Can't construct Scalar from invalid ScalarType"); std::ostringstream strm("Can't construct Scalar from invalid ScalarType ");
strm << scalarType;
THROW_EXCEPTION2(std::invalid_argument, strm.str());
}
return scalars[scalarType]; return scalars[scalarType];
} }
@@ -881,16 +903,22 @@ BoundedStringConstPtr FieldCreate::createBoundedString(std::size_t maxLength) co
ScalarArrayConstPtr FieldCreate::createScalarArray(ScalarType elementType) const ScalarArrayConstPtr FieldCreate::createScalarArray(ScalarType elementType) const
{ {
if(elementType<0 || elementType>MAX_SCALAR_TYPE) if(elementType<0 || elementType>MAX_SCALAR_TYPE) {
throw std::invalid_argument("Can't construct ScalarArray from invalid ScalarType"); std::ostringstream strm("Can't construct ScalarArray from invalid ScalarType ");
strm << elementType;
THROW_EXCEPTION2(std::invalid_argument, strm.str());
}
return scalarArrays[elementType]; return scalarArrays[elementType];
} }
ScalarArrayConstPtr FieldCreate::createFixedScalarArray(ScalarType elementType, size_t size) const ScalarArrayConstPtr FieldCreate::createFixedScalarArray(ScalarType elementType, size_t size) const
{ {
if(elementType<0 || elementType>MAX_SCALAR_TYPE) if(elementType<0 || elementType>MAX_SCALAR_TYPE) {
throw std::invalid_argument("Can't construct ScalarArray from invalid ScalarType"); 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 // TODO use std::make_shared
std::tr1::shared_ptr<ScalarArray> s(new FixedScalarArray(elementType, size), Field::Deleter()); 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 ScalarArrayConstPtr FieldCreate::createBoundedScalarArray(ScalarType elementType, size_t size) const
{ {
if(elementType<0 || elementType>MAX_SCALAR_TYPE) if(elementType<0 || elementType>MAX_SCALAR_TYPE) {
throw std::invalid_argument("Can't construct ScalarArray from invalid ScalarType"); 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 // TODO use std::make_shared
std::tr1::shared_ptr<ScalarArray> s(new BoundedScalarArray(elementType, size), Field::Deleter()); std::tr1::shared_ptr<ScalarArray> s(new BoundedScalarArray(elementType, size), Field::Deleter());
@@ -989,8 +1020,8 @@ StructureConstPtr FieldCreate::appendField(
string const & fieldName, string const & fieldName,
FieldConstPtr const & field) const FieldConstPtr const & field) const
{ {
StringArray oldNames = structure->getFieldNames(); StringArray const & oldNames = structure->getFieldNames();
FieldConstPtrArray oldFields = structure->getFields(); FieldConstPtrArray const & oldFields = structure->getFields();
size_t oldLen = oldNames.size(); size_t oldLen = oldNames.size();
StringArray newNames(oldLen+1); StringArray newNames(oldLen+1);
FieldConstPtrArray newFields(oldLen+1); FieldConstPtrArray newFields(oldLen+1);
@@ -1008,8 +1039,8 @@ StructureConstPtr FieldCreate::appendFields(
StringArray const & fieldNames, StringArray const & fieldNames,
FieldConstPtrArray const & fields) const FieldConstPtrArray const & fields) const
{ {
StringArray oldNames = structure->getFieldNames(); StringArray const & oldNames = structure->getFieldNames();
FieldConstPtrArray oldFields = structure->getFields(); FieldConstPtrArray const & oldFields = structure->getFields();
size_t oldLen = oldNames.size(); size_t oldLen = oldNames.size();
size_t extra = fieldNames.size(); size_t extra = fieldNames.size();
StringArray newNames(oldLen+extra); 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/lock.h>
#include <pv/pvIntrospect.h> #include <pv/pvIntrospect.h>
#include <pv/pvData.h> #include <pv/pvData.h>
#include <pv/convert.h>
#include <pv/factory.h> #include <pv/factory.h>
#include <pv/serializeHelper.h> #include <pv/serializeHelper.h>
@@ -527,7 +526,7 @@ PVFieldPtr PVDataCreate::createPVField(PVFieldPtr const & fieldToClone)
PVStructurePtr pvStructure PVStructurePtr pvStructure
= static_pointer_cast<PVStructure>(fieldToClone); = static_pointer_cast<PVStructure>(fieldToClone);
StringArray const & fieldNames = pvStructure->getStructure()->getFieldNames(); StringArray const & fieldNames = pvStructure->getStructure()->getFieldNames();
PVFieldPtrArray pvFieldPtrArray = pvStructure->getPVFields(); PVFieldPtrArray const & pvFieldPtrArray = pvStructure->getPVFields();
return createPVStructure(fieldNames,pvFieldPtrArray); return createPVStructure(fieldNames,pvFieldPtrArray);
} }
case structureArray: case structureArray:
@@ -537,7 +536,7 @@ PVFieldPtr PVDataCreate::createPVField(PVFieldPtr const & fieldToClone)
StructureArrayConstPtr structureArray = from->getStructureArray(); StructureArrayConstPtr structureArray = from->getStructureArray();
PVStructureArrayPtr to = createPVStructureArray( PVStructureArrayPtr to = createPVStructureArray(
structureArray); structureArray);
getConvert()->copyStructureArray(from, to); to->copyUnchecked(*from);
return to; return to;
} }
case union_: case union_:
@@ -552,7 +551,7 @@ PVFieldPtr PVDataCreate::createPVField(PVFieldPtr const & fieldToClone)
= static_pointer_cast<PVUnionArray>(fieldToClone); = static_pointer_cast<PVUnionArray>(fieldToClone);
UnionArrayConstPtr unionArray = from->getUnionArray(); UnionArrayConstPtr unionArray = from->getUnionArray();
PVUnionArrayPtr to = createPVUnionArray(unionArray); PVUnionArrayPtr to = createPVUnionArray(unionArray);
getConvert()->copyUnionArray(from, to); to->copyUnchecked(*from);
return to; return to;
} }
} }
@@ -602,7 +601,7 @@ PVScalarPtr PVDataCreate::createPVScalar(PVScalarPtr const & scalarToClone)
{ {
ScalarType scalarType = scalarToClone->getScalar()->getScalarType(); ScalarType scalarType = scalarToClone->getScalar()->getScalarType();
PVScalarPtr pvScalar = createPVScalar(scalarType); PVScalarPtr pvScalar = createPVScalar(scalarType);
getConvert()->copyScalar(scalarToClone, pvScalar); pvScalar->copyUnchecked(*scalarToClone);
return pvScalar; return pvScalar;
} }
@@ -712,7 +711,7 @@ PVStructurePtr PVDataCreate::createPVStructure(PVStructurePtr const & structToCl
} }
StructureConstPtr structure = structToClone->getStructure(); StructureConstPtr structure = structToClone->getStructure();
PVStructurePtr pvStructure(new PVStructure(structure)); PVStructurePtr pvStructure(new PVStructure(structure));
getConvert()->copyStructure(structToClone,pvStructure); pvStructure->copyUnchecked(*structToClone);
return pvStructure; 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/lock.h>
#include <pv/pvData.h> #include <pv/pvData.h>
#include <pv/factory.h> #include <pv/factory.h>
#include <pv/convert.h>
using std::tr1::const_pointer_cast; using std::tr1::const_pointer_cast;
using std::size_t; using std::size_t;
@@ -121,7 +120,7 @@ void PVField::computeOffset(const PVField * pvField) {
} }
size_t offset = 0; size_t offset = 0;
size_t nextOffset = 1; size_t nextOffset = 1;
PVFieldPtrArray pvFields = pvTop->getPVFields(); const PVFieldPtrArray & pvFields = pvTop->getPVFields();
for(size_t i=0; i < pvTop->getStructure()->getNumberFields(); i++) { for(size_t i=0; i < pvTop->getStructure()->getNumberFields(); i++) {
offset = nextOffset; offset = nextOffset;
PVField *pvField = pvFields[i].get(); PVField *pvField = pvFields[i].get();
@@ -153,7 +152,7 @@ void PVField::computeOffset(const PVField * pvField,size_t offset) {
size_t beginOffset = offset; size_t beginOffset = offset;
size_t nextOffset = offset + 1; size_t nextOffset = offset + 1;
const PVStructure *pvStructure = static_cast<const PVStructure *>(pvField); 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++) { for(size_t i=0; i < pvStructure->getStructure()->getNumberFields(); i++) {
offset = nextOffset; offset = nextOffset;
PVField *pvSubField = pvFields[i].get(); PVField *pvSubField = pvFields[i].get();
@@ -180,4 +179,117 @@ void PVField::computeOffset(const PVField * pvField,size_t offset) {
xxx->nextFieldOffset = nextOffset; 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 #define epicsExportSharedSymbols
#include <pv/pvData.h> #include <pv/pvData.h>
#include <pv/pvIntrospect.h> #include <pv/pvIntrospect.h>
#include <pv/convert.h>
#include <pv/factory.h> #include <pv/factory.h>
#include <pv/bitSet.h> #include <pv/bitSet.h>
@@ -45,18 +44,14 @@ PVUnionPtr PVStructure::nullPVUnion;
PVUnionArrayPtr PVStructure::nullPVUnionArray; PVUnionArrayPtr PVStructure::nullPVUnionArray;
PVScalarArrayPtr PVStructure::nullPVScalarArray; PVScalarArrayPtr PVStructure::nullPVScalarArray;
static PVFieldPtr findSubField(
string const &fieldName,
const PVStructure *pvStructure);
PVStructure::PVStructure(StructureConstPtr const & structurePtr) PVStructure::PVStructure(StructureConstPtr const & structurePtr)
: PVField(structurePtr), : PVField(structurePtr),
structurePtr(structurePtr), structurePtr(structurePtr),
extendsStructureName("") extendsStructureName("")
{ {
size_t numberFields = structurePtr->getNumberFields(); size_t numberFields = structurePtr->getNumberFields();
FieldConstPtrArray fields = structurePtr->getFields(); FieldConstPtrArray const & fields = structurePtr->getFields();
StringArray fieldNames = structurePtr->getFieldNames(); StringArray const & fieldNames = structurePtr->getFieldNames();
// PVFieldPtrArray * xxx = const_cast<PVFieldPtrArray *>(&pvFields); // PVFieldPtrArray * xxx = const_cast<PVFieldPtrArray *>(&pvFields);
pvFields.reserve(numberFields); pvFields.reserve(numberFields);
PVDataCreatePtr pvDataCreate = getPVDataCreate(); PVDataCreatePtr pvDataCreate = getPVDataCreate();
@@ -76,7 +71,7 @@ PVStructure::PVStructure(StructureConstPtr const & structurePtr,
extendsStructureName("") extendsStructureName("")
{ {
size_t numberFields = structurePtr->getNumberFields(); size_t numberFields = structurePtr->getNumberFields();
StringArray fieldNames = structurePtr->getFieldNames(); StringArray const & fieldNames = structurePtr->getFieldNames();
pvFields.reserve(numberFields); pvFields.reserve(numberFields);
for(size_t i=0; i<numberFields; i++) { for(size_t i=0; i<numberFields; i++) {
pvFields.push_back(pvs[i]); pvFields.push_back(pvs[i]);
@@ -112,7 +107,11 @@ const PVFieldPtrArray & PVStructure::getPVFields() const
PVFieldPtr PVStructure::getSubField(string const &fieldName) 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"); throw std::logic_error("PVStructure.getSubField: Logic error");
} }
PVFieldPtr PVStructure::getSubFieldT(std::size_t fieldOffset) const
PVBooleanPtr PVStructure::getBooleanField(string const &fieldName)
{ {
return getSubField<PVBoolean>(fieldName); PVFieldPtr pvField = getSubField(fieldOffset);
} if (pvField.get())
return pvField;
PVBytePtr PVStructure::getByteField(string const &fieldName) else
{ {
return getSubField<PVByte>(fieldName); std::stringstream ss;
} ss << "Failed to get field with offset "
<< fieldOffset << "(Invalid offset)" ;
PVShortPtr PVStructure::getShortField(string const &fieldName) throw std::runtime_error(ss.str());
{
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;
} }
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( PVField* PVStructure::getSubFieldImpl(const char *name, bool throws) const
string const &fieldName)
{ {
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( const PVFieldPtrArray& pvFields = parent->getPVFields();
string const &fieldName)
{ PVField *child = NULL;
return getSubField<PVUnionArray>(fieldName);
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 std::ostream& PVStructure::dumpValue(std::ostream& o) const
{ {
o << format::indent() << getStructure()->getID() << ' ' << getFieldName(); o << format::indent() << getStructure()->getID() << ' ' << getFieldName();
@@ -382,4 +354,79 @@ std::ostream& PVStructure::dumpValue(std::ostream& o) const
return o; 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 #define epicsExportSharedSymbols
#include <pv/pvData.h> #include <pv/pvData.h>
#include <pv/convert.h>
#include <pv/factory.h> #include <pv/factory.h>
#include <pv/serializeHelper.h> #include <pv/serializeHelper.h>
@@ -179,7 +178,7 @@ void PVStructureArray::deserialize(ByteBuffer *pbuffer,
data[i].reset(); data[i].reset();
} }
else { else {
if(data[i].get()==NULL) { if(data[i].get()==NULL || !data[i].unique()) {
data[i] = pvDataCreate->createPVStructure(structure); data[i] = pvDataCreate->createPVStructure(structure);
} }
data[i]->deserialize(pbuffer, pcontrol); 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 std::ostream& PVStructureArray::dumpValue(std::ostream& o, std::size_t index) const
{ {
const_svector temp(view()); const_svector temp(view());
if(index<temp.size()) if (index<temp.size())
o << *temp[index]; {
if (temp[index])
o << *temp[index];
else
o << format::indent() << "(none)" << std::endl;
}
return o; 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 #define epicsExportSharedSymbols
#include <pv/pvData.h> #include <pv/pvData.h>
#include <pv/pvIntrospect.h> #include <pv/pvIntrospect.h>
#include <pv/convert.h>
#include <pv/factory.h> #include <pv/factory.h>
#include <pv/serializeHelper.h> #include <pv/serializeHelper.h>
@@ -29,6 +28,8 @@ namespace epics { namespace pvData {
#define PVUNION_UNDEFINED_INDEX -1 #define PVUNION_UNDEFINED_INDEX -1
int32 PVUnion::UNDEFINED_INDEX = PVUNION_UNDEFINED_INDEX; int32 PVUnion::UNDEFINED_INDEX = PVUNION_UNDEFINED_INDEX;
PVDataCreatePtr PVUnion::pvDataCreate(getPVDataCreate());
PVUnion::PVUnion(UnionConstPtr const & unionPtr) PVUnion::PVUnion(UnionConstPtr const & unionPtr)
: PVField(unionPtr), : PVField(unionPtr),
unionPtr(unionPtr), unionPtr(unionPtr),
@@ -87,7 +88,7 @@ PVFieldPtr PVUnion::select(int32 index)
FieldConstPtr field = unionPtr->getField(index); FieldConstPtr field = unionPtr->getField(index);
selector = index; selector = index;
value = getPVDataCreate()->createPVField(field); value = pvDataCreate->createPVField(field);
return value; return value;
} }
@@ -171,7 +172,7 @@ void PVUnion::deserialize(ByteBuffer *pbuffer, DeserializableControl *pcontrol)
{ {
// try to reuse existing field instance // try to reuse existing field instance
if (!value.get() || *value->getField() != *field) if (!value.get() || *value->getField() != *field)
value = getPVDataCreate()->createPVField(field); value = pvDataCreate->createPVField(field);
value->deserialize(pbuffer, pcontrol); value->deserialize(pbuffer, pcontrol);
} }
else else
@@ -188,7 +189,7 @@ void PVUnion::deserialize(ByteBuffer *pbuffer, DeserializableControl *pcontrol)
FieldConstPtr field = unionPtr->getField(selector); FieldConstPtr field = unionPtr->getField(selector);
// try to reuse existing field instance // try to reuse existing field instance
if (!value.get() || *value->getField() != *field) if (!value.get() || *value->getField() != *field)
value = getPVDataCreate()->createPVField(field); value = pvDataCreate->createPVField(field);
} }
value->deserialize(pbuffer, pcontrol); value->deserialize(pbuffer, pcontrol);
} }
@@ -217,4 +218,57 @@ std::ostream& PVUnion::dumpValue(std::ostream& o) const
return o; 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 #define epicsExportSharedSymbols
#include <pv/pvData.h> #include <pv/pvData.h>
#include <pv/convert.h>
#include <pv/factory.h> #include <pv/factory.h>
#include <pv/serializeHelper.h> #include <pv/serializeHelper.h>
@@ -178,7 +177,7 @@ void PVUnionArray::deserialize(ByteBuffer *pbuffer,
data[i].reset(); data[i].reset();
} }
else { else {
if(data[i].get()==NULL) { if(data[i].get()==NULL || !data[i].unique()) {
data[i] = pvDataCreate->createPVUnion(punion); data[i] = pvDataCreate->createPVUnion(punion);
} }
data[i]->deserialize(pbuffer, pcontrol); 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 std::ostream& PVUnionArray::dumpValue(std::ostream& o, std::size_t index) const
{ {
const_svector temp(view()); const_svector temp(view());
if(index<temp.size()) if (index<temp.size())
o << *temp[index]; {
if (temp[index])
o << *temp[index];
else
o << format::indent() << "(none)" << std::endl;
}
return o; 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) { if(type==structure) {
StructureConstPtr structurePtr = static_pointer_cast<const Structure>(field); StructureConstPtr structurePtr = static_pointer_cast<const Structure>(field);
StringArray names = structurePtr->getFieldNames(); StringArray const & names = structurePtr->getFieldNames();
if(names.size()==2) { if(names.size()==2) {
FieldConstPtrArray fields = structurePtr->getFields(); FieldConstPtrArray const & fields = structurePtr->getFields();
FieldConstPtr first = fields[0]; FieldConstPtr first = fields[0];
FieldConstPtr second = fields[1]; FieldConstPtr second = fields[1];
string nameFirst = names[0]; string nameFirst = names[0];
@@ -554,7 +554,7 @@ StructureConstPtr StandardField::enumerated()
fields[0] = fieldCreate->createScalar(pvInt); fields[0] = fieldCreate->createScalar(pvInt);
fields[1] = fieldCreate->createScalarArray(pvString); fields[1] = fieldCreate->createScalarArray(pvString);
return fieldCreate->createStructure("enum_t",names,fields); return fieldCreate->createStructure("enum_t",names,fields);
// NOTE: if this method is used to get NTEnum wihtout properties the ID will be wrong! // NOTE: if this method is used to get NTEnum without properties the ID will be wrong!
} }
StructureConstPtr StandardField::enumerated(string const &properties) StructureConstPtr StandardField::enumerated(string const &properties)

View File

@@ -14,7 +14,6 @@
#include <pv/lock.h> #include <pv/lock.h>
#include <pv/pvIntrospect.h> #include <pv/pvIntrospect.h>
#include <pv/pvData.h> #include <pv/pvData.h>
#include <pv/convert.h>
#include <pv/standardField.h> #include <pv/standardField.h>
#include <pv/standardPVField.h> #include <pv/standardPVField.h>
@@ -67,11 +66,9 @@ PVStructurePtr StandardPVField::enumerated(StringArray const &choices)
{ {
StructureConstPtr field = standardField->enumerated(); StructureConstPtr field = standardField->enumerated();
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(field); PVStructurePtr pvStructure = pvDataCreate->createPVStructure(field);
PVScalarArrayPtr pvScalarArray = pvStructure->getScalarArrayField(
"choices",pvString);
PVStringArray::svector cdata(choices.size()); PVStringArray::svector cdata(choices.size());
std::copy(choices.begin(), choices.end(), cdata.begin()); std::copy(choices.begin(), choices.end(), cdata.begin());
static_cast<PVStringArray&>(*pvScalarArray).replace(freeze(cdata)); pvStructure->getSubField<PVStringArray>("choices")->replace(freeze(cdata));
return pvStructure; return pvStructure;
} }
@@ -80,11 +77,9 @@ PVStructurePtr StandardPVField::enumerated(
{ {
StructureConstPtr field = standardField->enumerated(properties); StructureConstPtr field = standardField->enumerated(properties);
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(field); PVStructurePtr pvStructure = pvDataCreate->createPVStructure(field);
PVScalarArrayPtr pvScalarArray = pvStructure->getScalarArrayField(
"value.choices",pvString);
PVStringArray::svector cdata(choices.size()); PVStringArray::svector cdata(choices.size());
std::copy(choices.begin(), choices.end(), cdata.begin()); 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; return pvStructure;
} }

View File

@@ -8,25 +8,22 @@
#include <deque> #include <deque>
#define epicsExportSharedSymbols #define epicsExportSharedSymbols
#include <pv/printer.h> #include <pv/pvIntrospect.h>
using std::string; using std::string;
namespace {
void indentN(std::ostream& strm, size_t N)
{
while(N--)
strm.put(' ');
}
}
namespace epics { namespace pvData { namespace epics { namespace pvData {
namespace format 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; indent_value(os) = indent.level;
return os; 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 += sharedPtr.h
INC += localStaticLock.h INC += localStaticLock.h
INC += typeCast.h INC += typeCast.h
INC += printer.h
INC += sharedVector.h INC += sharedVector.h
INC += templateMeta.h INC += templateMeta.h
INC += current_function.h INC += current_function.h

View File

@@ -24,16 +24,18 @@ namespace epics { namespace pvData {
typedef std::tr1::shared_ptr<BitSet> BitSetPtr; typedef std::tr1::shared_ptr<BitSet> BitSetPtr;
/** /**
* @brief A vector of bits.
*
* This class implements a vector of bits that grows as needed. Each * This class implements a vector of bits that grows as needed. Each
* component of the bit set has a {@code bool} value. The * component of the bit set has a @c bool value. The bits of a
* bits of a {@code BitSet} are indexed by nonnegative integers. * @c BitSet are indexed by nonnegative integers. Individual
* Individual indexed bits can be examined, set, or cleared. One * indexed bits can be examined, set, or cleared. One @c BitSet may
* {@code BitSet} may be used to modify the contents of another * be used to modify the contents of another @c BitSet through
* {@code BitSet} through logical AND, logical inclusive OR, and * logical AND, logical inclusive OR, and logical exclusive OR
* logical exclusive OR operations. * operations.
* *
* <p>By default, all bits in the set initially have the value * <p>By default, all bits in the set initially have the value
* {@code false}. * @c false.
* *
* <p>Every bit set has a current size, which is the number of bits * <p>Every bit set has a current size, which is the number of bits
* of space currently in use by the bit set. Note that the size is * of space currently in use by the bit set. Note that the size is
@@ -41,8 +43,8 @@ namespace epics { namespace pvData {
* implementation. The length of a bit set relates to logical length * implementation. The length of a bit set relates to logical length
* of a bit set and is defined independently of implementation. * of a bit set and is defined independently of implementation.
* *
* <p>A {@code BitSet} is not safe for multithreaded use without * <p>A @c BitSet is not safe for multithreaded use without external
* external synchronization. * synchronization.
* *
* Based on Java implementation. * Based on Java implementation.
*/ */
@@ -51,14 +53,14 @@ namespace epics { namespace pvData {
POINTER_DEFINITIONS(BitSet); POINTER_DEFINITIONS(BitSet);
static BitSetPtr create(uint32 nbits); static BitSetPtr create(uint32 nbits);
/** /**
* Creates a new bit set. All bits are initially {@code false}. * Creates a new bit set. All bits are initially @c false.
*/ */
BitSet(); BitSet();
/** /**
* Creates a bit set whose initial size is large enough to explicitly * Creates a bit set whose initial size is large enough to explicitly
* represent bits with indices in the range {@code 0} through * represent bits with indices in the range @c 0 through
* {@code nbits-1}. All bits are initially {@code false}. * @c nbits-1. All bits are initially @c false.
* *
* @param nbits the initial size of the bit set * @param nbits the initial size of the bit set
*/ */
@@ -78,14 +80,14 @@ namespace epics { namespace pvData {
void flip(uint32 bitIndex); void flip(uint32 bitIndex);
/** /**
* Sets the bit at the specified index to {@code true}. * Sets the bit at the specified index to @c true.
* *
* @param bitIndex a bit index * @param bitIndex a bit index
*/ */
void set(uint32 bitIndex); void set(uint32 bitIndex);
/** /**
* Sets the bit specified by the index to {@code false}. * Sets the bit specified by the index to @c false.
* *
* @param bitIndex the index of the bit to be cleared * @param bitIndex the index of the bit to be cleared
*/ */
@@ -101,9 +103,8 @@ namespace epics { namespace pvData {
/** /**
* Returns the value of the bit with the specified index. The value * Returns the value of the bit with the specified index. The value
* is {@code true} if the bit with the index {@code bitIndex} * is @c true if the bit with the index @c bitIndex is currently
* is currently set in this {@code BitSet}; otherwise, the result * set in this @c BitSet; otherwise, the result is @c false.
* is {@code false}.
* *
* @param bitIndex the bit index * @param bitIndex the bit index
* @return the value of the bit with the specified index * @return the value of the bit with the specified index
@@ -111,16 +112,16 @@ namespace epics { namespace pvData {
bool get(uint32 bitIndex) const; bool get(uint32 bitIndex) const;
/** /**
* Sets all of the bits in this BitSet to {@code false}. * Sets all of the bits in this BitSet to @c false.
*/ */
void clear(); void clear();
/** /**
* Returns the index of the first bit that is set to {@code true} * Returns the index of the first bit that is set to @c true that
* that occurs on or after the specified starting index. If no such * occurs on or after the specified starting index. If no such bit
* bit exists then {@code -1} is returned. * exists then @c -1 is returned.
* *
* <p>To iterate over the {@code true} bits in a {@code BitSet}, * <p>To iterate over the @c true bits in a @c BitSet,
* use the following loop: * use the following loop:
* *
* <pre> {@code * <pre> {@code
@@ -129,13 +130,13 @@ namespace epics { namespace pvData {
* }}</pre> * }}</pre>
* *
* @param fromIndex the index to start checking from (inclusive) * @param fromIndex the index to start checking from (inclusive)
* @return the index of the next set bit, or {@code -1} if there * @return the index of the next set bit, or @c -1 if there
* is no such bit * is no such bit
*/ */
int32 nextSetBit(uint32 fromIndex) const; int32 nextSetBit(uint32 fromIndex) const;
/** /**
* Returns the index of the first bit that is set to {@code false} * Returns the index of the first bit that is set to @c false
* that occurs on or after the specified starting index. * that occurs on or after the specified starting index.
* *
* @param fromIndex the index to start checking from (inclusive) * @param fromIndex the index to start checking from (inclusive)
@@ -144,23 +145,23 @@ namespace epics { namespace pvData {
int32 nextClearBit(uint32 fromIndex) const; int32 nextClearBit(uint32 fromIndex) const;
/** /**
* Returns true if this {@code BitSet} contains no bits that are set * Returns true if this @c BitSet contains no bits that are set
* to {@code true}. * to @c true.
* *
* @return indicating whether this {@code BitSet} is empty * @return indicating whether this @c BitSet is empty
*/ */
bool isEmpty() const; bool isEmpty() const;
/** /**
* Returns the number of bits set to {@code true} in this {@code BitSet}. * Returns the number of bits set to @c true in this @c BitSet.
* *
* @return the number of bits set to {@code true} in this {@code BitSet} * @return the number of bits set to @c true in this @c BitSet
*/ */
uint32 cardinality() const; uint32 cardinality() const;
/** /**
* Returns the number of bits of space actually in use by this * Returns the number of bits of space actually in use by this
* {@code BitSet} to represent bit values. * @c BitSet to represent bit values.
* The maximum element in the set is the size - 1st element. * The maximum element in the set is the size - 1st element.
* *
* @return the number of bits currently in this bit set * @return the number of bits currently in this bit set
@@ -170,9 +171,9 @@ namespace epics { namespace pvData {
/** /**
* Performs a logical <b>AND</b> of this target bit set with the * Performs a logical <b>AND</b> of this target bit set with the
* argument bit set. This bit set is modified so that each bit in it * argument bit set. This bit set is modified so that each bit in it
* has the value {@code true} if and only if it both initially * has the value @c true if and only if it both initially
* had the value {@code true} and the corresponding bit in the * had the value @c true and the corresponding bit in the
* bit set argument also had the value {@code true}. * bit set argument also had the value @c true.
* *
* @param set a bit set * @param set a bit set
*/ */
@@ -181,9 +182,9 @@ namespace epics { namespace pvData {
/** /**
* Performs a logical <b>OR</b> of this bit set with the bit set * Performs a logical <b>OR</b> of this bit set with the bit set
* argument. This bit set is modified so that a bit in it has the * argument. This bit set is modified so that a bit in it has the
* value {@code true} if and only if it either already had the * value @c true if and only if it either already had the
* value {@code true} or the corresponding bit in the bit set * value @c true or the corresponding bit in the bit set
* argument has the value {@code true}. * argument has the value @c true.
* *
* @param set a bit set * @param set a bit set
*/ */
@@ -192,13 +193,13 @@ namespace epics { namespace pvData {
/** /**
* Performs a logical <b>XOR</b> of this bit set with the bit set * Performs a logical <b>XOR</b> of this bit set with the bit set
* argument. This bit set is modified so that a bit in it has the * argument. This bit set is modified so that a bit in it has the
* value {@code true} if and only if one of the following * value @c true if and only if one of the following
* statements holds: * statements holds:
* <ul> * <ul>
* <li>The bit initially has the value {@code true}, and the * <li>The bit initially has the value @c true, and the
* corresponding bit in the argument has the value {@code false}. * corresponding bit in the argument has the value @c false.
* <li>The bit initially has the value {@code false}, and the * <li>The bit initially has the value @c false, and the
* corresponding bit in the argument has the value {@code true}. * corresponding bit in the argument has the value @c true.
* </ul> * </ul>
* *
* @param set a bit set * @param set a bit set
@@ -206,7 +207,7 @@ namespace epics { namespace pvData {
BitSet& operator^=(const BitSet& set); BitSet& operator^=(const BitSet& set);
/** /**
* Assigment operator. * Assignment operator.
*/ */
BitSet& operator=(const BitSet &set); BitSet& operator=(const BitSet &set);

View File

@@ -144,6 +144,24 @@ inline int64 swap(int64 val)
return swap64(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<> template<>
inline float swap(float val) inline float swap(float val)
{ {
@@ -188,8 +206,9 @@ inline double swap(double val)
#endif #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 *
* <p>A @c BitSet is not safe for multithreaded use without
* external synchronization. * external synchronization.
* *
* Based on Java implementation. * Based on Java implementation.
@@ -354,7 +373,7 @@ public:
template<typename T> template<typename T>
inline void put(std::size_t index, T value); inline void put(std::size_t index, T value);
/** /**
* Get the new object from the byte buffer. The item MUST have type {@code T}. * Get the new object from the byte buffer. The item MUST have type @c T.
* The position is adjusted based on the type. * The position is adjusted based on the type.
* *
* @return The object. * @return The object.
@@ -368,7 +387,7 @@ public:
#endif #endif
/** /**
* Get the new object from the byte buffer at the specified index. * Get the new object from the byte buffer at the specified index.
* The item MUST have type {@code T}. * The item MUST have type @c T.
* The position is adjusted based on the type. * The position is adjusted based on the type.
* *
* @param index The location in the byte buffer. * @param index The location in the byte buffer.
@@ -380,9 +399,9 @@ public:
* Put a sub-array of bytes into the byte buffer. * Put a sub-array of bytes into the byte buffer.
* The position is increased by the count. * The position is increased by the count.
* *
* @param src The source array. * @param src The source array.
* @param offset The starting position within src. * @param src_offset The starting position within src.
* @param count The number of bytes to put into the byte buffer, * @param count The number of bytes to put into the byte buffer,
*/ */
inline void put(const char* src, std::size_t src_offset, std::size_t count) { inline void put(const char* src, std::size_t src_offset, std::size_t count) {
//if(count>getRemaining()) THROW_BASE_EXCEPTION("buffer overflow"); //if(count>getRemaining()) THROW_BASE_EXCEPTION("buffer overflow");
@@ -393,9 +412,9 @@ public:
* Get a sub-array of bytes from the byte buffer. * Get a sub-array of bytes from the byte buffer.
* The position is increased by the count. * The position is increased by the count.
* *
* @param dest The destination array. * @param dest The destination array.
* @param offset The starting position within src. * @param dest_offset The starting position within src.
* @param count The number of bytes to put into the byte buffer, * @param count The number of bytes to put into the byte buffer.
*/ */
inline void get(char* dest, std::size_t dest_offset, std::size_t count) { inline void get(char* dest, std::size_t dest_offset, std::size_t count) {
//if(count>getRemaining()) THROW_BASE_EXCEPTION("buffer overflow"); //if(count>getRemaining()) THROW_BASE_EXCEPTION("buffer overflow");
@@ -403,7 +422,7 @@ public:
_position += count; _position += count;
} }
/** /**
* Put an array of type {@code T} into the byte buffer. * Put an array of type @c T into the byte buffer.
* The position is adjusted. * The position is adjusted.
* *
* @param values The input array. * @param values The input array.
@@ -412,7 +431,7 @@ public:
template<typename T> template<typename T>
inline void putArray(const T* values, std::size_t count); inline void putArray(const T* values, std::size_t count);
/** /**
* Get an array of type {@code T} from the byte buffer. * Get an array of type @c T from the byte buffer.
* The position is adjusted. * The position is adjusted.
* *
* @param values The destination array. * @param values The destination array.
@@ -618,7 +637,7 @@ public:
/** /**
* Get a boolean value from the byte buffer at the specified index. * Get a boolean value from the byte buffer at the specified index.
* *
* @param double The offset in the byte buffer. * @param index The offset in the byte buffer.
* @return The value. * @return The value.
*/ */
inline double getDouble (std::size_t index) { return get<double>(index); } inline double getDouble (std::size_t index) { return get<double>(index); }
@@ -695,7 +714,7 @@ private:
} }
else 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))) if (ADAPTIVE_ACCESS && is_aligned(_position, sizeof(T)))
{ {
*((T*)_position) = value; *((T*)_position) = value;
@@ -738,12 +757,12 @@ private:
if (UNALIGNED_ACCESS) 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; *((T*)(_buffer + index)) = value;
} }
else 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))) if (ADAPTIVE_ACCESS && is_aligned(_position, sizeof(T)))
{ {
*((T*)(_buffer + index)) = value; *((T*)(_buffer + index)) = value;
@@ -786,13 +805,13 @@ private:
if (UNALIGNED_ACCESS) 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); value = *((T*)_position);
_position += sizeof(T); _position += sizeof(T);
} }
else 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))) if (ADAPTIVE_ACCESS && is_aligned(_position, sizeof(T)))
{ {
value = *((T*)_position); value = *((T*)_position);
@@ -838,12 +857,12 @@ private:
if (UNALIGNED_ACCESS) 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)); value = *((T*)(_buffer + index));
} }
else 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))) if (ADAPTIVE_ACCESS && is_aligned(_position, sizeof(T)))
{ {
value = *((T*)(_buffer + index)); value = *((T*)(_buffer + index));
@@ -890,7 +909,7 @@ private:
memcpy(_position, values, n); memcpy(_position, values, n);
_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>()) if (ENDIANESS_SUPPORT && reverse<T>())
{ {
for (std::size_t i = 0; i < count; i++) for (std::size_t i = 0; i < count; i++)
@@ -918,7 +937,7 @@ private:
memcpy(values, _position, n); memcpy(values, _position, n);
_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>()) if (ENDIANESS_SUPPORT && reverse<T>())
{ {
for (std::size_t i = 0; i < count; i++) 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 * @author mse
*/ */
class epicsShareClass Destroyable { class epicsShareClass Destroyable {

View File

@@ -202,13 +202,26 @@ do { \
#define THROW_EXCEPTION2(E,A) do{throw (E)(A);}while(0) #define THROW_EXCEPTION2(E,A) do{throw (E)(A);}while(0)
#endif // THROW_EXCEPTION_COMPAT #endif // THROW_EXCEPTION_COMPAT
/**
* @brief Base for pvData exceptions.
*
*/
class epicsShareClass BaseException : public std::logic_error { class epicsShareClass BaseException : public std::logic_error {
public: public:
/**
* Constructor.
*/
explicit BaseException(const std::string msg) : std::logic_error(msg) {} explicit BaseException(const std::string msg) : std::logic_error(msg) {}
/**
* Destructor.
*/
virtual ~BaseException() throw(){}; virtual ~BaseException() throw(){};
/**
*
* Reason for excepton.
*/
virtual const char* what() const throw(); virtual const char* what() const throw();
private: private:

View File

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

View File

@@ -35,18 +35,44 @@ namespace epics { namespace pvData {
class Event; class Event;
typedef std::tr1::shared_ptr<Event> EventPtr; typedef std::tr1::shared_ptr<Event> EventPtr;
/**
* @brief C++ wrapper for epicsEvent from EPICS base.
*
*/
class epicsShareClass Event { class epicsShareClass Event {
public: public:
POINTER_DEFINITIONS(Event); POINTER_DEFINITIONS(Event);
/**
* Constructor
*/
explicit Event(bool = false); explicit Event(bool = false);
/**
* Destructor.
*/
~Event(); ~Event();
/**
* Signal the event i.e. ensures that the next or current call to wait completes.
*/
void signal(); void signal();
/**
* wait
* @return (false,true) if (some error, event signaled).
* The next wait or tryWait will clear signal.
*/
bool wait (); /* blocks until full */ 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 */ 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 */ bool tryWait (); /* false if empty */
private: private:
epicsEventId id; 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<Command> CommandPtr;
typedef std::tr1::shared_ptr<Executor> ExecutorPtr; typedef std::tr1::shared_ptr<Executor> ExecutorPtr;
/**
* @brief A command to be called by Executor
*
*/
class epicsShareClass Command { class epicsShareClass Command {
public: public:
POINTER_DEFINITIONS(Command); POINTER_DEFINITIONS(Command);
/**
*
* Destructor
*/
virtual ~Command(){} virtual ~Command(){}
/**
*
* The command that is executed.
*/
virtual void command() = 0; virtual void command() = 0;
private: private:
CommandPtr next; CommandPtr next;
friend class Executor; friend class Executor;
}; };
/**
* @brief A class that executes commands.
*
*/
class epicsShareClass Executor : public Runnable{ class epicsShareClass Executor : public Runnable{
public: public:
POINTER_DEFINITIONS(Executor); POINTER_DEFINITIONS(Executor);
/**
* Constructor
*
* @param threadName name for the executor thread.
* @param priority The thread priority.
*/
Executor(std::string const & threadName,ThreadPriority priority); Executor(std::string const & threadName,ThreadPriority priority);
/**
* Destructor
*/
~Executor(); ~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(); virtual void run();
private: private:
CommandPtr head; CommandPtr head;

View File

@@ -38,12 +38,30 @@ namespace epics { namespace pvData {
typedef epicsMutex Mutex; 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 { class epicsShareClass Lock : private NoDefaultMethods {
public: public:
/**
* Constructor
* @param m The mutex for the facility being locked.
*/
explicit Lock(Mutex &m) explicit Lock(Mutex &m)
: mutexPtr(m), locked(true) : mutexPtr(m), locked(true)
{ mutexPtr.lock();} { mutexPtr.lock();}
/**
* Destructor
* Note that destructor does an automatic unlock.
*/
~Lock(){unlock();} ~Lock(){unlock();}
/**
* Take the lock
* Recursive locks are supported but each lock must be matched with an unlock.
*/
void lock() void lock()
{ {
if(!locked) if(!locked)
@@ -52,6 +70,9 @@ public:
locked = true; locked = true;
} }
} }
/**
* release the lock.
*/
void unlock() void unlock()
{ {
if(locked) if(locked)
@@ -60,6 +81,10 @@ public:
locked=false; locked=false;
} }
} }
/**
* If lock is not held take the lock.
* @return (false,true) if caller (does not have, has) the lock.
*/
bool tryLock() bool tryLock()
{ {
if(locked) return true; if(locked) return true;
@@ -69,6 +94,10 @@ public:
} }
return false; return false;
} }
/**
* See if caller has the lock,
* @return (false,true) if caller (does not have, has) the lock.
*/
bool ownsLock() const{return locked;} bool ownsLock() const{return locked;}
private: private:
Mutex &mutexPtr; Mutex &mutexPtr;

View File

@@ -28,10 +28,26 @@ typedef std::tr1::shared_ptr<MessageNode> MessageNodePtr;
typedef std::vector<MessageNodePtr> MessageNodePtrArray; typedef std::vector<MessageNodePtr> MessageNodePtrArray;
typedef std::tr1::shared_ptr<MessageQueue> MessageQueuePtr; typedef std::tr1::shared_ptr<MessageQueue> MessageQueuePtr;
/**
* @brief A node that can be put on a MessageQueue.
*
*/
class epicsShareClass MessageNode { class epicsShareClass MessageNode {
public: public:
/**
* Constructor
*/
MessageNode(); MessageNode();
/**
*
* Get the message value.
* @return The message value.
*/
std::string getMessage() const; std::string getMessage() const;
/**
* Get the message type.
* @return The message type which is defined in Requester.
*/
MessageType getMessageType() const; MessageType getMessageType() const;
private: private:
std::string message; std::string message;
@@ -39,19 +55,65 @@ private:
friend class MessageQueue; friend class MessageQueue;
}; };
/**
* @brief A bounded queue for messages.
*
*
*/
class epicsShareClass MessageQueue : public Queue<MessageNode> { class epicsShareClass MessageQueue : public Queue<MessageNode> {
public: public:
POINTER_DEFINITIONS(MessageQueue); 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); static MessageQueuePtr create(int size);
/**
* Constructor
* @param nodeArray an array of shared_ptr to MessageNodes,
*/
MessageQueue(MessageNodePtrArray &nodeArray); MessageQueue(MessageNodePtrArray &nodeArray);
/**
* Destructor
*/
virtual ~MessageQueue(); 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(); MessageNodePtr &get();
// must call release before next get /**
* Release the MessageNode that was returned by the previous call to get.
*/
void release(); 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); bool put(std::string message,MessageType messageType,bool replaceLast);
/**
* Is queue empty?
* @return (false,true) if (is not, is) empty.
*/
bool isEmpty() ; bool isEmpty() ;
/**
* Is queue full?
* @return (false,true) if (is not, is) full.
*/
bool isFull() ; bool isFull() ;
/**
*
* Clear number of times queue was overrun and return the number
* of times the queue was overrun.
*/
int getClearOverrun(); int getClearOverrun();
private: private:
MessageNodePtr nullNode; MessageNodePtr nullNode;

View File

@@ -17,17 +17,26 @@ namespace epics { namespace pvData {
* Effective C++, Third Edition, Scott Meyers * Effective C++, Third Edition, Scott Meyers
*/ */
/**
class epicsShareClass NoDefaultMethods { * @brief Base class for not allowing default methods.
protected: *
// allow by derived objects * Note that copy constructor a copy methods are declared private.
*/
class epicsShareClass NoDefaultMethods {
protected:
/**
* Constructor
*/
NoDefaultMethods(){}; NoDefaultMethods(){};
/**
* Destructor
*/
~NoDefaultMethods(){} ~NoDefaultMethods(){}
private: private:
// do not implment // do not implement
NoDefaultMethods(const NoDefaultMethods&); NoDefaultMethods(const NoDefaultMethods&);
NoDefaultMethods & operator=(const NoDefaultMethods &); NoDefaultMethods & operator=(const NoDefaultMethods &);
}; };
}} }}
#endif /* NO_DEFAULT_METHODS_H */ #endif /* NO_DEFAULT_METHODS_H */

View File

@@ -308,6 +308,71 @@ noconvert:
return 0; 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 static
unsigned long long strtoull(const char *ptr, char ** endp, int base) unsigned long long strtoull(const char *ptr, char ** endp, int base)
{ {
@@ -350,7 +415,7 @@ noconvert:
*endp = (char*)ptr; *endp = (char*)ptr;
return 0; return 0;
} }
#endif
#endif #endif
/* do we need long long? */ /* do we need long long? */
@@ -486,6 +551,26 @@ void parseToPOD(const string& in, float *out) {
void parseToPOD(const string& in, double *out) { void parseToPOD(const string& in, double *out) {
int err = epicsParseDouble(in.c_str(), out, NULL); int err = epicsParseDouble(in.c_str(), out, NULL);
if(err) handleParseError(err); 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 { 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> template <typename T>
class Queue class Queue
{ {
@@ -25,15 +31,58 @@ public:
POINTER_DEFINITIONS(Queue); POINTER_DEFINITIONS(Queue);
typedef std::tr1::shared_ptr<T> queueElementPtr; typedef std::tr1::shared_ptr<T> queueElementPtr;
typedef std::vector<queueElementPtr> queueElementPtrArray; typedef std::vector<queueElementPtr> queueElementPtrArray;
Queue(queueElementPtrArray &); /**
* Constructor
* @param elementArray The vector of shared_ptr to queue elements.
*/
Queue(queueElementPtrArray & elementArray);
/**
* Destructor
*/
virtual ~Queue(); virtual ~Queue();
/**
* Clear the queue.
*/
void clear(); void clear();
/**
* get the capacity of the queue, i. e. number of queue elements,
* @return The capacity.
*/
int capacity(); int capacity();
/**
* Get the number of free elements in the queue.
* @return The number.
*/
int getNumberFree(); 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(); int getNumberUsed();
/**
* Get the next free element.
* @return a shared_ptr to the queue element.
* This is null if queue was full.
*/
queueElementPtr & getFree(); 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); 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(); queueElementPtr & getUsed();
/**
* Release the element obtained by the most recent call to getUsed.
* @param element The element.
*/
void releaseUsed(queueElementPtr const &element); void releaseUsed(queueElementPtr const &element);
private: private:
queueElementPtr nullElement; queueElementPtr nullElement;

View File

@@ -28,11 +28,43 @@ enum MessageType {
epicsShareExtern std::string getMessageTypeName(MessageType 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 { class epicsShareClass Requester {
public: public:
POINTER_DEFINITIONS(Requester); POINTER_DEFINITIONS(Requester);
/**
* Destructor
*/
virtual ~Requester(){} virtual ~Requester(){}
/**
* The requester must have a name.
* @return The requester's name.
*/
virtual std::string getRequesterName() = 0; 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; virtual void message(std::string const & message,MessageType messageType) = 0;
}; };

View File

@@ -25,52 +25,184 @@ namespace epics { namespace pvData {
class BitSet; class BitSet;
class Field; class Field;
/**
* @brief Callback class for serialization.
*
* This must be provided by code that calls serialize.
*/
class epicsShareClass SerializableControl { class epicsShareClass SerializableControl {
public: public:
/**
* Destructor.
*/
virtual ~SerializableControl(){} virtual ~SerializableControl(){}
/**
* Done with this buffer. Flush it.
*/
virtual void flushSerializeBuffer() =0; 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; 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 void alignBuffer(std::size_t alignment) =0;
virtual bool directSerialize(ByteBuffer *existingBuffer, const char* toSerialize, /**
std::size_t elementCount, std::size_t elementSize) = 0; * method for serializing array data.
virtual void cachedSerialize(std::tr1::shared_ptr<const Field> const & field, ByteBuffer* buffer) = 0; * 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 { class epicsShareClass DeserializableControl {
public: public:
/**
* Destructor.
*/
virtual ~DeserializableControl(){} 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; 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 void alignData(std::size_t alignment) =0;
virtual bool directDeserialize(ByteBuffer *existingBuffer, char* deserializeTo, /**
std::size_t elementCount, std::size_t elementSize) = 0; * method for deserializing array data.
virtual std::tr1::shared_ptr<const Field> cachedDeserialize(ByteBuffer* buffer) = 0; * This should only be used for arrays of primitive types.
* i. e. boolean,byte,...,double.
* It can not be called for string, structure, or union arrays.
* @param existingBuffer the existing buffer from the caller.
* @param deserializeTo location of data.
* @param elementCount number of elements.
* @param elementSize element size.
*/
virtual bool directDeserialize(
ByteBuffer *existingBuffer,
char* deserializeTo,
std::size_t elementCount,
std::size_t elementSize) = 0;
/**
* deserialize via cache
* @param buffer buffer to be deserialized from
*/
virtual std::tr1::shared_ptr<const Field> cachedDeserialize(
ByteBuffer* buffer) = 0;
}; };
/**
* @brief Base class for serialization.
*
*/
class epicsShareClass Serializable { class epicsShareClass Serializable {
public: public:
/**
* Destructor.
*/
virtual ~Serializable(){} virtual ~Serializable(){}
/**
* Serialize field into given buffer.
* @param buffer serialization buffer.
* @param flusher flush interface.
*/
virtual void serialize(ByteBuffer *buffer, virtual void serialize(ByteBuffer *buffer,
SerializableControl *flusher) const = 0; SerializableControl *flusher) const = 0;
/**
* Deserialize buffer.
* @param buffer serialization buffer.
* @param flusher deserialization control.
*/
virtual void deserialize(ByteBuffer *buffer, virtual void deserialize(ByteBuffer *buffer,
DeserializableControl *flusher) = 0; DeserializableControl *flusher) = 0;
}; };
/**
* @brief Class for serializing bitSets.
*
*/
class epicsShareClass BitSetSerializable { class epicsShareClass BitSetSerializable {
public: public:
/**
* Destructor.
*/
virtual ~BitSetSerializable(){} 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, virtual void serialize(ByteBuffer *buffer,
SerializableControl *flusher,BitSet *bitSet) const = 0; 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, virtual void deserialize(ByteBuffer *buffer,
DeserializableControl *flusher,BitSet *bitSet) = 0; DeserializableControl *flusher,BitSet *bitSet) = 0;
}; };
/**
* @brief Class for serializing arrays.
*
*/
class epicsShareClass SerializableArray : public virtual Serializable { class epicsShareClass SerializableArray : public virtual Serializable {
public: public:
/**
* Destructor.
*/
virtual ~SerializableArray(){} virtual ~SerializableArray(){}
using Serializable::serialize; 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 * serializeHelper.cpp
* *
* Created on: Oct 22, 2010 * Created on: Oct 22, 2010
* Author: Miha vitorovic * Author: Miha Vitorovic
*/ */
#include <algorithm> #include <algorithm>

View File

@@ -23,23 +23,33 @@
namespace epics { namespace epics {
namespace pvData { namespace pvData {
/**
* @brief Serialization helper.
*
*/
class epicsShareClass SerializeHelper : public NoDefaultMethods { class epicsShareClass SerializeHelper : public NoDefaultMethods {
public: public:
/** /**
* Serialize array size. * Serialize the specified array size into the specified
* buffer, flushing when necessary.
* The specified SerializableControl manages any flushing
* required.
* *
* @param[in] s size to encode * @param[in] s size to encode
* @param[in] buffer serialization buffer * @param[in] buffer serialization buffer
* @param[in] flusher flusher * @param[in] flusher SerializableControl to manage the flushing
*/ */
static void writeSize(std::size_t s, ByteBuffer* buffer, static void writeSize(std::size_t s, ByteBuffer* buffer,
SerializableControl* flusher); SerializableControl* flusher);
/** /**
* Deserialize array size. * Deserialize array size.
* The specified DeserializableControl ensures
* sufficient bytes are available.
* *
* @param[in] buffer deserialization buffer. * @param[in] buffer deserialization buffer.
* @param[in] control the DeserializableControl.
* @returns array size. * @returns array size.
*/ */
static std::size_t readSize(ByteBuffer* buffer, static std::size_t readSize(ByteBuffer* buffer,
@@ -59,7 +69,7 @@ namespace epics {
* std::string serialization helper method. * std::string serialization helper method.
* *
* @param[in] value std::string to serialize * @param[in] value std::string to serialize
* @param[in] offset start of the substring in {@code value} * @param[in] offset start of the substring in value
* @param[in] count the number of characters to write * @param[in] count the number of characters to write
* @param[in] buffer serialization buffer * @param[in] buffer serialization buffer
* @param[in] flusher flusher * @param[in] flusher flusher

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. * Data is shared, but offset and length are not.
* This allows one vector to have access to only a * This allows one vector to have access to only a
@@ -427,7 +427,7 @@ public:
* owner of the data array. * owner of the data array.
* *
* If a copy is needed, memory is allocated with new[]. If this is * 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 @code
shared_vector<E> original(...); shared_vector<E> original(...);
@@ -527,9 +527,12 @@ public:
}; };
//! Specialization for storing untyped pointers /**
//! Does not allow access or iteration of contents * @brief Specialization for storing untyped pointers.
//! other than as void* or const void* *
* Does not allow access or iteration of contents
* other than as void* or const void*
*/
template<typename E> template<typename E>
class shared_vector<E, typename meta::is_void<E>::type > class shared_vector<E, typename meta::is_void<E>::type >
: public detail::shared_vector_base<E> : 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 * The copy constructor and assignment operator allow implicit
* casting from type 'shared_vector<T>' to 'shared_vector<const T>'. * 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. * make_unique() are provided.
* *
* The slice() method selects a sub-set of the shared_vector. * The slice() method selects a sub-set of the shared_vector.

View File

@@ -21,7 +21,9 @@
namespace epics { namespace pvData { namespace epics { namespace pvData {
/** /**
* Status. * @brief Status.
*
* This is a class for returning status to clients.
* @author mse * @author mse
*/ */
class epicsShareClass Status : public epics::pvData::Serializable { class epicsShareClass Status : public epics::pvData::Serializable {

View File

@@ -47,9 +47,28 @@ typedef std::tr1::shared_ptr<epicsThread> EpicsThreadPtr;
typedef epicsThreadRunable Runnable; typedef epicsThreadRunable Runnable;
/**
* @brief C++ wrapper for epicsThread from EPICS base.
*
*/
class epicsShareClass Thread : public epicsThread, private NoDefaultMethods { class epicsShareClass Thread : public epicsThread, private NoDefaultMethods {
public: 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, Thread(std::string name,
ThreadPriority priority, ThreadPriority priority,
Runnable *runnable, Runnable *runnable,
@@ -62,6 +81,21 @@ public:
this->start(); 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, Thread(Runnable &runnable,
std::string name, std::string name,
unsigned int stksize, unsigned int stksize,
@@ -74,6 +108,9 @@ public:
this->start(); this->start();
} }
/**
* Destructor
*/
~Thread() ~Thread()
{ {
this->exitWait(); this->exitWait();

View File

@@ -21,19 +21,46 @@ class TimeFunction;
typedef std::tr1::shared_ptr<TimeFunctionRequester> TimeFunctionRequesterPtr; typedef std::tr1::shared_ptr<TimeFunctionRequester> TimeFunctionRequesterPtr;
typedef std::tr1::shared_ptr<TimeFunction> TimeFunctionPtr; typedef std::tr1::shared_ptr<TimeFunction> TimeFunctionPtr;
/**
* @brief Class that must be implemented by timeFunction requester.
*
*/
class epicsShareClass TimeFunctionRequester { class epicsShareClass TimeFunctionRequester {
public: public:
POINTER_DEFINITIONS(TimeFunctionRequester); POINTER_DEFINITIONS(TimeFunctionRequester);
/**
* Destructor
*/
virtual ~TimeFunctionRequester(){} virtual ~TimeFunctionRequester(){}
/**
* function to be timed.
* It will get called multiple times.
*/
virtual void function() = 0; virtual void function() = 0;
}; };
/**
* @brief Class for measuring time it takes to execute a function.
*
*/
class epicsShareClass TimeFunction { class epicsShareClass TimeFunction {
public: public:
POINTER_DEFINITIONS(TimeFunction); POINTER_DEFINITIONS(TimeFunction);
/**
* Constructor
* @param requester The class that has a function method.
*/
TimeFunction(TimeFunctionRequesterPtr const & requester); TimeFunction(TimeFunctionRequesterPtr const & requester);
/**
* Destructor
*/
~TimeFunction(); ~TimeFunction();
/**
* Time the function.
* @return the time in seconds to execute the function.
* Note that the function may be called many times.
*/
double timeCall(); double timeCall();
private: private:
TimeFunctionRequesterPtr requester; TimeFunctionRequesterPtr requester;

View File

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

View File

@@ -32,12 +32,28 @@ class Timer;
typedef std::tr1::shared_ptr<TimerCallback> TimerCallbackPtr; typedef std::tr1::shared_ptr<TimerCallback> TimerCallbackPtr;
typedef std::tr1::shared_ptr<Timer> TimerPtr; typedef std::tr1::shared_ptr<Timer> TimerPtr;
/**
* @brief Class that must be implemented by code that makes Timer requests.
*
*/
class epicsShareClass TimerCallback { class epicsShareClass TimerCallback {
public: public:
POINTER_DEFINITIONS(TimerCallback); POINTER_DEFINITIONS(TimerCallback);
/**
* Constructor
*/
TimerCallback(); TimerCallback();
/**
* Destructor
*/
virtual ~TimerCallback(){} virtual ~TimerCallback(){}
/**
* The method that is called when a timer expires.
*/
virtual void callback() = 0; virtual void callback() = 0;
/**
* The timer has stopped.
*/
virtual void timerStopped() = 0; virtual void timerStopped() = 0;
private: private:
TimerCallbackPtr next; TimerCallbackPtr next;
@@ -47,22 +63,60 @@ private:
friend class Timer; friend class Timer;
}; };
/**
* @brief Support for delayed or periodic callback execution.
*
*/
class epicsShareClass Timer : public Runnable { class epicsShareClass Timer : public Runnable {
public: public:
POINTER_DEFINITIONS(Timer); POINTER_DEFINITIONS(Timer);
/**
* Constructor
* @param threadName name for the timer thread.
* @param priority thread priority
*/
Timer(std::string threadName, ThreadPriority priority); Timer(std::string threadName, ThreadPriority priority);
/**
* Destructor
*/
virtual ~Timer(); virtual ~Timer();
/**
* The thread run method. This is called automatically.
*/
virtual void run(); virtual void run();
/**
* schedule a callback after a delay.
* @param timerCallback the timerCallback instance.
* @param delay number of seconds before calling callback.
*/
void scheduleAfterDelay( void scheduleAfterDelay(
TimerCallbackPtr const &timerCallback, TimerCallbackPtr const &timerCallback,
double delay); 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( void schedulePeriodic(
TimerCallbackPtr const &timerCallback, TimerCallbackPtr const &timerCallback,
double delay, double delay,
double period); double period);
/**
* cancel a callback.
* @param timerCallback the timerCallback to cancel.
*/
void cancel(TimerCallbackPtr const &timerCallback); 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); bool isScheduled(TimerCallbackPtr const &timerCallback);
/**
* show the elements in the timer queue.
* @param o The output stream for the output
*/
void dump(std::ostream& o); void dump(std::ostream& o);
private: private:

View File

@@ -59,7 +59,7 @@ namespace detail {
typedef T return_t; typedef T return_t;
static FORCE_INLINE return_t op(const T& i) { return i; } 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 // by promoting char to int
template<> template<>
struct print_convolute<int8> { struct print_convolute<int8> {
@@ -142,7 +142,7 @@ namespace detail {
* - float -> double * - float -> double
* *
* Conversions where out of range inputs always produce * 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 * - double -> float. When abs(value) is outside the range
* [FLT_MIN, FLT_MAX] the value is clipped to FLT_MIN or FLT_MAX * [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. * Class instance representing monitor element.
* @author mrk * @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 * @author mrk
*/ */
class epicsShareClass Monitor : public Destroyable{ class epicsShareClass Monitor : public Destroyable{
@@ -73,6 +77,7 @@ class epicsShareClass Monitor : public Destroyable{
virtual MonitorElementPtr poll() = 0; virtual MonitorElementPtr poll() = 0;
/** /**
* Release a MonitorElement that was returned by poll. * 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 * @param monitorElement
*/ */
virtual void release(MonitorElementPtr const & monitorElement) = 0; 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. * Requester for ChannelMonitor.
* @author mrk * @author mrk
*/ */

View File

@@ -20,32 +20,25 @@
namespace epics { namespace pvData { namespace epics { namespace pvData {
/**
* typedef for a pointer to a MonitorPlugin
*/
class MonitorPlugin; class MonitorPlugin;
typedef std::tr1::shared_ptr<MonitorPlugin> MonitorPluginPtr; typedef std::tr1::shared_ptr<MonitorPlugin> MonitorPluginPtr;
/**
* typedef for a pointer to a MonitorPluginCreator
*/
class MonitorPluginCreator; class MonitorPluginCreator;
typedef std::tr1::shared_ptr<MonitorPluginCreator> MonitorPluginCreatorPtr; typedef std::tr1::shared_ptr<MonitorPluginCreator> MonitorPluginCreatorPtr;
/**
* typedef for a pointer to a MonitorPluginManager
*/
class MonitorPluginManager; class MonitorPluginManager;
typedef std::tr1::shared_ptr<MonitorPluginManager> MonitorPluginManagerPtr; 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. * This is for use by pvAccess servers that support monitors.
* Since the interface has only a dependence on pvData it * Since the interface has only a dependence on pvData it
* can be used for other purposes. * 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. * structure.
*/ */
class epicsShareClass MonitorPlugin class epicsShareClass MonitorPlugin
@@ -60,8 +53,8 @@ public:
/** /**
* Should a monitor be raised? * Should a monitor be raised?
* @param pvField The field being monitored. * @param pvField The field being monitored.
* @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 client data and bitSets. * @param monitorElement The client data and bitsets.
* @returns true or false. * @returns true or false.
* True is returned if the change to this field should cause a monitor. * 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 * False is returned in a change only to this field should not cause a
@@ -73,9 +66,6 @@ public:
MonitorElementPtr const &monitorElement) = 0; MonitorElementPtr const &monitorElement) = 0;
/** /**
* A monitor will be sent to the client. * A monitor will be sent to the client.
* @param pvField The copy of the field being monitored.
* The plugin can modify the data.
* @param pvTop The top level sructure in which the field resides.
* @param monitorElement The data for the client. * @param monitorElement The data for the client.
* The plugin is allowed to change the data values. * The plugin is allowed to change the data values.
*/ */
@@ -100,7 +90,9 @@ public:
virtual void endGroupPut() {}; 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. * Normlly a plugin is created for a single client.
*/ */
class epicsShareClass MonitorPluginCreator class epicsShareClass MonitorPluginCreator
@@ -110,7 +102,7 @@ public:
/** /**
* Create a monitor plugin. * Create a monitor plugin.
* @param field The introspection interface for the field monitored. * @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. * @param pvFieldOptions The options the client requested.
* The structure has a set of PVString subfields. * The structure has a set of PVString subfields.
* The options are a set of name,value pairs. * The options are a set of name,value pairs.
@@ -130,6 +122,8 @@ public:
/** /**
* @brief Manager for plugins.
*
* This manages a set of monitor plugins. * This manages a set of monitor plugins.
* @author mrk * @author mrk
*/ */

View File

@@ -18,37 +18,129 @@
namespace epics { namespace pvData { namespace epics { namespace pvData {
/** @brief enum definition of AlarmSeverity
*
* AlarmSeverity is:
@code
enum AlarmSeverity {
noAlarm,minorAlarm,majorAlarm,invalidAlarm,undefinedAlarm
};
@endcode
*
*/
enum AlarmSeverity { enum AlarmSeverity {
noAlarm,minorAlarm,majorAlarm,invalidAlarm,undefinedAlarm 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 { enum AlarmStatus {
noStatus,deviceStatus,driverStatus,recordStatus, noStatus,deviceStatus,driverStatus,recordStatus,
dbStatus,confStatus,undefinedStatus,clientStatus dbStatus,confStatus,undefinedStatus,clientStatus
}; };
/** @brief methods for AlarmSeverity
*
*/
class epicsShareClass AlarmSeverityFunc { class epicsShareClass AlarmSeverityFunc {
public: 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); static AlarmSeverity getSeverity(int value);
/**
* Get the array of severity names.
* @return The array of severity names.
*/
static StringArrayPtr getSeverityNames(); static StringArrayPtr getSeverityNames();
}; };
/** @brief methods for AlarmStatus
*
*/
class epicsShareClass AlarmStatusFunc { class epicsShareClass AlarmStatusFunc {
public: 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); static AlarmStatus getStatus(int value);
/**
* Get the array of status names.
* @return The array of status names.
*/
static StringArrayPtr getStatusNames(); 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 { class epicsShareClass Alarm {
public: public:
/**
* Constructor
*/
Alarm() : severity(0),status(0), message(std::string("")) {} Alarm() : severity(0),status(0), message(std::string("")) {}
//default constructors and destructor are OK //default constructors and destructor are OK
/**
* get the current message.
* @return The message.
*/
std::string getMessage() const {return 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;} void setMessage(std::string const &value) {message = value;}
/**
* get the current severity.
* @return The severity.
*/
AlarmSeverity getSeverity() const; 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;} void setSeverity(AlarmSeverity value) {severity = value;}
/**
* get the current status.
* @return The status.
*/
AlarmStatus getStatus() const; 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;} void setStatus(AlarmStatus value) { status = value;}
private: private:
int32 severity; int32 severity;

View File

@@ -14,15 +14,58 @@
namespace epics { namespace pvData { 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 { class epicsShareClass Control {
public: public:
/**
* Constructor
*/
Control() : low(0.0), high(0.0), minStep(0.0) {} Control() : low(0.0), high(0.0), minStep(0.0) {}
//default constructors and destructor are OK //default constructors and destructor are OK
/**
* get limitLow
* @return the current value.
*/
double getLow() const {return low;} double getLow() const {return low;}
/**
* get limitHigh
* @return the current value.
*/
double getHigh() const {return high;} double getHigh() const {return high;}
/**
* get minStep
* @return the current value.
*/
double getMinStep() const {return minStep;} double getMinStep() const {return minStep;}
/**
* set limitLow
* @param value The new value.
*/
void setLow(double value) {low = value;} void setLow(double value) {low = value;}
/**
* set limitHigh
* @param value The new value.
*/
void setHigh(double value) {high = value;} void setHigh(double value) {high = value;}
/**
* set minStep
* @param value The new value.
*/
void setMinStep(double value) {minStep = value;} void setMinStep(double value) {minStep = value;}
private: private:
double low; double low;

View File

@@ -19,21 +19,83 @@
namespace epics { namespace pvData { 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 { class epicsShareClass Display {
public: public:
/**
* Constructor
*/
Display() Display()
: description(std::string("")),format(std::string("")),units(std::string("")), : description(std::string("")),format(std::string("")),units(std::string("")),
low(0.0),high(0.0) {} low(0.0),high(0.0) {}
//default constructors and destructor are OK //default constructors and destructor are OK
/**
* Get the current value of limitLow.
* @return The current value.
*/
double getLow() const {return low;} double getLow() const {return low;}
/**
* Get the current value of limitHigh.
* @return The current value.
*/
double getHigh() const{ return high;} double getHigh() const{ return high;}
/**
* Set limitLow to a new value.
* @param value The value.
*/
void setLow(double value){low = value;} void setLow(double value){low = value;}
/**
* Set limitHigh to a new value.
* @param value The value.
*/
void setHigh(double value){high = value;} void setHigh(double value){high = value;}
/**
* Get the current value of description.
* @return The current value.
*/
std::string getDescription() const {return description;} std::string getDescription() const {return description;}
/**
* Set description to a new value.
* @param value The value.
*/
void setDescription(std::string const & value) {description = 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;} 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;} void setFormat(std::string const & value) {format = value;}
/**
* Get the current value of units.
* @return The current value.
*/
std::string getUnits() const {return units;} std::string getUnits() const {return units;}
/**
* Set units to a new value.
* @param value The value.
*/
void setUnits(std::string const & value) {units = value;} void setUnits(std::string const & value) {units = value;}
private: private:
std::string description; std::string description;

View File

@@ -28,14 +28,14 @@ bool PVAlarm::attach(PVFieldPtr const & pvField)
{ {
if(pvField->getField()->getType()!=structure) return false; if(pvField->getField()->getType()!=structure) return false;
PVStructurePtr pvStructure = static_pointer_cast<PVStructure>(pvField); PVStructurePtr pvStructure = static_pointer_cast<PVStructure>(pvField);
pvSeverity = pvStructure->getIntField("severity"); pvSeverity = pvStructure->getSubField<PVInt>("severity");
if(pvSeverity.get()==NULL) return false; if(pvSeverity.get()==NULL) return false;
pvStatus = pvStructure->getIntField("status"); pvStatus = pvStructure->getSubField<PVInt>("status");
if(pvStatus.get()==NULL) { if(pvStatus.get()==NULL) {
pvSeverity.reset(); pvSeverity.reset();
return false; return false;
} }
pvMessage = pvStructure->getStringField("message"); pvMessage = pvStructure->getSubField<PVString>("message");
if(pvMessage.get()==NULL) { if(pvMessage.get()==NULL) {
pvSeverity.reset(); pvSeverity.reset();
pvStatus.reset(); pvStatus.reset();

View File

@@ -20,18 +20,65 @@
namespace epics { namespace pvData { 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 { class epicsShareClass PVAlarm {
public: public:
/**
*
* Constructor
*/
PVAlarm() {} PVAlarm() {}
//default constructors and destructor are OK //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. //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); bool attach(PVFieldPtr const & pvField);
/**
* Detach for pvField.
*/
void detach(); void detach();
/**
* Is the PVAlarm attached to a pvField?
* @return (false,true) (is not,is) attached to a pvField.
*/
bool isAttached(); bool isAttached();
// each of the following throws logic_error is not attached to PVField // each of the following throws logic_error is not attached to PVField
// set returns false if field is immutable // 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; 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); bool set(Alarm const & alarm);
private: private:
PVIntPtr pvSeverity; PVIntPtr pvSeverity;

View File

@@ -28,14 +28,14 @@ bool PVControl::attach(PVFieldPtr const & pvField)
{ {
if(pvField->getField()->getType()!=structure) return false; if(pvField->getField()->getType()!=structure) return false;
PVStructurePtr pvStructure = static_pointer_cast<PVStructure>(pvField); PVStructurePtr pvStructure = static_pointer_cast<PVStructure>(pvField);
pvLow = pvStructure->getDoubleField("limitLow"); pvLow = pvStructure->getSubField<PVDouble>("limitLow");
if(pvLow.get()==NULL) return false; if(pvLow.get()==NULL) return false;
pvHigh = pvStructure->getDoubleField("limitHigh"); pvHigh = pvStructure->getSubField<PVDouble>("limitHigh");
if(pvHigh.get()==NULL) { if(pvHigh.get()==NULL) {
pvLow.reset(); pvLow.reset();
return false; return false;
} }
pvMinStep = pvStructure->getDoubleField("minStep"); pvMinStep = pvStructure->getSubField<PVDouble>("minStep");
if(pvMinStep.get()==NULL) { if(pvMinStep.get()==NULL) {
pvLow.reset(); pvLow.reset();
pvHigh.reset(); pvHigh.reset();

View File

@@ -17,18 +17,60 @@
namespace epics { namespace pvData { 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 { class epicsShareClass PVControl {
public: public:
/**
*
* Constructor
*/
PVControl(){} PVControl(){}
//default constructors and destructor are OK //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. //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); bool attach(PVFieldPtr const & pvField);
/**
* Detach for pvField.
*/
void detach(); void detach();
/**
* Is the PVControl attached to a pvField?
* @return (false,true) (is not,is) attached to a pvField.
*/
bool isAttached(); 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 // 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); bool set(Control const & control);
private: private:
PVDoublePtr pvLow; PVDoublePtr pvLow;

View File

@@ -28,24 +28,24 @@ bool PVDisplay::attach(PVFieldPtr const & pvField)
{ {
if(pvField->getField()->getType()!=structure) return false; if(pvField->getField()->getType()!=structure) return false;
PVStructurePtr pvStructure = static_pointer_cast<PVStructure>(pvField); PVStructurePtr pvStructure = static_pointer_cast<PVStructure>(pvField);
pvDescription = pvStructure->getStringField("description"); pvDescription = pvStructure->getSubField<PVString>("description");
if(pvDescription.get()==NULL) return false; if(pvDescription.get()==NULL) return false;
pvFormat = pvStructure->getStringField("format"); pvFormat = pvStructure->getSubField<PVString>("format");
if(pvFormat.get()==NULL) { if(pvFormat.get()==NULL) {
detach(); detach();
return false; return false;
} }
pvUnits = pvStructure->getStringField("units"); pvUnits = pvStructure->getSubField<PVString>("units");
if(pvUnits.get()==NULL) { if(pvUnits.get()==NULL) {
detach(); detach();
return false; return false;
} }
pvLow = pvStructure->getDoubleField(string("limitLow")); pvLow = pvStructure->getSubField<PVDouble>(string("limitLow"));
if(pvLow.get()==NULL) { if(pvLow.get()==NULL) {
detach(); detach();
return false; return false;
} }
pvHigh = pvStructure->getDoubleField(string("limitHigh")); pvHigh = pvStructure->getSubField<PVDouble>(string("limitHigh"));
if(pvHigh.get()==NULL) { if(pvHigh.get()==NULL) {
detach(); detach();
return false; return false;

View File

@@ -20,17 +20,61 @@
namespace epics { namespace pvData { 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 { class epicsShareClass PVDisplay {
public: public:
/**
*
* Constructor
*/
PVDisplay() {} PVDisplay() {}
//default constructors and destructor are OK //default constructors and destructor are OK
//An automatic detach is issued if already attached. //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); bool attach(PVFieldPtr const & pvField);
/**
* Detach for pvField.
*/
void detach(); void detach();
/**
* Is the PVDisplay attached to a pvField?
* @return (false,true) (is not,is) attached to a pvField.
*/
bool isAttached(); 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 // 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); bool set(Display const & display);
private: private:
static std::string noDisplayFound; static std::string noDisplayFound;

View File

@@ -28,15 +28,14 @@ bool PVEnumerated::attach(PVFieldPtr const & pvField)
{ {
if(pvField->getField()->getType()!=structure) return false; if(pvField->getField()->getType()!=structure) return false;
PVStructurePtr pvStructure = static_pointer_cast<PVStructure>(pvField); PVStructurePtr pvStructure = static_pointer_cast<PVStructure>(pvField);
pvIndex = pvStructure->getIntField("index"); pvIndex = pvStructure->getSubField<PVInt>("index");
if(pvIndex.get()==NULL) return false; if(pvIndex.get()==NULL) return false;
PVScalarArrayPtr pvScalarArray = pvStructure->getScalarArrayField( PVStringArrayPtr pvStringArray = pvStructure->getSubField<PVStringArray>("choices");
"choices",pvString); if(pvStringArray.get()==NULL) {
if(pvScalarArray.get()==NULL) {
pvIndex.reset(); pvIndex.reset();
return false; return false;
} }
pvChoices = static_pointer_cast<PVStringArray>(pvScalarArray); pvChoices = pvStringArray;
return true; return true;
} }
@@ -74,8 +73,12 @@ string PVEnumerated::getChoice()
if(pvIndex.get()==NULL ) { if(pvIndex.get()==NULL ) {
throw std::logic_error(notAttached); throw std::logic_error(notAttached);
} }
int index = pvIndex->get(); size_t index = pvIndex->get();
const PVStringArray::const_svector& data(pvChoices->view()); const PVStringArray::const_svector& data(pvChoices->view());
if(/*index<0 ||*/ index>=data.size()) {
string nullString;
return nullString;
}
return data[index]; return data[index];
} }

View File

@@ -19,24 +19,89 @@
namespace epics { namespace pvData { 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 { class epicsShareClass PVEnumerated {
public: public:
/*
* Constructor.
*/
PVEnumerated() {} PVEnumerated() {}
//default constructors and destructor are OK //default constructors and destructor are OK
//This class should not be extended //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. //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); bool attach(PVFieldPtr const & pvField);
/**
* Detach for pvField.
*/
void detach(); void detach();
/**
* Is the PVEnumerated attached to a pvField?
* @return (false,true) (is not,is) attached to a pvField.
*/
bool isAttached(); bool isAttached();
// each of the following throws logic_error is not attached to PVField // each of the following throws logic_error is not attached to PVField
// a set returns false if field is immutable // 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); bool setIndex(int32 index);
/**
* Get the index.
* @return The current index.
* @throw if not attached.
*/
int32 getIndex(); 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(); std::string getChoice();
/**
* Can choices be changed?
* @return (false,true) if choices (can not, can) be changed.
* @throw if not attached.
*/
bool choicesMutable(); bool choicesMutable();
/**
* Get the choices.
* @return The current index.
* @throw if not attached.
*/
inline PVStringArray::const_svector getChoices(){return pvChoices->view();} inline PVStringArray::const_svector getChoices(){return pvChoices->view();}
/**
* Get the size of the choices array.
* @return The size.
* @throw if not attached.
*/
int32 getNumberChoices(); 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); bool setChoices(const StringArray & choices);
private: private:
static std::string notFound; static std::string notFound;

View File

@@ -30,11 +30,11 @@ bool PVTimeStamp::attach(PVFieldPtr const & pvField)
PVStructurePtr xxx = static_pointer_cast<PVStructure>(pvField); PVStructurePtr xxx = static_pointer_cast<PVStructure>(pvField);
PVStructure* pvStructure = xxx.get(); PVStructure* pvStructure = xxx.get();
while(true) { while(true) {
PVLongPtr pvLong = pvStructure->getLongField("secondsPastEpoch"); PVLongPtr pvLong = pvStructure->getSubField<PVLong>("secondsPastEpoch");
if(pvLong.get()!=NULL) { if(pvLong.get()!=NULL) {
pvSecs = pvLong; pvSecs = pvLong;
pvNano = pvStructure->getIntField("nanoseconds"); pvNano = pvStructure->getSubField<PVInt>("nanoseconds");
pvUserTag = pvStructure->getIntField("userTag"); pvUserTag = pvStructure->getSubField<PVInt>("userTag");
} }
if(pvSecs.get()!=NULL if(pvSecs.get()!=NULL
&& pvNano.get()!=NULL && pvNano.get()!=NULL

View File

@@ -21,19 +21,61 @@
namespace epics { namespace pvData { 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 { class epicsShareClass PVTimeStamp {
public: public:
/**
*
* Constructor
*/
PVTimeStamp(){} PVTimeStamp(){}
//default constructors and destructor are OK //default constructors and destructor are OK
//This class should not be extended //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); bool attach(PVFieldPtr const & pvField);
/**
* Detach for pvField.
*/
void detach(); void detach();
/**
* Is the PVTimeStamp attached to a pvField?
* @return (false,true) (is not,is) attached to a pvField.
*/
bool isAttached(); bool isAttached();
// following throw logic_error is not attached to PVField // following throw logic_error if not attached to PVField
// a set returns false if field is immutable // set returns false if field is immutable
void get(TimeStamp &) const; /**
* 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); bool set(TimeStamp const & timeStamp);
private: private:
static std::string noTimeStamp; static std::string noTimeStamp;

View File

@@ -35,43 +35,158 @@ epicsShareExtern int32 microSecPerSec;
epicsShareExtern int32 nanoSecPerSec; epicsShareExtern int32 nanoSecPerSec;
epicsShareExtern int64 posixEpochAtEpicsEpoch; 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 { class epicsShareClass TimeStamp {
public: public:
/**
* Default constructor
*/
TimeStamp() TimeStamp()
:secondsPastEpoch(0), nanoseconds(0), userTag(0) {} :secondsPastEpoch(0), nanoseconds(0), userTag(0) {}
/**
* Constructor
* @param secondsPastEpoch seconds since 1970 UTC
* @param nanoseconds nanoseconds since secondsPastEpoch
* @param userTag application specific
*/
TimeStamp(int64 secondsPastEpoch,int32 nanoseconds = 0,int32 userTag = 0); TimeStamp(int64 secondsPastEpoch,int32 nanoseconds = 0,int32 userTag = 0);
//default constructors and destructor are OK //default constructors and destructor are OK
//This class should not be extended //This class should not be extended
/**
* adjust secondsPastEpoch and nanoseconds so that
* 0 <= nanoseconds < nanoSecPerSec
*/
void normalize(); 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;} int64 getSecondsPastEpoch() const {return secondsPastEpoch;}
/**
* Get secondsPastEpoch for EPICS V3.
* This is seconds since 1990 UTC.
* @return The epics V3 secondsPastEpoch.
*/
int64 getEpicsSecondsPastEpoch() const { int64 getEpicsSecondsPastEpoch() const {
return secondsPastEpoch - posixEpochAtEpicsEpoch; return secondsPastEpoch - posixEpochAtEpicsEpoch;
} }
/**
* Get nanoseconds.
* @return nanoseconds within timeStamp.
*/
int32 getNanoseconds() const {return nanoseconds;} int32 getNanoseconds() const {return nanoseconds;}
/**
* Get userTag.
* @return userTag.
*/
int32 getUserTag() const {return userTag;} int32 getUserTag() const {return userTag;}
/**
* Set userTag.
* @param userTag application specific.
*/
void setUserTag(int userTag) {this->userTag = userTag;} 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) { void put(int64 secondsPastEpoch,int32 nanoseconds = 0) {
this->secondsPastEpoch = secondsPastEpoch; this->secondsPastEpoch = secondsPastEpoch;
this->nanoseconds = nanoseconds; this->nanoseconds = nanoseconds;
normalize(); normalize();
} }
/**
* Set time fields in timeStamp.
* @param milliseconds The number of milliseconds since the epoch.
*/
void put(int64 milliseconds); void put(int64 milliseconds);
/**
* Set the timeStamp to the current time.
*/
void getCurrent(); void getCurrent();
/**
* Convert the timeStamp to a double value that is seconds past epoch.
* @return seconds past 1970 UTC
*/
double toSeconds() const ; double toSeconds() const ;
/**
* Standard C++ operator.
*/
bool operator==(TimeStamp const &) const; bool operator==(TimeStamp const &) const;
/**
* Standard C++ operator.
*/
bool operator!=(TimeStamp const &) const; bool operator!=(TimeStamp const &) const;
/**
* Standard C++ operator.
*/
bool operator<=(TimeStamp const &) const; bool operator<=(TimeStamp const &) const;
/**
* Standard C++ operator.
*/
bool operator< (TimeStamp const &) const; bool operator< (TimeStamp const &) const;
/**
* Standard C++ operator.
*/
bool operator>=(TimeStamp const &) const; bool operator>=(TimeStamp const &) const;
/**
* Standard C++ operator.
*/
bool operator> (TimeStamp const &) const; bool operator> (TimeStamp const &) const;
/**
* Return a-b as a double value with units of seconds.
* @param a first timeStamp
* @param b second timeStamp
* @return time difference in seconds.
*/
static double diff(TimeStamp const & a,TimeStamp const & b); static double diff(TimeStamp const & a,TimeStamp const & b);
/**
* Standard C++ operator.
*/
TimeStamp & operator+=(int64 seconds); TimeStamp & operator+=(int64 seconds);
/**
* Standard C++ operator.
*/
TimeStamp & operator-=(int64 seconds); TimeStamp & operator-=(int64 seconds);
/**
* Standard C++ operator.
*/
TimeStamp & operator+=(double seconds); TimeStamp & operator+=(double seconds);
/**
* Standard C++ operator.
*/
TimeStamp & operator-=(double seconds); TimeStamp & operator-=(double seconds);
int64 getMilliseconds(); // milliseconds since epoch /**
* Get number of milliseconds past epoch.
* @return milliseconds past epoch.
*/
int64 getMilliseconds();
private: private:
static int64 diffInt(TimeStamp const &left,TimeStamp const &right ); static int64 diffInt(TimeStamp const &left,TimeStamp const &right );
int64 secondsPastEpoch; int64 secondsPastEpoch;

View File

@@ -22,40 +22,12 @@
namespace epics { namespace pvData { namespace epics { namespace pvData {
bool epicsShareExtern operator==(const PVField&, const PVField&); class Convert;
typedef std::tr1::shared_ptr<Convert> ConvertPtr;
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);}
/** /**
* @brief Conversion and Copy facility for pvData.
*
* Convert between numeric types, convert any field to a string, * Convert between numeric types, convert any field to a string,
* or convert from a string to a scalar field. * or convert from a string to a scalar field.
* <p>Numeric conversions are between scalar numeric types or between arrays of * <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> * 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> * <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 { class epicsShareClass Convert {
public: public:
static ConvertPtr getConvert(); 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. * Copy from a PVField to another PVField.
* * This calls one on copyScalar, copyArray, copyStructure.
* @param First field * The two arguments must be compatible.
* @param Second field * @param from The source.
* @return (false, true) if the fields (are not, are) the same. * @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) void copy(PVFieldPtr const & from, PVFieldPtr const & to) {
{ to->copy(*from);
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;
} }
/** /**
* Convert a PVField to a string. * 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. * If a PVField is a structure or array be prepared for a very long string.
* @param indentLevel indentation level * @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,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.
*/ */
inline void getString(std::string * buf,PVFieldPtr const & pvField) inline void getString(std::string * buf,PVFieldPtr const & pvField)
{getString(buf, pvField.get(), 0);} {getString(buf, pvField.get(), 0);}
/** /**
* Convert a PVField to a string. * 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. * 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 * @param indentLevel indentation level
*/ */
void getString(std::string * buf,PVField const * pvField,int indentLevel); 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 pv The PV.
* @param from The array of std::string value to convert and put into a 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. * @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. * @throws std::logic_error if the array of std::string does not have a valid values.
*/ */
std::size_t fromString( std::size_t fromString(
@@ -212,129 +144,7 @@ public:
StringArray & to, StringArray & to,
std::size_t toOffset); std::size_t toOffset);
/** /**
* Are from and to valid arguments to copy. * Convert a PV to a byte.
* 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 * @param pv a PV
* @return converted value * @return converted value
*/ */
@@ -478,13 +288,6 @@ public:
*/ */
inline void fromDouble(PVScalarPtr const & pv, double from) { pv->putFrom<double>(from); } 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(); } 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; typedef class std::ios std::ios_base;
#endif #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 { namespace epics { namespace pvData {
class PostHandler; class PostHandler;
@@ -122,7 +130,8 @@ class PVDataCreate;
typedef std::tr1::shared_ptr<PVDataCreate> PVDataCreatePtr; 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 class epicsShareClass PostHandler
{ {
@@ -133,13 +142,14 @@ public:
*/ */
virtual ~PostHandler(){} 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; 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. * Each PVData field has an interface that extends PVField.
*/ */
class epicsShareClass PVField class epicsShareClass PVField
@@ -158,19 +168,19 @@ public:
virtual ~PVField(); virtual ~PVField();
/** /**
* Get the fieldName for this field. * 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;} inline const std::string& getFieldName() const {return fieldName;}
/** /**
* Fully expand the name of this field using the * 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. * each name.
*/ */
std::string getFullName() const; 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. * 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 first field within the structure has offset equal to 1.
* The other offsets are determined by recursively traversing each structure of the tree. * The other offsets are determined by recursively traversing each structure of the tree.
* @return The offset. * @return The offset.
@@ -194,8 +204,8 @@ public:
*/ */
bool isImmutable() const; bool isImmutable() const;
/** /**
* Set the field to be immutable, i. e. it can no longer be modified. * 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. * This is permanent, i.e. once done the field cannot be made mutable.
*/ */
virtual void setImmutable(); virtual void setImmutable();
/** /**
@@ -231,12 +241,15 @@ public:
*/ */
virtual std::ostream& dumpValue(std::ostream& o) const = 0; virtual std::ostream& dumpValue(std::ostream& o) const = 0;
void copy(const PVField& from);
void copyUnchecked(const PVField& from);
protected: protected:
PVField::shared_pointer getPtrSelf() PVField::shared_pointer getPtrSelf()
{ {
return shared_from_this(); return shared_from_this();
} }
PVField(FieldConstPtr field); explicit PVField(FieldConstPtr field);
void setParentAndName(PVStructure *parent, std::string const & fieldName); void setParentAndName(PVStructure *parent, std::string const & fieldName);
private: private:
static void computeOffset(const PVField *pvField); static void computeOffset(const PVField *pvField);
@@ -256,7 +269,8 @@ private:
epicsShareExtern std::ostream& operator<<(std::ostream& o, const PVField& f); 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 { class epicsShareClass PVScalar : public PVField {
// friend our child class(s) so that it // friend our child class(s) so that it
@@ -317,12 +331,16 @@ public:
virtual void assign(const PVScalar&) = 0; virtual void assign(const PVScalar&) = 0;
virtual void copy(const PVScalar& from) = 0;
virtual void copyUnchecked(const PVScalar& from) = 0;
protected: 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> template<typename T>
class epicsShareClass PVScalarValue : public PVScalar { class epicsShareClass PVScalarValue : public PVScalar {
@@ -345,7 +363,7 @@ public:
virtual T get() const = 0; virtual T get() const = 0;
/** /**
* Put a new value into the PVScalar. * Put a new value into the PVScalar.
* @param The value. * @param value The value.
*/ */
virtual void put(T value) = 0; virtual void put(T value) = 0;
@@ -381,8 +399,27 @@ public:
put(castUnsafe<T,T1>(val)); 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: protected:
PVScalarValue(ScalarConstPtr const & scalar) explicit PVScalarValue(ScalarConstPtr const & scalar)
: PVScalar(scalar) {} : PVScalar(scalar) {}
virtual void getAs(void * result, ScalarType rtype) const virtual void getAs(void * result, ScalarType rtype) const
{ {
@@ -395,16 +432,6 @@ protected:
castUnsafeV(1, typeCode, (void*)&result, stype, src); castUnsafeV(1, typeCode, (void*)&result, stype, src);
put(result); 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: private:
friend class PVDataCreate; friend class PVDataCreate;
@@ -437,7 +464,8 @@ typedef std::tr1::shared_ptr<PVFloat> PVFloatPtr;
typedef std::tr1::shared_ptr<PVDouble> PVDoublePtr; 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 { class epicsShareClass PVString : public PVScalarValue<std::string>, SerializableArray {
public: public:
@@ -446,14 +474,18 @@ public:
*/ */
virtual ~PVString() {} virtual ~PVString() {}
protected: protected:
PVString(ScalarConstPtr const & scalar) explicit PVString(ScalarConstPtr const & scalar)
: PVScalarValue<std::string>(scalar) {} : PVScalarValue<std::string>(scalar) {}
}; };
typedef std::tr1::shared_ptr<PVString> PVStringPtr; 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 { class epicsShareClass PVArray : public PVField, public SerializableArray {
public: public:
@@ -472,8 +504,8 @@ public:
*/ */
virtual ArrayConstPtr getArray() const = 0; virtual ArrayConstPtr getArray() const = 0;
/** /**
* Set the field to be immutable, i. e. it can no longer be modified. * 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. * This is permanent, i.e. once done the field cannot be made mutable.
*/ */
virtual void setImmutable(); virtual void setImmutable();
/** /**
@@ -483,7 +515,7 @@ public:
virtual std::size_t getLength() const = 0; virtual std::size_t getLength() const = 0;
/** /**
* Set the array length. * Set the array length.
* @param The length. * @param length The length.
*/ */
virtual void setLength(std::size_t length) = 0; virtual void setLength(std::size_t length) = 0;
/** /**
@@ -503,7 +535,7 @@ public:
void setCapacityMutable(bool isMutable); void setCapacityMutable(bool isMutable);
/** /**
* Set the array capacity. * Set the array capacity.
* @param The capacity. * @param capacity The capacity.
*/ */
virtual void setCapacity(std::size_t capacity) = 0; virtual void setCapacity(std::size_t capacity) = 0;
@@ -511,7 +543,7 @@ public:
virtual std::ostream& dumpValue(std::ostream& o, std::size_t index) const = 0; virtual std::ostream& dumpValue(std::ostream& o, std::size_t index) const = 0;
protected: protected:
PVArray(FieldConstPtr const & field); explicit PVArray(FieldConstPtr const & field);
void checkLength(size_t length); void checkLength(size_t length);
private: private:
bool capacityMutable; bool capacityMutable;
@@ -520,9 +552,9 @@ private:
epicsShareExtern std::ostream& operator<<(format::array_at_internal const& manip, const PVArray& array); 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 { class epicsShareClass PVScalarArray : public PVArray {
public: public:
@@ -570,7 +602,7 @@ public:
* A copy and element-wise conversion is performed unless * A copy and element-wise conversion is performed unless
* the element type of the PVScalarArray matches the * the element type of the PVScalarArray matches the
* type of the provided data. * 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. * data is kept.
* *
* Calls postPut() * Calls postPut()
@@ -588,22 +620,38 @@ public:
* A copy and element-wise conversion is performed unless * A copy and element-wise conversion is performed unless
* the element type of the PVScalarArray matches the * the element type of the PVScalarArray matches the
* type of the provided data. * 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. * 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; shared_vector<const void> temp;
pv._getAsVoid(temp); from._getAsVoid(temp);
_putFromVoid(temp); _putFromVoid(temp);
} }
protected: protected:
PVScalarArray(ScalarArrayConstPtr const & scalarArray); explicit PVScalarArray(ScalarArrayConstPtr const & scalarArray);
private: private:
friend class PVDataCreate; friend class PVDataCreate;
}; };
/**
* @brief Data interface for a structure,
*
*/
class epicsShareClass PVStructure : public PVField, public BitSetSerializable class epicsShareClass PVStructure : public PVField, public BitSetSerializable
{ {
public: public:
@@ -615,8 +663,8 @@ public:
typedef PVStructure & reference; typedef PVStructure & reference;
typedef const PVStructure & const_reference; typedef const PVStructure & const_reference;
/** /**
* Set the field to be immutable, i. e. it can no longer be modified. * 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. * This is permanent, i.e. once done the field cannot be made mutable.
*/ */
virtual void setImmutable(); virtual void setImmutable();
/** /**
@@ -636,23 +684,42 @@ public:
*/ */
PVFieldPtr getSubField(std::string const &fieldName) const; 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> 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); return this->getSubField<PVT>(fieldName.c_str());
if (pvField.get()) }
return std::tr1::dynamic_pointer_cast<PVT>(pvField);
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 else
return std::tr1::shared_ptr<PVT>(); return std::tr1::shared_ptr<PVT>();
} }
/** /**
* Get the subfield with the specified offset. * Get the subfield with the specified offset.
* @param fieldOffset The offset. * @param fieldOffset The offset.
* @return Pointer to the field or null if field does not exist. * @return Pointer to the field or null if field does not exist.
*/ */
PVFieldPtr getSubField(std::size_t fieldOffset) const; 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> template<typename PVT>
std::tr1::shared_ptr<PVT> getSubField(std::size_t fieldOffset) const std::tr1::shared_ptr<PVT> getSubField(std::size_t fieldOffset) const
{ {
@@ -664,127 +731,51 @@ public:
} }
/** /**
* Get a boolean field with the specified name. * Get a subfield with the specified name.
* No longer needed. Use templete version of getSubField * @param fieldName a '.' separated list of child field names (no whitespace allowed)
* @param fieldName The name of the field to get. * @returns A reference to the sub-field (never NULL)
* @return Pointer to the field of null if a field with that name and type does not exist. * @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. * Get a subfield with the specified name.
* No longer needed. Use templete version of getSubField * @param fieldName a '.' separated list of child field names (no whitespace allowed)
* @param fieldName The name of the field to get. * @returns A reference to the sub-field (never NULL)
* @return Pointer to the field of null if a field with that name and type does not exist. * @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. * Get the subfield with the specified offset.
* No longer needed. Use templete version of getSubField * @param fieldOffset The offset.
* @param fieldName The name of the field to get. * @returns A reference to the sub-field (never NULL)
* @return Pointer to the field of null if a field with that name and type does not exist. * @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. * Get the subfield with the specified offset.
* No longer needed. Use templete version of getSubField * @param fieldOffset The offset.
* @param fieldName The name of the field to get. * @returns A reference to the sub-field (never NULL)
* @return Pointer to the field of null if a field with that name and type does not exist. * @throws std::runtime_error if the requested sub-field doesn't exist, or has a different type
*/ */
PVIntPtr getIntField(std::string const &fieldName) ; template<typename PVT>
/** std::tr1::shared_ptr<PVT> getSubFieldT(std::size_t fieldOffset) const;
* 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) ;
/** /**
* Serialize. * Serialize.
* @param pbuffer The byte buffer. * @param pbuffer The byte buffer.
@@ -819,7 +810,7 @@ public:
* Constructor * Constructor
* @param structure The introspection interface. * @param structure The introspection interface.
*/ */
PVStructure(StructureConstPtr const & structure); explicit PVStructure(StructureConstPtr const & structure);
/** /**
* Constructor * Constructor
* @param structure The introspection interface. * @param structure The introspection interface.
@@ -829,7 +820,14 @@ public:
virtual std::ostream& dumpValue(std::ostream& o) const; 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: private:
PVField *getSubFieldImpl(const char *name, bool throws = true) const;
static PVFieldPtr nullPVField; static PVFieldPtr nullPVField;
static PVBooleanPtr nullPVBoolean; static PVBooleanPtr nullPVBoolean;
static PVBytePtr nullPVByte; 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 class epicsShareClass PVUnion : public PVField
{ {
@@ -873,7 +906,7 @@ public:
/** /**
* Undefined index. * Undefined index.
* Default value upon PVUnion construction. Can be set by the user. * Default value upon PVUnion construction. Can be set by the user.
* Corresponds to {@code null} value. * Corresponds to @c null value.
*/ */
static int32 UNDEFINED_INDEX; static int32 UNDEFINED_INDEX;
@@ -884,8 +917,8 @@ public:
UnionConstPtr getUnion() const; UnionConstPtr getUnion() const;
/** /**
* Get the {@code PVField} value stored in the field. * Get the @c PVField value stored in the field.
* @return {@code PVField} value of field, {@code null} if {@code getSelectedIndex() == UNDEFINED_INDEX}. * @return @c PVField value of field, @c null if {@code getSelectedIndex() == UNDEFINED_INDEX}.
*/ */
PVFieldPtr get() const; PVFieldPtr get() const;
@@ -897,8 +930,8 @@ public:
/** /**
* Select field (set index) and get the field at the index. * Select field (set index) and get the field at the index.
* @param index index of the field to select. * @param index index of the field to select.
* @return corresponding PVField (of undetermined value), {@code null} if {@code index == UNDEFINED_INDEX}. * @return corresponding PVField (of undetermined value), @c null if {@code index == UNDEFINED_INDEX}.
* @throws {@code std::invalid_argument} if index is invalid (out of range). * @throws std::invalid_argument if index is invalid (out of range).
*/ */
PVFieldPtr select(int32 index); PVFieldPtr select(int32 index);
@@ -911,7 +944,7 @@ public:
* Select field (set index) and get the field by given name. * Select field (set index) and get the field by given name.
* @param fieldName the name of the field to select. * @param fieldName the name of the field to select.
* @return corresponding PVField (of undetermined value). * @return corresponding PVField (of undetermined value).
* @throws {@code std::invalid_argument} if field does not exist. * @throws std::invalid_argument if field does not exist.
*/ */
PVFieldPtr select(std::string const & fieldName); PVFieldPtr select(std::string const & fieldName);
@@ -933,27 +966,30 @@ public:
std::string getSelectedFieldName() const; std::string getSelectedFieldName() const;
/** /**
* Set the {@code PVField} (by reference!) as selected field. * Set the @c PVField (by reference!) as selected field.
* If a value is not a valid union field an {@code std::invalid_argument} exception is thrown. * If a value is not a valid union field an @c std::invalid_argument
* exception is thrown.
* @param value the field to set. * @param value the field to set.
*/ */
void set(PVFieldPtr const & value); void set(PVFieldPtr const & value);
/** /**
* Set the {@code PVField} (by reference!) as field at given index. * Set the @c PVField (by reference!) as field at given index.
* If a value is not a valid union field an {@code std::invalid_argument} exception is thrown. * If a value is not a valid union field an @c std::invalid_argument
* Use {@code select(int)} to put by value. * exception is thrown.
* Use @c select(int32) to put by value.
* @param index index of a field to put. * @param index index of a field to put.
* @param value the field to set. * @param value the field to set.
* @see #select(int) * @see #select(int32)
*/ */
void set(int32 index, PVFieldPtr const & value); void set(int32 index, PVFieldPtr const & value);
/** /**
* Set the {@code PVField} (by reference!) as field by given name. * Set the @c PVField (by reference!) as field by given name.
* If a value is not a valid union field an {@code std::invalid_argument} exception is thrown. * If a value is not a valid union field an @c std::invalid_argument
* Use {@code select(std::string)} to put by value. * exception is thrown.
* Use @c select(std::string const &) to put by value.
* @param fieldName Name of the field to put. * @param fieldName Name of the field to put.
* @param value the field to set. * @param value the field to set.
* @see #select(std::string) * @see #select(std::string const &)
*/ */
void set(std::string const & fieldName, PVFieldPtr const & value); void set(std::string const & fieldName, PVFieldPtr const & value);
@@ -975,11 +1011,16 @@ public:
* Constructor * Constructor
* @param punion The introspection interface. * @param punion The introspection interface.
*/ */
PVUnion(UnionConstPtr const & punion); explicit PVUnion(UnionConstPtr const & punion);
virtual std::ostream& dumpValue(std::ostream& o) const; virtual std::ostream& dumpValue(std::ostream& o) const;
void copy(const PVUnion& from);
void copyUnchecked(const PVUnion& from);
private: private:
static PVDataCreatePtr pvDataCreate;
friend class PVDataCreate; friend class PVDataCreate;
UnionConstPtr unionPtr; UnionConstPtr unionPtr;
@@ -1018,11 +1059,11 @@ namespace detail {
PVVectorStorage() : Base() {} PVVectorStorage() : Base() {}
template<typename A> template<typename A>
PVVectorStorage(A a) : Base(a) {} explicit PVVectorStorage(A a) : Base(a) {}
public: public:
virtual ~PVVectorStorage(){}; virtual ~PVVectorStorage(){};
// Primative array manipulations // Primitive array manipulations
//! Fetch a read-only view of the current array data //! Fetch a read-only view of the current array data
virtual const_svector view() const = 0; virtual const_svector view() const = 0;
@@ -1064,6 +1105,13 @@ namespace detail {
}; };
} // 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> template<typename T>
class epicsShareClass PVValueArray : public detail::PVVectorStorage<T,PVScalarArray> { class epicsShareClass PVValueArray : public detail::PVVectorStorage<T,PVScalarArray> {
typedef detail::PVVectorStorage<T,PVScalarArray> base_t; typedef detail::PVVectorStorage<T,PVScalarArray> base_t;
@@ -1085,6 +1133,9 @@ public:
*/ */
virtual ~PVValueArray() {} virtual ~PVValueArray() {}
/**
* Get introspection interface.
*/
virtual ArrayConstPtr getArray() const virtual ArrayConstPtr getArray() const
{ {
return std::tr1::static_pointer_cast<const Array>(this->getField()); return std::tr1::static_pointer_cast<const Array>(this->getField());
@@ -1122,14 +1173,15 @@ protected:
this->replace(shared_vector_convert<const T>(in)); this->replace(shared_vector_convert<const T>(in));
} }
PVValueArray(ScalarArrayConstPtr const & scalar) explicit PVValueArray(ScalarArrayConstPtr const & scalar)
: base_t(scalar) {} : base_t(scalar) {}
friend class PVDataCreate; friend class PVDataCreate;
}; };
/** /**
* Data class for a structureArray * @brief Data class for a structureArray
*
*/ */
template<> template<>
class epicsShareClass PVValueArray<PVStructurePtr> : public detail::PVVectorStorage<PVStructurePtr,PVArray> class epicsShareClass PVValueArray<PVStructurePtr> : public detail::PVVectorStorage<PVStructurePtr,PVArray>
@@ -1211,8 +1263,11 @@ public:
virtual std::ostream& dumpValue(std::ostream& o) const; virtual std::ostream& dumpValue(std::ostream& o) const;
virtual std::ostream& dumpValue(std::ostream& o, std::size_t index) const; virtual std::ostream& dumpValue(std::ostream& o, std::size_t index) const;
void copy(const PVStructureArray& from);
void copyUnchecked(const PVStructureArray& from);
protected: protected:
PVValueArray(StructureArrayConstPtr const & structureArray) explicit PVValueArray(StructureArrayConstPtr const & structureArray)
:base_t(structureArray) :base_t(structureArray)
,structureArray(structureArray) ,structureArray(structureArray)
{} {}
@@ -1225,7 +1280,8 @@ private:
/** /**
* Data class for a unionArray * @brief Data class for a unionArray
*
*/ */
template<> template<>
class epicsShareClass PVValueArray<PVUnionPtr> : public detail::PVVectorStorage<PVUnionPtr,PVArray> class epicsShareClass PVValueArray<PVUnionPtr> : public detail::PVVectorStorage<PVUnionPtr,PVArray>
@@ -1307,8 +1363,11 @@ public:
virtual std::ostream& dumpValue(std::ostream& o) const; virtual std::ostream& dumpValue(std::ostream& o) const;
virtual std::ostream& dumpValue(std::ostream& o, std::size_t index) const; virtual std::ostream& dumpValue(std::ostream& o, std::size_t index) const;
void copy(const PVUnionArray& from);
void copyUnchecked(const PVUnionArray& from);
protected: protected:
PVValueArray(UnionArrayConstPtr const & unionArray) explicit PVValueArray(UnionArrayConstPtr const & unionArray)
:base_t(unionArray) :base_t(unionArray)
,unionArray(unionArray) ,unionArray(unionArray)
{} {}
@@ -1359,7 +1418,8 @@ typedef PVValueArray<std::string> PVStringArray;
typedef std::tr1::shared_ptr<PVStringArray> PVStringArrayPtr; 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 { class epicsShareClass PVDataCreate {
public: public:
@@ -1390,7 +1450,7 @@ public:
PVScalarPtr createPVScalar(ScalarConstPtr const & scalar); PVScalarPtr createPVScalar(ScalarConstPtr const & scalar);
/** /**
* Create an implementation of a scalar field. A Scalar introspection interface is created. * Create an implementation of a scalar field. A Scalar introspection interface is created.
* @param fieldType The field type. * @param scalarType The scalar type.
* @return The PVScalar implementation. * @return The PVScalar implementation.
*/ */
PVScalarPtr createPVScalar(ScalarType scalarType); PVScalarPtr createPVScalar(ScalarType scalarType);
@@ -1403,7 +1463,7 @@ public:
PVScalarPtr createPVScalar(PVScalarPtr const & scalarToClone); PVScalarPtr createPVScalar(PVScalarPtr const & scalarToClone);
/** /**
* template version * template version
* @param PVT must ve a valid pvType * @tparam PVT must be a valid PVType
* @return The PVScalar implementation. * @return The PVScalar implementation.
*/ */
template<typename PVT> template<typename PVT>
@@ -1435,7 +1495,7 @@ public:
/** /**
* Create implementation for PVUnion. * Create implementation for PVUnion.
* @param union The introspection interface. * @param punion The introspection interface.
* @return The PVUnion implementation * @return The PVUnion implementation
*/ */
PVUnionPtr createPVUnion(UnionConstPtr const & punion); PVUnionPtr createPVUnion(UnionConstPtr const & punion);
@@ -1453,13 +1513,12 @@ public:
/** /**
* Create an implementation of an array field reusing the Array introspection interface. * Create an implementation of an array field reusing the Array introspection interface.
* @param array The introspection interface. * @param scalarArray The introspection interface.
* @return The PVScalarArray implementation. * @return The PVScalarArray implementation.
*/ */
PVScalarArrayPtr createPVScalarArray(ScalarArrayConstPtr const & scalarArray); PVScalarArrayPtr createPVScalarArray(ScalarArrayConstPtr const & scalarArray);
/** /**
* Create an implementation for an array field. An Array introspection interface is created. * Create an implementation for an array field. An Array introspection interface is created.
* @param parent The parent interface.
* @param elementType The element type. * @param elementType The element type.
* @return The PVScalarArray implementation. * @return The PVScalarArray implementation.
*/ */
@@ -1467,13 +1526,13 @@ public:
/** /**
* Create an implementation of an array field by cloning an existing PVArray. * Create an implementation of an array field by cloning an existing PVArray.
* The new PVArray will have the same value and auxInfo as the original. * The new PVArray will have the same value and auxInfo as the original.
* @param arrayToClone The PVScalarArray to clone. * @param scalarArrayToClone The PVScalarArray to clone.
* @return The PVScalarArray implementation. * @return The PVScalarArray implementation.
*/ */
PVScalarArrayPtr createPVScalarArray(PVScalarArrayPtr const & scalarArrayToClone); PVScalarArrayPtr createPVScalarArray(PVScalarArrayPtr const & scalarArrayToClone);
/** /**
* template version * template version
* @param PVT must ve a valid pvType * @tparam PVT must be a valid pvType
* @return The PVScalarArray implementation. * @return The PVScalarArray implementation.
*/ */
template<typename PVAT> template<typename PVAT>
@@ -1509,7 +1568,7 @@ public:
PVUnionArrayPtr createPVUnionArray(UnionArrayConstPtr const & unionArray); PVUnionArrayPtr createPVUnionArray(UnionArrayConstPtr const & unionArray);
/** /**
* Create an implementation of an array with union elements. * 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. * All elements share the same introspection interface.
* @return The PVUnionArray implementation. * @return The PVUnionArray implementation.
*/ */
@@ -1529,11 +1588,32 @@ private:
}; };
/** /**
* Get the single class that implemnents PVDataCreate * Get the single class that implements PVDataCreate
* @param The PVDataCreate factory. * @return The PVDataCreate factory.
*/ */
epicsShareExtern PVDataCreatePtr getPVDataCreate(); 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 */ #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) {} indent_level(long l) : level(l) {}
}; };
inline long& indent_value(std::ios_base& ios) epicsShareExtern long& indent_value(std::ios_base& ios);
{
static int indent_index = std::ios_base::xalloc();
return ios.iword(indent_index);
}
epicsShareExtern std::ostream& operator<<(std::ostream& os, indent_level const& indent); 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 { namespace TypeFunc {
/** /**
@@ -186,51 +183,51 @@ epicsShareExtern std::ostream& operator<<(std::ostream& o, const Type& type);
*/ */
enum ScalarType { 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 @c false or @c true
*/ */
pvBoolean, pvBoolean,
/** /**
* The type is byte, i. e. a 8 bit signed integer. * The type is byte, i.e. a 8 bit signed integer.
*/ */
pvByte, pvByte,
/** /**
* The type is short, i. e. a 16 bit signed integer. * The type is short, i.e. a 16 bit signed integer.
*/ */
pvShort, pvShort,
/** /**
* The type is int, i. e. a 32 bit signed integer. * The type is int, i.e. a 32 bit signed integer.
*/ */
pvInt, pvInt,
/** /**
* The type is long, i. e. a 64 bit signed integer. * The type is long, i.e. a 64 bit signed integer.
*/ */
pvLong, 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, 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, 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, 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, pvULong,
/** /**
* The type is float, i. e. 32 bit IEEE floating point, * The type is float, i.e. 32 bit IEEE floating point,
*/ */
pvFloat, pvFloat,
/** /**
* The type is float, i. e. 64 bit IEEE floating point, * The type is float, i.e. 64 bit IEEE floating point,
*/ */
pvDouble, pvDouble,
/** /**
* The type is string, i. e. a UTF8 character string. * The type is string, i.e. a UTF8 character string.
*/ */
pvString pvString
}; };
@@ -238,29 +235,30 @@ enum ScalarType {
#define MAX_SCALAR_TYPE pvString #define MAX_SCALAR_TYPE pvString
/** /**
* Convenience functions for ScalarType. * @brief Convenience functions for ScalarType.
*
*/ */
namespace ScalarTypeFunc { 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. * @param scalarType The type.
* @return (false,true) if the scalarType is an integer. * @return (false,true) if the scalarType is an integer.
*/ */
epicsShareExtern bool isInteger(ScalarType scalarType); 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. * @param scalarType The type.
* @return (false,true) if the scalarType is an integer. * @return (false,true) if the scalarType is an integer.
*/ */
epicsShareExtern bool isUInteger(ScalarType scalarType); 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. * @param scalarType The type.
* @return (false,true) if the scalarType is a numeric * @return (false,true) if the scalarType is a numeric
*/ */
epicsShareExtern bool isNumeric(ScalarType scalarType); 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. * @param scalarType The type.
* @return (false,true) if the scalarType is primitive. * @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 : class epicsShareClass Field :
virtual public Serializable, virtual public Serializable,
@@ -319,7 +318,7 @@ public:
protected: protected:
/** /**
* Constructor * Constructor
* @param fieldName The field type. * @param type The field type.
*/ */
Field(Type type); Field(Type type);
private: private:
@@ -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{ class epicsShareClass Scalar : public Field{
public: 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{ class epicsShareClass BoundedString : public Scalar{
public: 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{ class epicsShareClass Array : public Field{
public: public:
@@ -431,20 +433,15 @@ public:
protected: protected:
/** /**
* Constructor * Constructor
* @param fieldName The field type. * @param type The field type.
*/ */
Array(Type type); Array(Type type);
}; };
/** /**
* This class implements introspection object for scalar array. * @brief This class implements introspection object for scalar array.
*
*/ */
class epicsShareClass ScalarArray : public Array{ class epicsShareClass ScalarArray : public Array{
public: 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{ class epicsShareClass BoundedScalarArray : public ScalarArray{
public: 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{ class epicsShareClass FixedScalarArray : public ScalarArray{
public: public:
@@ -555,12 +554,9 @@ private:
friend class FieldCreate; 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{ class epicsShareClass StructureArray : public Array{
public: 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{ class epicsShareClass UnionArray : public Array{
public: public:
@@ -629,7 +626,7 @@ public:
protected: protected:
/** /**
* Constructor. * Constructor.
* @param union The introspection interface for the elements. * @param _punion The introspection interface for the elements.
*/ */
UnionArray(UnionConstPtr const & _punion); UnionArray(UnionConstPtr const & _punion);
/** /**
@@ -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 { class epicsShareClass Structure : public Field {
public: public:
@@ -651,7 +649,13 @@ public:
/** /**
* Default structure ID. * 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. * Destructor.
@@ -672,13 +676,35 @@ public:
* This will hold a null pointer if the field is not in the structure. * This will hold a null pointer if the field is not in the structure.
*/ */
FieldConstPtr getField(std::string const &fieldName) const; 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. * Get the field for the specified fieldName.
* @param fieldName The index of the field to get; * @param index The index of the field to get;
* @return The introspection interface. * @return The introspection interface.
* This will hold a null pointer if the field is not in the structure. * 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. * Get the field index for the specified fieldName.
* @return The introspection interface. * @return The introspection interface.
@@ -700,7 +726,7 @@ public:
* @param fieldIndex The index of the desired field. * @param fieldIndex The index of the desired field.
* @return The fieldName. * @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; virtual std::string getID() const;
@@ -710,7 +736,7 @@ public:
virtual void deserialize(ByteBuffer *buffer, DeserializableControl *control); virtual void deserialize(ByteBuffer *buffer, DeserializableControl *control);
protected: 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: private:
StringArray fieldNames; StringArray fieldNames;
FieldConstPtrArray fields; 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 { class epicsShareClass Union : public Field {
public: public:
@@ -732,12 +759,24 @@ public:
/** /**
* Default union ID. * 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. * 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. * Destructor.
@@ -758,13 +797,35 @@ public:
* This will hold a null pointer if the field is not in the union. * This will hold a null pointer if the field is not in the union.
*/ */
FieldConstPtr getField(std::string const &fieldName) const; 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. * Get the field for the specified fieldName.
* @param fieldName The index of the field to get; * @param index The index of the field to get;
* @return The introspection interface. * @return The introspection interface.
* This will hold a null pointer if the field is not in the union. * 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. * Get the field index for the specified fieldName.
* @return The introspection interface. * @return The introspection interface.
@@ -786,7 +847,7 @@ public:
* @param fieldIndex The index of the desired field. * @param fieldIndex The index of the desired field.
* @return The fieldName. * @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). * Check if this union is variant union (aka any type).
* @return <code>true</code> if this union is variant union, otherwise <code>false</code>. * @return <code>true</code> if this union is variant union, otherwise <code>false</code>.
@@ -802,7 +863,7 @@ public:
protected: protected:
Union(); 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: private:
StringArray fieldNames; StringArray fieldNames;
FieldConstPtrArray fields; FieldConstPtrArray fields;
@@ -821,8 +882,9 @@ class FieldBuilder;
typedef std::tr1::shared_ptr<FieldBuilder> FieldBuilderPtr; 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. *
* One instance can be used to create multiple @c Field instances.
* An instance of this object must not be used concurrently (an object has a state). * An instance of this object must not be used concurrently (an object has a state).
* @author mse * @author mse
*/ */
@@ -833,127 +895,127 @@ public:
/** /**
* Set ID of an object to be created. * Set ID of an object to be created.
* @param id id to be set. * @param id id to be set.
* @return this instance of a {@code FieldBuilder}. * @return this instance of a @c FieldBuilder.
*/ */
FieldBuilderPtr setId(std::string const & id); FieldBuilderPtr setId(std::string const & id);
/** /**
* Add a {@code Scalar}. * Add a @c Scalar.
* @param name name of the array. * @param name name of the array.
* @param scalarType type of a scalar to add. * @param scalarType type of a scalar to add.
* @return this instance of a {@code FieldBuilder}. * @return this instance of a @c FieldBuilder.
*/ */
FieldBuilderPtr add(std::string const & name, ScalarType scalarType); FieldBuilderPtr add(std::string const & name, ScalarType scalarType);
/** /**
* Add a {@code BoundedString}. * Add a @c BoundedString.
* @param name name of the array. * @param name name of the array.
* @param maxLength a string maximum length. * @param maxLength a string maximum length.
* @return this instance of a {@code FieldBuilder}. * @return this instance of a @c FieldBuilder.
*/ */
FieldBuilderPtr addBoundedString(std::string const & name, std::size_t maxLength); FieldBuilderPtr addBoundedString(std::string const & name, std::size_t maxLength);
/** /**
* Add a {@code Field} (e.g. {@code Structure}, {@code Union}). * Add a @c Field (e.g. @c Structure, @c Union).
* @param name name of the array. * @param name name of the array.
* @param field a field to add. * @param field a field to add.
* @return this instance of a {@code FieldBuilder}. * @return this instance of a @c FieldBuilder.
*/ */
FieldBuilderPtr add(std::string const & name, FieldConstPtr const & field); FieldBuilderPtr add(std::string const & name, FieldConstPtr const & field);
/** /**
* Add variable size array of {@code Scalar} elements. * Add variable size array of @c Scalar elements.
* @param name name of the array. * @param name name of the array.
* @param scalarType type of a scalar element. * @param scalarType type of a scalar element.
* @return this instance of a {@code FieldBuilder}. * @return this instance of a @c FieldBuilder.
*/ */
FieldBuilderPtr addArray(std::string const & name, ScalarType scalarType); FieldBuilderPtr addArray(std::string const & name, ScalarType scalarType);
/** /**
* Add fixed-size array of {@code Scalar} elements. * Add fixed-size array of @c Scalar elements.
* @param name name of the array. * @param name name of the array.
* @param scalarType type of a scalar element. * @param scalarType type of a scalar element.
* @param size Array fixed size. * @param size Array fixed size.
* @return this instance of a {@code FieldBuilder}. * @return this instance of a @c FieldBuilder.
*/ */
FieldBuilderPtr addFixedArray(std::string const & name, ScalarType scalarType, std::size_t size); FieldBuilderPtr addFixedArray(std::string const & name, ScalarType scalarType, std::size_t size);
/** /**
* Add bounded-size array of {@code Scalar} elements. * Add bounded-size array of @c Scalar elements.
* @param name name of the array. * @param name name of the array.
* @param scalarType type of a scalar element. * @param scalarType type of a scalar element.
* @param bound Array maximum capacity (size). * @param bound Array maximum capacity (size).
* @return this instance of a {@code FieldBuilder}. * @return this instance of a @c FieldBuilder.
*/ */
FieldBuilderPtr addBoundedArray(std::string const & name, ScalarType scalarType, std::size_t bound); FieldBuilderPtr addBoundedArray(std::string const & name, ScalarType scalarType, std::size_t bound);
/** /**
* Add array of {@code Field} elements. * Add array of @c Field elements.
* @param name name of the array. * @param name name of the array.
* @param field a type of an array element. * @param element a type of an array element.
* @return this instance of a {@code FieldBuilder}. * @return this instance of a @c FieldBuilder.
*/ */
FieldBuilderPtr addArray(std::string const & name, FieldConstPtr const & element); FieldBuilderPtr addArray(std::string const & name, FieldConstPtr const & element);
/** /**
* Create a {@code Structure}. * Create a @c Structure.
* This resets this instance state and allows new {@code Field} instance to be created. * This resets this instance state and allows new @c Field instance to be created.
* @return a new instance of a {@code Structure}. * @return a new instance of a @c Structure.
*/ */
StructureConstPtr createStructure(); StructureConstPtr createStructure();
/** /**
* Create an {@code Union}. * Create an @c Union.
* This resets this instance state and allows new {@code Field} instance to be created. * This resets this instance state and allows new @c Field instance to be created.
* @return a new instance of an {@code Union}. * @return a new instance of an @c Union.
*/ */
UnionConstPtr createUnion(); UnionConstPtr createUnion();
/** /**
* Add new nested {@code Structure}. * Add new nested @c Structure.
* {@code endNested()} method must be called * endNested() method must be called
* to complete creation of the nested {@code Structure}. * to complete creation of the nested @c Structure.
* @param name nested structure name. * @param name nested structure name.
* @return a new instance of a {@code FieldBuilder} is returned. * @return a new instance of a @c FieldBuilder is returned.
* @see #endNested() * @see #endNested()
*/ */
FieldBuilderPtr addNestedStructure(std::string const & name); FieldBuilderPtr addNestedStructure(std::string const & name);
/** /**
* Add new nested {@code Union}. * Add new nested @c Union.
* {@code endNested()} method must be called * endNested() method must be called
* to complete creation of the nested {@code Union}. * to complete creation of the nested @c Union.
* @param name nested union name. * @param name nested union name.
* @return a new instance of a {@code FieldBuilder} is returned. * @return a new instance of a @c FieldBuilder is returned.
* @see #endNested() * @see #endNested()
*/ */
FieldBuilderPtr addNestedUnion(std::string const & name); FieldBuilderPtr addNestedUnion(std::string const & name);
/** /**
* Add new nested {@code Structure[]}. * Add new nested @c Structure[].
* {@code endNested()} method must be called * endNested() method must be called
* to complete creation of the nested {@code Structure}. * to complete creation of the nested @c Structure.
* @param name nested structure name. * @param name nested structure name.
* @return a new instance of a {@code FieldBuilder} is returned. * @return a new instance of a @c FieldBuilder is returned.
* @see #endNested() * @see #endNested()
*/ */
FieldBuilderPtr addNestedStructureArray(std::string const & name); FieldBuilderPtr addNestedStructureArray(std::string const & name);
/** /**
* Add new nested {@code Union[]}. * Add new nested @c Union[].
* {@code endNested()} method must be called * endNested() method must be called
* to complete creation of the nested {@code Union}. * to complete creation of the nested @c Union.
* @param name nested union name. * @param name nested union name.
* @return a new instance of a {@code FieldBuilder} is returned. * @return a new instance of a @c FieldBuilder is returned.
* @see #endNested() * @see #endNested()
*/ */
FieldBuilderPtr addNestedUnionArray(std::string const & name); FieldBuilderPtr addNestedUnionArray(std::string const & name);
/** /**
* Complete the creation of a nested object. * Complete the creation of a nested object.
* @see #addNestedStructure(std::string) * @see #addNestedStructure(std::string const & name)
* @see #addNestedUnion(std::string) * @see #addNestedUnion(std::string const & name)
* @return a previous (parent) {@code FieldBuilder}. * @return a previous (parent) @c FieldBuilder.
*/ */
FieldBuilderPtr endNested(); FieldBuilderPtr endNested();
@@ -985,114 +1047,113 @@ private:
}; };
/** /**
* This is a singleton class for creating introspection interfaces. * @brief This is a singleton class for creating introspection interfaces.
*
*/ */
class epicsShareClass FieldCreate { class epicsShareClass FieldCreate {
public: public:
static FieldCreatePtr getFieldCreate(); static FieldCreatePtr getFieldCreate();
/** /**
* Create a new instance of in-line {@code Field} builder. * Create a new instance of in-line @c Field builder.
* @return a new instance of a {@code FieldBuilder}. * @return a new instance of a @c FieldBuilder.
*/ */
FieldBuilderPtr createFieldBuilder() const; FieldBuilderPtr createFieldBuilder() const;
/** /**
* Create a {@code ScalarField}. * Create a @c ScalarField.
* @param scalarType The scalar type. * @param scalarType The scalar type.
* @return a {@code Scalar} interface for the newly created object. * @return a @c Scalar interface for the newly created object.
* @throws An {@code IllegalArgumentException} if an illegal type is specified. * @throws IllegalArgumentException if an illegal type is specified.
*/ */
ScalarConstPtr createScalar(ScalarType scalarType) const; ScalarConstPtr createScalar(ScalarType scalarType) const;
/** /**
* Create a {@code BoundedString}. * Create a @c BoundedString.
* @param maxLength a string maximum length. * @param maxLength a string maximum length.
* @return a {@code BoundedString} interface for the newly created object. * @return a @c BoundedString interface for the newly created object.
* @throws An {@code IllegalArgumentException} if maxLength == 0. * @throws IllegalArgumentException if maxLength == 0.
*/ */
BoundedStringConstPtr createBoundedString(std::size_t maxLength) const; BoundedStringConstPtr createBoundedString(std::size_t maxLength) const;
/** /**
* Create an {@code Array} field, variable size array. * Create an @c Array field, variable size array.
* @param elementType The {@code scalarType} for array elements * @param elementType The @c ScalarType for array elements
* @return An {@code Array} Interface for the newly created object. * @return An @c Array Interface for the newly created object.
*/ */
ScalarArrayConstPtr createScalarArray(ScalarType elementType) const; ScalarArrayConstPtr createScalarArray(ScalarType elementType) const;
/* /*
* Create an {@code Array} field, fixed size array. * Create an @c Array field, fixed size array.
* @param elementType The {@code scalarType} for array elements * @param elementType The @c ScalarType for array elements
* @param size Fixed array size. * @param size Fixed array size.
* @return An {@code Array} Interface for the newly created object. * @return An @c Array Interface for the newly created object.
*/ */
ScalarArrayConstPtr createFixedScalarArray(ScalarType elementType, std::size_t size) const; ScalarArrayConstPtr createFixedScalarArray(ScalarType elementType, std::size_t size) const;
/** /**
* Create an {@code Array} field, bounded size array. * Create an @c Array field, bounded size array.
* @param elementType The {@code scalarType} for array elements * @param elementType The @c ScalarType for array elements
* @param size Array maximum capacity (bound). * @param bound Array maximum capacity.
* @return An {@code Array} Interface for the newly created object. * @return An @c Array Interface for the newly created object.
*/ */
ScalarArrayConstPtr createBoundedScalarArray(ScalarType elementType, std::size_t bound) const; ScalarArrayConstPtr createBoundedScalarArray(ScalarType elementType, std::size_t bound) const;
/** /**
* Create an {@code Array} field that is has element type <i>Structure</i> * Create an @c Array field that is has element type @c Structure
* @param fieldName The field name * @param structure The @c Structure for each array element.
* @param elementStructure The {@code Structure} for each array element. * @return An @c Array Interface for the newly created object.
* @return An {@code Array} Interface for the newly created object.
*/ */
StructureArrayConstPtr createStructureArray(StructureConstPtr const & structure) const; StructureArrayConstPtr createStructureArray(StructureConstPtr const & structure) const;
/** /**
* Create a {@code Structure} field. * Create a @c Structure field.
* @return a {@code Structure} interface for the newly created object. * @return a @c Structure interface for the newly created object.
*/ */
StructureConstPtr createStructure () const; StructureConstPtr createStructure () const;
/** /**
* Create a {@code Structure} field. * Create a @c Structure field.
* @param fieldNames The array of {@code fieldNames} for the structure. * @param fieldNames the names of the fields for the structure.
* @param fields The array of {@code fields} for the structure. * @param fields The array of @c Field objects for the structure.
* @return a {@code Structure} interface for the newly created object. * @return a @c Structure interface for the newly created object.
*/ */
StructureConstPtr createStructure ( StructureConstPtr createStructure (
StringArray const & fieldNames, StringArray const & fieldNames,
FieldConstPtrArray const & fields) const; FieldConstPtrArray const & fields) const;
/** /**
* Create a {@code Structure} field with identification string. * Create a @c Structure field with identification string.
* @param id The identification string for the structure. * @param id The identification string for the structure.
* @param fieldNames The array of {@code fieldNames} for the structure. * @param fieldNames the names of the fields for the structure.
* @param fields The array of {@code fields} for the structure. * @param fields The array of @c Field objects for the structure.
* @return a {@code Structure} interface for the newly created object. * @return a @c Structure interface for the newly created object.
*/ */
StructureConstPtr createStructure ( StructureConstPtr createStructure (
std::string const & id, std::string const & id,
StringArray const & fieldNames, StringArray const & fieldNames,
FieldConstPtrArray const & fields) const; FieldConstPtrArray const & fields) const;
/** /**
* Create an {@code Array} field that is has element type <i>Union</i> * Create an @c Array field that is has element type @c Union
* @param fieldName The field name * @param punion The @c Union for each array element.
* @param elementUnion The {@code Union} for each array element. * @return An @c Array Interface for the newly created object.
* @return An {@code Array} Interface for the newly created object.
*/ */
UnionArrayConstPtr createUnionArray(UnionConstPtr const & punion) const; UnionArrayConstPtr createUnionArray(UnionConstPtr const & punion) const;
/** /**
* Create a variant {@code UnionArray} (aka any type) field. * Create a variant @c UnionArray (aka any type) field.
* @return a {@code UnionArray} interface for the newly created object. * @return a @c UnionArray interface for the newly created object.
*/ */
UnionArrayConstPtr createVariantUnionArray() const; UnionArrayConstPtr createVariantUnionArray() const;
/** /**
* Create a variant {@code Union} (aka any type) field. * Create a variant @c Union (aka any type) field.
* @return a {@code Union} interface for the newly created object. * @return a @c Union interface for the newly created object.
*/ */
UnionConstPtr createVariantUnion() const; UnionConstPtr createVariantUnion() const;
/** /**
* Create a {@code Union} field. * Create a @c Union field.
* @param fieldNames The array of {@code fieldNames} for the union. * @param fieldNames the names of the fields for the union.
* @param fields The array of {@code fields} for the union. * @param fields The @c Field for each fields for the union.
* @return a {@code Union} interface for the newly created object. * @return a @c Union interface for the newly created object.
*/ */
UnionConstPtr createUnion ( UnionConstPtr createUnion (
StringArray const & fieldNames, StringArray const & fieldNames,
FieldConstPtrArray const & fields) const; FieldConstPtrArray const & fields) const;
/** /**
* Create a {@code Union} field with identification string. * Create a @c Union field with identification string.
* @param id The identification string for the union. * @param id The identification string for the union.
* @param fieldNames The array of {@code fieldNames} for the union. * @param fieldNames the names of the fields for the union.
* @param fields The array of {@code fields} for the union. * @param fields The array of @c Field objects for the union.
* @return a {@code Union} interface for the newly created object. * @return a @c Union interface for the newly created object.
*/ */
UnionConstPtr createUnion ( UnionConstPtr createUnion (
std::string const & id, std::string const & id,
@@ -1103,7 +1164,7 @@ public:
* @param structure The structure to which the field is appended. * @param structure The structure to which the field is appended.
* @param fieldName The name of the field. * @param fieldName The name of the field.
* @param field The field. * @param field The field.
* @return a {@code Structure} interface for the newly created object. * @return a @c Structure interface for the newly created object.
*/ */
StructureConstPtr appendField( StructureConstPtr appendField(
StructureConstPtr const & structure, StructureConstPtr const & structure,
@@ -1111,19 +1172,19 @@ public:
/** /**
* Append fields to a structure. * Append fields to a structure.
* @param structure The structure to which the fields appended. * @param structure The structure to which the fields appended.
* @param fieldName The names of the fields. * @param fieldNames The names of the fields.
* @param field The fields. * @param fields The fields.
* @return a {@code Structure} interface for the newly created object. * @return a @c Structure interface for the newly created object.
*/ */
StructureConstPtr appendFields( StructureConstPtr appendFields(
StructureConstPtr const & structure, StructureConstPtr const & structure,
StringArray const & fieldNames, StringArray const & fieldNames,
FieldConstPtrArray const & fields) const; FieldConstPtrArray const & fields) const;
/** /**
* Deserialize {@code Field} instance from given byte buffer. * Deserialize @c Field instance from given byte buffer.
* @param buffer Buffer containing serialized {@code Field} instance. * @param buffer Buffer containing serialized @c Field instance.
* @param control Deserialization control instance. * @param control Deserialization control instance.
* @return a deserialized {@code Field} instance. * @return a deserialized @c Field instance.
*/ */
FieldConstPtr deserialize(ByteBuffer* buffer, DeserializableControl* control) const; FieldConstPtr deserialize(ByteBuffer* buffer, DeserializableControl* control) const;
@@ -1137,8 +1198,8 @@ private:
}; };
/** /**
* Get the single class that implemnents FieldCreate, * Get the single class that implements FieldCreate,
* @param The fieldCreate factory. * @return The fieldCreate factory.
*/ */
epicsShareExtern FieldCreatePtr getFieldCreate(); epicsShareExtern FieldCreatePtr getFieldCreate();
@@ -1153,7 +1214,7 @@ epicsShareExtern FieldCreatePtr getFieldCreate();
* value (eg -1). * value (eg -1).
*/ */
template<typename T> template<typename T>
struct ScalarTypeID { enum {value=-1}; }; struct ScalarTypeID {};
/** /**
* Static mapping from ScalarType enum to value type. * Static mapping from ScalarType enum to value type.
@@ -1183,14 +1244,26 @@ OP(pvDouble, double)
OP(pvString, std::string) OP(pvString, std::string)
#undef OP #undef OP
/**
* @brief Hash a Scalar
*
*/
struct ScalarHashFunction { struct ScalarHashFunction {
size_t operator() (const Scalar& scalar) const { return scalar.getScalarType(); } size_t operator() (const Scalar& scalar) const { return scalar.getScalarType(); }
}; };
/**
* @brief Hash a ScalarArray
*
*/
struct ScalarArrayHashFunction { struct ScalarArrayHashFunction {
size_t operator() (const ScalarArray& scalarArray) const { return 0x10 | scalarArray.getElementType(); } size_t operator() (const ScalarArray& scalarArray) const { return 0x10 | scalarArray.getElementType(); }
}; };
/**
* @brief Hash a Structure
*
*/
struct StructureHashFunction { struct StructureHashFunction {
size_t operator() (const Structure& /*structure*/) const { return 0; } size_t operator() (const Structure& /*structure*/) const { return 0; }
// TODO hash // TODO hash
@@ -1198,9 +1271,47 @@ struct StructureHashFunction {
// return PRIME * Arrays.hashCode(fieldNames) + Arrays.hashCode(fields); // return PRIME * Arrays.hashCode(fieldNames) + Arrays.hashCode(fields);
}; };
/**
* @brief Hash a StructureArray
*
*/
struct StructureArrayHashFunction { struct StructureArrayHashFunction {
size_t operator() (const StructureArray& structureArray) const { StructureHashFunction shf; return (0x10 | shf(*(structureArray.getStructure()))); } 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 */ #endif /* PVINTROSPECT_H */

View File

@@ -71,7 +71,7 @@ epicsShareExtern void copy(
PVStructureArray & pvFrom, PVStructureArray & pvFrom,
size_t fromOffset, size_t fromOffset,
size_t fromStride, size_t fromStride,
PVStructureArray & pvToo, PVStructureArray & pvTo,
size_t toOffset, size_t toOffset,
size_t toStride, size_t toStride,
size_t count); size_t count);
@@ -91,7 +91,7 @@ epicsShareExtern void copy(
PVArray & pvFrom, PVArray & pvFrom,
size_t fromOffset, size_t fromOffset,
size_t fromStride, size_t fromStride,
PVArray & pvToo, PVArray & pvTo,
size_t toOffset, size_t toOffset,
size_t toStride, size_t toStride,
size_t count); size_t count);
@@ -111,7 +111,7 @@ epicsShareExtern void copy(
PVArray::shared_pointer const & pvFrom, PVArray::shared_pointer const & pvFrom,
size_t fromOffset, size_t fromOffset,
size_t fromStride, size_t fromStride,
PVArray::shared_pointer & pvToo, PVArray::shared_pointer & pvTo,
size_t toOffset, size_t toOffset,
size_t toStride, size_t toStride,
size_t count); size_t count);

View File

@@ -29,7 +29,7 @@ typedef int intptr_t;
typedef unsigned int uintptr_t; typedef unsigned int uintptr_t;
#ifndef INT64_MAX #ifndef INT64_MAX
#define INT64_MAX (0x7fffffffffffffffLL) #define INT64_MAX (0x7fffffffffffffffLL)
#define UINT64_MAX (0xffffffffffffffffLL) #define UINT64_MAX (0xffffffffffffffffULL)
#endif #endif
#else #else
#include <stdint.h> #include <stdint.h>
@@ -49,11 +49,11 @@ namespace detail {
} }
/** /**
* This is a set of typdefs used by pvData. * This is a set of typedefs used by pvData.
*/ */
/** /**
* boolean, i.e. can only have the values {@code false} or {@code true} * boolean, i.e. can only have the values @c false or @c true
*/ */
typedef detail::pick_type<int8_t, signed char, typedef detail::pick_type<int8_t, signed char,
detail::pick_type<uint8_t, char, unsigned char>::type detail::pick_type<uint8_t, char, unsigned char>::type

View File

@@ -25,7 +25,8 @@ class StandardField;
typedef std::tr1::shared_ptr<StandardField> StandardFieldPtr; 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 * For each type of standard object two methods are defined:s
* one with no properties and with properties * one with no properties and with properties
* The property field is a comma separated string of property names of the following: * The property field is a comma separated string of property names of the following:
@@ -85,21 +86,21 @@ public:
StructureConstPtr regUnion( StructureConstPtr regUnion(
UnionConstPtr const & punion, UnionConstPtr const & punion,
std::string const & properties); 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. * @param properties A comma separated list of properties.
* This is some combination of "alarm,timeStamp,display,control,valueAlarm". * This is some combination of "alarm,timeStamp,display,control,valueAlarm".
* @return The const shared pointer to the structure. * @return The const shared pointer to the structure.
*/ */
StructureConstPtr variantUnion(std::string const & properties); StructureConstPtr variantUnion(std::string const & properties);
/** Create a structure that has a scalarArray value field. /** Create a structure that has a scalarArray value field.
* @param type The type. * @param elementType The element type.
* @param properties A comma separated list of properties. * @param properties A comma separated list of properties.
* This is some combination of "alarm,timeStamp,display,control,valueAlarm". * This is some combination of "alarm,timeStamp,display,control,valueAlarm".
* @return The const shared pointer to the structure. * @return The const shared pointer to the structure.
*/ */
StructureConstPtr scalarArray(ScalarType elementType, std::string const & properties); StructureConstPtr scalarArray(ScalarType elementType, std::string const & properties);
/** Create a structure that has a structureArray value field. /** Create a structure that has a structureArray value field.
* @param type The type. * @param structure The Structure introspection object for elements of the value field.
* @param properties A comma separated list of properties. * @param properties A comma separated list of properties.
* This is some combination of "alarm,timeStamp,display,control,valueAlarm". * This is some combination of "alarm,timeStamp,display,control,valueAlarm".
* @return The const shared pointer to the structure. * @return The const shared pointer to the structure.
@@ -108,7 +109,7 @@ public:
StructureConstPtr const & structure, StructureConstPtr const & structure,
std::string const & properties); std::string const & properties);
/** Create a structure that has a unionArray value field. /** Create a structure that has a unionArray value field.
* @param type The type. * @param punion The Union introspection object for elements of the value field.
* @param properties A comma separated list of properties. * @param properties A comma separated list of properties.
* This is some combination of "alarm,timeStamp,display,control". * This is some combination of "alarm,timeStamp,display,control".
* @return The const shared pointer to the structure. * @return The const shared pointer to the structure.
@@ -117,7 +118,7 @@ public:
UnionConstPtr const & punion, UnionConstPtr const & punion,
std::string const & properties); std::string const & properties);
/** Create a structure that has an enumerated structure value field. /** Create a structure that has an enumerated structure value field.
* The id for the structure is "enum-t". * The id for the structure is "enum_t".
* @return The const shared pointer to the structure. * @return The const shared pointer to the structure.
*/ */
StructureConstPtr enumerated(); StructureConstPtr enumerated();

View File

@@ -25,7 +25,8 @@ class StandardPVField;
typedef std::tr1::shared_ptr<StandardPVField> StandardPVFieldPtr; 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: * Like class StandardField it has two forms of the methods which create a fields:
* one without properties and one with properties. * one without properties and one with properties.
* The properties are some combination of alarm, timeStamp, control, display, and valueAlarm. * The properties are some combination of alarm, timeStamp, control, display, and valueAlarm.
@@ -53,7 +54,7 @@ public:
PVStructurePtr scalar(ScalarType type,std::string const & properties); PVStructurePtr scalar(ScalarType type,std::string const & properties);
/** /**
* Create a structure that has a scalar array value field. * Create a structure that has a scalar array value field.
* @param type The type. * @param elementType The element scalar type.
* @param properties A comma separated list of properties. * @param properties A comma separated list of properties.
* This is some combination of "alarm,timeStamp,display,control,valueAlarm". * This is some combination of "alarm,timeStamp,display,control,valueAlarm".
* @return The const shared pointer to the structure. * @return The const shared pointer to the structure.
@@ -61,7 +62,7 @@ public:
PVStructurePtr scalarArray(ScalarType elementType, std::string const & properties); PVStructurePtr scalarArray(ScalarType elementType, std::string const & properties);
/** /**
* Create a structure that has a structure array value field. * Create a structure that has a structure array value field.
* @param type The type. * @param structure The Structure introspection object for elements of the value field.
* @param properties A comma separated list of properties. * @param properties A comma separated list of properties.
* This is some combination of "alarm,timeStamp,display,control,valueAlarm". * This is some combination of "alarm,timeStamp,display,control,valueAlarm".
* @return The const shared pointer to the structure. * @return The const shared pointer to the structure.
@@ -69,7 +70,7 @@ public:
PVStructurePtr structureArray(StructureConstPtr const &structure,std::string const & properties); PVStructurePtr structureArray(StructureConstPtr const &structure,std::string const & properties);
/** /**
* Create a structure that has a union array value field. * Create a structure that has a union array value field.
* @param type The type. * @param punion The Union introspection object for elements of the value field.
* @param properties A comma separated list of properties. * @param properties A comma separated list of properties.
* This is some combination of "alarm,timeStamp,display,control,valueAlarm". * This is some combination of "alarm,timeStamp,display,control,valueAlarm".
* @return The const shared pointer to the structure. * @return The const shared pointer to the structure.

View File

@@ -18,8 +18,20 @@
namespace epics { namespace pvData { namespace epics { namespace pvData {
/**
* @brief Compress a bitSet.
*
*/
class epicsShareClass BitSetUtil : private NoDefaultMethods { class epicsShareClass BitSetUtil : private NoDefaultMethods {
public: 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); static bool compress(BitSetPtr const &bitSet,PVStructurePtr const &pvStructure);
}; };

View File

@@ -1,8 +1,31 @@
# Makefile for the pvData tests
TOP = .. TOP = ..
include $(TOP)/configure/CONFIG include $(TOP)/configure/CONFIG
DIRS += misc
DIRS += pv PVDATA_TEST = $(TOP)/testApp
DIRS += property
DIRS += copy PROD_LIBS += pvData Com
include $(TOP)/configure/RULES_DIRS
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_SRCS = testCreateRequest.cpp
testCreateRequest_LIBS = pvData Com testHarness_SRCS += testCreateRequest.cpp
TESTS += testCreateRequest TESTS += testCreateRequest
PROD_HOST += testPVCopy TESTPROD_HOST += testPVCopy
testPVCopy_SRCS += testPVCopy.cpp testPVCopy_SRCS += testPVCopy.cpp
testPVCopy_LIBS += pvData Com testHarness_SRCS += testPVCopy.cpp
TESTS += testPVCopy 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 bool debug = false;
static void testCreateRequest() { static void testCreateRequestInternal() {
printf("testCreateRequest... \n"); printf("testCreateRequest... \n");
CreateRequest::shared_pointer createRequest = CreateRequest::create(); CreateRequest::shared_pointer createRequest = CreateRequest::create();
PVStringPtr pvString; PVStringPtr pvString;
@@ -30,8 +30,8 @@ static void testCreateRequest() {
string request = ""; string request = "";
if(debug) { cout << "request " << request <<endl;} if(debug) { cout << "request " << request <<endl;}
PVStructurePtr pvRequest = createRequest->createRequest(request); PVStructurePtr pvRequest = createRequest->createRequest(request);
if(pvRequest.get()==NULL) { cout<< createRequest->getMessage() << endl;} if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
if(debug) { cout << *pvRequest << endl;} if(debug) { cout << pvRequest << endl;}
testOk1(pvRequest.get()!=NULL); testOk1(pvRequest.get()!=NULL);
testOk1(pvRequest->getStructure()->getNumberFields()==0); testOk1(pvRequest->getStructure()->getNumberFields()==0);
testPass("request %s",request.c_str()); testPass("request %s",request.c_str());
@@ -39,8 +39,8 @@ static void testCreateRequest() {
request = "record[]field()getField()putField()"; request = "record[]field()getField()putField()";
if(debug) { cout << "request " << request <<endl;} if(debug) { cout << "request " << request <<endl;}
pvRequest = createRequest->createRequest(request); pvRequest = createRequest->createRequest(request);
if(pvRequest.get()==NULL) { cout<< createRequest->getMessage() << endl;} if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
if(debug) { cout << *pvRequest << endl;} if(debug) { cout << pvRequest << endl;}
testOk1(pvRequest.get()!=NULL); testOk1(pvRequest.get()!=NULL);
testOk1(pvRequest->getSubField("field").get()!=NULL); testOk1(pvRequest->getSubField("field").get()!=NULL);
testOk1(pvRequest->getSubField("putField").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)"; request = "record[a=b,x=y]field(a) putField(a),getField(a)";
if(debug) { cout << "request " << request <<endl;} if(debug) { cout << "request " << request <<endl;}
pvRequest = createRequest->createRequest(request); pvRequest = createRequest->createRequest(request);
if(pvRequest.get()==NULL) { cout<< createRequest->getMessage() << endl;} if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
if(debug) { cout << *pvRequest << endl;} if(debug) { cout << pvRequest << endl;}
testOk1(pvRequest.get()!=NULL); testOk1(pvRequest.get()!=NULL);
pvString = pvRequest->getSubField<PVString>("record._options.a"); pvString = pvRequest->getSubField<PVString>("record._options.a");
sval = pvString->get(); sval = pvString->get();
@@ -67,8 +67,8 @@ static void testCreateRequest() {
request = "field(a.b[x=y])"; request = "field(a.b[x=y])";
if(debug) { cout << "request " << request <<endl;} if(debug) { cout << "request " << request <<endl;}
pvRequest = createRequest->createRequest(request); pvRequest = createRequest->createRequest(request);
if(pvRequest.get()==NULL) { cout<< createRequest->getMessage() << endl;} if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
if(debug) { cout << *pvRequest << endl;} if(debug) { cout << pvRequest << endl;}
testOk1(pvRequest.get()!=NULL); testOk1(pvRequest.get()!=NULL);
pvString = pvRequest->getSubField<PVString>("field.a.b._options.x"); pvString = pvRequest->getSubField<PVString>("field.a.b._options.x");
sval = pvString->get(); sval = pvString->get();
@@ -78,8 +78,8 @@ static void testCreateRequest() {
request = "field(a.b{c.d})"; request = "field(a.b{c.d})";
if(debug) { cout << "request " << request <<endl;} if(debug) { cout << "request " << request <<endl;}
pvRequest = createRequest->createRequest(request); pvRequest = createRequest->createRequest(request);
if(pvRequest.get()==NULL) { cout<< createRequest->getMessage() << endl;} if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
if(debug) { cout << *pvRequest << endl;} if(debug) { cout << pvRequest << endl;}
testOk1(pvRequest.get()!=NULL); testOk1(pvRequest.get()!=NULL);
testOk1(pvRequest->getSubField("field.a.b.c.d").get()!=NULL); testOk1(pvRequest->getSubField("field.a.b.c.d").get()!=NULL);
testPass("request %s",request.c_str()); testPass("request %s",request.c_str());
@@ -87,8 +87,8 @@ static void testCreateRequest() {
request = "field(a.b[x=y]{c.d})"; request = "field(a.b[x=y]{c.d})";
if(debug) { cout << "request " << request <<endl;} if(debug) { cout << "request " << request <<endl;}
pvRequest = createRequest->createRequest(request); pvRequest = createRequest->createRequest(request);
if(pvRequest.get()==NULL) { cout<< createRequest->getMessage() << endl;} if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
if(debug) { cout << *pvRequest << endl;} if(debug) { cout << pvRequest << endl;}
testOk1(pvRequest.get()!=NULL); testOk1(pvRequest.get()!=NULL);
pvString = pvRequest->getSubField<PVString>("field.a.b._options.x"); pvString = pvRequest->getSubField<PVString>("field.a.b._options.x");
sval = pvString->get(); sval = pvString->get();
@@ -99,8 +99,8 @@ static void testCreateRequest() {
request = "field(a.b[x=y]{c.d[x=y]})"; request = "field(a.b[x=y]{c.d[x=y]})";
if(debug) { cout << "request " << request <<endl;} if(debug) { cout << "request " << request <<endl;}
pvRequest = createRequest->createRequest(request); pvRequest = createRequest->createRequest(request);
if(pvRequest.get()==NULL) { cout<< createRequest->getMessage() << endl;} if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
if(debug) { cout << *pvRequest << endl;} if(debug) { cout << pvRequest << endl;}
testOk1(pvRequest.get()!=NULL); testOk1(pvRequest.get()!=NULL);
pvString = pvRequest->getSubField<PVString>("field.a.b._options.x"); pvString = pvRequest->getSubField<PVString>("field.a.b._options.x");
sval = pvString->get(); 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})"; 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;} if(debug) { cout << "request " << request <<endl;}
pvRequest = createRequest->createRequest(request); pvRequest = createRequest->createRequest(request);
if(pvRequest.get()==NULL) { cout<< createRequest->getMessage() << endl;} if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
if(debug) { cout << *pvRequest << endl;} if(debug) { cout << pvRequest << endl;}
testOk1(pvRequest.get()!=NULL); testOk1(pvRequest.get()!=NULL);
pvString = pvRequest->getSubField<PVString>("field.a.a._options.a"); pvString = pvRequest->getSubField<PVString>("field.a.a._options.a");
sval = pvString->get(); sval = pvString->get();
@@ -133,8 +133,8 @@ static void testCreateRequest() {
request = "alarm,timeStamp,power.value"; request = "alarm,timeStamp,power.value";
if(debug) { cout << "request " << request <<endl;} if(debug) { cout << "request " << request <<endl;}
pvRequest = createRequest->createRequest(request); pvRequest = createRequest->createRequest(request);
if(pvRequest.get()==NULL) { cout<< createRequest->getMessage() << endl;} if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
if(debug) { cout << *pvRequest << endl;} if(debug) { cout << pvRequest << endl;}
testOk1(pvRequest.get()!=NULL); testOk1(pvRequest.get()!=NULL);
testOk1(pvRequest->getSubField("field.alarm").get()!=NULL); testOk1(pvRequest->getSubField("field.alarm").get()!=NULL);
testOk1(pvRequest->getSubField("field.timeStamp").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)"; request = "record[process=true]field(alarm,timeStamp,power.value)";
if(debug) { cout << "request " << request <<endl;} if(debug) { cout << "request " << request <<endl;}
pvRequest = createRequest->createRequest(request); pvRequest = createRequest->createRequest(request);
if(pvRequest.get()==NULL) { cout<< createRequest->getMessage() << endl;} if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
if(debug) { cout << *pvRequest << endl;} if(debug) { cout << pvRequest << endl;}
testOk1(pvRequest.get()!=NULL); testOk1(pvRequest.get()!=NULL);
pvString = pvRequest->getSubField<PVString>("record._options.process"); pvString = pvRequest->getSubField<PVString>("record._options.process");
sval = pvString->get(); sval = pvString->get();
@@ -158,8 +158,8 @@ static void testCreateRequest() {
request = "record[process=true]field(alarm,timeStamp[algorithm=onChange,causeMonitor=false],power{value,alarm})"; request = "record[process=true]field(alarm,timeStamp[algorithm=onChange,causeMonitor=false],power{value,alarm})";
if(debug) { cout << "request " << request <<endl;} if(debug) { cout << "request " << request <<endl;}
pvRequest = createRequest->createRequest(request); pvRequest = createRequest->createRequest(request);
if(pvRequest.get()==NULL) { cout<< createRequest->getMessage() << endl;} if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
if(debug) { cout << *pvRequest << endl;} if(debug) { cout << pvRequest << endl;}
testOk1(pvRequest.get()!=NULL); testOk1(pvRequest.get()!=NULL);
pvString = pvRequest->getSubField<PVString>("record._options.process"); pvString = pvRequest->getSubField<PVString>("record._options.process");
sval = pvString->get(); sval = pvString->get();
@@ -179,8 +179,8 @@ static void testCreateRequest() {
request = "record[int=2,float=3.14159]field(alarm,timeStamp[shareData=true],power.value)"; request = "record[int=2,float=3.14159]field(alarm,timeStamp[shareData=true],power.value)";
if(debug) { cout << "request " << request <<endl;} if(debug) { cout << "request " << request <<endl;}
pvRequest = createRequest->createRequest(request); pvRequest = createRequest->createRequest(request);
if(pvRequest.get()==NULL) { cout<< createRequest->getMessage() << endl;} if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
if(debug) { cout << *pvRequest << endl;} if(debug) { cout << pvRequest << endl;}
testOk1(pvRequest.get()!=NULL); testOk1(pvRequest.get()!=NULL);
pvString = pvRequest->getSubField<PVString>("record._options.int"); pvString = pvRequest->getSubField<PVString>("record._options.int");
sval = pvString->get(); sval = pvString->get();
@@ -201,8 +201,8 @@ static void testCreateRequest() {
+ "current{value,alarm},voltage{value,alarm})"; + "current{value,alarm},voltage{value,alarm})";
if(debug) { cout << "request " << request <<endl;} if(debug) { cout << "request " << request <<endl;}
pvRequest = createRequest->createRequest(request); pvRequest = createRequest->createRequest(request);
if(pvRequest.get()==NULL) { cout<< createRequest->getMessage() << endl;} if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
if(debug) { cout << *pvRequest << endl;} if(debug) { cout << pvRequest << endl;}
testOk1(pvRequest.get()!=NULL); testOk1(pvRequest.get()!=NULL);
testOk1(pvRequest->getSubField("putField.power.value").get()!=NULL); testOk1(pvRequest->getSubField("putField.power.value").get()!=NULL);
testOk1(pvRequest->getSubField("getField.alarm").get()!=NULL); testOk1(pvRequest->getSubField("getField.alarm").get()!=NULL);
@@ -221,8 +221,8 @@ static void testCreateRequest() {
+ "})"; + "})";
if(debug) { cout << "request " << request <<endl;} if(debug) { cout << "request " << request <<endl;}
pvRequest = createRequest->createRequest(request); pvRequest = createRequest->createRequest(request);
if(pvRequest.get()==NULL) { cout<< createRequest->getMessage() << endl;} if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
if(debug) { cout << *pvRequest << endl;} if(debug) { cout << pvRequest << endl;}
testOk1(pvRequest.get()!=NULL); testOk1(pvRequest.get()!=NULL);
testOk1(pvRequest->getSubField("field.alarm").get()!=NULL); testOk1(pvRequest->getSubField("field.alarm").get()!=NULL);
testOk1(pvRequest->getSubField("field.timeStamp").get()!=NULL); testOk1(pvRequest->getSubField("field.timeStamp").get()!=NULL);
@@ -243,8 +243,8 @@ static void testCreateRequest() {
+ ")"; + ")";
if(debug) { cout << "request " << request <<endl;} if(debug) { cout << "request " << request <<endl;}
pvRequest = createRequest->createRequest(request); pvRequest = createRequest->createRequest(request);
if(pvRequest.get()==NULL) { cout<< createRequest->getMessage() << endl;} if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
if(debug) { cout << *pvRequest << endl;} if(debug) { cout << pvRequest << endl;}
testOk1(pvRequest.get()!=NULL); testOk1(pvRequest.get()!=NULL);
testOk1(pvRequest->getSubField("putField.power.value").get()!=NULL); testOk1(pvRequest->getSubField("putField.power.value").get()!=NULL);
testOk1(pvRequest->getSubField("getField.alarm").get()!=NULL); testOk1(pvRequest->getSubField("getField.alarm").get()!=NULL);
@@ -276,8 +276,8 @@ static void testCreateRequest() {
request = "a{b{c{d}}}"; request = "a{b{c{d}}}";
if(debug) { cout << "request " << request <<endl;} if(debug) { cout << "request " << request <<endl;}
pvRequest = createRequest->createRequest(request); pvRequest = createRequest->createRequest(request);
if(pvRequest.get()==NULL) { cout<< createRequest->getMessage() << endl;} if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
if(debug) { cout << *pvRequest << endl;} if(debug) { cout << pvRequest << endl;}
testOk1(pvRequest.get()!=NULL); testOk1(pvRequest.get()!=NULL);
testOk1(pvRequest->getSubField("field.a.b.c.d").get()!=NULL); testOk1(pvRequest->getSubField("field.a.b.c.d").get()!=NULL);
testPass("request %s",request.c_str()); testPass("request %s",request.c_str());
@@ -302,12 +302,28 @@ static void testCreateRequest() {
cout << "reason " << createRequest->getMessage() << endl; cout << "reason " << createRequest->getMessage() << endl;
testOk1(pvRequest.get()==NULL); testOk1(pvRequest.get()==NULL);
testPass("request %s",request.c_str()); 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) MAIN(testCreateRequest)
{ {
testPlan(117); testPlan(121);
testCreateRequest(); testCreateRequestInternal();
return testDone(); return testDone();
} }

View File

@@ -108,7 +108,6 @@ static void testPVScalar(
} }
static void testPVScalarArray( static void testPVScalarArray(
ScalarType scalarType,
string const & valueNameMaster, string const & valueNameMaster,
string const & valueNameCopy, string const & valueNameCopy,
PVStructurePtr const & pvMaster, PVStructurePtr const & pvMaster,
@@ -123,14 +122,14 @@ static void testPVScalarArray(
shared_vector<double> values(n); shared_vector<double> values(n);
shared_vector<const double> cvalues; 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; for(size_t i=0; i<n; i++) values[i] = i;
const shared_vector<const double> xxx(freeze(values)); const shared_vector<const double> xxx(freeze(values));
pvValueMaster->putFrom(xxx); pvValueMaster->putFrom(xxx);
StructureConstPtr structure = pvCopy->getStructure(); StructureConstPtr structure = pvCopy->getStructure();
if(debug) { cout << "structure from copy" << endl << *structure << endl;} if(debug) { cout << "structure from copy" << endl << *structure << endl;}
pvStructureCopy = pvCopy->createPVStructure(); pvStructureCopy = pvCopy->createPVStructure();
pvValueCopy = pvStructureCopy->getScalarArrayField(valueNameCopy,scalarType); pvValueCopy = pvStructureCopy->getSubField<PVScalarArray>(valueNameCopy);
bitSet = BitSetPtr(new BitSet(pvStructureCopy->getNumberFields())); bitSet = BitSetPtr(new BitSet(pvStructureCopy->getNumberFields()));
pvCopy->initCopy(pvStructureCopy, bitSet); pvCopy->initCopy(pvStructureCopy, bitSet);
if(debug) { cout << "after initCopy pvValueCopy " << *pvValueCopy << endl; } if(debug) { cout << "after initCopy pvValueCopy " << *pvValueCopy << endl; }
@@ -256,7 +255,7 @@ static void arrayTest()
if(debug) { cout << "pvRequest\n" << *pvRequest << endl; } if(debug) { cout << "pvRequest\n" << *pvRequest << endl; }
pvCopy = PVCopy::create(pvMaster,pvRequest,""); pvCopy = PVCopy::create(pvMaster,pvRequest,"");
valueNameCopy = "value"; valueNameCopy = "value";
testPVScalarArray(pvDouble,valueNameMaster,valueNameCopy,pvMaster,pvCopy); testPVScalarArray(valueNameMaster,valueNameCopy,pvMaster,pvCopy);
request = ""; request = "";
valueNameMaster = "value"; valueNameMaster = "value";
pvRequest = createRequest->createRequest(request); pvRequest = createRequest->createRequest(request);
@@ -264,7 +263,7 @@ static void arrayTest()
if(debug) { cout << "pvRequest\n" << *pvRequest << endl; } if(debug) { cout << "pvRequest\n" << *pvRequest << endl; }
pvCopy = PVCopy::create(pvMaster,pvRequest,""); pvCopy = PVCopy::create(pvMaster,pvRequest,"");
valueNameCopy = "value"; valueNameCopy = "value";
testPVScalarArray(pvDouble,valueNameMaster,valueNameCopy,pvMaster,pvCopy); testPVScalarArray(valueNameMaster,valueNameCopy,pvMaster,pvCopy);
request = "alarm,timeStamp,value"; request = "alarm,timeStamp,value";
valueNameMaster = "value"; valueNameMaster = "value";
pvRequest = createRequest->createRequest(request); pvRequest = createRequest->createRequest(request);
@@ -272,7 +271,7 @@ static void arrayTest()
if(debug) { cout << "pvRequest\n" << *pvRequest << endl; } if(debug) { cout << "pvRequest\n" << *pvRequest << endl; }
pvCopy = PVCopy::create(pvMaster,pvRequest,""); pvCopy = PVCopy::create(pvMaster,pvRequest,"");
valueNameCopy = "value"; valueNameCopy = "value";
testPVScalarArray(pvDouble,valueNameMaster,valueNameCopy,pvMaster,pvCopy); testPVScalarArray(valueNameMaster,valueNameCopy,pvMaster,pvCopy);
} }
static PVStructurePtr createPowerSupply() 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 TESTPROD_HOST += testThread
PROD_HOST += testThread
testThread_SRCS += testThread.cpp testThread_SRCS += testThread.cpp
testHarness_SRCS += testThread.cpp
TESTS += testThread 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 testTimer_SRCS += testTimer.cpp
testHarness_SRCS += testTimer.cpp
TESTS += testTimer TESTS += testTimer
PROD_HOST += testBitSet TESTPROD_HOST += testBitSet
testBitSet_SRCS += testBitSet.cpp testBitSet_SRCS += testBitSet.cpp
testHarness_SRCS += testBitSet.cpp
TESTS += testBitSet TESTS += testBitSet
PROD_HOST += testOverrunBitSet TESTPROD_HOST += testOverrunBitSet
testOverrunBitSet_SRCS += testOverrunBitSet.cpp testOverrunBitSet_SRCS += testOverrunBitSet.cpp
testHarness_SRCS += testOverrunBitSet.cpp
TESTS += testOverrunBitSet TESTS += testOverrunBitSet
PROD_HOST += testByteOrder TESTPROD_HOST += testByteOrder
testByteOrder_SRCS += testByteOrder.cpp testByteOrder_SRCS += testByteOrder.cpp
PROD_HOST += testByteBuffer TESTPROD_HOST += testByteBuffer
testByteBuffer_SRCS += testByteBuffer.cpp testByteBuffer_SRCS += testByteBuffer.cpp
testHarness_SRCS += testByteBuffer.cpp
TESTS += testByteBuffer TESTS += testByteBuffer
PROD_HOST += testBaseException TESTPROD_HOST += testBaseException
testBaseException_SRCS += testBaseException.cpp testBaseException_SRCS += testBaseException.cpp
testHarness_SRCS += testBaseException.cpp
TESTS += testBaseException TESTS += testBaseException
PROD_HOST += testSharedVector TESTPROD_HOST += testSharedVector
testSharedVector_SRCS += testSharedVector.cpp testSharedVector_SRCS += testSharedVector.cpp
testHarness_SRCS += testSharedVector.cpp
TESTS += testSharedVector TESTS += testSharedVector
PROD_HOST += testSerialization TESTPROD_HOST += testSerialization
testSerialization_SRCS += testSerialization.cpp testSerialization_SRCS += testSerialization.cpp
testHarness_SRCS += testSerialization.cpp
TESTS += testSerialization TESTS += testSerialization
PROD_HOST += testTimeStamp TESTPROD_HOST += testTimeStamp
testTimeStamp_SRCS += testTimeStamp.cpp testTimeStamp_SRCS += testTimeStamp.cpp
testHarness_SRCS += testTimeStamp.cpp
TESTS += testTimeStamp TESTS += testTimeStamp
PROD_HOST += testQueue TESTPROD_HOST += testQueue
testQueue_SRCS += testQueue.cpp testQueue_SRCS += testQueue.cpp
testHarness_SRCS += testQueue.cpp
TESTS += testQueue TESTS += testQueue
PROD_HOST += testMessageQueue TESTPROD_HOST += testMessageQueue
testMessageQueue_SRCS += testMessageQueue.cpp testMessageQueue_SRCS += testMessageQueue.cpp
testHarness_SRCS += testMessageQueue.cpp
TESTS += testMessageQueue TESTS += testMessageQueue
PROD_HOST += testTypeCast TESTPROD_HOST += testTypeCast
testTypeCast_SRCS += testTypeCast.cpp testTypeCast_SRCS += testTypeCast.cpp
testHarness_SRCS += testTypeCast.cpp
TESTS += testTypeCast 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... "); printf("testBaseException... ");
try { try {
@@ -86,7 +86,7 @@ MAIN(testBaseException)
testPlan(2); testPlan(2);
testDiag("Tests base exception"); testDiag("Tests base exception");
testLogicException(); testLogicException();
testBaseException(); testBaseExceptionTest();
return testDone(); return testDone();
} }

View File

@@ -1,7 +1,8 @@
#include <testMain.h>
#include <epicsEndian.h> #include <epicsEndian.h>
#include <stdio.h> #include <stdio.h>
int main() MAIN(testByteOrder)
{ {
printf("EPICS_BYTE_ORDER: %s\n", (EPICS_BYTE_ORDER == EPICS_ENDIAN_LITTLE) ? "little" : "big"); 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"); 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 buffer;
string properties("alarm,timeStamp,display"); string properties("alarm,timeStamp,display");
PVStructurePtr pvStructure = standardPVField->scalar(pvDouble,properties); PVStructurePtr pvStructure = standardPVField->scalar(pvDouble,properties);
PVDoublePtr pvValue = pvStructure->getDoubleField("value"); PVDoublePtr pvValue = pvStructure->getSubField<PVDouble>("value");
uint32 valueOffset = (uint32) pvValue->getFieldOffset(); uint32 valueOffset = (uint32) pvValue->getFieldOffset();
PVStructurePtr pvAlarm = pvStructure->getStructureField("alarm"); PVStructurePtr pvAlarm = pvStructure->getSubField<PVStructure>("alarm");
PVIntPtr pvSeverity = pvAlarm->getIntField("severity"); PVIntPtr pvSeverity = pvAlarm->getSubField<PVInt>("severity");
PVStringPtr pvMessage = pvAlarm->getStringField("message"); PVStringPtr pvMessage = pvAlarm->getSubField<PVString>("message");
uint32 severityOffset = (uint32) pvSeverity->getFieldOffset(); uint32 severityOffset = (uint32) pvSeverity->getFieldOffset();
uint32 messageOffset = (uint32) pvMessage->getFieldOffset(); uint32 messageOffset = (uint32) pvMessage->getFieldOffset();
PVStructurePtr pvTimeStamp = pvStructure->getStructureField("timeStamp"); PVStructurePtr pvTimeStamp = pvStructure->getSubField<PVStructure>("timeStamp");
PVLongPtr pvSeconds = pvTimeStamp->getLongField("secondsPastEpoch"); PVLongPtr pvSeconds = pvTimeStamp->getSubField<PVLong>("secondsPastEpoch");
PVIntPtr pvNanoseconds = pvTimeStamp->getIntField("nanoseconds"); PVIntPtr pvNanoseconds = pvTimeStamp->getSubField<PVInt>("nanoseconds");
PVIntPtr pvUserTag = pvTimeStamp->getIntField("userTag"); PVIntPtr pvUserTag = pvTimeStamp->getSubField<PVInt>("userTag");
uint32 timeStampOffset = (uint32) pvTimeStamp->getFieldOffset(); uint32 timeStampOffset = (uint32) pvTimeStamp->getFieldOffset();
uint32 secondsOffset = (uint32) pvSeconds->getFieldOffset(); uint32 secondsOffset = (uint32) pvSeconds->getFieldOffset();
uint32 nanosecondsOffset = (uint32) pvNanoseconds->getFieldOffset(); uint32 nanosecondsOffset = (uint32) pvNanoseconds->getFieldOffset();
@@ -132,7 +132,7 @@ void test()
} }
MAIN(testOverrunBitSet`) MAIN(testOverrunBitSet)
{ {
testPlan(41); testPlan(41);
testDiag("Tests for changeBitSet and overrunBitSet"); testDiag("Tests for changeBitSet and overrunBitSet");

View File

@@ -385,9 +385,9 @@ void testStructure() {
testDiag("\tSimple structure serialization"); testDiag("\tSimple structure serialization");
PVStructurePtr pvStructure = factory->createPVStructure(getStandardField()->timeStamp()); PVStructurePtr pvStructure = factory->createPVStructure(getStandardField()->timeStamp());
pvStructure->getLongField("secondsPastEpoch")->put(123); pvStructure->getSubField<PVLong>("secondsPastEpoch")->put(123);
pvStructure->getIntField("nanoseconds")->put(456); pvStructure->getSubField<PVInt>("nanoseconds")->put(456);
pvStructure->getIntField("userTag")->put(789); pvStructure->getSubField<PVInt>("userTag")->put(789);
serializationTest(pvStructure); serializationTest(pvStructure);
@@ -716,7 +716,9 @@ void testArraySizeType() {
serializationFieldTest(s); serializationFieldTest(s);
PVStructurePtr pvs = getPVDataCreate()->createPVStructure(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); serializationTest(pvs);
} }
@@ -790,7 +792,6 @@ MAIN(testSerialization) {
delete control; delete control;
delete flusher; delete flusher;
epicsExitCallAtExits();
return testDone(); return testDone();
} }

Some files were not shown because too many files have changed in this diff Show More