111 Commits
4.0.0 ... 5.0.2

Author SHA1 Message Date
Dave Hickin
892f1e2242 Merge branch 'master' into release/5.0 2015-10-17 10:36:39 +01:00
Dave Hickin
eb440e4662 Corrections to ntCPP.html 2015-10-17 10:29:39 +01:00
Dave Hickin
bd5d0dee12 Add new (markdown) README 2015-10-17 00:33:02 +01:00
Dave Hickin
f02ac3c139 Merge branch 'master' into release/5.0 2015-10-16 23:25:24 +01:00
Dave Hickin
3b645933f5 Javadoc corrections 2015-10-16 19:19:58 +01:00
Dave Hickin
5cca3a10ac Rename variable to match header. 2015-10-16 15:47:38 +01:00
Dave Hickin
bab0d964ab Add missing implementation of NTScalarArray::value
Use value in unit tests instead of deprecated arrayValue.
2015-10-16 15:46:56 +01:00
Dave Hickin
51d4d270cd Multiple Doxygen improvements 2015-10-16 15:42:56 +01:00
Dave Hickin
3aa1f533bf Add new version of ntCPP.html
Only state that the new types have been added.
Document these in next version.
2015-10-16 15:38:55 +01:00
Dave Hickin
cebc68474d Update TODO 2015-10-16 15:37:03 +01:00
Dave Hickin
a1ac2f41b4 Doxygen fix 2015-10-09 11:44:36 +01:00
Dave Hickin
d8eb50bff8 Release notes: add for 5.0 and improve for 4.0
Add list of new supported types and summary of API changes.
2015-10-08 10:05:42 +01:00
Ralph Lange
e93d1c5c42 jenkins: fix CloudBees doc job 2015-09-28 15:00:47 +02:00
Ralph Lange
fc641b48c3 jenkins: fix CloudBees doc job 2015-09-28 14:59:35 +02:00
Ralph Lange
bcaac0163a jenkins: adapt doc script to new CloudBees jenkins job 2015-09-14 15:17:55 +02:00
Ralph Lange
8e97c2e8bd jenkins: adapt doc script to new CloudBees jenkins job 2015-09-14 15:13:51 +02:00
Dave Hickin
f9d27b2d74 Merge branch 'master' into release/5.0 2015-09-05 07:38:15 +01:00
Dave Hickin
2bc01a482e Doxygen fixes 2015-09-05 07:34:18 +01:00
Ralph Lange
392cc7426d jenkins: update dependencies pvCommonCPP/4.1 pvDataCPP/5.0 2015-09-04 11:55:29 +02:00
Dave Hickin
dd955ea81e Ammend license notice in unit tests
Replaced references to "EPICS pvData" with "this software" in per-file
copyright notice - consistent with other files.
2015-09-04 09:41:08 +01:00
Dave Hickin
a0a19bcfd9 Fix bug in NTUtils::is_a
Previous implementation matches <type-name>:1x.0 and <type-name>:1.0,
depending on the order of the arguments, e.g.
NTUtils::is_a("epics:nt/NTTable:11.0", "epics:nt/NTTable:1.0") returned
true. Fix this and add unit tests to cover this.
2015-09-04 09:39:27 +01:00
Dave Hickin
16b46448c0 License and copyright
Replaced references to "EPICS pvData" and "EPICS JavaIOC" with "this
software" in per-file copyright notice - consistent with other files.
Add BNL and DLS to copyright and legal disclaimers.
2015-09-04 09:24:54 +01:00
Dave Hickin
e5947aa0a2 Add unit tests for NTNDArrayAttribute 2015-09-04 08:37:09 +01:00
Dave Hickin
3c30598a56 Add unit test for NTHistogram 2015-09-04 00:34:41 +01:00
Dave Hickin
85673cadad Add unit test for NTContinuum 2015-09-04 00:33:57 +01:00
Dave Hickin
db0d1e8f9e Fix for NTHistogram::isCompatible()
Correct null pointer check - logic was inverted
2015-09-04 00:33:06 +01:00
Dave Hickin
99f9e0429f Remove duplicate NTField 2015-09-03 14:10:08 +01:00
Dave Hickin
3dc852e2b7 Delete commented out code 2015-09-03 14:09:36 +01:00
Dave Hickin
d9c3dfcf26 Use NTNDArrayAttribute in constructing NTNDArray
Use NTNDArrayAttribute wrapper to construct NTAttributes in NTNDArray.
Delete unused attribute string.
2015-09-03 14:08:56 +01:00
Ralph Lange
38f7d6bea1 jenkins: add configurable dependent branch versions 2015-09-03 13:44:17 +02:00
Matej Sekoranja
4f38e7904d fixed rtems/vxworks compilation 2015-09-01 21:12:47 +02:00
Matej Sekoranja
ad03935c5b Merge pull request #4 from anjohnson/add-license-file
Add license and copyright files
2015-09-01 20:06:49 +02:00
Dave Hickin
5574452b08 Call addIsConnected() in unit tests
for multi-channel types
2015-09-01 16:50:46 +01:00
Dave Hickin
649cd6800d Make isConnected optional in multi channel types 2015-09-01 15:55:21 +01:00
Dave Hickin
05a7a6923f Implement NTNDArray::isValid() 2015-09-01 15:53:52 +01:00
Dave Hickin
f5226f23dc Implement NTNDArray::isCompatible(Structure)
Add implementation of NTNDArray::isCompatible(Structure). Implement
NTNDArray::isCompatible(PVStructure) in terms of this.
2015-09-01 15:53:09 +01:00
Dave Hickin
e1fdcfcab0 Add implementation of NTID 2015-09-01 15:50:18 +01:00
Dave Hickin
5ec16a1772 Fix build error
boolean replaced by bool
2015-09-01 02:40:14 +01:00
Dave Hickin
ba64c6a6a5 Add isValid() implementations
for NTMultiChannel, NTScalarMultiChannel, NTTable and NTURI.
2015-08-31 23:53:10 +01:00
Dave Hickin
ed9a707f14 More efficient implementation of NTTable
Cache the value field. Allows simpler implementation of getColumn().
2015-08-31 23:50:51 +01:00
Dave Hickin
6ec5fb6ef9 Add implentations of isValid()
for NTAggregate, NTAttibute, NTContinuum, NTEnum, NTHistogram, NTMatrix,
NTNameValue, NTNDArrayAttribute, NTScalar, NTScalarArray and NTUnion.
2015-08-30 23:46:02 +01:00
Dave Hickin
ddab44823f Use NTAttribute wrapper in NTNDArray
Use the wrapper NTAttribute wrapper NTNDArrayAttribute to test the
attribute field in implementation of NTNDArray::isCompatible(Structure).
2015-08-29 11:09:32 +01:00
Dave Hickin
d54060576a Add implementation of isCompatible(Structure)
for all types except NTNDArray and implement isCompatible(PVStructure)
in terms of it.
2015-08-29 11:06:37 +01:00
Dave Hickin
e8a9beec07 Remove excess blank lines 2015-08-29 11:00:40 +01:00
Dave Hickin
84304d9b4e Add utility class for parsing NT IDs 2015-08-21 14:46:26 +01:00
Dave Hickin
b62cb22818 Added NTNDArrayAttribute
Added wrapper for NTAttributes extended as required by NTNDArray.
2015-08-21 07:45:16 +01:00
Dave Hickin
1e6fb17e92 Add NTURI 2015-08-21 06:47:52 +01:00
Dave Hickin
bc2622f70a Add getColumnNames() to NTTable 2015-08-21 06:46:17 +01:00
Dave Hickin
da81f8db83 Add NTHistogram 2015-08-21 03:55:35 +01:00
Dave Hickin
7c58eae97e Add NTContinuum 2015-08-21 03:55:04 +01:00
Dave Hickin
0b3e1c9fd1 Add isValid() and overloads of is_a() and isCompatible()
Add convenience methods is_a(PVStructure). Add overloads of isCompatible
taking a Structure since implementation of isCompatible(PVStructure)
only uses introspection interface. Implement for NTScalar and
NTScalarArray. Add isValid() function that checks NT is valid through data
interface.
2015-08-21 01:15:40 +01:00
Dave Hickin
59afc5335a Fixed unit NTTable test failure 2015-08-20 18:32:18 +01:00
Dave Hickin
399a39a20a Tell git to ignore build output of unit tests 2015-08-20 17:26:03 +01:00
Dave Hickin
000dde0454 Make attach* functions return bool in multi-channel types
The attachAlarm and attachTimeStamps() return true if successful, false
otherwise in other classes. In NTMultiChannel and NTScalarMultiChannel
they returned void. Bring multi-channel behaviour in line.
2015-08-20 17:23:59 +01:00
Dave Hickin
5076057d8d Make isConnected optional field of multi-channel types
A boolean[] isConnected field was included in all constructed
NTMultiChannels and NTScalarMultiChannels. However this is neither a
required nor optional field of these types. Applications use this
though, (specifically pvaClient) so treat as if optional field. Add
addIsConnected() function to builders and retain isConnected() in
wrapper classes. Leave isConnected field in structures until clients
updated.
2015-08-20 17:19:18 +01:00
Dave Hickin
fd60732a8c Rename add() addColumn() in NTTable
Function for adding columns to table (i.e. to value subfield) was
add(ScalarType). However add(Field) adds extra field to top-level
structure. Rename former to avoid confusion and as more meaningful
name. Update unit tests.
2015-08-20 17:07:27 +01:00
Dave Hickin
002a465705 Clear up confusion between labels and column names
The labels are strings used in the displaying of the columns of a table
e.g. column titles or headers. The column names of an NTTable are the
names of the fields containing the column data. There was some confusion
in the implementation between these. Rename the labels variable
columnNames and correct the comments. Tables were created with labels
equal to the column names. Retain this behaviour for backwards
compatibility, as a sensible default and to always create a valid table,
but document this.
2015-08-20 17:03:27 +01:00
dhickin
28186f0e3d Merge pull request #6 from dhickin/add_missing_types
Add normative types
2015-08-20 16:35:53 +01:00
Dave Hickin
fc037cf6dc Add unit tests for NTAttribute 2015-08-20 16:16:58 +01:00
Dave Hickin
5ddcc70993 Add getName() and getTags() functions to NTAttribute 2015-08-20 16:16:34 +01:00
Dave Hickin
dc93316856 Merge branch 'add_missing_types' of github.com:dhickin/normativeTypesCPP into add_missing_types 2015-08-20 09:44:27 +01:00
Dave Hickin
b40eca79cf Add NTAttribute including builder 2015-08-20 08:43:27 +01:00
Dave Hickin
f6f5539f7b Add NTAggregate including builder and unit tests 2015-08-20 08:41:45 +01:00
Dave Hickin
0d66034092 Add NTUnion including builder and unit tests 2015-08-20 08:01:29 +01:00
Dave Hickin
1de2666993 Add NTEnum including builder and unit tests 2015-08-20 07:59:29 +01:00
Dave Hickin
7d0b6d86ea Add NTMatrix including builder and unit tests 2015-08-20 07:56:20 +01:00
Ralph Lange
bef1a86b8b jenkins: fix cut-n-paste issue in doc job 2015-08-18 16:54:42 +02:00
Ralph Lange
8f66d21cca Remove mercurial debris (.hg*) 2015-08-18 16:10:42 +02:00
Ralph Lange
f4b7bdbdf0 jenkins: remove hgweb job; split build and doc jobs; update EPICS Base version 2015-08-18 16:10:11 +02:00
Dave Hickin
5f8922e349 Incremented number of tests in NTTable test plan 2015-08-13 12:46:27 +01:00
Dave Hickin
5b7c6ea4d8 Fixed NTTable units tests for extra fields
After fix for NTTable extra fields not being created was merged, unit
tests failed. Tests were wrong. Test was checking number of fields of
constructed structure against number expected without the extra fields.
Corrected check and added checks for extra fields.
2015-08-13 10:59:15 +01:00
dhickin
08f8b56740 Merge pull request #5 from brunoseivam/patch-1
Fix extra fields not being created
2015-08-13 09:51:02 +01:00
Bruno Martins
b52fc4fce8 Fix extra fields not being created
FieldBuilder::createStructure() was being called too early inside NTTableBuilder::createStructure(), preventing extra fields from being properly created.
2015-08-12 22:46:46 -04:00
Andrew Johnson
b976d918d5 Resolves epics-base/normativeTypesCPP #1 2015-08-11 17:43:31 -05:00
Andrew Johnson
c7a58af787 Add COPYRIGHT file 2015-08-11 16:53:36 -05:00
Dave Hickin
b1143fea9e Make #endif comments match #ifdef in inclusion guards 2015-08-06 14:06:14 +01:00
Dave Hickin
efa9dff1d4 Change references to NTTableBuilder to NTScalarBuilder in NTScalar 2015-08-06 14:04:47 +01:00
Dave Hickin
3b9f8a26c0 Include ntscalarMultiChannel.h in nt.h 2015-08-06 13:57:11 +01:00
dhickin
f64329e661 Merge pull request #3 from dhickin/NTScalarMultiChannel
Add NTScalarMultiChannel
2015-08-05 22:13:19 +01:00
Dave Hickin
8b9a8e7050 Add tests for NTScalarMultiChannel 2015-08-04 21:32:34 +01:00
Dave Hickin
5381a0c294 Add NTScalarMultiChannel 2015-08-04 21:30:13 +01:00
Andrew Johnson
36b8e60152 Fix module name in sources LICENSE reference 2015-08-03 16:47:28 -05:00
Andrew Johnson
f226c7ac96 Add LICENSE file copied from pvDataCPP 2015-08-03 16:23:21 -05:00
Andrew Johnson
2f54b89227 Added .gitignore file 2015-06-16 18:06:08 -05:00
Andrew Johnson
ec02b9f7ee Cleanup: Remove extraneous / from SRC 2015-06-08 17:47:14 -05:00
dhickin
efff7f5041 Improve thread-safety of NTNDArray. 2015-06-08 10:34:10 +01:00
dhickin
8c292eeebc Reorder optional fields to consistent order to match new NT spec. 2015-05-11 14:02:18 +01:00
dhickin
25e8c65bb0 Reorder declarations/definitions. 2015-04-22 14:55:40 +01:00
dhickin
f47b059a5b Add definition of missing uniqueId() function. 2015-04-22 14:47:34 +01:00
dhickin
16d8284131 merge branch release/4.0 to default. 2015-04-22 14:42:00 +01:00
Ralph Lange
ef4a9d6b4b jenkins: fix cloudbees script (commands must return 0) 2014-12-19 14:16:57 +01:00
Ralph Lange
8ec19d25f1 jenkins: create and update documentation in only one build configuration 2014-12-19 13:18:23 +01:00
Matej Sekoranja
2d3b415c00 removed bin dbd from upload TAR 2014-12-16 10:43:47 +01:00
Matej Sekoranja
177a048220 added jenkins support 2014-12-15 23:26:01 +01:00
Marty Kraimer
acd986c19d work on doxygen 2014-12-15 08:31:41 -05:00
dhickin
3cb954aefa make local RELEASE.local files take precedence over those in TOP/.. 2014-12-09 13:48:15 +00:00
dhickin
bffeca57a8 Added tag 4.0.2 for changeset e4b8d66cee36 2014-12-05 12:07:35 +00:00
dhickin
e8a04138b0 Added dated version (20141009) for latest html documentation. 2014-12-04 16:05:51 +00:00
dhickin
9f5aec1609 Corrected some spelling and some minor formatting issues. 2014-12-04 15:49:43 +00:00
dhickin
8dadad8101 make "local" *.local files take precedence over those in TOP/.. 2014-12-03 16:55:25 +00:00
dhickin
9cc7c65df6 include CONFIG_SITE.local instead of CONFIG.local at top-level. 2014-12-03 16:10:23 +00:00
Matej Sekoranja
518718357c Added tag 4.0.1 for changeset 1c140dd0e199 2014-11-11 17:03:05 +01:00
Matej Sekoranja
1ae93ddaed merge 2014-11-11 17:02:58 +01:00
Matej Sekoranja
99bf23e8fa fixed Makefile for ntutils test 2014-11-11 17:02:33 +01:00
Matej Sekoranja
b5846433bf Added tag 4.0.1 for changeset 0daade17a744 2014-11-10 21:54:39 +01:00
Matej Sekoranja
8760d5e314 merge 2014-11-10 21:53:52 +01:00
Matej Sekoranja
a25a89fadc win32 build, all test pass 2014-11-10 21:52:10 +01:00
Matej Sekoranja
49312d62d5 added epicsShared export declarations 2014-11-10 10:24:10 +01:00
Matej Sekoranja
42fb15211a NTUtils added, is_a for new URI scheme 2014-11-10 10:04:32 +01:00
Matej Sekoranja
86ee0c5295 merge 2014-10-29 13:26:21 +01:00
Matej Sekoranja
1fca4d5757 Added tag 4.0.0 for changeset ec29bda853f5 2014-10-29 13:26:06 +01:00
79 changed files with 15255 additions and 1995 deletions

9
.gitignore vendored Normal file
View File

@@ -0,0 +1,9 @@
bin/
include/
lib/
db/
dbd/
configure/*.local
html/
**/O.*
**/**/O.*

View File

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

View File

@@ -1,20 +0,0 @@
QtC*
syntax: glob
.DS_Store
./bin
./include
./lib
./doc
./db
./dbd
./envPaths
./documentation/html
./O.*
./*.pyc
./*.so
./documentation/html
./RELEASE.local
./CONFIG_SITE.local
syntax: regexp

View File

@@ -1,4 +0,0 @@
b9a943e6828731a8a89e811818b2d91faff69d86 1.0-BETA
aaa5f5840b7eea8afaafb4d13a49bf78975aac0f 4.0.0
aaa5f5840b7eea8afaafb4d13a49bf78975aac0f 4.0.0
df4c65e13c2cfaa92e42f84a7afc97c81b5f3888 4.0.0

31
COPYRIGHT Normal file
View File

@@ -0,0 +1,31 @@
This software is in part copyrighted by the various organizations and
individuals listed below. Permission to use it is set out in the file
LICENSE that accompanies the software.
In no event shall any copyright holder be liable to any party for
direct, indirect, special, incidental, or consequential damages arising
out of the use of this software, its documentation, or any derivatives
thereof, even if they have been advised of the possibility of such
damage.
The copyright holders specifically disclaim any warranties, including,
but not limited to, the implied warranties of merchantability, fitness
for a particular purpose, and non-infringement. This software is
provided on an "as is" basis, and the copyright holders have no
obligation either collectively or individually to provide maintenance,
support, updates, enhancements, or modifications.
Copyright (c) 2006 - 2015 All rights reserved
Martin R. Kraimer
The University of Chicago, as Operator of Argonne National Laboratory.
Deutsches Elektronen-Synchroton, Member of the Helmholtz Association,
(DESY), HAMBURG, GERMANY,
BERLINER SPEICHERRING GESELLSCHAFT FUER SYNCHROTRONSTRAHLUNG M.B.H.
(BESSY), BERLIN, GERMANY.
COSYLAB (Control System Laboratory), Ljubljana, Slovenia.
Brookhaven Science Associates, as Operator of Brookhaven
National Laboratory.
Diamond Light Source Ltd., Didcot, United Kingdom.

2366
Doxyfile

File diff suppressed because it is too large Load Diff

114
LICENSE Normal file
View File

@@ -0,0 +1,114 @@
Copyright (c) 2006-2015 Martin R. Kraimer
Copyright (c) 2006 The University of Chicago, as Operator of Argonne
National Laboratory.
Copyright (c) 2006 Deutsches Elektronen-Synchrotron,
Member of the Helmholtz Association, (DESY), HAMBURG, GERMANY.
Copyright (c) 2007-2015 Control System Laboratory,
(COSYLAB) Ljubljana Slovenia
Copyright (c) 2010-2015 Brookhaven Science Associates, as Operator of Brookhaven
National Laboratory
Copyright (c) 2011-2015 Diamond Light Source Limited,
(DLS) Didcot, United Kingdom
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
________________________________________________________________________
This software is in part copyrighted by the University of Chicago (UofC)
In no event shall UofC 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
UofC has been advised of the possibility of such damage.
UofC 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 UofC has no obligation to provide maintenance, support,
updates, enhancements, or modifications.
________________________________________________________________________
This software is in part copyrighted by the BERLINER SPEICHERRING
GESELLSCHAFT FUER SYNCHROTRONSTRAHLUNG M.B.H. (BESSY), BERLIN, GERMANY.
In no event shall BESSY 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
BESSY has been advised of the possibility of such damage.
BESSY 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 BESSY has no obligation to provide maintenance, support,
updates, enhancements, or modifications.
________________________________________________________________________
This software is in part copyrighted by the Deutsches Elektronen-Synchroton,
Member of the Helmholtz Association, (DESY), HAMBURG, GERMANY.
In no event shall DESY 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
DESY has been advised of the possibility of such damage.
DESY 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 DESY has no obligation to provide maintenance, support,
updates, enhancements, or modifications.
______________________________________________________________________
This software is in part copyrighted by the Brookhaven
National Laboratory (BNL).
In no event shall BNL be liable to any party for direct, indirect,
special, incidental, or consequential damages arising out of the use of
this software, its documentation, or any derivatives thereof, even if
BNL has been advised of the possibility of such damage.
BNL specifically disclaims any warranties, including, but not limited
to, the implied warranties of merchantability, fitness for a particular
purpose, and non-infringement. This software is provided on an "as is"
basis, and BNL has no obligation to provide maintenance, support,
updates, enhancements, or modifications.
________________________________________________________________________
This software is in part copyrighted by Diamond Light Source Limited (DLS)
In no event shall DLS be liable to any party for direct, indirect,
special, incidental, or consequential damages arising out of the use of
this software, its documentation, or any derivatives thereof, even if
DLS has been advised of the possibility of such damage.
DLS specifically disclaims any warranties, including, but not limited
to, the implied warranties of merchantability, fitness for a particular
purpose, and non-infringement. This software is provided on an "as is"
basis, and DLS has no obligation to provide maintenance, support,
updates, enhancements, or modifications.
________________________________________________________________________

4
README
View File

@@ -1,4 +0,0 @@
Since the Normative Types specification is not yet at Public Working Draft level,
any implementation must be considered alpha. The implementations of helpers under
this repo must be considered alpha level.

78
README.md Normal file
View File

@@ -0,0 +1,78 @@
normativeTypesCPP
=================
normativeTypesCPP is a C++ module containing helper classes which implement
and provide support for the EPICS V4 Normative Types.
The latter are a set of standard high-level data types to aid interoperability
of EPICS V4 applications and are specified in the
[NormativeTypes Specification](http://epics-pvdata.sourceforge.net/alpha/normativeTypes/normativeTypes.html).
Status
------
The current release (5.0) implements fully the
[16 Mar 2015 version](http://epics-pvdata.sourceforge.net/alpha/normativeTypes/normativeTypes_20150316.html)
of the Normative Types Specification.
The module status is alpha and the API and behaviour may change in future
versions.
The previous release (4.0) supported only 6 types.
There is no documentation yet for the new types added in 5.0.
Further Info
------------
Consult the documents in the documentation directory, in particular
* normativeTypesCPP.html
* RELEASE_NOTES.md
Also see the [EPICS Version 4 website](http://epics-pvdata.sourceforge.net)
Prerequisites
-------------
normativeTypesCPP requires recent versions of the following software:
1. EPICS Base (v3.14.12.3 or later)
2. EPICS4 pvCommonCPP (4.1.0 or later)
2. pvDataCPP (5.0.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
PVDATA = /home/install/epicsV4/pvDataCPP
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 normativeTypesCPP.
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

@@ -32,6 +32,6 @@ endif
INSTALL_INCLUDE = $(INSTALL_LOCATION)/include/pv
USR_INCLUDES += -I $(INSTALL_LOCATION)/include
-include $(TOP)/../CONFIG_SITE.local
-include $(TOP)/configure/CONFIG_SITE.local
-include $(TOP)/../CONFIG.local

View File

@@ -28,5 +28,5 @@ TEMPLATE_TOP=$(EPICS_BASE)/templates/makeBaseApp/top
#CAPFAST_TEMPLATES=
#SCH2EDIF_PATH=
-include $(TOP)/configure/RELEASE.local
-include $(TOP)/../RELEASE.local
-include $(TOP)/configure/RELEASE.local

View File

@@ -1,4 +1,81 @@
<h1>Release 4.0 IN DEVELOPMENT</h1>
<h1>Release 5.0</h1>
<p>This release adds support through wrapper classes and builders for the
remaining Normative Types:</p>
<ul>
<li>NTEnum</li>
<li>NTMatrix</li>
<li>NTURI</li>
<li>NTAttribute</li>
<li>NTContinuum</li>
<li>NTHistogram</li>
<li>NTAggregate</li>
<li>NTUnion</li>
<li>NTScalarMultiChannel</li>
</ul>
<p>Release 5.0 therefore implements fully the
<a href="http://epics-pvdata.sourceforge.net/alpha/normativeTypes/normativeTypes_20150316.html">16 Mar 2015 version</a>
of the normativeTypes specification.</p>
<p>Each wrapper class has an extended API:</p>
<ul>
<li>is_a now has a convenience overload taking a PVStructure.</li>
<li>isCompatible, reporting introspection type compatibility, now has an overload
taking a Structure. The PVStructure version is retained as a convenience
method and for backwards compatibility.</li>
<li>An isValid function now reports validity of a compatible PVStructure's data
with respect to the specification.</li>
</ul>
<p>Other changes are:</p>
<ul>
<li>Support for NTAttributes extended as required by NTNDArray
(NTNDArrayAttributes).</li>
<li>A new class for parsing NT IDs (NTID).</li>
<li>Resolution of the confusion between column names and labels in NTTable and
improved API. Function for adding columns is now addColumn rather than add.
New getColumnNames function provided.</li>
<li>isConnected is treated as an optional rather than a required field in
NTMultiChannelArray. isConnected() and addIsConnected() functions added to
wrapper and builder respectively.</li>
<li>Unit tests for all new classes.</li>
</ul>
<h1>Release 4.0</h1>
<p>This is the first release of normativeTypesCPP that is part of an official
EPICS V4 release.
It is a major rewrite of the previous versions of normativeTypesCPP.</p>
It is a major rewrite of the previous versions of normativeTypesCPP.</p>
<p>This release provides support through wrapper classes and builders for the
following Normative Types:</p>
<ul>
<li>NTScalar</li>
<li>NTScalarArray</li>
<li>NTNameValue</li>
<li>NTTable</li>
<li>NTMultiChannel</li>
<li>NTNDArray</li>
</ul>
<p>Each type has a wrapper class of the same name which has functions for checking
compatibility of existing PVStructures (isCompatible) and the reported types of
Structures (is_a), wraps existing PVStructures (wrap, wrapUnsafe) and provides
a convenient interface to all required and optional fields.</p>
<p>Each type has a builder which can create a Structure, a PVStructure or a
wrapper around a new PVStructure. In each case optional or extra fields can be
added and options such as choice of scalar type can be made.</p>
<p>Additional features are:</p>
<ul>
<li>Utility classes NTField and NTPVField for standard structure fields and
NTUtils for type IDs.</li>
<li>Unit tests for the implemented classes.</li>
</ul>

View File

@@ -1,7 +1,75 @@
Release 4.0 IN DEVELOPMENT
Release 5.0
===========
This release adds support through wrapper classes and builders for the
remaining Normative Types:
* NTEnum
* NTMatrix
* NTURI
* NTAttribute
* NTContinuum
* NTHistogram
* NTAggregate
* NTUnion
* NTScalarMultiChannel
Release 5.0 therefore implements fully the
[16 Mar 2015 version](http://epics-pvdata.sourceforge.net/alpha/normativeTypes/normativeTypes_20150316.html)
of the normativeTypes specification.
Each wrapper class has an extended API:
* is_a now has a convenience overload taking a PVStructure.
* isCompatible, reporting introspection type compatibility, now has an overload
taking a Structure. The PVStructure version is retained as a convenience
method and for backwards compatibility.
* An isValid function now reports validity of a compatible PVStructure's data
with respect to the specification.
Other changes are:
* Support for NTAttributes extended as required by NTNDArray
(NTNDArrayAttributes).
* A new class for parsing NT IDs (NTID).
* Resolution of the confusion between column names and labels in NTTable and
improved API. Function for adding columns is now addColumn rather than add.
New getColumnNames function provided.
* isConnected is treated as an optional rather than a required field in
NTMultiChannelArray. isConnected() and addIsConnected() functions added to
wrapper and builder respectively.
* Unit tests for all new classes.
Release 4.0
===========
This is the first release of normativeTypesCPP that is part of an official
EPICS V4 release.
It is a major rewrite of the previous versions of normativeTypesCPP.
This release provides support through wrapper classes and builders for the
following Normative Types:
* NTScalar
* NTScalarArray
* NTNameValue
* NTTable
* NTMultiChannel
* NTNDArray
Each type has a wrapper class of the same name which has functions for checking
compatibility of existing PVStructures (isCompatible) and the reported types of
Structures (is_a), wraps existing PVStructures (wrap, wrapUnsafe) and provides
a convenient interface to all required and optional fields.
Each type has a builder which can create a Structure, a PVStructure or a
wrapper around a new PVStructure. In each case optional or extra fields can be
added and options such as choice of scalar type can be made.
Additional features are:
* Utility classes NTField and NTPVField for standard structure fields and
NTUtils for type IDs.
* Unit tests for the implemented classes.

View File

@@ -1,22 +0,0 @@
<h1>TODO</h1>
<h2>NTScalarArray</h2>
<p>NTScalarArrayBuilder::arrayValue</p>
<p>Should this be:</p>
<p>NTScalarArrayBuilder::value</p>
<p>This makes NTScalarArray consistent with other NTTypes.</p>
<h2>NTNameValue</h2>
<p>This does not have a value field like all the other NTTypes.
Perhaps instead of</p>
<pre><code>NTNameValue
string[] name
string[] value
</code></pre>
<p>It should be</p>
<pre><code>NTNameValue
value
string[] name
string[] value
</code></pre>
<h2>NTTable</h2>
<p>Should lables be label?
Compare with name,value from NTNameValue.</p>

View File

@@ -1,37 +1,5 @@
TODO
===========
====
NTScalarArray
------------
Documentation for recently added types.
NTScalarArrayBuilder::arrayValue
Should this be:
NTScalarArrayBuilder::value
This makes NTScalarArray consistent with other NTTypes.
NTNameValue
------------
This does not have a value field like all the other NTTypes.
Perhaps instead of
NTNameValue
string[] name
string[] value
It should be
NTNameValue
value
string[] name
string[] value
NTTable
----------
Should lables be label?
Compare with name,value from NTNameValue.

View File

@@ -37,7 +37,7 @@
<h1>EPICS ntCPP</h1>
<!-- Maturity: Working Draft or Request for Comments, or Recommendation, and date. -->
<h2 class="nocount">EPICS v4 Working Group, Working Draft, 09-Oct-2014</h2>
<h2 class="nocount">EPICS v4 Working Group, Working Draft, 16-Oct-2015</h2>
<dl>
<dt>Latest version:</dt>
@@ -46,16 +46,16 @@
</dd>
<dt>This version:</dt>
<dd><a
href="ntCPP_20140919.html">ntCPP_20140919.html</a>
href="ntCPP_20151016.html">ntCPP_20151016.html</a>
</dd>
<dt>Previous version:</dt>
<dd><a
href="ntCPP_20140723.html">ntCPP_20140723.html</a>
href="ntCPP_20141009.html">ntCPP_20141009.html</a>
</dd>
<dt>Editors:</dt>
<dd> Marty Kraimer, BNL<br />
Matej Sekoranja, CosyLab<br />
David Hicken, Diamond Light Source
David Hickin, Diamond Light Source
</dd>
</dl>
@@ -80,7 +80,7 @@ V4 control system programming environment:<br />
<h2 class="nocount">Status of this Document</h2>
<p>This is the 09-Oct-2014 version of the C++ implementation of pvData.
<p>This is the 16-Oct-2015 version of the C++ implementation of pvData.
</p>
@@ -106,28 +106,54 @@ pvDataCPP.html
</a>
</p>
<p>At present the following normative types are implemented:</p>
<ul>
<li><b>NTScalar</b></li>
<li><b>NTScalarArray</b></li>
<li><b>NTEnum</b></li>
<li><b>NTMatrix</b></li>
<li><b>NTURI</b></li>
<li><b>NTNameValue</b></li>
<li><b>NTTable</b></li>
<li><b>NTAttribute</b></li>
<li><b>NTMultiChannel</b></li>
<li><b>NTNDArray</b></li>
<li><b>NTContinuum</b></li>
<li><b>NTHistogram</b></li>
<li><b>NTAggregate</b></li>
</ul>
<p>There is also additional support for NTAttributes which are extended as required by NTNDArray.</p>
<p>Thus normativeTypesCPP implements fully the <a href="http://epics-pvdata.sourceforge.net/alpha/normativeTypes/normativeTypes_20150316.html">
March 16 2015</a> version the Normative Types Specification.</p>
<p>This version of the document only covers the types originally implemented:</p>
<dl>
<dt>NTScalar</dt>
<dd>This has a value field that has type scalar</dd>
<dd>This has a value field that has type scalar.</dd>
<dt>NTScalarArray</dt>
<dd>This has a value field that has type scalarArray</dd>
<dd>This has a value field that has type scalarArray.</dd>
<dt>NTNameValue</dt>
<dd>This has a field name that is a string array
and a field value that has type scalarArray.
Each name[i] is associated with value[i].
</dd>
<dt>NTTable</dt>
<dd>This has a string array field named labels
For each label there is a scalar array field with name = label.
<dd>This has a number of scalar array fields representing the columns of
a table as well as a string array called containing representing column headers.
</dd>
<dt>NTMultiChannel</dt>
<dd>This has a value field that is a union array.
A primary use of this type is to access data from a set of pvAccess channels.
Each element of value holds data from a channel.</dd>
<dt>NTNDArray</dt>
<dd>This type holds NDArray data as defined by the areaDetector facilility.
<dd>This type holds NDArray data as defined by the areaDetector facility.
</dd>
</dl>
<p>Documentation for the remaining types will addressed in the next version of this document.</p>
<p>Each normative type consists of a set of mandatory fields, a set of optional fields,
and any arbitrary number of extra fields.
The mandatory and optional fields are meant for use by standard tools such
@@ -230,20 +256,20 @@ structure parent
<p>An alarm structure is used to report alarms and other problems to the client.
An alarm may be associated with a value field or can be used by a server
to report problems to the client.
An alarm attached to a substructure of the top level structure is normally
An alarm attached to a substructure of the top-level structure is normally
associated with a value field.
An alarm field attached to the top level structure can be used for either:
An alarm field attached to the top-level structure can be used for either:
</p>
<ol>
<li>If the top level structure has a value field then it is an alarm
<li>If the top-level structure has a value field then it is an alarm
for that field.
</li>
<li>To report other problems to the client.</li>
</ol>
<p>If alarms do appear at multiple levels then an alarm is always
provided at the top level.
provided at the top-level.
It uses "maximize severity" to report the highest level severity
of all alarms, i. e. the top level severity is the maximum severity
of all alarms, i.e. the top-level severity is the maximum severity
of all the alarms.</p>
<p>An example is:</p>
<pre>
@@ -260,7 +286,7 @@ structure top
structure alarm
</pre>
<p>In this example power, voltage, and current all have an associated alarm.
The top level alarm would have a severity that matches the highest level
The top-level alarm would have a severity that matches the highest level
severity of power, voltage, an current.</p>
<p>A alarm structure has the following fields:</p>
@@ -289,15 +315,15 @@ a the data for a value field was collected.
There can be multiple timeStamp fields.
A timeStamp associated with a substructure is usually associated with
a value field.
An timeStamp field attached to the top level structure can be used for either:
An timeStamp field attached to the top-level structure can be used for either:
</p>
<ol>
<li>If the top level structure has a value field then it can be the
<li>If the top-level structure has a value field then it can be the
timeStamp for that field.
</li>
<li>The time when the server executed.</li>
</ol>
<p>NTNDArray is an example that has two top level timeStamp field with different
<p>NTNDArray is an example that has two top-level timeStamp fields with different
field names because it wants to report both.</p>
<p>A timeStamp structure has the following fields:</p>
@@ -343,8 +369,8 @@ structure display
string format
string units
</pre>
<p>Note that the format should be a simplifed version of the standard
C formattimg conventions.</p>
<p>Note that the format should be a simplified version of the standard
C formatting conventions.</p>
<h3>enumerated</h3>
<p>This is used to specify a set of choices and an index that selects one
of the choices.
@@ -374,19 +400,19 @@ structure
<p><b>NOTE:</b> NTField, described above, has support for checking to see if
a structure is an alarmLimit structure but no other support for alarmLimit.</p>
<p>
PVData has support named <b>valueAlarm</b> instead of <b>alarmLimit</b>
pvData has support named <b>valueAlarm</b> instead of <b>alarmLimit</b>
(alarmLimit is identical to valueAlarm for type double).
For numeric types the field names are the same but the type
for lowAlarmLimit, lowWarningLimit, highWarningLimit, and highAlarmLimit
is based on the scalarType.
PVData also defines valueAlarm for a scalar boolean value field
pvData also defines valueAlarm for a scalar boolean value field
and for an enumerated structure.
For these completely different field names are defined.
valueAlarm is more for use by servers than for clients.
Thus normative types only defines alarmLimit since this is what
clients like plot tools use.
If the valueAlarm fields, including alarmLimit, are desired than the standardField support from
PVData can be used to generate a valueAlarm field as an extra field.
pvData can be used to generate a valueAlarm field as an extra field.
</p>
<h2>Normative Type Common Features</h2>
@@ -403,7 +429,7 @@ PVData can be used to generate a valueAlarm field as an extra field.
For example <b>NTScalar</b>
</dd>
</dl>
<p>Each bulder also has a number of additional methods for optional fields
<p>Each builder also has a number of additional methods for optional fields
and a method to add extra fields.</p>
<h3>Normative Type Class</h3>
<p>
@@ -479,26 +505,26 @@ where
<dd>This determines the scalar type for the value field.
This must be specified or createStructure will throw an exception.</dd>
<dt>addDescriptor</dt>
<dd>Add optional field descriptor</dd>
<dd>Add optional field descriptor.</dd>
<dt>addAlarm</dt>
<dd>Add optional field alarm</dd>
<dd>Add optional field alarm.</dd>
<dt>addTimeStamp</dt>
<dd>Add optional field timeStamp</dd>
<dd>Add optional field timeStamp.</dd>
<dt>addDisplay</dt>
<dd>Add optional field display</dd>
<dd>Add optional field display.</dd>
<dt>addControl</dt>
<dd>Add optional field control</dd>
<dd>Add optional field control.</dd>
<dt>createStructure</dt>
<dd>Create a introspection instance.</dd>
<dd>Create an introspection instance.</dd>
<dt>createPVStructure</dt>
<dd>Create the data instance.</dd>
<dt>create</dt>
<dd>create an PVScalar instance.</dd>
<dd>create a PVScalar instance.</dd>
<dt>add</dt>
<dd>Add an extra field. As many fields as desired can be added but each must have
a unique name that is not the name of any mandatory or possible optional field.</dd>
</dl>
<p>An NTScalaBuilder can be used to create multiple PVStructure and/or NTScalar instances.
<p>An NTScalarBuilder can be used to create multiple PVStructure and/or NTScalar instances.
Each time createPVScalar is called it clears all internal data after the PVStructure
is created.</p>
<h4>NTScalarBuilder Examples</h4>
@@ -540,7 +566,7 @@ public:
static shared_pointer wrap(PVStructurePtr const &amp; structure);
static shared_pointer wrapUnsafe(PVStructurePtr const &amp; structure);
static bool is_a(StructureConstPtr const &amp; structure);
static bool isComparible(PVStructurePtr const &amp;pvStructure);
static bool isCompatible(PVStructurePtr const &amp;pvStructure);
static NTScalarBuilderPtr createBuilder();
bool attachTimeStamp(PVTimeStamp &amp;pvTimeStamp) const;
@@ -561,19 +587,19 @@ private:
where
<dl>
<dt>wrap</dt>
<dd>Given a pvStructure this creates an NTScalar that warps it.
<dd>Given a PVStructure this creates an NTScalar that wraps it.
It calls <b>isCompatible</b>.
It returns a null PVScalar if <b>isCompatible</b> returns false.
<br />
The primary use of wrap is by pvAccess client code.
The server creates a pvStructure that is valid for an NTScalar
The server creates a PVStructure that is valid for an NTScalar
and passes it to the client.
The client can call wrap to create an NTScalar for it's own use.
An example is:
<pre>
void myCallback(PVStructurePtr const &amp; pvStructure)
void myCallback(PVStructurePtr const &amp; PVStructure)
{
NTScalarPtr ntscalar = NTScalar::wrap(pvStructure);
NTScalarPtr ntscalar = NTScalar::wrap(PVStructure);
if(!ntscalar) {
// not a valid NTScalar
}
@@ -582,20 +608,20 @@ void myCallback(PVStructurePtr const &amp; pvStructure)
</pre>
</dd>
<dt>wrapUnsafe</dt>
<dd>Given a pvStructure this creates an NTScalar that warps it.
<dd>Given a PVStructure this creates an NTScalar that wraps it.
It does not check that the introspection interface is compatible.
This method is dangerous.</dd>
<dt>is_a</dt>
<dd>This method checks to see if the structure has an ID that is
correct for NTScalar.</dd>
<dt>isComparible</dt>
<dd>This method checks to see if the pvStructure has appropriate
<dt>isCompatible</dt>
<dd>This method checks to see if the PVStructure has appropriate
fields to be an NTScalar.
</dd>
<dt>createBuilder</dt>
<dd>This method creates an NTScalarBuilder.</dd>
<dt>attachTimeStamp</dt>
<dd>The timeStamp field of the NTScalar is attached to the pvTimeStamp.
<dd>The timeStamp field of the NTScalar is attached to pvTimeStamp.
<br />
An example is:
<pre>
@@ -610,7 +636,7 @@ double diff = TimeStamp::diff(timeStamp,current); // timeStamp - current
</pre>
</dd>
<dt>attachAlarm</dt>
<dd>The alarm field of the NTScalar is attached to the pvAlarm.
<dd>The alarm field of the NTScalar is attached to pvAlarm.
If alarm is not selected as an optional field false is returned.
If this is successful then the pvAlarm can be used to access that alarm
fields.<br />
@@ -627,36 +653,36 @@ string message = alarm.getMessage();
</pre>
</dd>
<dt>attachDisplay</dt>
<dd>The display field of the NTScalar is attached to the pvDisplay.
<dd>The display field of the NTScalar is attached to pvDisplay.
Used similar to attachAlarm.
</dd>
<dt>attachControl</dt>
<dd>The control field of the NTScalar is attached to the pvControl.
<dd>The control field of the NTScalar is attached to pvControl.
Used similar to attachAlarm.
</dd>
<dt>getPVStructure</dt>
<dd>Returns the pvStructure that NTScalar wraps.</dd>
<dd>Returns the PVStructure that NTScalar wraps.</dd>
<dt>getDescriptor</dt>
<dd>Get the descriptor.</dd>
<dt>getTimeStamp</dt>
<dd>Returns the top level timeStamp.
<dd>Returns the top-level timeStamp.
If the timeStamp was not selected as an optional field
a null pvStructure is returned.
a null PVStructure is returned.
</dd>
<dt>getAlarm</dt>
<dd>Returns the top level alarm.
<dd>Returns the top-level alarm.
If the alarm was not selected as an optional field
a null pvStructure is returned.
a null PVStructure is returned.
</dd>
<dt>getDisplay</dt>
<dd>Returns the top level display.
<dd>Returns the top-level display.
If the display was not selected as an optional field
a null pvStructure is returned.
a null PVStructure is returned.
</dd>
<dt>getControl</dt>
<dd>Returns the top level control.
<dd>Returns the top-level control.
If the control was not selected as an optional field
a null pvStructure is returned.
a null PVStructure is returned.
</dd>
<dt>getValue</dt>
<dd>Returns the value field.</dd>
@@ -721,21 +747,21 @@ where
<dd>This determines the element type for the value field.
This must be specified or createStructure will throw an exception.</dd>
<dt>addDescriptor</dt>
<dd>Add optional field descriptor</dd>
<dd>Add optional field descriptor.</dd>
<dt>addAlarm</dt>
<dd>Add optional field alarm</dd>
<dd>Add optional field alarm.</dd>
<dt>addTimeStamp</dt>
<dd>Add optional field timeStamp</dd>
<dd>Add optional field timeStamp.</dd>
<dt>addDisplay</dt>
<dd>Add optional field display</dd>
<dd>Add optional field display.</dd>
<dt>addControl</dt>
<dd>Add optional field control</dd>
<dd>Add optional field control.</dd>
<dt>createStructure</dt>
<dd>Create a introspection instance.</dd>
<dd>Create an introspection instance.</dd>
<dt>createPVStructure</dt>
<dd>Create the data instance.</dd>
<dt>create</dt>
<dd>create an PVScalar instance.</dd>
<dd>create a PVScalar instance.</dd>
<dt>add</dt>
<dd>Add an extra field. As many fields as desired can be added but each must have
a unique name that is not the name of any mandatory or possible optional field.</dd>
@@ -754,7 +780,7 @@ public:
static shared_pointer wrap(PVStructurePtr const &amp; structure);
static shared_pointer wrapUnsafe(PVStructurePtr const &amp; structure);
static bool is_a(StructureConstPtr const &amp; structure);
static bool isComparible(PVStructurePtr const &amp;pvStructure);
static bool isCompatible(PVStructurePtr const &amp;pvStructure);
static NTScalarArrayBuilderPtr createBuilder();
bool attachTimeStamp(PVTimeStamp &amp;pvTimeStamp) const;
@@ -775,62 +801,62 @@ private:
where
<dl>
<dt>wrap</dt>
<dd>Given a pvStructure this creates an NTScalarArray that warps it.
It calls <b>isCompatible</b> returns a null PVScalarArray if <b>isCompatible</b> returns false.
<dd>Given a PVStructure this creates an NTScalarArray that wraps it.
It calls <b>isCompatible</b> and returns a null PVScalarArray if <b>isCompatible</b> returns false.
</dd>
<dt>wrapUnsafe</dt>
<dd>Given a pvStructure this creates an NTScalarArray that warps it.
<dd>Given a PVStructure this creates an NTScalarArray that wraps it.
It does not check that the introspection interface is compatible.
This method is dangerous.</dd>
<dt>is_a</dt>
<dd>This method checks to see if the structure has an ID that is
correct for NTScalarArray.</dd>
<dt>isComparible</dt>
<dd>This method checks to see if the pvStructure has appropriate
<dt>isCompatible</dt>
<dd>This method checks to see if the PVStructure has appropriate
fields to be an NTScalarArray.
</dd>
<dt>createBuilder</dt>
<dd>This method creates a NTScalarArrayBuilder.</dd>
<dt>attachTimeStamp</dt>
<dd>The timeStamp field of the NTScalarArray is attached to the pvTimeStamp.
<dd>The timeStamp field of the NTScalarArray is attached to pvTimeStamp.
</dd>
<dt>attachAlarm</dt>
<dd>The alarm field of the NTScalarArray is attached to the pvAlarm.
<dd>The alarm field of the NTScalarArray is attached to pvAlarm.
If alarm is not selected as an optional field false is returned.
If this is successful then the pvAlarm can be used to access that alarm
fields.
</dd>
<dt>attachDisplay</dt>
<dd>The display field of the NTScalarArray is attached to the pvDisplay.
<dd>The display field of the NTScalarArray is attached to pvDisplay.
Used similar to attachAlarm.
</dd>
<dt>attachControl</dt>
<dd>The control field of the NTScalarArray is attached to the pvControl.
<dd>The control field of the NTScalarArray is attached to pvControl.
Used similar to attachAlarm.
</dd>
<dt>getPVStructure</dt>
<dd>Returns the pvStructure that NTScalarArray wraps.</dd>
<dd>Returns the PVStructure that NTScalarArray wraps.</dd>
<dt>getDescriptor</dt>
<dd>Get the descriptor.</dd>
<dt>getTimeStamp</dt>
<dd>Returns the top level timeStamp.
<dd>Returns the top-level timeStamp.
If the timeStamp was not selected as an optional field
a null pvStructure is returned.
a null PVStructure is returned.
</dd>
<dt>getAlarm</dt>
<dd>Returns the top level alarm.
<dd>Returns the top-level alarm.
If the alarm was not selected as an optional field
a null pvStructure is returned.
a null PVStructure is returned.
</dd>
<dt>getDisplay</dt>
<dd>Returns the top level display.
<dd>Returns the top-level display.
If the display was not selected as an optional field
a null pvStructure is returned.
a null PVStructure is returned.
</dd>
<dt>getControl</dt>
<dd>Returns the top level control.
<dd>Returns the top-level control.
If the control was not selected as an optional field
a null pvStructure is returned.
a null PVStructure is returned.
</dd>
<dt>getValue</dt>
<dd>Returns the value field.</dd>
@@ -840,9 +866,9 @@ where
<pre>
epics:nt/NTNameValue:1.0
string[] name // mandatory
double[] value // madatory, can be any type, must be same length as name
string descriptor // optional
alarm_t alarm // optional
double[] value // mandatory, can be any type, must be same length as name
string descriptor // optional
alarm_t alarm // optional
int severity
int status
string message
@@ -883,17 +909,17 @@ where
<dd>This determines the element type for the value field.
This must be specified or createStructure will throw an exception.</dd>
<dt>addDescriptor</dt>
<dd>Add optional field descriptor</dd>
<dd>Add optional field descriptor.</dd>
<dt>addAlarm</dt>
<dd>Add optional field alarm</dd>
<dd>Add optional field alarm.</dd>
<dt>addTimeStamp</dt>
<dd>Add optional field timeStamp</dd>
<dd>Add optional field timeStamp.</dd>
<dt>createStructure</dt>
<dd>Create a introspection instance.</dd>
<dd>Create an introspection instance.</dd>
<dt>createPVStructure</dt>
<dd>Create the data instance.</dd>
<dt>create</dt>
<dd>create an PVScalar instance.</dd>
<dd>create a PVScalar instance.</dd>
<dt>add</dt>
<dd>Add an extra field. As many fields as desired can be added but each must have
a unique name that is not the name of any mandatory or possible optional field.</dd>
@@ -912,7 +938,7 @@ public:
static shared_pointer wrap(PVStructurePtr const &amp; structure);
static shared_pointer wrapUnsafe(PVStructurePtr const &amp; structure);
static bool is_a(StructureConstPtr const &amp; structure);
static bool isComparible(PVStructurePtr const &amp;pvStructure);
static bool isCompatible(PVStructurePtr const &amp;pvStructure);
static NTNameValueBuilderPtr createBuilder();
bool attachTimeStamp(PVTimeStamp &amp;pvTimeStamp) const;
@@ -931,44 +957,44 @@ private:
where
<dl>
<dt>wrap</dt>
<dd>Given a pvStructure this creates an NTNameValue that warps it.
It calls <b>isCompatible</b> returns a null NTNameValue if <b>isCompatible</b> returns false.
<dd>Given a PVStructure this creates an NTNameValue that wraps it.
It calls <b>isCompatible</b> and returns a null NTNameValue if <b>isCompatible</b> returns false.
</dd>
<dt>wrapUnsafe</dt>
<dd>Given a pvStructure this creates an NTNameValue that warps it.
<dd>Given a PVStructure this creates an NTNameValue that wraps it.
It does not check that the introspection interface is compatible.
This method is dangerous.</dd>
<dt>is_a</dt>
<dd>This method checks to see if the structure has an ID that is
correct for NTNameValue.</dd>
<dt>isComparible</dt>
<dd>This method checks to see if the pvStructure has appropriate
<dt>isCompatible</dt>
<dd>This method checks to see if the PVStructure has appropriate
fields to be an NTNameValue.
</dd>
<dt>createBuilder</dt>
<dd>This method creates an NTNameValueBuilder.</dd>
<dt>attachTimeStamp</dt>
<dd>The timeStamp field of the NTNameValue is attached to the pvTimeStamp.
<dd>The timeStamp field of the NTNameValue is attached to pvTimeStamp.
</dd>
<dt>attachAlarm</dt>
<dd>The alarm field of the NTNameValue is attached to the pvAlarm.
<dd>The alarm field of the NTNameValue is attached to pvAlarm.
If alarm is not selected as an optional field false is returned.
If this is successful then the pvAlarm can be used to access that alarm
fields.
</dd>
<dt>getPVStructure</dt>
<dd>Returns the pvStructure that NTNameValue wraps.</dd>
<dd>Returns the PVStructure that NTNameValue wraps.</dd>
<dt>getDescriptor</dt>
<dd>Get the descriptor.</dd>
<dt>getTimeStamp</dt>
<dd>Returns the top level timeStamp.
<dd>Returns the top-level timeStamp.
If the timeStamp was not selected as an optional field
a null pvStructure is returned.
a null PVStructure is returned.
</dd>
<dt>getAlarm</dt>
<dd>Returns the top level alarm.
<dd>Returns the top-level alarm.
If the alarm was not selected as an optional field
a null pvStructure is returned.
a null PVStructure is returned.
</dd>
<dt>getName</dt>
<dd>Returns field name.</dd>
@@ -980,10 +1006,10 @@ where
<pre>
epics:nt/NTTable:1.0
string[] labels [column0,column1,column2] // mandatory
structure value // mandatory;
double[] column0 [] // name=labels[0]; can be any scalar type
string[] column1 [] // name=labels[1]; can be any scalar type
int[] column2 [] // name=labels[2]; can be any scalar type
structure value // mandatory
double[] column0 [] // can be any scalar type
string[] column1 [] // can be any scalar type
int[] column2 [] // can be any scalar type
string descriptor // optional
alarm_t alarm // optional
int severity
@@ -1006,7 +1032,7 @@ class NTTableBuilder
{
public:
POINTER_DEFINITIONS(NTTableBuilder);
shared_pointer add(string const &amp; name,ScalarType scalarType);
shared_pointer addColumn(string const &amp; name,ScalarType scalarType);
shared_pointer addDescriptor();
shared_pointer addAlarm();
shared_pointer addTimeStamp();
@@ -1021,20 +1047,20 @@ private:
</pre>
where
<dl>
<dt>add</dt>
<dt>addColumn</dt>
<dd>This is the name and elementType for the next column</dd>
<dt>addDescriptor</dt>
<dd>Add optional field descriptor</dd>
<dd>Add optional field descriptor.</dd>
<dt>addAlarm</dt>
<dd>Add optional field alarm</dd>
<dd>Add optional field alarm.</dd>
<dt>addTimeStamp</dt>
<dd>Add optional field timeStamp</dd>
<dd>Add optional field timeStamp.</dd>
<dt>createStructure</dt>
<dd>Create a introspection instance.</dd>
<dd>Create an introspection instance.</dd>
<dt>createPVStructure</dt>
<dd>Create the data instance.</dd>
<dt>create</dt>
<dd>create an PVScalar instance.</dd>
<dd>create a PVScalar instance.</dd>
<dt>add</dt>
<dd>Add an extra field. As many fields as desired can be added but each must have
a unique name that is not the name of any mandatory or possible optional field.</dd>
@@ -1052,7 +1078,7 @@ public:
static shared_pointer wrap(PVStructurePtr const &amp; structure);
static shared_pointer wrapUnsafe(PVStructurePtr const &amp; structure);
static bool is_a(StructureConstPtr const &amp; structure);
static bool isComparible(PVStructurePtr const &amp;pvStructure);
static bool isCompatible(PVStructurePtr const &amp;pvStructure);
static NTTableBuilderPtr createBuilder();
bool attachTimeStamp(PVTimeStamp &amp;pvTimeStamp) const;
@@ -1071,44 +1097,44 @@ private:
where
<dl>
<dt>wrap</dt>
<dd>Given a pvStructure this creates an NTTable that warps it.
It calls <b>isCompatible</b> returns a null NTTable if <b>isCompatible</b> returns false.
<dd>Given a PVStructure this creates an NTTable that wraps it.
It calls <b>isCompatible</b> and returns a null NTTable if <b>isCompatible</b> returns false.
</dd>
<dt>wrapUnsafe</dt>
<dd>Given a pvStructure this creates an NTTable that warps it.
<dd>Given a PVStructure this creates an NTTable that wraps it.
It does not check that the introspection interface is compatible.
This method is dangerous.</dd>
<dt>is_a</dt>
<dd>This method checks to see if the structure has an ID that is
correct for NTTable.</dd>
<dt>isComparible</dt>
<dd>This method checks to see if the pvStructure has appropriate
<dt>isCompatible</dt>
<dd>This method checks to see if the PVStructure has appropriate
fields to be an NTTable.
</dd>
<dt>createBuilder</dt>
<dd>This method creates an NTTableBuilder.</dd>
<dt>attachTimeStamp</dt>
<dd>The timeStamp field of the NTTable is attached to the pvTimeStamp.
<dd>The timeStamp field of the NTTable is attached to pvTimeStamp.
</dd>
<dt>attachAlarm</dt>
<dd>The alarm field of the NTTable is attached to the pvAlarm.
<dd>The alarm field of the NTTable is attached to pvAlarm.
If alarm is not selected as an optional field false is returned.
If this is successful then the pvAlarm can be used to access that alarm
fields.
</dd>
<dt>getPVStructure</dt>
<dd>Returns the pvStructure that NTTable wraps.</dd>
<dd>Returns the PVStructure that NTTable wraps.</dd>
<dt>getDescriptor</dt>
<dd>Get the descriptor.</dd>
<dt>getTimeStamp</dt>
<dd>Returns the top level timeStamp.
<dd>Returns the top-level timeStamp.
If the timeStamp was not selected as an optional field
a null pvStructure is returned.
a null PVStructure is returned.
</dd>
<dt>getAlarm</dt>
<dd>Returns the top level alarm.
<dd>Returns the top-level alarm.
If the alarm was not selected as an optional field
a null pvStructure is returned.
a null PVStructure is returned.
</dd>
<dt>getLabels</dt>
<dd>Returns the labels field.</dd>
@@ -1121,14 +1147,14 @@ where
structure NTMultiChannel
union_t[] value // mandatory
string[] channelName // mandatory; must be same length as value
time_t timeStamp //optional; time when data collected
alarm_t alarm //optional; alarm associated with data collection
int[] severity //optional; alarm severity for each value
int[] status //optional; alarm status for each value
string[] message //optional; alarm message for each value
long[] secondsPastEpoch //optional; seconds for each value.
int[] nanoseconds //optional; nanoseconds for each value
string descriptor //optional; descriptor data
time_t timeStamp // optional; time when data collected
alarm_t alarm // optional; alarm associated with data collection
int[] severity // optional; alarm severity for each value
int[] status // optional; alarm status for each value
string[] message // optional; alarm message for each value
long[] secondsPastEpoch // optional; seconds for each value.
int[] nanoseconds // optional; nanoseconds for each value
string descriptor // optional; descriptor data
</pre>
<h3>NTMultiChannelBuilder</h3>
<p><b>ntmultiChannel.h</b> defines the following:</p>
@@ -1166,11 +1192,11 @@ where
If not specified the type will be a variant union.
</dd>
<dt>addDescriptor</dt>
<dd>Add optional field descriptor</dd>
<dd>Add optional field descriptor.</dd>
<dt>addAlarm</dt>
<dd>Add optional field alarm</dd>
<dd>Add optional field alarm.</dd>
<dt>addTimeStamp</dt>
<dd>Add optional field timeStamp</dd>
<dd>Add optional field timeStamp.</dd>
<dt>addSeverity</dt>
<dd>Add a field that has the alarm severity for each channel.</dd>
<dt>addStatus</dt>
@@ -1184,11 +1210,11 @@ where
<dt>addUserTag</dt>
<dd>Add a field that has the userTag for each channel.</dd>
<dt>createStructure</dt>
<dd>Create a introspection instance.</dd>
<dd>Create an introspection instance.</dd>
<dt>createPVStructure</dt>
<dd>Create the data instance.</dd>
<dt>create</dt>
<dd>create an PVScalar instance.</dd>
<dd>create a PVScalar instance.</dd>
<dt>add</dt>
<dd>Add an extra field. As many fields as desired can be added but each must have
a unique name that is not the name of any mandatory or possible optional field.</dd>
@@ -1206,7 +1232,7 @@ public:
static shared_pointer wrap(PVStructurePtr const &amp; structure);
static shared_pointer wrapUnsafe(PVStructurePtr const &amp; structure);
static bool is_a(StructureConstPtr const &amp; structure);
static bool isComparible(PVStructurePtr const &amp;pvStructure);
static bool isCompatible(PVStructurePtr const &amp;pvStructure);
static NTMultiChannelBuilderPtr createBuilder();
bool attachTimeStamp(PVTimeStamp &amp;pvTimeStamp) const;
@@ -1230,44 +1256,44 @@ private:
where
<dl>
<dt>wrap</dt>
<dd>Given a pvStructure this creates an NTMultiChannel that warps it.
It calls <b>isCompatible</b> returns a null NTMultiChannel if <b>isCompatible</b> returns false.
<dd>Given a PVStructure this creates an NTMultiChannel that wraps it.
It calls <b>isCompatible</b> and returns a null NTMultiChannel if <b>isCompatible</b> returns false.
</dd>
<dt>wrapUnsafe</dt>
<dd>Given a pvStructure this creates an NTMultiChannel that warps it.
<dd>Given a PVStructure this creates an NTMultiChannel that wraps it.
It does not check that the introspection interface is compatible.
This method is dangerous.</dd>
<dt>is_a</dt>
<dd>This method checks to see if the structure has an ID that is
correct for NTMultiChannel.</dd>
<dt>isComparible</dt>
<dd>This method checks to see if the pvStructure has appropriate
<dt>isCompatible</dt>
<dd>This method checks to see if the PVStructure has appropriate
fields to be an NTMultiChannel.
</dd>
<dt>createBuilder</dt>
<dd>This method creates an NTMultiChannelBuilder.</dd>
<dt>attachTimeStamp</dt>
<dd>The timeStamp field of the NTMultiChannel is attached to the pvTimeStamp.
<dd>The timeStamp field of the NTMultiChannel is attached to pvTimeStamp.
</dd>
<dt>attachAlarm</dt>
<dd>The alarm field of the NTMultiChannel is attached to the pvAlarm.
<dd>The alarm field of the NTMultiChannel is attached to pvAlarm.
If alarm is not selected as an optional field false is returned.
If this is successful then the pvAlarm can be used to access that alarm
fields.
</dd>
<dt>getPVStructure</dt>
<dd>Returns the pvStructure that NTMultiChannel wraps.</dd>
<dd>Returns the PVStructure that NTMultiChannel wraps.</dd>
<dt>getDescriptor</dt>
<dd>Get the descriptor.</dd>
<dt>getTimeStamp</dt>
<dd>Returns the top level timeStamp.
<dd>Returns the top-level timeStamp.
If the timeStamp was not selected as an optional field
a null pvStructure is returned.
a null PVStructure is returned.
</dd>
<dt>getAlarm</dt>
<dd>Returns the top level alarm.
<dd>Returns the top-level alarm.
If the alarm was not selected as an optional field
a null pvStructure is returned.
a null PVStructure is returned.
</dd>
<dt>getValue</dt>
<dd>Returns the value field.</dd>
@@ -1292,13 +1318,13 @@ where
<h2>Normative Type NTNDArray</h2>
<pre>
epics:nt/NTNDArray:1.0
union value //mandatory
codec_t codec //mandatory
union value // mandatory
codec_t codec // mandatory
string name
any parameters
long compressedSize //mandatory
long uncompressedSize //mandatory
dimension_t[] dimension //mandatory
long compressedSize // mandatory
long uncompressedSize // mandatory
dimension_t[] dimension // mandatory
dimension_t[]
dimension_t
int size
@@ -1306,12 +1332,12 @@ epics:nt/NTNDArray:1.0
int fullSize
int binning
boolean reverse
int uniqueId //mandatory
time_t dataTimeStamp //mandatory
int uniqueId // mandatory
time_t dataTimeStamp // mandatory
long secondsPastEpoch
int nanoseconds
int userTag
epics:nt/NTAttribute:1.0[] attribute //mandatory
epics:nt/NTAttribute:1.0[] attribute // mandatory
epics:nt/NTAttribute:1.0[]
epics:nt/NTAttribute:1.0
string name
@@ -1334,7 +1360,7 @@ epics:nt/NTNDArray:1.0
string description
string format
string units
string extra1 //extra
string extra1 // extra
</pre>
<h3>NTNDArrayBuilder</h3>
<p><b>ntndArray.h</b> defines the following:</p>
@@ -1362,19 +1388,19 @@ private:
where
<dl>
<dt>addDescriptor</dt>
<dd>Add optional field descriptor</dd>
<dd>Add optional field descriptor.</dd>
<dt>addAlarm</dt>
<dd>Add optional field alarm</dd>
<dd>Add optional field alarm.</dd>
<dt>addTimeStamp</dt>
<dd>Add optional field timeStamp</dd>
<dd>Add optional field timeStamp.</dd>
<dt>addDisplay</dt>
<dd>Add optional field display</dd>
<dd>Add optional field display.</dd>
<dt>createStructure</dt>
<dd>Create a introspection instance.</dd>
<dd>Create an introspection instance.</dd>
<dt>createPVStructure</dt>
<dd>Create the data instance.</dd>
<dt>create</dt>
<dd>create an PVScalar instance.</dd>
<dd>create a PVScalar instance.</dd>
<dt>add</dt>
<dd>Add an extra field. As many fields as desired can be added but each must have
a unique name that is not the name of any mandatory or possible optional field.</dd>
@@ -1392,7 +1418,7 @@ public:
static shared_pointer wrap(PVStructurePtr const &amp; structure);
static shared_pointer wrapUnsafe(PVStructurePtr const &amp; structure);
static bool is_a(StructureConstPtr const &amp; structure);
static bool isComparible(PVStructurePtr const &amp;pvStructure);
static bool isCompatible(PVStructurePtr const &amp;pvStructure);
static NTNDArrayBuilderPtr createBuilder();
PVStringPtr getDescriptor() const;
@@ -1418,36 +1444,36 @@ private:
where
<dl>
<dt>wrap</dt>
<dd>Given a pvStructure this creates an NTNDArray that warps it.
It calls <b>isCompatible</b> returns a null NTNDArray if <b>isCompatible</b> returns false.
<dd>Given a PVStructure this creates an NTNDArray that wraps it.
It calls <b>isCompatible</b> and returns a null NTNDArray if <b>isCompatible</b> returns false.
</dd>
<dt>wrapUnsafe</dt>
<dd>Given a pvStructure this creates an NTNDArray that warps it.
<dd>Given a PVStructure this creates an NTNDArray that wraps it.
It does not check that the introspection interface is compatible.
This method is dangerous.</dd>
<dt>is_a</dt>
<dd>This method checks to see if the structure has an ID that is
correct for NTNDArray.</dd>
<dt>isComparible</dt>
<dd>This method checks to see if the pvStructure has appropriate
<dt>isCompatible</dt>
<dd>This method checks to see if the PVStructure has appropriate
fields to be an NTNDArray.
</dd>
<dt>createBuilder</dt>
<dd>This method creates an NTNDArrayBuilder.</dd>
<dt>attachTimeStamp</dt>
<dd>The timeStamp field of the NTNDArray is attached to the pvTimeStamp.
<dd>The timeStamp field of the NTNDArray is attached to pvTimeStamp.
</dd>
<dt>attachDataTimeStamp</dt>
<dd>The dataTimeStamp field of the NTNDArray is attached to the pvTimeStamp.
<dd>The dataTimeStamp field of the NTNDArray is attached to pvTimeStamp.
</dd>
<dt>attachAlarm</dt>
<dd>The alarm field of the NTNDArray is attached to the pvAlarm.
<dd>The alarm field of the NTNDArray is attached to pvAlarm.
If alarm is not selected as an optional field false is returned.
If this is successful then the pvAlarm can be used to access that alarm
fields.
</dd>
<dt>getPVStructure</dt>
<dd>Returns the pvStructure that NTNDArray wraps.</dd>
<dd>Returns the PVStructure that NTNDArray wraps.</dd>
<dt>getValue</dt>
<dd>Returns the value field.</dd>
<dt>getCodec</dt>
@@ -1468,19 +1494,19 @@ where
<dt>getDescriptor</dt>
<dd>Get the descriptor.</dd>
<dt>getTimeStamp</dt>
<dd>Returns the top level timeStamp.
<dd>Returns the top-level timeStamp.
If the timeStamp was not selected as an optional field
a null pvStructure is returned.
a null PVStructure is returned.
</dd>
<dt>getAlarm</dt>
<dd>Returns the top level alarm.
<dd>Returns the top-level alarm.
If the alarm was not selected as an optional field
a null pvStructure is returned.
a null PVStructure is returned.
</dd>
<dt>getDisplay</dt>
<dd>Returns the top level display.
<dd>Returns the top-level display.
If the display was not selected as an optional field
a null pvStructure is returned.
a null PVStructure is returned.
</dd>
</dl>

View File

@@ -55,7 +55,7 @@
<dt>Editors:</dt>
<dd> Marty Kraimer, BNL<br />
Matej Sekoranja, CosyLab<br />
David Hicken, Diamond Light Source
David Hickin, Diamond Light Source
</dd>
</dl>
@@ -125,7 +125,7 @@ pvDataCPP.html
A primary use of this type is to access data from a set of pvAccess channels.
Each element of value holds data from a channel.</dd>
<dt>NTNDArray</dt>
<dd>This type holds NDArray data as defined by the areaDetector facilility.
<dd>This type holds NDArray data as defined by the areaDetector facility.
</dd>
</dl>
<p>Each normative type consists of a set of mandatory fields, a set of optional fields,

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

67
jenkins/cloudbees_build Normal file
View File

@@ -0,0 +1,67 @@
# normativeTypes C++ implementation
# Jenkins @ Cloudbees build script
#
# Jenkins invokes scripts with the "-ex" option. So the build is considered a failure
# if any of the commands exits with a non-zero exit code.
#
# Author: Ralph Lange <ralph.lange@gmx.de>
# Copyright (C) 2013 Helmholtz-Zentrum Berlin für Materialien und Energie GmbH
# Copyright (C) 2014-2015 ITER Organization.
# All rights reserved. Use is subject to license terms.
###########################################
# Determine EPICS Base version
DEFAULT_BASE=3.14.12.5
BASE=${1:-${DEFAULT_BASE}}
USE_MB=${2:-"MB_NO"}
# Dependent module branches (empty = master)
PVCOMMON_BRANCH="Release-4.1-"
PVDATA_BRANCH="Release-5.0-"
###########################################
# Fetch and unpack dependencies
export STUFF=/tmp/stuff
rm -fr ${STUFF}
mkdir -p ${STUFF}
cd ${STUFF}
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/pvDataCPP_${PVDATA_BRANCH}Build/BASE=${BASE},USE_MB=MB_NO/lastSuccessfulBuild/artifact/pvData.CB-dist.tar.gz
tar -xzf base-${BASE}.CB-dist.tar.gz
tar -xzf pvData.CB-dist.tar.gz
if [ "${USE_MB}" = "MB_YES" ]; then
wget -nv https://openepics.ci.cloudbees.com/job/pvCommonCPP_${PVCOMMON_BRANCH}Build/BASE=${BASE},USE_MB=MB_YES/lastSuccessfulBuild/artifact/pvCommon.CB-dist.tar.gz
tar -xzf pvCommon.CB-dist.tar.gz
fi
###########################################
# Build
cd ${WORKSPACE}
export EPICS_BASE=${STUFF}
export EPICS_HOST_ARCH=$(${EPICS_BASE}/startup/EpicsHostArch)
export LD_LIBRARY_PATH=${EPICS_BASE}/lib/${EPICS_HOST_ARCH}
export PATH=${STUFF}/bin:${PATH}
cat > configure/RELEASE.local << EOF
EPICS_BASE=${EPICS_BASE}
EOF
make distclean all
###########################################
# Test
make runtests
###########################################
# Create distribution
tar --exclude=test* -czf normativeTypes.CB-dist.tar.gz lib include

51
jenkins/cloudbees_doc Normal file
View File

@@ -0,0 +1,51 @@
# normativeTypes 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/normativeTypesCPP_Build/BASE=${BASE},USE_MB=MB_NO/lastSuccessfulBuild/artifact/normativeTypes.CB-dist.tar.gz
tar -xzf normativeTypes.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/normativeTypesCPP/${PUBLISH}/
rsync -aqP --delete -e ssh documentation epics-jenkins@web.sourceforge.net:/home/project-web/epics-pvdata/htdocs/docbuild/normativeTypesCPP/${PUBLISH}/
fi

View File

@@ -1,28 +1,52 @@
TOP = ..
include $(TOP)/configure/CONFIG
SRC = $(TOP)/src/
SRC = $(TOP)/src
SRC_DIRS += $(SRC)/nt
INC += nt.h
INC += ntutils.h
INC += ntid.h
INC += ntfield.h
INC += ntscalar.h
INC += ntscalarArray.h
INC += ntnameValue.h
INC += nttable.h
INC += ntmultiChannel.h
INC += ntscalarMultiChannel.h
INC += ntndarray.h
INC += ntmatrix.h
INC += ntenum.h
INC += ntunion.h
INC += ntaggregate.h
INC += ntattribute.h
INC += ntcontinuum.h
INC += nthistogram.h
INC += nturi.h
INC += ntndarrayAttribute.h
LIBSRCS += ntutils.cpp
LIBSRCS += ntid.cpp
LIBSRCS += ntfield.cpp
LIBSRCS += ntscalar.cpp
LIBSRCS += ntscalarArray.cpp
LIBSRCS += ntnameValue.cpp
LIBSRCS += nttable.cpp
LIBSRCS += ntmultiChannel.cpp
LIBSRCS += ntscalarMultiChannel.cpp
LIBSRCS += ntndarray.cpp
LIBSRCS += ntmatrix.cpp
LIBSRCS += ntenum.cpp
LIBSRCS += ntunion.cpp
LIBSRCS += ntaggregate.cpp
LIBSRCS += ntattribute.cpp
LIBSRCS += ntcontinuum.cpp
LIBSRCS += nthistogram.cpp
LIBSRCS += nturi.cpp
LIBSRCS += ntndarrayAttribute.cpp
LIBRARY=nt
LIBRARY = nt
nt_LIBS += pvData Com

View File

@@ -1,12 +1,15 @@
/* nt.h */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* This software is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#ifndef NT_H
#define NT_H
/*
* Include all the normative types here.
*/
#include <pv/ntfield.h>
#include <pv/ntscalar.h>
#include <pv/ntscalarArray.h>
@@ -14,6 +17,22 @@
#include <pv/nttable.h>
#include <pv/ntndarray.h>
#include <pv/ntmultiChannel.h>
#include <pv/ntscalarMultiChannel.h>
#include <pv/ntmatrix.h>
#include <pv/ntenum.h>
#include <pv/ntunion.h>
#include <pv/ntaggregate.h>
#include <pv/ntattribute.h>
#include <pv/ntcontinuum.h>
#include <pv/nthistogram.h>
#include <pv/nturi.h>
#include <pv/ntndarrayAttribute.h>
#endif /* NT_H */
/** @page Overview Documentation
*
* <a href = "ntCPP.html">ntCPP.html</a>
*
*/

376
src/nt/ntaggregate.cpp Normal file
View File

@@ -0,0 +1,376 @@
/* ntaggregate.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* This software is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#define epicsExportSharedSymbols
#include <pv/ntaggregate.h>
#include <pv/ntutils.h>
using namespace std;
using namespace epics::pvData;
namespace epics { namespace nt {
static NTFieldPtr ntField = NTField::get();
namespace detail {
StructureConstPtr NTAggregateBuilder::createStructure()
{
FieldBuilderPtr builder =
getFieldCreate()->createFieldBuilder()->
setId(NTAggregate::URI)->
add("value", pvDouble)->
add("N", pvLong);
if (dispersion)
builder->add("dispersion", pvDouble);
if (first)
builder->add("first", pvDouble);
if (firstTimeStamp)
builder->add("firstTimeStamp", ntField->createTimeStamp());
if (last)
builder->add("last" , pvDouble);
if (lastTimeStamp)
builder->add("lastTimeStamp", ntField->createTimeStamp());
if (max)
builder->add("max", pvDouble);
if (min)
builder->add("min", pvDouble);
if (descriptor)
builder->add("descriptor", pvString);
if (alarm)
builder->add("alarm", ntField->createAlarm());
if (timeStamp)
builder->add("timeStamp", ntField->createTimeStamp());
size_t extraCount = extraFieldNames.size();
for (size_t i = 0; i< extraCount; i++)
builder->add(extraFieldNames[i], extraFields[i]);
StructureConstPtr s = builder->createStructure();
reset();
return s;
}
NTAggregateBuilder::shared_pointer NTAggregateBuilder::addDispersion()
{
dispersion = true;
return shared_from_this();
}
NTAggregateBuilder::shared_pointer NTAggregateBuilder::addFirst()
{
first = true;
return shared_from_this();
}
NTAggregateBuilder::shared_pointer NTAggregateBuilder::addFirstTimeStamp()
{
firstTimeStamp = true;
return shared_from_this();
}
NTAggregateBuilder::shared_pointer NTAggregateBuilder::addLast()
{
last = true;
return shared_from_this();
}
NTAggregateBuilder::shared_pointer NTAggregateBuilder::addLastTimeStamp()
{
lastTimeStamp = true;
return shared_from_this();
}
NTAggregateBuilder::shared_pointer NTAggregateBuilder::addMax()
{
max = true;
return shared_from_this();
}
NTAggregateBuilder::shared_pointer NTAggregateBuilder::addMin()
{
min = true;
return shared_from_this();
}
NTAggregateBuilder::shared_pointer NTAggregateBuilder::addDescriptor()
{
descriptor = true;
return shared_from_this();
}
NTAggregateBuilder::shared_pointer NTAggregateBuilder::addAlarm()
{
alarm = true;
return shared_from_this();
}
NTAggregateBuilder::shared_pointer NTAggregateBuilder::addTimeStamp()
{
timeStamp = true;
return shared_from_this();
}
PVStructurePtr NTAggregateBuilder::createPVStructure()
{
return getPVDataCreate()->createPVStructure(createStructure());
}
NTAggregatePtr NTAggregateBuilder::create()
{
return NTAggregatePtr(new NTAggregate(createPVStructure()));
}
NTAggregateBuilder::NTAggregateBuilder()
{
reset();
}
void NTAggregateBuilder::reset()
{
dispersion = false;
first = false;
firstTimeStamp = false;
last = false;
lastTimeStamp = false;
max = false;
min = false;
descriptor = false;
alarm = false;
timeStamp = false;
extraFieldNames.clear();
extraFields.clear();
}
NTAggregateBuilder::shared_pointer NTAggregateBuilder::add(string const & name, FieldConstPtr const & field)
{
extraFields.push_back(field); extraFieldNames.push_back(name);
return shared_from_this();
}
}
const std::string NTAggregate::URI("epics:nt/NTAggregate:1.0");
NTAggregate::shared_pointer NTAggregate::wrap(PVStructurePtr const & pvStructure)
{
if(!isCompatible(pvStructure)) return shared_pointer();
return wrapUnsafe(pvStructure);
}
NTAggregate::shared_pointer NTAggregate::wrapUnsafe(PVStructurePtr const & pvStructure)
{
return shared_pointer(new NTAggregate(pvStructure));
}
bool NTAggregate::is_a(StructureConstPtr const & structure)
{
return NTUtils::is_a(structure->getID(), URI);
}
bool NTAggregate::isCompatible(StructureConstPtr const &structure)
{
if (structure.get() == 0) return false;
ScalarConstPtr valueField = structure->getField<Scalar>("value");
if (valueField.get() == 0 || valueField->getScalarType() != pvDouble)
return false;
ScalarConstPtr nField = structure->getField<Scalar>("N");
if (nField.get() == 0 || nField->getScalarType() != pvLong)
return false;
FieldConstPtr field = structure->getField("dispersion");
if (field.get())
{
ScalarConstPtr dispersionField = structure->getField<Scalar>("dispersion");
if (!dispersionField.get() || dispersionField->getScalarType() != pvDouble)
return false;
}
field = structure->getField("first");
if (field.get())
{
ScalarConstPtr firstField = structure->getField<Scalar>("first");
if (!firstField.get() || firstField->getScalarType() != pvDouble)
return false;
}
field = structure->getField("firstTimeStamp");
if (field.get() && !ntField->isTimeStamp(field))
return false;
field = structure->getField("last");
if (field.get())
{
ScalarConstPtr lastField = structure->getField<Scalar>("last");
if (!lastField.get() || lastField->getScalarType() != pvDouble)
return false;
}
field = structure->getField("lastTimeStamp");
if (field.get() && !ntField->isTimeStamp(field))
return false;
field = structure->getField("max");
if (field.get())
{
ScalarConstPtr maxField = structure->getField<Scalar>("max");
if (!maxField.get() || maxField->getScalarType() != pvDouble)
return false;
}
field = structure->getField("min");
if (field.get())
{
ScalarConstPtr minField = structure->getField<Scalar>("min");
if (!minField.get() || minField->getScalarType() != pvDouble)
return false;
}
field = structure->getField("descriptor");
if (field.get())
{
ScalarConstPtr descriptorField = structure->getField<Scalar>("descriptor");
if (!descriptorField.get() || descriptorField->getScalarType() != pvString)
return false;
}
NTFieldPtr ntField = NTField::get();
field = structure->getField("alarm");
if (field.get() && !ntField->isAlarm(field))
return false;
field = structure->getField("timeStamp");
if (field.get() && !ntField->isTimeStamp(field))
return false;
return true;
}
bool NTAggregate::isCompatible(PVStructurePtr const & pvStructure)
{
if(!pvStructure) return false;
return isCompatible(pvStructure->getStructure());
}
bool NTAggregate::isValid()
{
return true;
}
NTAggregateBuilderPtr NTAggregate::createBuilder()
{
return NTAggregateBuilderPtr(new detail::NTAggregateBuilder());
}
bool NTAggregate::attachTimeStamp(PVTimeStamp &pvTimeStamp) const
{
PVStructurePtr ts = getTimeStamp();
if (ts)
return pvTimeStamp.attach(ts);
else
return false;
}
bool NTAggregate::attachAlarm(PVAlarm &pvAlarm) const
{
PVStructurePtr al = getAlarm();
if (al)
return pvAlarm.attach(al);
else
return false;
}
PVStructurePtr NTAggregate::getPVStructure() const
{
return pvNTAggregate;
}
PVStringPtr NTAggregate::getDescriptor() const
{
return pvNTAggregate->getSubField<PVString>("descriptor");
}
PVStructurePtr NTAggregate::getTimeStamp() const
{
return pvNTAggregate->getSubField<PVStructure>("timeStamp");
}
PVStructurePtr NTAggregate::getAlarm() const
{
return pvNTAggregate->getSubField<PVStructure>("alarm");
}
PVDoublePtr NTAggregate::getValue() const
{
return pvValue;
}
PVLongPtr NTAggregate::getN() const
{
return pvNTAggregate->getSubField<PVLong>("N");
}
PVDoublePtr NTAggregate::getDispersion() const
{
return pvNTAggregate->getSubField<PVDouble>("dispersion");
}
PVDoublePtr NTAggregate::getFirst() const
{
return pvNTAggregate->getSubField<PVDouble>("first");
}
PVStructurePtr NTAggregate::getFirstTimeStamp() const
{
return pvNTAggregate->getSubField<PVStructure>("firstTimeStamp");
}
PVDoublePtr NTAggregate::getLast() const
{
return pvNTAggregate->getSubField<PVDouble>("last");
}
PVStructurePtr NTAggregate::getLastTimeStamp() const
{
return pvNTAggregate->getSubField<PVStructure>("lastTimeStamp");
}
PVDoublePtr NTAggregate::getMax() const
{
return pvNTAggregate->getSubField<PVDouble>("max");
}
PVDoublePtr NTAggregate::getMin() const
{
return pvNTAggregate->getSubField<PVDouble>("min");
}
NTAggregate::NTAggregate(PVStructurePtr const & pvStructure) :
pvNTAggregate(pvStructure), pvValue(pvNTAggregate->getSubField<PVDouble>("value"))
{}
}}

373
src/nt/ntaggregate.h Normal file
View File

@@ -0,0 +1,373 @@
/* ntaggregate.h */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* This software is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#ifndef NTAGGREGATE_H
#define NTAGGREGATE_H
#ifdef epicsExportSharedSymbols
# define ntaggregateEpicsExportSharedSymbols
# undef epicsExportSharedSymbols
#endif
#ifdef ntaggregateEpicsExportSharedSymbols
# define epicsExportSharedSymbols
# undef ntaggregateEpicsExportSharedSymbols
#endif
#include <pv/ntfield.h>
#include <shareLib.h>
namespace epics { namespace nt {
class NTAggregate;
typedef std::tr1::shared_ptr<NTAggregate> NTAggregatePtr;
namespace detail {
/**
* @brief Interface for in-line creating of NTAggregate.
*
* One instance can be used to create multiple instances.
* An instance of this object must not be used concurrently (an object has a state).
* @author dgh
*/
class epicsShareClass NTAggregateBuilder :
public std::tr1::enable_shared_from_this<NTAggregateBuilder>
{
public:
POINTER_DEFINITIONS(NTAggregateBuilder);
/**
* Adds dispersion field to the NTAggregate.
* @return this instance of <b>NTAggregateBuilder</b>.
*/
shared_pointer addDispersion();
/**
* Adds first field to the NTAggregate.
* @return this instance of <b>NTAggregateBuilder</b>.
*/
shared_pointer addFirst();
/**
* Adds firstTimeStamp field to the NTAggregate.
* @return this instance of <b>NTAggregateBuilder</b>.
*/
shared_pointer addFirstTimeStamp();
/**
* Adds last field to the NTAggregate.
* @return this instance of <b>NTAggregateBuilder</b>.
*/
shared_pointer addLast();
/**
* Adds lastTimeStamp field to the NTAggregate.
* @return this instance of <b>NTAggregateBuilder</b>.
*/
shared_pointer addLastTimeStamp();
/**
* Adds max field to the NTAggregate.
* @return this instance of <b>NTAggregateBuilder</b>.
*/
shared_pointer addMax();
/**
* Adds min field to the NTAggregate.
* @return this instance of <b>NTAggregateBuilder</b>.
*/
shared_pointer addMin();
/**
* Adds descriptor field to the NTAggregate.
* @return this instance of <b>NTAggregateBuilder</b>.
*/
shared_pointer addDescriptor();
/**
* Adds alarm field to the NTAggregate.
* @return this instance of <b>NTAggregateBuilder</b>.
*/
shared_pointer addAlarm();
/**
* Adds timeStamp field to the NTAggregate.
* @return this instance of <b>NTAggregateBuilder</b>.
*/
shared_pointer addTimeStamp();
/**
* Creates a <b>Structure</b> that represents NTAggregate.
* This resets this instance state and allows new instance to be created.
* @return a new instance of a <b>Structure</b>.
*/
epics::pvData::StructureConstPtr createStructure();
/**
* Creates a <b>PVStructure</b> that represents NTAggregate.
* This resets this instance state and allows new instance to be created.
* @return a new instance of a <b>PVStructure</b>.
*/
epics::pvData::PVStructurePtr createPVStructure();
/**
* Creates a <b>NTAggregate</b> instance.
* This resets this instance state and allows new instance to be created.
* @return a new instance of a <b>NTAggregate</b>.
*/
NTAggregatePtr create();
/**
* Adds extra <b>Field</b> to the type.
* @param name the name of the field.
* @param field the field to be added.
* @return this instance of <b>NTAggregateBuilder</b>.
*/
shared_pointer add(std::string const & name, epics::pvData::FieldConstPtr const & field);
private:
NTAggregateBuilder();
void reset();
bool dispersion;
bool first;
bool firstTimeStamp;
bool last;
bool lastTimeStamp;
bool max;
bool min;
bool descriptor;
bool alarm;
bool timeStamp;
// NOTE: this preserves order, however it does not handle duplicates
epics::pvData::StringArray extraFieldNames;
epics::pvData::FieldConstPtrArray extraFields;
friend class ::epics::nt::NTAggregate;
};
}
typedef std::tr1::shared_ptr<detail::NTAggregateBuilder> NTAggregateBuilderPtr;
/**
* @brief Convenience Class for NTAggregate
*
* @author dgh
*/
class epicsShareClass NTAggregate
{
public:
POINTER_DEFINITIONS(NTAggregate);
static const std::string URI;
/**
* Creates an NTAggregate wrapping the specified PVStructure if the latter is compatible.
* <p>
* Checks the supplied PVStructure is compatible with NTAggregate
* and if so returns an NTAggregate which wraps it.
* This method will return null if the structure is is not compatible
* or is null.
*
* @param pvStructure the PVStructure to be wrapped
* @return the NTAggregate instance on success, null otherwise
*/
static shared_pointer wrap(epics::pvData::PVStructurePtr const & pvStructure);
/**
* Creates an NTAggregate wrapping the specified PVStructure, regardless of the latter's compatibility.
* <p>
* No checks are made as to whether the specified PVStructure
* is compatible with NTAggregate or is non-null.
*
* @param pvStructure the PVStructure to be wrapped
* @return the NTAggregate instance
*/
static shared_pointer wrapUnsafe(epics::pvData::PVStructurePtr const & pvStructure);
/**
* Returns whether the specified Structure reports to be a compatible NTAggregate.
* <p>
* Checks if the specified Structure reports compatibility with this
* version of NTAggregate through its type ID, including checking version numbers.
* The return value does not depend on whether the structure is actually
* compatible in terms of its introspection type.
*
* @param structure the Structure to test
* @return (false,true) if the specified Structure (is not, is) a compatible NTAggregate
*/
static bool is_a(epics::pvData::StructureConstPtr const & structure);
/**
* Returns whether the specified PVStructure reports to be a compatible NTAggregate.
* <p>
* Checks if the specified PVStructure reports compatibility with this
* version of NTAggregate through its type ID, including checking version numbers.
* The return value does not depend on whether the structure is actually
* compatible in terms of its introspection type.
*
* @param pvStructure the PVStructure to test.
* @return (false,true) if the specified PVStructure (is not, is) a compatible NTAggregate.
*/
static bool is_a(epics::pvData::PVStructurePtr const & pvStructure);
/**
* Returns whether the specified Structure is compatible with NTAggregate.
* <p>
* Checks if the specified Structure is compatible with this version
* of NTAggregate through introspection interface.
*
* @param structure the Structure to test
* @return (false,true) if the specified Structure (is not, is) a compatible NTAggregate
*/
static bool isCompatible(
epics::pvData::StructureConstPtr const &structure);
/**
* Returns whether the specified PVStructure is compatible with NTAggregate.
* <p>
* Checks if the specified PVStructure is compatible with this version
* of NTAggregate through introspection interface.
*
* @param pvStructure the PVStructure to test
* @return (false,true) if the specified PVStructure (is not, is) a compatible NTAggregate
*/
static bool isCompatible(
epics::pvData::PVStructurePtr const &pvStructure);
/**
* Returns whether the wrapped PVStructure is valid with respect to this
* version of NTAggregate.
* <p>
* Unlike isCompatible(), isValid() may perform checks on the value data as
* well as the introspection data.
*
* @return (false,true) if wrapped PVStructure a valid NTAggregate
*/
bool isValid();
/**
* Creates an NTAggregate builder instance.
* @return builder instance.
*/
static NTAggregateBuilderPtr createBuilder();
/**
* Destructor.
*/
~NTAggregate() {}
/**
* Attaches a PVTimeStamp to the wrapped PVStructure.
* Does nothing if no timeStamp field.
* @param pvTimeStamp the PVTimeStamp that will be attached.
* @return true if the operation was successfull (i.e. this instance has a timeStamp field), otherwise false.
*/
bool attachTimeStamp(epics::pvData::PVTimeStamp &pvTimeStamp) const;
/**
* Attaches a PVAlarm to the wrapped PVStructure.
* Does nothing if no alarm field.
* @param pvAlarm the PVAlarm that will be attached.
* @return true if the operation was successfull (i.e. this instance has an alarm field), otherwise false.
*/
bool attachAlarm(epics::pvData::PVAlarm &pvAlarm) const;
/**
* Returns the PVStructure wrapped by this instance.
* @return the PVStructure wrapped by this instance.
*/
epics::pvData::PVStructurePtr getPVStructure() const;
/**
* Returns the descriptor field.
* @return the descriptor field or null if no such field.
*/
epics::pvData::PVStringPtr getDescriptor() const;
/**
* Returns the timeStamp field.
* @return the timStamp field or null if no such field.
*/
epics::pvData::PVStructurePtr getTimeStamp() const;
/**
* Returns the alarm field.
* @return the alarm field or null if no such field.
*/
epics::pvData::PVStructurePtr getAlarm() const;
/**
* Returns the value field.
* @return the value field.
*/
epics::pvData::PVDoublePtr getValue() const;
/**
* Returns the N field.
* @return the N field.
*/
epics::pvData::PVLongPtr getN() const;
/**
* Returns the dispersion field.
* @return the dispersion or null if no such field.
*/
epics::pvData::PVDoublePtr getDispersion() const;
/**
* Returns the first field.
* @return the first field or null if no such field.
*/
epics::pvData::PVDoublePtr getFirst() const;
/**
* Returns the firstTimeStamp field.
* @return the firstTimeStamp field or null if no such field.
*/
epics::pvData::PVStructurePtr getFirstTimeStamp() const;
/**
* Returns the last field.
* @return the last field or null if no such field.
*/
epics::pvData::PVDoublePtr getLast() const;
/**
* Returns the lastTimeStamp field.
* @return the lastTimeStamp field or null if no such field.
*/
epics::pvData::PVStructurePtr getLastTimeStamp() const;
/**
* Returns the max field.
* @return the max field or null if no such field.
*/
epics::pvData::PVDoublePtr getMax() const;
/**
* Returns the min field.
* @return the min field or null if no such field.
*/
epics::pvData::PVDoublePtr getMin() const;
private:
NTAggregate(epics::pvData::PVStructurePtr const & pvStructure);
epics::pvData::PVStructurePtr pvNTAggregate;
epics::pvData::PVDoublePtr pvValue;
friend class detail::NTAggregateBuilder;
};
}}
#endif /* NTAGGREGATE_H */

246
src/nt/ntattribute.cpp Normal file
View File

@@ -0,0 +1,246 @@
/* ntattribute.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* This software is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#define epicsExportSharedSymbols
#include <pv/ntattribute.h>
#include <pv/ntutils.h>
using namespace std;
using namespace epics::pvData;
namespace epics { namespace nt {
static NTFieldPtr ntField = NTField::get();
namespace detail {
StructureConstPtr NTAttributeBuilder::createStructure()
{
FieldBuilderPtr builder =
getFieldCreate()->createFieldBuilder()->
setId(NTAttribute::URI)->
add("name", pvString)->
add("value", getFieldCreate()->createVariantUnion());
if (tags)
builder->addArray("tags", pvString);
if (descriptor)
builder->add("descriptor", pvString);
if (alarm)
builder->add("alarm", ntField->createAlarm());
if (timeStamp)
builder->add("timeStamp", ntField->createTimeStamp());
size_t extraCount = extraFieldNames.size();
for (size_t i = 0; i< extraCount; i++)
builder->add(extraFieldNames[i], extraFields[i]);
StructureConstPtr s = builder->createStructure();
reset();
return s;
}
NTAttributeBuilder::shared_pointer NTAttributeBuilder::addTags()
{
tags = true;
return shared_from_this();
}
NTAttributeBuilder::shared_pointer NTAttributeBuilder::addDescriptor()
{
descriptor = true;
return shared_from_this();
}
NTAttributeBuilder::shared_pointer NTAttributeBuilder::addAlarm()
{
alarm = true;
return shared_from_this();
}
NTAttributeBuilder::shared_pointer NTAttributeBuilder::addTimeStamp()
{
timeStamp = true;
return shared_from_this();
}
PVStructurePtr NTAttributeBuilder::createPVStructure()
{
return getPVDataCreate()->createPVStructure(createStructure());
}
NTAttributePtr NTAttributeBuilder::create()
{
return NTAttributePtr(new NTAttribute(createPVStructure()));
}
NTAttributeBuilder::NTAttributeBuilder()
{
reset();
}
void NTAttributeBuilder::reset()
{
descriptor = false;
alarm = false;
timeStamp = false;
extraFieldNames.clear();
extraFields.clear();
}
NTAttributeBuilder::shared_pointer NTAttributeBuilder::add(string const & name, FieldConstPtr const & field)
{
extraFields.push_back(field); extraFieldNames.push_back(name);
return shared_from_this();
}
}
const std::string NTAttribute::URI("epics:nt/NTAttribute:1.0");
NTAttribute::shared_pointer NTAttribute::wrap(PVStructurePtr const & pvStructure)
{
if(!isCompatible(pvStructure)) return shared_pointer();
return wrapUnsafe(pvStructure);
}
NTAttribute::shared_pointer NTAttribute::wrapUnsafe(PVStructurePtr const & pvStructure)
{
return shared_pointer(new NTAttribute(pvStructure));
}
bool NTAttribute::is_a(StructureConstPtr const & structure)
{
return NTUtils::is_a(structure->getID(), URI);
}
bool NTAttribute::isCompatible(StructureConstPtr const & structure)
{
if (structure.get() == 0) return false;
ScalarConstPtr nameField = structure->getField<Scalar>("name");
if (nameField.get() == 0 || nameField->getScalarType() != pvString)
return false;
UnionConstPtr valueField = structure->getField<Union>("value");
if (valueField.get() == 0 || !valueField->isVariant())
return false;
FieldConstPtr field = structure->getField("tags");
if (field.get())
{
ScalarArrayConstPtr tagsField = structure->getField<ScalarArray>("tags");
if (tagsField.get() == 0 || tagsField->getElementType() != pvString)
return false;
}
field = structure->getField("descriptor");
if (field.get())
{
ScalarConstPtr descriptorField = structure->getField<Scalar>("descriptor");
if (!descriptorField.get() || descriptorField->getScalarType() != pvString)
return false;
}
NTFieldPtr ntField = NTField::get();
field = structure->getField("alarm");
if (field.get() && !ntField->isAlarm(field))
return false;
field = structure->getField("timeStamp");
if (field.get() && !ntField->isTimeStamp(field))
return false;
return true;
}
bool NTAttribute::isCompatible(PVStructurePtr const & pvStructure)
{
if(!pvStructure) return false;
return isCompatible(pvStructure->getStructure());
}
bool NTAttribute::isValid()
{
return true;
}
NTAttributeBuilderPtr NTAttribute::createBuilder()
{
return NTAttributeBuilderPtr(new detail::NTAttributeBuilder());
}
bool NTAttribute::attachTimeStamp(PVTimeStamp &pvTimeStamp) const
{
PVStructurePtr ts = getTimeStamp();
if (ts)
return pvTimeStamp.attach(ts);
else
return false;
}
bool NTAttribute::attachAlarm(PVAlarm &pvAlarm) const
{
PVStructurePtr al = getAlarm();
if (al)
return pvAlarm.attach(al);
else
return false;
}
PVStructurePtr NTAttribute::getPVStructure() const
{
return pvNTAttribute;
}
PVStringPtr NTAttribute::getDescriptor() const
{
return pvNTAttribute->getSubField<PVString>("descriptor");
}
PVStructurePtr NTAttribute::getTimeStamp() const
{
return pvNTAttribute->getSubField<PVStructure>("timeStamp");
}
PVStructurePtr NTAttribute::getAlarm() const
{
return pvNTAttribute->getSubField<PVStructure>("alarm");
}
PVStringPtr NTAttribute::getName() const
{
return pvNTAttribute->getSubField<PVString>("name");
}
PVUnionPtr NTAttribute::getValue() const
{
return pvValue;
}
PVStringArrayPtr NTAttribute::getTags() const
{
return pvNTAttribute->getSubField<PVStringArray>("tags");
}
NTAttribute::NTAttribute(PVStructurePtr const & pvStructure) :
pvNTAttribute(pvStructure), pvValue(pvNTAttribute->getSubField<PVUnion>("value"))
{
}
}}

295
src/nt/ntattribute.h Normal file
View File

@@ -0,0 +1,295 @@
/* ntattribute.h */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* This software is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#ifndef NTATTRIBUTE_H
#define NTATTRIBUTE_H
#ifdef epicsExportSharedSymbols
# define ntattributeEpicsExportSharedSymbols
# undef epicsExportSharedSymbols
#endif
#ifdef ntattributeEpicsExportSharedSymbols
# define epicsExportSharedSymbols
# undef ntattributeEpicsExportSharedSymbols
#endif
#include <pv/ntfield.h>
#include <shareLib.h>
namespace epics { namespace nt {
class NTAttribute;
typedef std::tr1::shared_ptr<NTAttribute> NTAttributePtr;
namespace detail {
/**
* @brief Interface for in-line creating of NTAttribute.
*
* One instance can be used to create multiple instances.
* An instance of this object must not be used concurrently (an object has a state).
* @author dgh
*/
class epicsShareClass NTAttributeBuilder :
public std::tr1::enable_shared_from_this<NTAttributeBuilder>
{
public:
POINTER_DEFINITIONS(NTAttributeBuilder);
/**
* Adds tags field to the NTAttribute.
* @return this instance of <b>NTAttributeBuilder</b>.
*/
virtual shared_pointer addTags();
/**
* Adds descriptor field to the NTAttribute.
* @return this instance of <b>NTAttributeBuilder</b>.
*/
shared_pointer addDescriptor();
/**
* Adds alarm field to the NTAttribute.
* @return this instance of <b>NTAttributeBuilder</b>.
*/
shared_pointer addAlarm();
/**
* Adds timeStamp field to the NTAttribute.
* @return this instance of <b>NTAttributeBuilder</b>.
*/
shared_pointer addTimeStamp();
/**
* Creates a <b>Structure</b> that represents NTAttribute.
* This resets this instance state and allows new instance to be created.
* @return a new instance of a <b>Structure</b>.
*/
epics::pvData::StructureConstPtr createStructure();
/**
* Creates a <b>PVStructure</b> that represents NTAttribute.
* This resets this instance state and allows new instance to be created.
* @return a new instance of a <b>PVStructure</b>.
*/
epics::pvData::PVStructurePtr createPVStructure();
/**
* Creates a <b>NTAttribute</b> instance.
* This resets this instance state and allows new instance to be created.
* @return a new instance of a <b>NTAttribute</b>.
*/
NTAttributePtr create();
/**
* Adds extra <b>Field</b> to the type.
* @param name the name of the field.
* @param field the field to be added.
* @return this instance of <b>NTAttributeBuilder</b>.
*/
shared_pointer add(std::string const & name, epics::pvData::FieldConstPtr const & field);
protected://private:
NTAttributeBuilder();
void reset();
bool tags;
bool descriptor;
bool alarm;
bool timeStamp;
// NOTE: this preserves order, however it does not handle duplicates
epics::pvData::StringArray extraFieldNames;
epics::pvData::FieldConstPtrArray extraFields;
friend class ::epics::nt::NTAttribute;
};
}
typedef std::tr1::shared_ptr<detail::NTAttributeBuilder> NTAttributeBuilderPtr;
/**
* @brief Convenience Class for NTAttribute
*
* @author dgh
*/
class epicsShareClass NTAttribute
{
public:
POINTER_DEFINITIONS(NTAttribute);
static const std::string URI;
/**
* Creates an NTAttribute wrapping the specified PVStructure if the latter is compatible.
* <p>
* Checks the supplied PVStructure is compatible with NTAttribute
* and if so returns an NTAttribute which wraps it.
* This method will return null if the structure is is not compatible
* or is null.
*
* @param pvStructure the PVStructure to be wrapped
* @return NTAttribute instance wrapping pvStructure on success, null otherwise
*/
static shared_pointer wrap(epics::pvData::PVStructurePtr const & pvStructure);
/**
* Creates an NTAttribute wrapping the specified PVStructure, regardless of the latter's compatibility.
* <p>
* No checks are made as to whether the specified PVStructure
* is compatible with NTAttribute or is non-null.
*
* @param pvStructure the PVStructure to be wrapped
* @return NTAttribute instance wrapping pvStructure
*/
static shared_pointer wrapUnsafe(epics::pvData::PVStructurePtr const & pvStructure);
/**
* Returns whether the specified Structure reports to be a compatible NTAttribute.
* <p>
* Checks if the specified Structure reports compatibility with this
* version of NTAttribute through its type ID, including checking version numbers.
* The return value does not depend on whether the structure is actually
* compatible in terms of its introspection type.
*
* @param structure the Structure to test
* @return (false,true) if the specified Structure (is not, is) a compatible NTAttribute
*/
static bool is_a(epics::pvData::StructureConstPtr const & structure);
/**
* Returns whether the specified PVStructure reports to be a compatible NTAttribute.
* <p>
* Checks if the specified PVStructure reports compatibility with this
* version of NTAttribute through its type ID, including checking version numbers.
* The return value does not depend on whether the structure is actually
* compatible in terms of its introspection type.
*
* @param pvStructure the PVStructure to test
* @return (false,true) if the specified PVStructure (is not, is) a compatible NTAttribute
*/
static bool is_a(epics::pvData::PVStructurePtr const & pvStructure);
/**
* Returns whether the specified Structure is compatible with NTAttribute.
* <p>
* Checks if the specified Structure is compatible with this version
* of NTAttribute through the introspection interface.
*
* @param structure the Structure to test
* @return (false,true) if the specified Structure (is not, is) a compatible NTAttribute
*/
static bool isCompatible(
epics::pvData::StructureConstPtr const &structure);
/**
* Returns whether the specified PVStructure is compatible with NTAttribute.
* <p>
* Checks if the specified tructure is compatible with this version
* of NTAttribute through the introspection interface.
* @param pvStructure the PVStructure to test
* @return (false,true) if the specified PVStructure (is not, is) a compatible NTAttribute
*/
static bool isCompatible(
epics::pvData::PVStructurePtr const &pvStructure);
/**
* Returns whether the wrapped PVStructure is valid with respect to this
* version of NTAttribute.
* <p>
* Unlike isCompatible(), isValid() may perform checks on the value
* data as well as the introspection data.
*
* @return (false,true) if the wrapped PVStructure (is not, is) a valid NTAttribute
*/
bool isValid();
/**
* Creates an NTAttribute builder instance.
* @return builder instance.
*/
static NTAttributeBuilderPtr createBuilder();
/**
* Destructor.
*/
~NTAttribute() {}
/**
* Attaches a PVTimeStamp to the wrapped PVStructure.
* Does nothing if no timeStamp field.
* @param pvTimeStamp the PVTimeStamp that will be attached.
* @return true if the operation was successfull (i.e. this instance has a timeStamp field), otherwise false.
*/
bool attachTimeStamp(epics::pvData::PVTimeStamp &pvTimeStamp) const;
/**
* Attaches a PVAlarm to the wrapped PVStructure.
* Does nothing if no alarm field.
* @param pvAlarm the PVAlarm that will be attached.
* @return true if the operation was successfull (i.e. this instance has an alarm field), otherwise false.
*/
bool attachAlarm(epics::pvData::PVAlarm &pvAlarm) const;
/**
* Returns the PVStructure wrapped by this instance.
* @return the PVStructure wrapped by this instance.
*/
epics::pvData::PVStructurePtr getPVStructure() const;
/**
* Returns the descriptor field.
* @return the descriptor field or null if no such field.
*/
epics::pvData::PVStringPtr getDescriptor() const;
/**
* Returns the timeStamp field.
* @return the timStamp field or null if no such field.
*/
epics::pvData::PVStructurePtr getTimeStamp() const;
/**
* Returns the alarm field.
* @return the alarm field or null if no such field.
*/
epics::pvData::PVStructurePtr getAlarm() const;
/**
* Returns the name field.
* @return the name field.
*/
epics::pvData::PVStringPtr getName() const;
/**
* Returns the value field.
* @return the value field.
*/
epics::pvData::PVUnionPtr getValue() const;
/**
* Returns the tags field.
* @return the tags field or null if no such field.
*/
epics::pvData::PVStringArrayPtr getTags() const;
private:
NTAttribute(epics::pvData::PVStructurePtr const & pvStructure);
epics::pvData::PVStructurePtr pvNTAttribute;
epics::pvData::PVUnionPtr pvValue;
friend class detail::NTAttributeBuilder;
};
}}
#endif /* NTATTRIBUTE_H */

234
src/nt/ntcontinuum.cpp Normal file
View File

@@ -0,0 +1,234 @@
/* ntcontinuum.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* This software is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#define epicsExportSharedSymbols
#include <pv/ntcontinuum.h>
#include <pv/ntutils.h>
using namespace std;
using namespace epics::pvData;
namespace epics { namespace nt {
static NTFieldPtr ntField = NTField::get();
namespace detail {
StructureConstPtr NTContinuumBuilder::createStructure()
{
FieldBuilderPtr builder =
getFieldCreate()->createFieldBuilder()->
setId(NTContinuum::URI)->
addArray("base", pvDouble)->
addArray("value", pvDouble)->
addArray("units", pvString);
if (descriptor)
builder->add("descriptor", pvString);
if (alarm)
builder->add("alarm", ntField->createAlarm());
if (timeStamp)
builder->add("timeStamp", ntField->createTimeStamp());
size_t extraCount = extraFieldNames.size();
for (size_t i = 0; i< extraCount; i++)
builder->add(extraFieldNames[i], extraFields[i]);
StructureConstPtr s = builder->createStructure();
reset();
return s;
}
NTContinuumBuilder::shared_pointer NTContinuumBuilder::addDescriptor()
{
descriptor = true;
return shared_from_this();
}
NTContinuumBuilder::shared_pointer NTContinuumBuilder::addAlarm()
{
alarm = true;
return shared_from_this();
}
NTContinuumBuilder::shared_pointer NTContinuumBuilder::addTimeStamp()
{
timeStamp = true;
return shared_from_this();
}
PVStructurePtr NTContinuumBuilder::createPVStructure()
{
return getPVDataCreate()->createPVStructure(createStructure());
}
NTContinuumPtr NTContinuumBuilder::create()
{
return NTContinuumPtr(new NTContinuum(createPVStructure()));
}
NTContinuumBuilder::NTContinuumBuilder()
{
reset();
}
void NTContinuumBuilder::reset()
{
descriptor = false;
alarm = false;
timeStamp = false;
extraFieldNames.clear();
extraFields.clear();
}
NTContinuumBuilder::shared_pointer NTContinuumBuilder::add(string const & name, FieldConstPtr const & field)
{
extraFields.push_back(field); extraFieldNames.push_back(name);
return shared_from_this();
}
}
const std::string NTContinuum::URI("epics:nt/NTContinuum:1.0");
NTContinuum::shared_pointer NTContinuum::wrap(PVStructurePtr const & pvStructure)
{
if(!isCompatible(pvStructure)) return shared_pointer();
return wrapUnsafe(pvStructure);
}
NTContinuum::shared_pointer NTContinuum::wrapUnsafe(PVStructurePtr const & pvStructure)
{
return shared_pointer(new NTContinuum(pvStructure));
}
bool NTContinuum::is_a(StructureConstPtr const & structure)
{
return NTUtils::is_a(structure->getID(), URI);
}
bool NTContinuum::isCompatible(StructureConstPtr const & structure)
{
if (structure.get() == 0) return false;
ScalarArrayConstPtr baseField = structure->getField<ScalarArray>("base");
if (baseField.get() == 0 || baseField->getElementType() != pvDouble)
return false;
ScalarArrayConstPtr valueField = structure->getField<ScalarArray>("value");
if (valueField.get() == 0 || valueField->getElementType() != pvDouble)
return false;
ScalarArrayConstPtr unitsField = structure->getField<ScalarArray>("units");
if (unitsField.get() == 0 || unitsField->getElementType() != pvString)
return false;
FieldConstPtr field = structure->getField("descriptor");
if (field.get())
{
ScalarConstPtr descriptorField = structure->getField<Scalar>("descriptor");
if (!descriptorField.get() || descriptorField->getScalarType() != pvString)
return false;
}
NTFieldPtr ntField = NTField::get();
field = structure->getField("alarm");
if (field.get() && !ntField->isAlarm(field))
return false;
field = structure->getField("timeStamp");
if (field.get() && !ntField->isTimeStamp(field))
return false;
return true;
}
bool NTContinuum::isCompatible(PVStructurePtr const & pvStructure)
{
if(!pvStructure) return false;
return isCompatible(pvStructure->getStructure());
}
bool NTContinuum::isValid()
{
return ((getUnits()->getLength()-1)*getBase()->getLength() ==
getValue()->getLength());
}
NTContinuumBuilderPtr NTContinuum::createBuilder()
{
return NTContinuumBuilderPtr(new detail::NTContinuumBuilder());
}
bool NTContinuum::attachTimeStamp(PVTimeStamp &pvTimeStamp) const
{
PVStructurePtr ts = getTimeStamp();
if (ts)
return pvTimeStamp.attach(ts);
else
return false;
}
bool NTContinuum::attachAlarm(PVAlarm &pvAlarm) const
{
PVStructurePtr al = getAlarm();
if (al)
return pvAlarm.attach(al);
else
return false;
}
PVStructurePtr NTContinuum::getPVStructure() const
{
return pvNTContinuum;
}
PVStringPtr NTContinuum::getDescriptor() const
{
return pvNTContinuum->getSubField<PVString>("descriptor");
}
PVStructurePtr NTContinuum::getTimeStamp() const
{
return pvNTContinuum->getSubField<PVStructure>("timeStamp");
}
PVStructurePtr NTContinuum::getAlarm() const
{
return pvNTContinuum->getSubField<PVStructure>("alarm");
}
PVDoubleArrayPtr NTContinuum::getBase() const
{
return pvNTContinuum->getSubField<PVDoubleArray>("base");
}
PVDoubleArrayPtr NTContinuum::getValue() const
{
return pvValue;
}
PVStringArrayPtr NTContinuum::getUnits() const
{
return pvNTContinuum->getSubField<PVStringArray>("units");
}
NTContinuum::NTContinuum(PVStructurePtr const & pvStructure) :
pvNTContinuum(pvStructure),
pvValue(pvNTContinuum->getSubField<PVDoubleArray>("value"))
{}
}}

290
src/nt/ntcontinuum.h Normal file
View File

@@ -0,0 +1,290 @@
/* ntcontinuum.h */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* This software is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#ifndef NTCONTINUUM_H
#define NTCONTINUUM_H
#ifdef epicsExportSharedSymbols
# define ntcontinuumEpicsExportSharedSymbols
# undef epicsExportSharedSymbols
#endif
#ifdef ntcontinuumEpicsExportSharedSymbols
# define epicsExportSharedSymbols
# undef ntcontinuumEpicsExportSharedSymbols
#endif
#include <pv/ntfield.h>
#include <shareLib.h>
namespace epics { namespace nt {
class NTContinuum;
typedef std::tr1::shared_ptr<NTContinuum> NTContinuumPtr;
namespace detail {
/**
* @brief Interface for in-line creating of NTContinuum.
*
* One instance can be used to create multiple instances.
* An instance of this object must not be used concurrently (an object has a state).
* @author dgh
*/
class epicsShareClass NTContinuumBuilder :
public std::tr1::enable_shared_from_this<NTContinuumBuilder>
{
public:
POINTER_DEFINITIONS(NTContinuumBuilder);
/**
* Adds descriptor field to the NTContinuum.
* @return this instance of <b>NTContinuumBuilder</b>.
*/
shared_pointer addDescriptor();
/**
* Adds alarm field to the NTContinuum.
* @return this instance of <b>NTContinuumBuilder</b>.
*/
shared_pointer addAlarm();
/**
* Adds timeStamp field to the NTContinuum.
* @return this instance of <b>NTContinuumBuilder</b>.
*/
shared_pointer addTimeStamp();
/**
* Creates a <b>Structure</b> that represents NTContinuum.
* This resets this instance state and allows new instance to be created.
* @return a new instance of <b>Structure</b>.
*/
epics::pvData::StructureConstPtr createStructure();
/**
* Creates a <b>PVStructure</b> that represents NTContinuum.
* This resets this instance state and allows new instance to be created.
* @return a new instance of <b>PVStructure</b>.
*/
epics::pvData::PVStructurePtr createPVStructure();
/**
* Creates a <b>NTContinuum</b> instance.
* This resets this instance state and allows new instance to be created.
* @return a new instance of <b>NTContinuum</b>.
*/
NTContinuumPtr create();
/**
* Adds extra <b>Field</b> to the type.
* @param name the name of the field.
* @param field the field to be added.
* @return this instance of <b>NTContinuumBuilder</b>.
*/
shared_pointer add(std::string const & name, epics::pvData::FieldConstPtr const & field);
private:
NTContinuumBuilder();
void reset();
bool dim;
bool descriptor;
bool alarm;
bool timeStamp;
// NOTE: this preserves order, however it does not handle duplicates
epics::pvData::StringArray extraFieldNames;
epics::pvData::FieldConstPtrArray extraFields;
friend class ::epics::nt::NTContinuum;
};
}
typedef std::tr1::shared_ptr<detail::NTContinuumBuilder> NTContinuumBuilderPtr;
/**
* @brief Convenience Class for NTContinuum
*
* @author dgh
*/
class epicsShareClass NTContinuum
{
public:
POINTER_DEFINITIONS(NTContinuum);
static const std::string URI;
/**
* Creates an NTContinuum wrapping the specified PVStructure if the latter is compatible.
* <p>
* Checks the supplied structure is compatible with NTContinuum
* and if so returns an NTContinuum which wraps it.
* This method will return null if the structure is is not compatible
* or is null.
*
* @param pvStructure the PVStructure to be wrapped
* @return NTContinuum instance wrapping pvStructure on success, null otherwise
*/
static shared_pointer wrap(epics::pvData::PVStructurePtr const & pvStructure);
/**
* Creates an NTContinuum wrapping the specified PVStructure, regardless of the latter's compatibility.
* <p>
* No checks are made as to whether the specified PVStructure
* is compatible with NTContinuum or is non-null.
*
* @param pvStructure the PVStructure to be wrapped
* @return NTContinuum instance wrapping pvStructure.
*/
static shared_pointer wrapUnsafe(epics::pvData::PVStructurePtr const & pvStructure);
/**
* Returns whether the specified Structure reports to be a compatible NTContinuum.
* <p>
* Checks if the specified Structure reports compatibility with this
* version of NTContinuum through its type ID, including checking version numbers.
* The return value does not depend on whether the structure is actually
* compatible in terms of its introspection type
*
* @param structure the Structure to test
* @return (false,true) if the specified Structure (is not, is) a compatible NTContinuum
*/
static bool is_a(epics::pvData::StructureConstPtr const & structure);
/**
* Returns whether the specified PVStructure reports to be a compatible NTContinuum.
* <p>
* Checks if the specified Structure reports compatibility with this
* version of NTContinuum through its type ID, including checking version numbers.
* The return value does not depend on whether the structure is actually
* compatible in terms of its introspection type
*
* @param pvStructure The PVStructure to test
* @return (false,true) if the specified PVStructure (is not, is) a compatible NTContinuum
*/
static bool is_a(epics::pvData::PVStructurePtr const & pvStructure);
/**
* Returns whether the specified Structure is compatible with NTContinuum.
* <p>
* Checks if the specified Structure is compatible with this version
* of NTContinuum through the introspection interface.
*
* @param structure the Structure to test
* @return (false,true) if the specified Structure (is not, is) a compatible NTContinuum
*/
static bool isCompatible(
epics::pvData::StructureConstPtr const &structure);
/**
* Returns whether the specified PVStructure is compatible with NTContinuum.
* <p>
* Checks if the specified PVStructure is compatible with this version
* of NTContinuum through the introspection interface.
*
* @param pvStructure the PVStructure to test
* @return (false,true) if the specified PVStructure (is not, is) a compatible NTContinuum
*/
static bool isCompatible(
epics::pvData::PVStructurePtr const &pvStructure);
/**
* Returns whether the wrapped structure is valid with respect to this
* version of NTContinuum.
* <p>
* Unlike isCompatible(), isValid() may perform checks on the value
* data as well as the introspection data.
*
* @return (false,true) if the wrapped PVStructure (is not, is) a valid NTContinuum
*/
bool isValid();
/**
* Creates an NTContinuum builder instance.
* @return builder instance.
*/
static NTContinuumBuilderPtr createBuilder();
/**
* Destructor.
*/
~NTContinuum() {}
/**
* Attaches a PVTimeStamp to the wrapped PVStructure.
* Does nothing if no timeStamp field.
* @param pvTimeStamp the PVTimeStamp that will be attached.
* @return true if the operation was successfull (i.e. this instance has a timeStamp field), otherwise false.
*/
bool attachTimeStamp(epics::pvData::PVTimeStamp &pvTimeStamp) const;
/**
* Attaches a PVAlarm to the wrapped PVStructure.
* Does nothing if no alarm field.
* @param pvAlarm the PVAlarm that will be attached.
* @return true if the operation was successfull (i.e. this instance has an alarm field), otherwise false.
*/
bool attachAlarm(epics::pvData::PVAlarm &pvAlarm) const;
/**
* Returns the PVStructure wrapped by this instance.
* @return the PVStructure wrapped by this instance.
*/
epics::pvData::PVStructurePtr getPVStructure() const;
/**
* Returns the descriptor field.
* @return the descriptor field or null if no such field.
*/
epics::pvData::PVStringPtr getDescriptor() const;
/**
* Returns the timeStamp field.
* @return the timStamp field or null if no such field.
*/
epics::pvData::PVStructurePtr getTimeStamp() const;
/**
* Returns the alarm field.
* @return the alarm field or null if no such field.
*/
epics::pvData::PVStructurePtr getAlarm() const;
/**
* Returns the base field.
* @return the base field.
*/
epics::pvData::PVDoubleArrayPtr getBase() const;
/**
* Returns the value field.
* @return the value field.
*/
epics::pvData::PVDoubleArrayPtr getValue() const;
/**
* Returns the units field.
* @return the units field.
*/
epics::pvData::PVStringArrayPtr getUnits() const;
private:
NTContinuum(epics::pvData::PVStructurePtr const & pvStructure);
epics::pvData::PVStructurePtr pvNTContinuum;
epics::pvData::PVDoubleArrayPtr pvValue;
friend class detail::NTContinuumBuilder;
};
}}
#endif /* NTCONTINUUM_H */

213
src/nt/ntenum.cpp Normal file
View File

@@ -0,0 +1,213 @@
/* ntenum.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* This software is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#define epicsExportSharedSymbols
#include <pv/ntenum.h>
#include <pv/ntutils.h>
using namespace std;
using namespace epics::pvData;
namespace epics { namespace nt {
static NTFieldPtr ntField = NTField::get();
namespace detail {
StructureConstPtr NTEnumBuilder::createStructure()
{
FieldBuilderPtr builder =
getFieldCreate()->createFieldBuilder()->
setId(NTEnum::URI)->
add("value", ntField->createEnumerated());
if (descriptor)
builder->add("descriptor", pvString);
if (alarm)
builder->add("alarm", ntField->createAlarm());
if (timeStamp)
builder->add("timeStamp", ntField->createTimeStamp());
size_t extraCount = extraFieldNames.size();
for (size_t i = 0; i< extraCount; i++)
builder->add(extraFieldNames[i], extraFields[i]);
StructureConstPtr s = builder->createStructure();
reset();
return s;
}
NTEnumBuilder::shared_pointer NTEnumBuilder::addDescriptor()
{
descriptor = true;
return shared_from_this();
}
NTEnumBuilder::shared_pointer NTEnumBuilder::addAlarm()
{
alarm = true;
return shared_from_this();
}
NTEnumBuilder::shared_pointer NTEnumBuilder::addTimeStamp()
{
timeStamp = true;
return shared_from_this();
}
PVStructurePtr NTEnumBuilder::createPVStructure()
{
return getPVDataCreate()->createPVStructure(createStructure());
}
NTEnumPtr NTEnumBuilder::create()
{
return NTEnumPtr(new NTEnum(createPVStructure()));
}
NTEnumBuilder::NTEnumBuilder()
{
reset();
}
void NTEnumBuilder::reset()
{
descriptor = false;
alarm = false;
timeStamp = false;
extraFieldNames.clear();
extraFields.clear();
}
NTEnumBuilder::shared_pointer NTEnumBuilder::add(string const & name, FieldConstPtr const & field)
{
extraFields.push_back(field); extraFieldNames.push_back(name);
return shared_from_this();
}
}
const std::string NTEnum::URI("epics:nt/NTEnum:1.0");
NTEnum::shared_pointer NTEnum::wrap(PVStructurePtr const & pvStructure)
{
if(!isCompatible(pvStructure)) return shared_pointer();
return wrapUnsafe(pvStructure);
}
NTEnum::shared_pointer NTEnum::wrapUnsafe(PVStructurePtr const & pvStructure)
{
return shared_pointer(new NTEnum(pvStructure));
}
bool NTEnum::is_a(StructureConstPtr const & structure)
{
return NTUtils::is_a(structure->getID(), URI);
}
bool NTEnum::isCompatible(StructureConstPtr const &structure)
{
if (structure.get() == 0) return false;
NTFieldPtr ntField = NTField::get();
FieldConstPtr valueField = structure->getField("value");
if (!valueField.get() || !ntField->isEnumerated(valueField))
return false;
FieldConstPtr field = structure->getField("descriptor");
if (field.get())
{
ScalarConstPtr descriptorField = structure->getField<Scalar>("descriptor");
if (!descriptorField.get() || descriptorField->getScalarType() != pvString)
return false;
}
field = structure->getField("alarm");
if (field.get() && !ntField->isAlarm(field))
return false;
field = structure->getField("timeStamp");
if (field.get() && !ntField->isTimeStamp(field))
return false;
return true;
}
bool NTEnum::isCompatible(PVStructurePtr const & pvStructure)
{
if(!pvStructure) return false;
return isCompatible(pvStructure->getStructure());
}
bool NTEnum::isValid()
{
return true;
}
NTEnumBuilderPtr NTEnum::createBuilder()
{
return NTEnumBuilderPtr(new detail::NTEnumBuilder());
}
bool NTEnum::attachTimeStamp(PVTimeStamp &pvTimeStamp) const
{
PVStructurePtr ts = getTimeStamp();
if (ts)
return pvTimeStamp.attach(ts);
else
return false;
}
bool NTEnum::attachAlarm(PVAlarm &pvAlarm) const
{
PVStructurePtr al = getAlarm();
if (al)
return pvAlarm.attach(al);
else
return false;
}
PVStructurePtr NTEnum::getPVStructure() const
{
return pvNTEnum;
}
PVStringPtr NTEnum::getDescriptor() const
{
return pvNTEnum->getSubField<PVString>("descriptor");
}
PVStructurePtr NTEnum::getTimeStamp() const
{
return pvNTEnum->getSubField<PVStructure>("timeStamp");
}
PVStructurePtr NTEnum::getAlarm() const
{
return pvNTEnum->getSubField<PVStructure>("alarm");
}
PVStructurePtr NTEnum::getValue() const
{
return pvValue;
}
NTEnum::NTEnum(PVStructurePtr const & pvStructure) :
pvNTEnum(pvStructure), pvValue(pvNTEnum->getSubField<PVStructure>("value"))
{}
}}

274
src/nt/ntenum.h Normal file
View File

@@ -0,0 +1,274 @@
/* ntenum.h */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* This software is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#ifndef NTENUM_H
#define NTENUM_H
#ifdef epicsExportSharedSymbols
# define ntenumEpicsExportSharedSymbols
# undef epicsExportSharedSymbols
#endif
#ifdef ntenumEpicsExportSharedSymbols
# define epicsExportSharedSymbols
# undef ntenumEpicsExportSharedSymbols
#endif
#include <pv/ntfield.h>
#include <shareLib.h>
namespace epics { namespace nt {
class NTEnum;
typedef std::tr1::shared_ptr<NTEnum> NTEnumPtr;
namespace detail {
/**
* @brief Interface for in-line creating of NTEnum.
*
* One instance can be used to create multiple instances.
* An instance of this object must not be used concurrently (an object has a state).
* @author dgh
*/
class epicsShareClass NTEnumBuilder :
public std::tr1::enable_shared_from_this<NTEnumBuilder>
{
public:
POINTER_DEFINITIONS(NTEnumBuilder);
/**
* Adds descriptor field to the NTEnum.
* @return this instance of <b>NTEnumBuilder</b>.
*/
shared_pointer addDescriptor();
/**
* Adds alarm field to the NTEnum.
* @return this instance of <b>NTEnumBuilder</b>.
*/
shared_pointer addAlarm();
/**
* Adds timeStamp field to the NTEnum.
* @return this instance of <b>NTEnumBuilder</b>.
*/
shared_pointer addTimeStamp();
/**
* Creates a <b>Structure</b> that represents NTEnum.
* This resets this instance state and allows new instance to be created.
* @return a new instance of a <b>Structure</b>.
*/
epics::pvData::StructureConstPtr createStructure();
/**
* Creates a <b>PVStructure</b> that represents NTEnum.
* This resets this instance state and allows new instance to be created.
* @return a new instance of a <b>PVStructure</b>.
*/
epics::pvData::PVStructurePtr createPVStructure();
/**
* Creates a <b>NTEnum</b> instance.
* This resets this instance state and allows new instance to be created.
* @return a new instance of a <b>NTEnum</b>.
*/
NTEnumPtr create();
/**
* Adds extra <b>Field</b> to the type.
* @param name the name of the field.
* @param field the field to be added.
* @return this instance of <b>NTEnumBuilder</b>.
*/
shared_pointer add(std::string const & name, epics::pvData::FieldConstPtr const & field);
private:
NTEnumBuilder();
void reset();
bool descriptor;
bool alarm;
bool timeStamp;
// NOTE: this preserves order, however it does not handle duplicates
epics::pvData::StringArray extraFieldNames;
epics::pvData::FieldConstPtrArray extraFields;
friend class ::epics::nt::NTEnum;
};
}
typedef std::tr1::shared_ptr<detail::NTEnumBuilder> NTEnumBuilderPtr;
/**
* @brief Convenience Class for NTEnum
*
* @author dgh
*/
class epicsShareClass NTEnum
{
public:
POINTER_DEFINITIONS(NTEnum);
static const std::string URI;
/**
* Creates an NTEnum wrapping the specified PVStructure, regardless of the latter's compatibility.
* <p>
* No checks are made as to whether the specified PVStructure
* is compatible with NTEnum or is non-null.
*
* @param pvStructure the PVStructure to be wrapped
* @return NTEnum instance wrapping pvStructure
*/
static shared_pointer wrap(epics::pvData::PVStructurePtr const & pvStructure);
/**
* Creates an NTEnum wrapping the specified PVStructure, regardless of the latter's compatibility.
* <p>
* No checks are made as to whether the specified PVStructure
* is compatible with NTEnum or is non-null.
*
* @param pvStructure the PVStructure to be wrapped
* @return NTEnum instance wrapping pvStructure
*/
static shared_pointer wrapUnsafe(epics::pvData::PVStructurePtr const & pvStructure);
/**
* Returns whether the specified Structure reports to be a compatible NTEnum.
* <p>
* Checks if the specified Structure reports compatibility with this
* version of NTEnum through its type ID, including checking version numbers.
* The return value does not depend on whether the structure is actually
* compatible in terms of its introspection type.
*
* @param structure the Structure to test.
* @return (false,true) if the specified Structure (is not, is) a compatible NTEnum.
*/
static bool is_a(epics::pvData::StructureConstPtr const & structure);
/**
* Returns whether the specified PVStructure reports to be a compatible NTEnum.
* <p>
* Checks if the specified PVStructure reports compatibility with this
* version of NTEnum through its type ID, including checking version numbers.
* The return value does not depend on whether the structure is actually
* compatible in terms of its introspection type.
*
* @param pvStructure the PVStructure to test
* @return (false,true) if the specified PVStructure (is not, is) a compatible NTEnum
*/
static bool is_a(epics::pvData::PVStructurePtr const & pvStructure);
/**
* Returns whether the specified Structure is compatible with NTEnum.
* <p>
* Checks if the specified Structure is compatible with this version
* of NTEnum through the introspection interface.
*
* @param structure The Structure to test
* @return (false,true) if the specified Structure (is not, is) a compatible NTEnum
*/
static bool isCompatible(
epics::pvData::StructureConstPtr const &structure);
/**
* Returns whether the specified PVStructure is compatible with NTEnum.
* <p>
* Checks if the specified PVStructure is compatible with this version
* of NTEnum through the introspection interface.
*
* @param pvStructure the PVStructure to test
* @return (false,true) if the specified PVStructure (is not, is) a compatible NTEnum
*/
static bool isCompatible(
epics::pvData::PVStructurePtr const &pvStructure);
/**
* Returns whether the wrapped PVStructure is valid with respect to this
* version of NTEnum.
* <p>
* Unlike isCompatible(), isValid() may perform checks on the value
* data as well as the introspection data.
*
* @return (false,true) if the wrapped PVStructure (is not, is) a valid NTEnum
*/
bool isValid();
/**
* Creates an NTEnum builder instance.
* @return builder instance.
*/
static NTEnumBuilderPtr createBuilder();
/**
* Destructor.
*/
~NTEnum() {}
/**
* Attaches a PVTimeStamp to the wrapped PVStructure.
* Does nothing if no timeStamp field.
* @param pvTimeStamp the PVTimeStamp that will be attached.
* @return true if the operation was successfull (i.e. this instance has a timeStamp field), otherwise false.
*/
bool attachTimeStamp(epics::pvData::PVTimeStamp &pvTimeStamp) const;
/**
* Attaches a PVAlarm to the wrapped PVStructure.
* Does nothing if no alarm field.
* @param pvAlarm the PVAlarm that will be attached.
* @return true if the operation was successfull (i.e. this instance has an alarm field), otherwise false.
*/
bool attachAlarm(epics::pvData::PVAlarm &pvAlarm) const;
/**
* Returns the PVStructure wrapped by this instance.
* @return the PVStructure wrapped by this instance.
*/
epics::pvData::PVStructurePtr getPVStructure() const;
/**
* Returns the descriptor field.
* @return the descriptor field or null if no such field.
*/
epics::pvData::PVStringPtr getDescriptor() const;
/**
* Returns the timeStamp field.
* @return the timStamp field or or null if no such field.
*/
epics::pvData::PVStructurePtr getTimeStamp() const;
/**
* Returns the alarm field.
* @return the alarm field or or null if no such field.
*/
epics::pvData::PVStructurePtr getAlarm() const;
/**
* Get the value field.
* @return the value field.
*/
epics::pvData::PVStructurePtr getValue() const;
private:
NTEnum(epics::pvData::PVStructurePtr const & pvStructure);
epics::pvData::PVStructurePtr pvNTEnum;
epics::pvData::PVStructurePtr pvValue;
friend class detail::NTEnumBuilder;
};
}}
#endif /* NTENUM_H */

View File

@@ -1,16 +1,19 @@
/* ntfield.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* This software is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#include <pv/lock.h>
#define epicsExportSharedSymbols
#include <pv/ntfield.h>
using namespace epics::pvData;
using std::tr1::static_pointer_cast;
namespace epics { namespace pvData {
namespace epics { namespace nt {
NTFieldPtr NTField::get()
{

View File

@@ -1,7 +1,7 @@
/* ntfield.h */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* This software is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#ifndef NTFIELD_H
@@ -9,6 +9,11 @@
#include <cstdarg>
#ifdef epicsExportSharedSymbols
# define ntfieldEpicsExportSharedSymbols
# undef epicsExportSharedSymbols
#endif
#include <pv/standardField.h>
#include <pv/standardPVField.h>
#include <pv/alarm.h>
@@ -17,12 +22,14 @@
#include <pv/pvTimeStamp.h>
#include <pv/sharedVector.h>
namespace epics { namespace pvData {
/**
* Convenience Class for introspection fields of a Normative Type
* @author mrk
*
*/
#ifdef ntfieldEpicsExportSharedSymbols
# define epicsExportSharedSymbols
# undef ntfieldEpicsExportSharedSymbols
#endif
#include <shareLib.h>
namespace epics { namespace nt {
class NTField;
typedef std::tr1::shared_ptr<NTField> NTFieldPtr;
@@ -30,11 +37,17 @@ typedef std::tr1::shared_ptr<NTField> NTFieldPtr;
class PVNTField;
typedef std::tr1::shared_ptr<PVNTField> PVNTFieldPtr;
class NTField {
/**
* @brief Convenience Class for introspection fields of a Normative Type
*
* @author mrk
*
*/
class epicsShareClass NTField {
public:
POINTER_DEFINITIONS(NTField);
/**
* get the single implementation of this class.
* Gets the single implementation of this class.
* @return the implementation
*/
static NTFieldPtr get();
@@ -42,162 +55,187 @@ public:
* destructor
*/
~NTField() {}
/**
* Is field an enumerated structure.
* @param field The field to test.
* @param field the field to test.
* @return (false,true) if field (is not,is) an enumerated structure.
*/
bool isEnumerated(FieldConstPtr const & field);
bool isEnumerated(epics::pvData::FieldConstPtr const & field);
/**
* Is field a timeStamp structure.
* @param field The field to test.
* @param field the field to test.
* @return (false,true) if field (is not,is) a timeStamp structure.
*/
bool isTimeStamp(FieldConstPtr const & field);
bool isTimeStamp(epics::pvData::FieldConstPtr const & field);
/**
* Is field an alarm structure.
* @param field The field to test.
* @param field the field to test.
* @return (false,true) if field (is not,is) an alarm structure.
*/
bool isAlarm(FieldConstPtr const & field);
bool isAlarm(epics::pvData::FieldConstPtr const & field);
/**
* Is field a display structure.
* @param field The field to test.
* @param field the field to test.
* @return (false,true) if field (is not,is) a display structure.
*/
bool isDisplay(FieldConstPtr const & field);
bool isDisplay(epics::pvData::FieldConstPtr const & field);
/**
* Is field an alarmLimit structure.
* @param field The field to test.
* @param field the field to test.
* @return (false,true) if field (is not,is) an alarmLimit structure.
*/
bool isAlarmLimit(FieldConstPtr const & field);
bool isAlarmLimit(epics::pvData::FieldConstPtr const & field);
/**
* Is field a control structure.
* @param field The field to test.
* @param field the field to test.
* @return (false,true) if field (is not,is) a control structure.
*/
bool isControl(FieldConstPtr const & field);
bool isControl(epics::pvData::FieldConstPtr const & field);
/**
* Create an enumerated structure.
* Creates an enumerated structure.
* @return an enumerated structure.
*/
StructureConstPtr createEnumerated();
/**
* Create a timeStamp structure.
* @return a timeStamp structure.
*/
StructureConstPtr createTimeStamp();
/**
* Create an alarm structure.
* @return an alarm structure.
*/
StructureConstPtr createAlarm();
/**
* Create a display structure.
* @return a displayalarm structure.
*/
StructureConstPtr createDisplay();
/**
* Create a control structure.
* @return a control structure.
*/
StructureConstPtr createControl();
epics::pvData::StructureConstPtr createEnumerated();
/**
* Create an array of enumerated structures.
* Creates a timeStamp structure.
* @return a timeStamp structure.
*/
epics::pvData::StructureConstPtr createTimeStamp();
/**
* Creates an alarm structure.
* @return an alarm structure.
*/
epics::pvData::StructureConstPtr createAlarm();
/**
* Creates a display structure.
* @return a displayalarm structure.
*/
epics::pvData::StructureConstPtr createDisplay();
/**
* Creates a control structure.
* @return a control structure.
*/
epics::pvData::StructureConstPtr createControl();
/**
* Creates an array of enumerated structures.
* @return an array of enumerated structures.
*/
StructureArrayConstPtr createEnumeratedArray();
epics::pvData::StructureArrayConstPtr createEnumeratedArray();
/**
* Create an array of timeStamp structures.
* Creates an array of timeStamp structures.
* @return an array of timeStamp structures.
*/
StructureArrayConstPtr createTimeStampArray();
epics::pvData::StructureArrayConstPtr createTimeStampArray();
/**
* Create an array of alarm structures.
* Creates an array of alarm structures.
* @return an array of alarm structures.
*/
StructureArrayConstPtr createAlarmArray();
epics::pvData::StructureArrayConstPtr createAlarmArray();
private:
NTField();
FieldCreatePtr fieldCreate;
StandardFieldPtr standardField;
epics::pvData::FieldCreatePtr fieldCreate;
epics::pvData::StandardFieldPtr standardField;
};
/**
* Convenience Class for data fields of a Normative Type
* @brief Convenience Class for data fields of a Normative Type
*
* @author mrk
*
*/
class PVNTField {
class epicsShareClass PVNTField {
public:
POINTER_DEFINITIONS(PVNTField);
/**
* get the single implementation of this class.
* Returns the single implementation of this class.
* @return the implementation
*/
static PVNTFieldPtr get();
/**
* destructor
*/
~PVNTField() {}
/**
* Create an enumerated PVStructure.
* @param choices The array of choices.
* @return an enumerated PVStructure..
*/
PVStructurePtr createEnumerated(
StringArray const & choices);
/**
* Create a timeStamp PVStructure.
* @return a timeStamp PVStructure..
*/
PVStructurePtr createTimeStamp();
/**
* Create an alarm PVStructure.
* @return an alarm PVStructure..
*/
PVStructurePtr createAlarm();
/**
* Create a display PVStructure.
* @return a display PVStructure..
*/
PVStructurePtr createDisplay();
/**
* Create an alarmLimit PVStructure.
* @return an alarmLimit PVStructure..
*/
PVStructurePtr createAlarmLimit();
/**
* Create a control PVStructure.
* @return a control PVStructure..
*/
PVStructurePtr createControl();
/**
* Create an enumerated PVStructureArray.
* @return an enumerated PVStructureArray..
* Creates an enumerated PVStructure.
* @param choices The array of choices.
* @return an enumerated PVStructure.
*/
PVStructureArrayPtr createEnumeratedArray();
epics::pvData::PVStructurePtr createEnumerated(
epics::pvData::StringArray const & choices);
/**
* Create a timeStamp PVStructureArray.
* @return a timeStamp PVStructureArray
* Creates a timeStamp PVStructure.
* @return a timeStamp PVStructure.
*/
PVStructureArrayPtr createTimeStampArray();
epics::pvData::PVStructurePtr createTimeStamp();
/**
* Create an alarm PVStructureArray.
* @return an alarm PVStructureArray..
* Creates an alarm PVStructure.
* @return an alarm PVStructure.
*/
PVStructureArrayPtr createAlarmArray();
epics::pvData::PVStructurePtr createAlarm();
/**
* Creates a display PVStructure.
* @return a display PVStructure.
*/
epics::pvData::PVStructurePtr createDisplay();
/**
* Creates an alarmLimit PVStructure.
* @return an alarmLimit PVStructure.
*/
epics::pvData::PVStructurePtr createAlarmLimit();
/**
* Creates a control PVStructure.
* @return a control PVStructure.
*/
epics::pvData::PVStructurePtr createControl();
/**
* Creates an enumerated PVStructureArray.
* @return an enumerated PVStructureArray.
*/
epics::pvData::PVStructureArrayPtr createEnumeratedArray();
/**
* Creates a timeStamp PVStructureArray.
* @return a timeStamp PVStructureArray.
*/
epics::pvData::PVStructureArrayPtr createTimeStampArray();
/**
* Creates an alarm PVStructureArray.
* @return an alarm PVStructureArray.
*/
epics::pvData::PVStructureArrayPtr createAlarmArray();
private:
PVNTField();
PVDataCreatePtr pvDataCreate;
StandardFieldPtr standardField;
StandardPVFieldPtr standardPVField;
epics::pvData::PVDataCreatePtr pvDataCreate;
epics::pvData::StandardFieldPtr standardField;
epics::pvData::StandardPVFieldPtr standardPVField;
NTFieldPtr ntstructureField;
};
}}
#endif /* NTFIELD_H */

238
src/nt/nthistogram.cpp Normal file
View File

@@ -0,0 +1,238 @@
/* ntcontinuum.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* This software is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#define epicsExportSharedSymbols
#include <pv/nthistogram.h>
#include <pv/ntutils.h>
using namespace std;
using namespace epics::pvData;
namespace epics { namespace nt {
static NTFieldPtr ntField = NTField::get();
namespace detail {
NTHistogramBuilder::shared_pointer NTHistogramBuilder::value(
epics::pvData::ScalarType scalarType
)
{
valueType = scalarType;
valueTypeSet = true;
return shared_from_this();
}
StructureConstPtr NTHistogramBuilder::createStructure()
{
if (!valueTypeSet)
throw std::runtime_error("value array element type not set");
FieldBuilderPtr builder =
getFieldCreate()->createFieldBuilder()->
setId(NTHistogram::URI)->
addArray("ranges", pvDouble)->
addArray("value", valueType);
if (descriptor)
builder->add("descriptor", pvString);
if (alarm)
builder->add("alarm", ntField->createAlarm());
if (timeStamp)
builder->add("timeStamp", ntField->createTimeStamp());
size_t extraCount = extraFieldNames.size();
for (size_t i = 0; i< extraCount; i++)
builder->add(extraFieldNames[i], extraFields[i]);
StructureConstPtr s = builder->createStructure();
reset();
return s;
}
NTHistogramBuilder::shared_pointer NTHistogramBuilder::addDescriptor()
{
descriptor = true;
return shared_from_this();
}
NTHistogramBuilder::shared_pointer NTHistogramBuilder::addAlarm()
{
alarm = true;
return shared_from_this();
}
NTHistogramBuilder::shared_pointer NTHistogramBuilder::addTimeStamp()
{
timeStamp = true;
return shared_from_this();
}
PVStructurePtr NTHistogramBuilder::createPVStructure()
{
return getPVDataCreate()->createPVStructure(createStructure());
}
NTHistogramPtr NTHistogramBuilder::create()
{
return NTHistogramPtr(new NTHistogram(createPVStructure()));
}
NTHistogramBuilder::NTHistogramBuilder()
{
reset();
}
void NTHistogramBuilder::reset()
{
valueTypeSet = false;
descriptor = false;
alarm = false;
timeStamp = false;
extraFieldNames.clear();
extraFields.clear();
}
NTHistogramBuilder::shared_pointer NTHistogramBuilder::add(string const & name, FieldConstPtr const & field)
{
extraFields.push_back(field); extraFieldNames.push_back(name);
return shared_from_this();
}
}
const std::string NTHistogram::URI("epics:nt/NTHistogram:1.0");
NTHistogram::shared_pointer NTHistogram::wrap(PVStructurePtr const & pvStructure)
{
if(!isCompatible(pvStructure)) return shared_pointer();
return wrapUnsafe(pvStructure);
}
NTHistogram::shared_pointer NTHistogram::wrapUnsafe(PVStructurePtr const & pvStructure)
{
return shared_pointer(new NTHistogram(pvStructure));
}
bool NTHistogram::is_a(StructureConstPtr const & structure)
{
return NTUtils::is_a(structure->getID(), URI);
}
bool NTHistogram::isCompatible(StructureConstPtr const &structure)
{
if(!structure.get()) return false;
ScalarArrayConstPtr rangesField = structure->getField<ScalarArray>("ranges");
if(!rangesField.get() || rangesField->getElementType() != pvDouble) return false;
ScalarArrayConstPtr valueField = structure->getField<ScalarArray>("value");
if(!valueField.get()) return false;
ScalarType scalarType = valueField->getElementType();
if (scalarType != pvShort &&
scalarType != pvInt &&
scalarType != pvLong)
return false;
FieldConstPtr field = structure->getField("descriptor");
if(field)
{
ScalarConstPtr descriptorField = structure->getField<Scalar>("descriptor");
if (!descriptorField.get() || descriptorField->getScalarType() != pvString)
return false;
}
field = structure->getField("alarm");
if (field.get() && !ntField->isAlarm(field))
return false;
field = structure->getField("timeStamp");
if (field.get() && !ntField->isTimeStamp(field))
return false;
return true;
}
bool NTHistogram::isCompatible(PVStructurePtr const & pvStructure)
{
if(!pvStructure.get()) return false;
return isCompatible(pvStructure->getStructure());
}
bool NTHistogram::isValid()
{
return (getValue()->getLength()+1 == getRanges()->getLength());
}
NTHistogramBuilderPtr NTHistogram::createBuilder()
{
return NTHistogramBuilderPtr(new detail::NTHistogramBuilder());
}
bool NTHistogram::attachTimeStamp(PVTimeStamp &pvTimeStamp) const
{
PVStructurePtr ts = getTimeStamp();
if (ts)
return pvTimeStamp.attach(ts);
else
return false;
}
bool NTHistogram::attachAlarm(PVAlarm &pvAlarm) const
{
PVStructurePtr al = getAlarm();
if (al)
return pvAlarm.attach(al);
else
return false;
}
PVStructurePtr NTHistogram::getPVStructure() const
{
return pvNTHistogram;
}
PVStringPtr NTHistogram::getDescriptor() const
{
return pvNTHistogram->getSubField<PVString>("descriptor");
}
PVStructurePtr NTHistogram::getTimeStamp() const
{
return pvNTHistogram->getSubField<PVStructure>("timeStamp");
}
PVStructurePtr NTHistogram::getAlarm() const
{
return pvNTHistogram->getSubField<PVStructure>("alarm");
}
PVDoubleArrayPtr NTHistogram::getRanges() const
{
return pvNTHistogram->getSubField<PVDoubleArray>("ranges");
}
PVScalarArrayPtr NTHistogram::getValue() const
{
return pvValue;
}
NTHistogram::NTHistogram(PVStructurePtr const & pvStructure) :
pvNTHistogram(pvStructure),
pvValue(pvNTHistogram->getSubField<PVScalarArray>("value"))
{}
}}

307
src/nt/nthistogram.h Normal file
View File

@@ -0,0 +1,307 @@
/* nthistogram.h */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* This software is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#ifndef NTHISTOGRAM_H
#define NTHISTOGRAM_H
#ifdef epicsExportSharedSymbols
# define nthistogramEpicsExportSharedSymbols
# undef epicsExportSharedSymbols
#endif
#ifdef nthistogramEpicsExportSharedSymbols
# define epicsExportSharedSymbols
# undef nthistogramEpicsExportSharedSymbols
#endif
#include <pv/ntfield.h>
#include <shareLib.h>
namespace epics { namespace nt {
class NTHistogram;
typedef std::tr1::shared_ptr<NTHistogram> NTHistogramPtr;
namespace detail {
/**
* @brief Interface for in-line creating of NTHistogram.
*
* One instance can be used to create multiple instances.
* An instance of this object must not be used concurrently (an object has a state).
* @author dgh
*/
class epicsShareClass NTHistogramBuilder :
public std::tr1::enable_shared_from_this<NTHistogramBuilder>
{
public:
POINTER_DEFINITIONS(NTHistogramBuilder);
/**
* Sets the scalar type of the value field array.
* @param scalarType the scalar type of the value field array.
* @return this instance of <b>NTHistogramBuilder</b>.
*/
shared_pointer value(epics::pvData::ScalarType scalarType);
/**
* Adds descriptor field to the NTHistogram.
* @return this instance of <b>NTHistogramBuilder</b>.
*/
shared_pointer addDescriptor();
/**
* Adds alarm field to the NTHistogram.
* @return this instance of <b>NTHistogramBuilder</b>.
*/
shared_pointer addAlarm();
/**
* Adds timeStamp field to the NTHistogram.
* @return this instance of <b>NTHistogramBuilder</b>.
*/
shared_pointer addTimeStamp();
/**
* Creates a <b>Structure</b> that represents NTHistogram.
* This resets this instance state and allows new instance to be created.
* @return a new instance of <b>Structure</b>.
*/
epics::pvData::StructureConstPtr createStructure();
/**
* Creates a <b>PVStructure</b> that represents NTHistogram.
* This resets this instance state and allows new instance to be created.
* @return a new instance of <b>PVStructure</b>.
*/
epics::pvData::PVStructurePtr createPVStructure();
/**
* Creates a <b>NTHistogram</b> instance.
* This resets this instance state and allows new instance to be created.
* @return a new instance of <b>NTHistogram</b>.
*/
NTHistogramPtr create();
/**
* Adds extra <b>Field</b> to the type.
* @param name the name of the field.
* @param field the field to be added.
* @return this instance of <b>NTHistogramBuilder</b>.
*/
shared_pointer add(std::string const & name, epics::pvData::FieldConstPtr const & field);
private:
NTHistogramBuilder();
void reset();
bool valueTypeSet;
epics::pvData::ScalarType valueType;
bool dim;
bool descriptor;
bool alarm;
bool timeStamp;
// NOTE: this preserves order, however it does not handle duplicates
epics::pvData::StringArray extraFieldNames;
epics::pvData::FieldConstPtrArray extraFields;
friend class ::epics::nt::NTHistogram;
};
}
typedef std::tr1::shared_ptr<detail::NTHistogramBuilder> NTHistogramBuilderPtr;
/**
* @brief Convenience Class for NTHistogram
*
* @author dgh
*/
class epicsShareClass NTHistogram
{
public:
POINTER_DEFINITIONS(NTHistogram);
static const std::string URI;
/**
* Creates an NTHistogram wrapping the specified PVStructure if the latter is compatible.
* <p>
* Checks the supplied PVStructure is compatible with NTHistogram
* and if so returns an NTHistogram which wraps it.
* This method will return null if the structure is is not compatible
* or is null.
*
* @param pvStructure the PVStructure to be wrapped
* @return NTHistogram instance wrapping pvStructure on success, null otherwise
*/
static shared_pointer wrap(epics::pvData::PVStructurePtr const & pvStructure);
/**
* Creates an NTHistogram wrapping the specified PVStructure, regardless of the latter's compatibility.
* <p>
* No checks are made as to whether the specified PVStructure
* is compatible with NTHistogram or is non-null.
*
* @param pvStructure the PVStructure to be wrapped.
* @return NTHistogram instance wrapping pvStructure.
*/
static shared_pointer wrapUnsafe(epics::pvData::PVStructurePtr const & pvStructure);
/**
* Returns whether the specified Structure reports to be a compatible NTHistogram.
* <p>
* Checks whether the specified Structure reports compatibility with this
* version of NTHistogram through its type ID, including checking version numbers.
* The return value does not depend on whether the structure is actually
* compatible in terms of its introspection type.
*
* @param structure the Structure to test.
* @return (false,true) if the specified Structure (is not, is) a compatible NTHistogram
*/
static bool is_a(epics::pvData::StructureConstPtr const & structure);
/**
* Returns whether the specified PVStructure reports to be a compatible NTHistogram.
* <p>
* Checks whether the specified PVStructure reports compatibility with this
* version of NTHistogram through its type ID, including checking version numbers.
* The return value does not depend on whether the structure is actually
* compatible in terms of its introspection type.
*
* @param pvStructure the PVStructure to test
* @return (false,true) if the specified PVStructure (is not, is) a compatible NTHistogram
*/
static bool is_a(epics::pvData::PVStructurePtr const & pvStructure);
/**
* Returns whether the specified Structure is compatible with NTHistogram.
* <p>
* Checks whether the specified Structure is compatible with this version
* of NTHistogram through the introspection interface.
*
* @param structure the Structure to test
* @return (false,true) if the specified Structure (is not, is) a compatible NTHistogram
*/
static bool isCompatible(
epics::pvData::StructureConstPtr const &structure);
/**
* Returns whether the specified PVStructure is compatible with NTHistogram.
* <p>
* Checks whether the specified PVStructure is compatible with this version
* of NTHistogram through the introspection interface.
*
* @param pvStructure the PVStructure to test
* @return (false,true) if the specified PVStructure (is not, is) a compatible NTHistogram
*/
static bool isCompatible(
epics::pvData::PVStructurePtr const &pvStructure);
/**
* Returns whether the wrapped structure is valid with respect to this
* version of NTHistogram.
* <p>
* Unlike isCompatible(), isValid() may perform checks on the value
* data as well as the introspection data.
*
* @return (false,true) if the wrapped PVStructure (is not, is) a valid NTHistogram
*/
bool isValid();
/**
* Creates an NTHistogram builder instance.
* @return builder instance.
*/
static NTHistogramBuilderPtr createBuilder();
/**
* Destructor.
*/
~NTHistogram() {}
/**
* Attaches a PVTimeStamp to the wrapped PVStructure.
* Does nothing if no timeStamp field.
* @param pvTimeStamp the PVTimeStamp that will be attached.
* @return true if the operation was successfull (i.e. this instance has a timeStamp field), otherwise false.
*/
bool attachTimeStamp(epics::pvData::PVTimeStamp &pvTimeStamp) const;
/**
* Attaches a PVAlarm to the wrapped PVStructure.
* Does nothing if no alarm field.
* @param pvAlarm the PVAlarm that will be attached.
* @return true if the operation was successfull (i.e. this instance has an alarm field), otherwise false.
*/
bool attachAlarm(epics::pvData::PVAlarm &pvAlarm) const;
/**
* Get the PVStructure wrapped by this instance.
* @return the PVStructure wrapped by this instance.
*/
epics::pvData::PVStructurePtr getPVStructure() const;
/**
* Returns the descriptor field.
* @return the descriptor field or null if no such field.
*/
epics::pvData::PVStringPtr getDescriptor() const;
/**
* Returns the timeStamp field.
* @return the timStamp field or null if no such field.
*/
epics::pvData::PVStructurePtr getTimeStamp() const;
/**
* Returns the alarm field.
* @return the alarm field or null if no such field.
*/
epics::pvData::PVStructurePtr getAlarm() const;
/**
* Returns the ranges field.
* @return the ranges field.
*/
epics::pvData::PVDoubleArrayPtr getRanges() const;
/**
* Returns the value field.
* @return the value field.
*/
epics::pvData::PVScalarArrayPtr getValue() const;
/**
* Returns the value field of a specified type (e.g. PVIntArray).
* @tparam PVT the expected type of the value field which should be
* be PVShortArray, PVIntArray pr PVLongArray.
* @return the value field or null if it is not of the expected type.
*/
template<typename PVT>
std::tr1::shared_ptr<PVT> getValue() const
{
return std::tr1::dynamic_pointer_cast<PVT>(pvValue);
}
private:
NTHistogram(epics::pvData::PVStructurePtr const & pvStructure);
epics::pvData::PVStructurePtr pvNTHistogram;
epics::pvData::PVScalarArrayPtr pvValue;
friend class detail::NTHistogramBuilder;
};
}}
#endif /* NTHISTOGRAM_H */

190
src/nt/ntid.cpp Normal file
View File

@@ -0,0 +1,190 @@
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* This software is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#include <pv/ntid.h>
#include <pv/typeCast.h>
namespace epics {
namespace nt {
const static std::string BAD_NAME = "?";
NTID::NTID(const std::string & id)
: fullName(id),
qualifiedName(BAD_NAME),
namespaceStr(BAD_NAME),
name(BAD_NAME),
version(BAD_NAME),
nsSepIndex(std::string::npos),
versionSepIndex(std::string::npos),
nsQualified(false),
hasVersion(false),
endMajorIndex(0),
majorVersionStr(BAD_NAME),
majorVersionParsed(false),
hasMajor(false),
majorVersion(0),
endMinorIndex(0),
minorVersionStr(BAD_NAME),
minorVersionParsed(false),
hasMinor(false),
minorVersion(0)
{
nsSepIndex = id.find('/');
nsQualified = nsSepIndex != std::string::npos;
size_t startIndex = nsQualified ? nsSepIndex+1 : 0;
versionSepIndex = id.find(':', startIndex);
hasVersion = versionSepIndex != std::string::npos;
}
std::string NTID::getFullName() { return fullName; }
std::string NTID::getQualifiedName()
{
if (qualifiedName == BAD_NAME)
{
qualifiedName = hasVersion ?
fullName.substr(0, versionSepIndex) : fullName;
}
return qualifiedName;
}
std::string NTID::getNamespace()
{
if (namespaceStr == BAD_NAME)
{
namespaceStr = nsQualified ?
fullName.substr(0, nsSepIndex) : "";
}
return namespaceStr;
}
std::string NTID::getName()
{
if (name == BAD_NAME)
{
if (hasVersion)
{
size_t startIndex = nsQualified ? nsSepIndex+1 : 0;
name = fullName.substr(startIndex, versionSepIndex);
}
else if (nsQualified)
{
name = fullName.substr(nsSepIndex+1);
}
else
{
name = fullName;
}
}
return name;
}
std::string NTID::getVersion()
{
if (version == BAD_NAME)
{
version = (hasVersion) ? fullName.substr(versionSepIndex+1) : "";
}
return version;
}
std::string NTID::getMajorVersionString()
{
if (majorVersionStr == BAD_NAME)
{
if (hasVersion)
{
endMajorIndex = fullName.find('.', versionSepIndex+1);
majorVersionStr = (endMajorIndex != std::string::npos)
? fullName.substr(versionSepIndex+1, endMajorIndex-(versionSepIndex+1)) :
fullName.substr(versionSepIndex+1);
}
else
majorVersionStr = "";
}
return majorVersionStr;
}
bool NTID::hasMajorVersion()
{
if (hasVersion && !majorVersionParsed)
{
try {
using pvData::detail::parseToPOD;
uint32_t mv;
parseToPOD(getMajorVersionString(), &mv);
majorVersion = static_cast<int>(mv);
hasMajor = true;
} catch (...) {}
majorVersionParsed = true;
}
return hasMajor;
}
int NTID::getMajorVersion()
{
// call hasMajorVersion() to calculate values
hasMajorVersion();
return majorVersion;
}
std::string NTID::getMinorVersionString()
{
// call hasMinorVersion() to calculate start of minor
getMajorVersionString();
if (minorVersionStr == BAD_NAME)
{
if (hasVersion && endMajorIndex != std::string::npos)
{
endMinorIndex = fullName.find('.', endMajorIndex+1);
minorVersionStr = (endMinorIndex != std::string::npos)
? fullName.substr(endMajorIndex+1, endMinorIndex-(endMajorIndex+1)) :
fullName.substr(endMajorIndex+1);
}
else
minorVersionStr = "";
}
return minorVersionStr;
}
bool NTID::hasMinorVersion()
{
if (hasVersion && !minorVersionParsed)
{
try {
using pvData::detail::parseToPOD;
uint32_t mv;
parseToPOD(getMinorVersionString(), &mv);
minorVersion = static_cast<int>(mv);
hasMinor = true;
} catch (...) {}
minorVersionParsed = true;
}
return hasMinor;
}
int NTID::getMinorVersion()
{
// call hasMinorVersion() to calculate values
hasMinorVersion();
return minorVersion;
}
}}

153
src/nt/ntid.h Normal file
View File

@@ -0,0 +1,153 @@
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* This software is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#ifndef NTID_H
#define NTID_H
#include <string>
namespace epics {
namespace nt {
/**
* @brief Utility class for parsing a type ID that follows the NT type ID conventions
*
* An NT type ID will be of the from
@code
epics:nt/<type-name>:<Major>.<Minor>
@endcode
* e.g.
@code
epics:nt/NTNDArray:1.2
@endcode
* @author dgh
*/
class NTID
{
public:
/**
* Creates an NTID from the specified type ID.
*
* @param id the the ID to be parsed.
* @return NTNDArray instance on success, null otherwise.
*/
NTID(const std::string &id);
/**
* Returns the full name of the id, i.e. the original ID
* <p>
* For example above returns "epics:nt/NTNDArray:1.2".
* @return the full name
*/
std::string getFullName();
/**
* Returns the fully qualified name including namespaces, but excluding version numbers.
* <p>
* For example above return "epics:nt/NTNDArray"
* @return the fully qualified name
*/
std::string getQualifiedName();
/**
* Returns the namespace
* <p>
* For example above return "epics:nt".
* @return the namespace
*/
std::string getNamespace();
/**
* Returns the unqualified name, without namespace or version.
* <p>
* For example above return "NTNDArray".
* @return the unqualified name
*/
std::string getName();
/**
* Returns the version as a string.
* <p>
* For example above return "NTNDArray".
* @return the the version string
*/
std::string getVersion();
/**
* Returns the Major version as a string.
* <p>
* For example above return "1".
* @return the Major string
*/
std::string getMajorVersionString();
/**
* Does the ID contain a major version and is it a number.
* <p>
* @return true if it contains a major version number
*/
bool hasMajorVersion();
/**
* Returns the Major version as an integer.
* <p>
* For example above return 1.
* @return the Major string
*/
int getMajorVersion();
/**
* Returns the Major version as a string.
* <p>
* For example above return "1".
* @return the Major string
*/
std::string getMinorVersionString();
/**
* Does the ID contain a minor version and is it a number.
* <p>
* @return true if it contains a minor version number
*/
bool hasMinorVersion();
/**
* Returns the Minor version as an integer.
* <p>
* For example above return 1.
* @return the Minor string
*/
int getMinorVersion();
private:
std::string fullName;
std::string qualifiedName;
std::string namespaceStr;
std::string name;
std::string version;
size_t nsSepIndex;
size_t versionSepIndex;
bool nsQualified;
bool hasVersion;
size_t endMajorIndex;
std::string majorVersionStr;
bool majorVersionParsed;
bool hasMajor;
int majorVersion;
size_t endMinorIndex;
std::string minorVersionStr;
bool minorVersionParsed;
bool hasMinor;
int minorVersion;
};
}}
#endif

283
src/nt/ntmatrix.cpp Normal file
View File

@@ -0,0 +1,283 @@
/* ntmatrix.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* This software is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#define epicsExportSharedSymbols
#include <pv/ntmatrix.h>
#include <pv/ntutils.h>
using namespace std;
using namespace epics::pvData;
namespace epics { namespace nt {
static NTFieldPtr ntField = NTField::get();
namespace detail {
StructureConstPtr NTMatrixBuilder::createStructure()
{
FieldBuilderPtr builder =
getFieldCreate()->createFieldBuilder()->
setId(NTMatrix::URI)->
addArray("value", pvDouble);
if (dim)
builder->addArray("dim", pvInt);
if (descriptor)
builder->add("descriptor", pvString);
if (alarm)
builder->add("alarm", ntField->createAlarm());
if (timeStamp)
builder->add("timeStamp", ntField->createTimeStamp());
if (display)
builder->add("display", ntField->createDisplay());
size_t extraCount = extraFieldNames.size();
for (size_t i = 0; i< extraCount; i++)
builder->add(extraFieldNames[i], extraFields[i]);
StructureConstPtr s = builder->createStructure();
reset();
return s;
}
NTMatrixBuilder::shared_pointer NTMatrixBuilder::addDim()
{
dim = true;
return shared_from_this();
}
NTMatrixBuilder::shared_pointer NTMatrixBuilder::addDescriptor()
{
descriptor = true;
return shared_from_this();
}
NTMatrixBuilder::shared_pointer NTMatrixBuilder::addAlarm()
{
alarm = true;
return shared_from_this();
}
NTMatrixBuilder::shared_pointer NTMatrixBuilder::addTimeStamp()
{
timeStamp = true;
return shared_from_this();
}
NTMatrixBuilder::shared_pointer NTMatrixBuilder::addDisplay()
{
display = true;
return shared_from_this();
}
PVStructurePtr NTMatrixBuilder::createPVStructure()
{
return getPVDataCreate()->createPVStructure(createStructure());
}
NTMatrixPtr NTMatrixBuilder::create()
{
return NTMatrixPtr(new NTMatrix(createPVStructure()));
}
NTMatrixBuilder::NTMatrixBuilder()
{
reset();
}
void NTMatrixBuilder::reset()
{
dim = false;
descriptor = false;
alarm = false;
timeStamp = false;
display = false;
extraFieldNames.clear();
extraFields.clear();
}
NTMatrixBuilder::shared_pointer NTMatrixBuilder::add(string const & name, FieldConstPtr const & field)
{
extraFields.push_back(field); extraFieldNames.push_back(name);
return shared_from_this();
}
}
const std::string NTMatrix::URI("epics:nt/NTMatrix:1.0");
NTMatrix::shared_pointer NTMatrix::wrap(PVStructurePtr const & pvStructure)
{
if(!isCompatible(pvStructure)) return shared_pointer();
return wrapUnsafe(pvStructure);
}
NTMatrix::shared_pointer NTMatrix::wrapUnsafe(PVStructurePtr const & pvStructure)
{
return shared_pointer(new NTMatrix(pvStructure));
}
bool NTMatrix::is_a(StructureConstPtr const & structure)
{
return NTUtils::is_a(structure->getID(), URI);
}
bool NTMatrix::isCompatible(StructureConstPtr const & structure)
{
if (structure.get() == 0) return false;
ScalarArrayConstPtr valueField = structure->getField<ScalarArray>("value");
if (valueField.get() == 0 || valueField->getElementType() != pvDouble)
return false;
FieldConstPtr field = structure->getField("dim");
if (field.get())
{
ScalarArrayConstPtr dimField = structure->getField<ScalarArray>("dim");
if (dimField.get() == 0 || dimField->getElementType() != pvInt)
return false;
}
field = structure->getField("descriptor");
if (field.get())
{
ScalarConstPtr descriptorField = structure->getField<Scalar>("descriptor");
if (!descriptorField.get() || descriptorField->getScalarType() != pvString)
return false;
}
NTFieldPtr ntField = NTField::get();
field = structure->getField("alarm");
if (field.get() && !ntField->isAlarm(field))
return false;
field = structure->getField("timeStamp");
if (field.get() && !ntField->isTimeStamp(field))
return false;
field = structure->getField("display");
if (field.get() && !ntField->isDisplay(field))
return false;
return true;
}
bool NTMatrix::isCompatible(PVStructurePtr const & pvStructure)
{
if(!pvStructure) return false;
return isCompatible(pvStructure->getStructure());
}
bool NTMatrix::isValid()
{
int valueLength = getValue()->getLength();
if (valueLength == 0)
return false;
PVIntArrayPtr pvDim = getDim();
if (pvDim.get())
{
int length = pvDim->getLength();
if (length != 1 && length !=2)
return false;
PVIntArray::const_svector data = pvDim->view();
int expectedLength = 1;
for (PVIntArray::const_svector::const_iterator it = data.begin();
it != data.end(); ++it)
{
expectedLength *= *it;
}
if (expectedLength != valueLength)
return false;
}
return true;
}
NTMatrixBuilderPtr NTMatrix::createBuilder()
{
return NTMatrixBuilderPtr(new detail::NTMatrixBuilder());
}
bool NTMatrix::attachTimeStamp(PVTimeStamp &pvTimeStamp) const
{
PVStructurePtr ts = getTimeStamp();
if (ts)
return pvTimeStamp.attach(ts);
else
return false;
}
bool NTMatrix::attachAlarm(PVAlarm &pvAlarm) const
{
PVStructurePtr al = getAlarm();
if (al)
return pvAlarm.attach(al);
else
return false;
}
bool NTMatrix::attachDisplay(PVDisplay &pvDisplay) const
{
PVStructurePtr dp = getDisplay();
if (dp)
return pvDisplay.attach(dp);
else
return false;
}
PVStructurePtr NTMatrix::getPVStructure() const
{
return pvNTMatrix;
}
PVStringPtr NTMatrix::getDescriptor() const
{
return pvNTMatrix->getSubField<PVString>("descriptor");
}
PVStructurePtr NTMatrix::getTimeStamp() const
{
return pvNTMatrix->getSubField<PVStructure>("timeStamp");
}
PVStructurePtr NTMatrix::getAlarm() const
{
return pvNTMatrix->getSubField<PVStructure>("alarm");
}
PVStructurePtr NTMatrix::getDisplay() const
{
return pvNTMatrix->getSubField<PVStructure>("display");
}
PVDoubleArrayPtr NTMatrix::getValue() const
{
return pvValue;
}
PVIntArrayPtr NTMatrix::getDim() const
{
return pvNTMatrix->getSubField<PVIntArray>("dim");
}
NTMatrix::NTMatrix(PVStructurePtr const & pvStructure) :
pvNTMatrix(pvStructure),
pvValue(pvNTMatrix->getSubField<PVDoubleArray>("value"))
{}
}}

313
src/nt/ntmatrix.h Normal file
View File

@@ -0,0 +1,313 @@
/* ntmatrix.h */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* This software is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#ifndef NTMATRIX_H
#define NTMATRIX_H
#ifdef epicsExportSharedSymbols
# define ntmatrixEpicsExportSharedSymbols
# undef epicsExportSharedSymbols
#endif
#include <pv/pvDisplay.h>
#ifdef ntmatrixEpicsExportSharedSymbols
# define epicsExportSharedSymbols
# undef ntmatrixEpicsExportSharedSymbols
#endif
#include <pv/ntfield.h>
#include <shareLib.h>
namespace epics { namespace nt {
class NTMatrix;
typedef std::tr1::shared_ptr<NTMatrix> NTMatrixPtr;
namespace detail {
/**
* @brief Interface for in-line creating of NTMatrix.
*
* One instance can be used to create multiple instances.
* An instance of this object must not be used concurrently (an object has a state).
* @author dgh
*/
class epicsShareClass NTMatrixBuilder :
public std::tr1::enable_shared_from_this<NTMatrixBuilder>
{
public:
POINTER_DEFINITIONS(NTMatrixBuilder);
/**
* Adds dimension field to the NTMatrix.
* @return this instance of <b>NTMatrixBuilder</b>.
*/
shared_pointer addDim();
/**
* Adds descriptor field to the NTMatrix.
* @return this instance of <b>NTMatrixBuilder</b>.
*/
shared_pointer addDescriptor();
/**
* Adds alarm field to the NTMatrix.
* @return this instance of <b>NTMatrixBuilder</b>.
*/
shared_pointer addAlarm();
/**
* Adds timeStamp field to the NTMatrix.
* @return this instance of <b>NTMatrixBuilder</b>.
*/
shared_pointer addTimeStamp();
/**
* Adds display field to the NTMatrix.
* @return this instance of <b>NTMatrixBuilder</b>.
*/
shared_pointer addDisplay();
/**
* Creates a <b>Structure</b> that represents NTMatrix.
* This resets this instance state and allows new instance to be created.
* @return a new instance of <b>Structure</b>.
*/
epics::pvData::StructureConstPtr createStructure();
/**
* Creates a <b>PVStructure</b> that represents NTMatrix.
* This resets this instance state and allows new instance to be created.
* @return a new instance of <b>PVStructure</b>.
*/
epics::pvData::PVStructurePtr createPVStructure();
/**
* Creates a <b>NTMatrix</b> instance.
* This resets this instance state and allows new instance to be created.
* @return a new instance of <b>NTMatrix</b>.
*/
NTMatrixPtr create();
/**
* Adds extra <b>Field</b> to the type.
* @param name the name of the field.
* @param field the field to be added.
* @return this instance of <b>NTMatrixBuilder</b>.
*/
shared_pointer add(std::string const & name, epics::pvData::FieldConstPtr const & field);
private:
NTMatrixBuilder();
void reset();
bool dim;
bool descriptor;
bool alarm;
bool timeStamp;
bool display;
// NOTE: this preserves order, however it does not handle duplicates
epics::pvData::StringArray extraFieldNames;
epics::pvData::FieldConstPtrArray extraFields;
friend class ::epics::nt::NTMatrix;
};
}
typedef std::tr1::shared_ptr<detail::NTMatrixBuilder> NTMatrixBuilderPtr;
/**
* @brief Convenience Class for NTMatrix
*
* @author dgh
*/
class epicsShareClass NTMatrix
{
public:
POINTER_DEFINITIONS(NTMatrix);
static const std::string URI;
/**
* Creates an NTMatrix wrapping the specified PVStructure if the latter is compatible.
* <p>
* Checks the supplied PVStructure is compatible with NTMatrix
* and if so returns an NTMatrix which wraps it.
* This method will return null if the structure is is not compatible
* or is null.
*
* @param pvStructure the PVStructure to be wrapped
* @return NTMatrix instance wrapping pvStructure on success, null otherwise
*/
static shared_pointer wrap(epics::pvData::PVStructurePtr const & pvStructure);
/**
* Creates an NTMatrix wrapping the specified PVStructure, regardless of the latter's compatibility.
* <p>
* No checks are made as to whether the specified PVStructure
* is compatible with NTMatrix or is non-null.
*
* @param pvStructure the PVStructure to be wrapped
* @return NTMatrix instance wrapping pvStructure
*/
static shared_pointer wrapUnsafe(epics::pvData::PVStructurePtr const & pvStructure);
/**
* Returns whether the specified Structure reports to be a compatible NTMatrix.
* <p>
* Checks if the specified Structure reports compatibility with this
* version of NTMatrix through its type ID, including checking version numbers.
* The return value does not depend on whether the structure is actually
* compatible in terms of its introspection type.
*
* @param structure the structure to test
* @return (false,true) if the specified Structure (is not, is) a compatible NTMatrix
*/
static bool is_a(epics::pvData::StructureConstPtr const & structure);
/**
* Returns whether the specified PVStructure reports to be a compatible NTMatrix.
* <p>
* Checks if the specified PVStructure reports compatibility with this
* version of NTMatrix through its type ID, including checking version numbers.
* The return value does not depend on whether the structure is actually
* compatible in terms of its introspection type.
*
* @param pvStructure the PVStructure to test
* @return (false,true) if the specified PVStructure (is not, is) a compatible NTMatrix
*/
static bool is_a(epics::pvData::PVStructurePtr const & pvStructure);
/**
* Returns whether the specified Structure is compatible with NTMatrix.
* <p>
* Checks if the specified Structure is compatible with this version
* of NTMatrix through the introspection interface.
*
* @param structure the Structure to test
* @return (false,true) if the specified Structure (is not, is) a compatible NTMatrix
*/
static bool isCompatible(
epics::pvData::StructureConstPtr const &structure);
/**
* Returns whether the specified PVStructure is compatible with NTMatrix.
* <p>
* Checks if the specified PVStructure is compatible with this version
* of NTMatrix through the introspection interface.
*
* @param pvStructure the PVStructure to test
* @return (false,true) if the specified PVStructure (is not, is) a compatible NTMatrix
*/
static bool isCompatible(
epics::pvData::PVStructurePtr const &pvStructure);
/**
* Returns whether the wrapped PVStructure is valid with respect to this
* version of NTMatrix.
* <p>
* Unlike isCompatible(), isValid() may perform checks on the value
* data as well as the introspection data.
*
* @return (false,true) if the wrapped PVStructure (is not, is) a valid NTMatrix
*/
bool isValid();
/**
* Creates an NTMatrix builder instance.
* @return builder instance.
*/
static NTMatrixBuilderPtr createBuilder();
/**
* Destructor.
*/
~NTMatrix() {}
/**
* Attaches a PVTimeStamp to the wrapped PVStructure.
* Does nothing if no timeStamp field.
* @param pvTimeStamp the PVTimeStamp that will be attached.
* @return true if the operation was successfull (i.e. this instance has a timeStamp field), otherwise false.
*/
bool attachTimeStamp(epics::pvData::PVTimeStamp &pvTimeStamp) const;
/**
* Attaches a PVAlarm to the wrapped PVStructure.
* Does nothing if no alarm field.
* @param pvAlarm the PVAlarm that will be attached.
* @return true if the operation was successfull (i.e. this instance has an alarm field), otherwise false.
*/
bool attachAlarm(epics::pvData::PVAlarm &pvAlarm) const;
/**
* Attaches a PVDisplay to the wrapped PVStructure.
* Does nothing if no display.
* @param pvDisplay the PVDisplay that will be attached.
* @return true if the operation was successfull (i.e. this instance has a display field), otherwise false.
*/
bool attachDisplay(epics::pvData::PVDisplay &pvDisplay) const;
/**
* Get the PVStructure wrapped by this instance.
* @return the PVStructure wrapped by this instance.
*/
epics::pvData::PVStructurePtr getPVStructure() const;
/**
* Returns the descriptor field.
* @return the descriptor field or null if no such field.
*/
epics::pvData::PVStringPtr getDescriptor() const;
/**
* Returns the timeStamp field.
* @return the timStamp field or null if no such field.
*/
epics::pvData::PVStructurePtr getTimeStamp() const;
/**
* Returns the alarm field.
* @return the alarm field or null if no such field.
*/
epics::pvData::PVStructurePtr getAlarm() const;
/**
* Returns the display field.
* @return the display field or null if no such field.
*/
epics::pvData::PVStructurePtr getDisplay() const;
/**
* Returns the value field.
* @return the value field.
*/
epics::pvData::PVDoubleArrayPtr getValue() const;
/**
* Returns the dim field.
* @return the dim field or or null if no such field.
*/
epics::pvData::PVIntArrayPtr getDim() const;
private:
NTMatrix(epics::pvData::PVStructurePtr const & pvStructure);
epics::pvData::PVStructurePtr pvNTMatrix;
epics::pvData::PVDoubleArrayPtr pvValue;
friend class detail::NTMatrixBuilder;
};
}}
#endif /* NTMATRIX_H */

View File

@@ -1,13 +1,16 @@
/* ntmultiChannel.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* This software is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#include <pv/ntmultiChannel.h>
#include <algorithm>
#define epicsExportSharedSymbols
#include <pv/ntmultiChannel.h>
#include <pv/ntutils.h>
using namespace std;
using namespace epics::pvData;
@@ -81,10 +84,16 @@ NTMultiChannelBuilder::shared_pointer NTMultiChannelBuilder::addUserTag()
return shared_from_this();
}
NTMultiChannelBuilder::shared_pointer NTMultiChannelBuilder::addIsConnected()
{
isConnected = true;
return shared_from_this();
}
StructureConstPtr NTMultiChannelBuilder::createStructure()
{
StandardFieldPtr standardField = getStandardField();
size_t nfields = 3;
size_t nfields = 2;
size_t extraCount = extraFieldNames.size();
nfields += extraCount;
if(descriptor) ++nfields;
@@ -96,6 +105,7 @@ StructureConstPtr NTMultiChannelBuilder::createStructure()
if(secondsPastEpoch) ++nfields;
if(nanoseconds) ++nfields;
if(userTag) ++nfields;
if(isConnected) ++nfields;
FieldConstPtrArray fields(nfields);
StringArray names(nfields);
size_t ind = 0;
@@ -107,19 +117,17 @@ StructureConstPtr NTMultiChannelBuilder::createStructure()
}
names[ind] = "channelName";
fields[ind++] = fieldCreate->createScalarArray(pvString);
names[ind] = "isConnected";
fields[ind++] = fieldCreate->createScalarArray(pvBoolean);
if(timeStamp) {
names[ind] = "timeStamp";
fields[ind++] = standardField->timeStamp();
if(descriptor) {
names[ind] = "descriptor";
fields[ind++] = fieldCreate->createScalar(pvString);
}
if(alarm) {
names[ind] = "alarm";
fields[ind++] = standardField->alarm();
}
if(descriptor) {
names[ind] = "descriptor";
fields[ind++] = fieldCreate->createScalar(pvString);
if(timeStamp) {
names[ind] = "timeStamp";
fields[ind++] = standardField->timeStamp();
}
if(severity) {
names[ind] = "severity";
@@ -145,6 +153,10 @@ StructureConstPtr NTMultiChannelBuilder::createStructure()
names[ind] = "userTag";
fields[ind++] = fieldCreate->createScalarArray(pvInt);
}
if(isConnected) {
names[ind] = "isConnected";
fields[ind++] = fieldCreate->createScalarArray(pvBoolean);
}
for (size_t i = 0; i< extraCount; i++) {
names[ind] = extraFieldNames[i];
fields[ind++] = extraFields[i];
@@ -155,7 +167,7 @@ StructureConstPtr NTMultiChannelBuilder::createStructure()
return st;
}
PVStructurePtr NTMultiChannelBuilder::NTMultiChannelBuilder::createPVStructure()
PVStructurePtr NTMultiChannelBuilder::createPVStructure()
{
return pvDataCreate->createPVStructure(createStructure());
}
@@ -184,6 +196,7 @@ void NTMultiChannelBuilder::reset()
secondsPastEpoch = false;
nanoseconds = false;
userTag = false;
isConnected = false;
}
@@ -197,54 +210,140 @@ NTMultiChannelBuilder::shared_pointer NTMultiChannelBuilder::add(string const &
const std::string NTMultiChannel::URI("epics:nt/NTMultiChannel:1.0");
NTMultiChannel::shared_pointer NTMultiChannel::wrap(PVStructurePtr const & structure)
NTMultiChannel::shared_pointer NTMultiChannel::wrap(PVStructurePtr const & pvStructure)
{
if(!isCompatible(structure)) return shared_pointer();
return wrapUnsafe(structure);
if(!isCompatible(pvStructure)) return shared_pointer();
return wrapUnsafe(pvStructure);
}
NTMultiChannel::shared_pointer NTMultiChannel::wrapUnsafe(PVStructurePtr const & structure)
NTMultiChannel::shared_pointer NTMultiChannel::wrapUnsafe(PVStructurePtr const & pvStructure)
{
return shared_pointer(new NTMultiChannel(structure));
return shared_pointer(new NTMultiChannel(pvStructure));
}
bool NTMultiChannel::is_a(StructureConstPtr const &structure)
{
return structure->getID() == URI;
return NTUtils::is_a(structure->getID(), URI);
}
bool NTMultiChannel::isCompatible(StructureConstPtr const & structure)
{
if (!structure.get()) return false;
UnionArrayConstPtr valueField = structure->getField<UnionArray>("value");
if (!valueField.get()) return false;
ScalarArrayConstPtr channelNameField = structure->getField<ScalarArray>(
"channelName");
if (!channelNameField.get()) return false;
if (channelNameField->getElementType() != pvString) return false;
FieldConstPtr field = structure->getField("severity");
if (field.get())
{
ScalarArrayConstPtr severityField = structure->getField<ScalarArray>("severity");
if (!severityField.get() || severityField->getElementType() != pvInt)
return false;
}
field = structure->getField("status");
if (field.get())
{
ScalarArrayConstPtr statusField = structure->getField<ScalarArray>("status");
if (!statusField.get() || statusField->getElementType() != pvInt)
return false;
}
field = structure->getField("message");
if (field.get())
{
ScalarArrayConstPtr messageField = structure->getField<ScalarArray>("message");
if (!messageField.get() || messageField->getElementType() != pvString)
return false;
}
field = structure->getField("secondsPastEpoch");
if (field.get())
{
ScalarArrayConstPtr secondsPastEpochField = structure->getField<ScalarArray>("secondsPastEpoch");
if (!secondsPastEpochField.get() || secondsPastEpochField->getElementType() != pvLong)
return false;
}
field = structure->getField("nanoseconds");
if (field.get())
{
ScalarArrayConstPtr nanosecondsField = structure->getField<ScalarArray>("nanoseconds");
if (!nanosecondsField.get() || nanosecondsField->getElementType() != pvInt)
return false;
}
field = structure->getField("userTag");
if (field.get())
{
ScalarArrayConstPtr userTagField = structure->getField<ScalarArray>("userTag");
if (!userTagField.get() || userTagField->getElementType() != pvInt)
return false;
}
field = structure->getField("descriptor");
if (field.get())
{
ScalarConstPtr descriptorField = structure->getField<Scalar>("descriptor");
if (!descriptorField.get() || descriptorField->getScalarType() != pvString)
return false;
}
NTFieldPtr ntField = NTField::get();
field = structure->getField("alarm");
if (field.get() && !ntField->isAlarm(field))
return false;
field = structure->getField("timeStamp");
if (field.get() && !ntField->isTimeStamp(field))
return false;
return true;
}
bool NTMultiChannel::isCompatible(PVStructurePtr const &pvStructure)
{
if(!pvStructure) return false;
PVUnionArrayPtr pvValue = pvStructure->getSubField<PVUnionArray>("value");
if(!pvValue) return false;
PVFieldPtr pvField = pvStructure->getSubField("descriptor");
if(pvField && !pvStructure->getSubField<PVString>("descriptor")) return false;
pvField = pvStructure->getSubField("alarm");
if(pvField && !ntField->isAlarm(pvField->getField())) return false;
pvField = pvStructure->getSubField("timeStamp");
if(pvField && !ntField->isTimeStamp(pvField->getField())) return false;
pvField = pvStructure->getSubField("severity");
if(pvField && !pvStructure->getSubField<PVIntArray>("severity")) return false;
pvField = pvStructure->getSubField("status");
if(pvField && !pvStructure->getSubField<PVIntArray>("status")) return false;
pvField = pvStructure->getSubField("message");
if(pvField && !pvStructure->getSubField<PVStringArray>("message")) return false;
pvField = pvStructure->getSubField("secondsPastEpoch");
if(pvField && !pvStructure->getSubField<PVLongArray>("secondsPastEpoch")) return false;
pvField = pvStructure->getSubField("nanoseconds");
if(pvField && !pvStructure->getSubField<PVIntArray>("nanoseconds")) return false;
pvField = pvStructure->getSubField("userTag");
if(pvField && !pvStructure->getSubField<PVIntArray>("userTag")) return false;
return true;
if(!pvStructure.get()) return false;
return isCompatible(pvStructure->getStructure());
}
bool NTMultiChannel::isValid()
{
size_t valueLength = getValue()->getLength();
if (getChannelName()->getLength() != valueLength) return false;
PVScalarArrayPtr arrayFields[] = {
getSeverity(), getStatus(), getMessage(),
getSecondsPastEpoch(), getNanoseconds(), getUserTag()
};
size_t N = sizeof(arrayFields)/sizeof(arrayFields[0]);
PVScalarArrayPtr arrayField;
for (PVScalarArrayPtr * pa = arrayFields; pa != arrayFields+N; ++pa)
{
arrayField = *pa;
if (arrayField.get() && arrayField->getLength() != valueLength)
return false;
}
return true;
}
NTMultiChannelBuilderPtr NTMultiChannel::createBuilder()
{
return NTMultiChannelBuilderPtr(new detail::NTMultiChannelBuilder());
}
NTMultiChannel::NTMultiChannel(PVStructurePtr const & pvStructure)
: pvNTMultiChannel(pvStructure),
pvTimeStamp(pvStructure->getSubField<PVStructure>("timeStamp")),
@@ -263,16 +362,20 @@ NTMultiChannel::NTMultiChannel(PVStructurePtr const & pvStructure)
}
void NTMultiChannel::attachTimeStamp(PVTimeStamp &pv) const
bool NTMultiChannel::attachTimeStamp(PVTimeStamp &pv) const
{
if(!pvTimeStamp) return;
pv.attach(pvTimeStamp);
if (pvTimeStamp)
return pv.attach(pvTimeStamp);
else
return false;
}
void NTMultiChannel::attachAlarm(PVAlarm &pv) const
bool NTMultiChannel::attachAlarm(PVAlarm &pv) const
{
if(!pvAlarm) return;
pv.attach(pvAlarm);
if (pvAlarm)
return pv.attach(pvAlarm);
else
return false;
}
}}

View File

@@ -1,24 +1,35 @@
/* ntmultiChannel.h */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* This software is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#ifndef NTMULTICHANNEL_H
#define NTMULTICHANNEL_H
#include <pv/ntfield.h>
#include <vector>
#include <string>
#ifdef epicsExportSharedSymbols
# define ntmultiChannelEpicsExportSharedSymbols
# undef epicsExportSharedSymbols
#endif
#include <pv/pvDisplay.h>
#include <pv/pvControl.h>
#ifdef ntmultiChannelEpicsExportSharedSymbols
# define epicsExportSharedSymbols
# undef ntmultiChannelEpicsExportSharedSymbols
#endif
#include <pv/ntfield.h>
#include <shareLib.h>
namespace epics { namespace nt {
/**
* Convenience Class for NTMultiChannel
* @author mrk
*
*/
class NTMultiChannel;
typedef std::tr1::shared_ptr<NTMultiChannel> NTMultiChannelPtr;
@@ -26,7 +37,8 @@ typedef std::tr1::shared_ptr<NTMultiChannel> NTMultiChannelPtr;
namespace detail {
/**
* Interface for in-line creating of NTMultiChannel.
* @brief Interface for in-line creating of NTMultiChannel.
*
* One instance can be used to create multiple instances.
* An instance of this object must not be used concurrently (an object has a state).
* @author mse
@@ -39,79 +51,99 @@ namespace detail {
/**
* specify the union for the value field.
* If this is not called then a variantUnion is the default.
* @return this instance of a {@code NTMultiChannelBuilder}.
* @return this instance of <b>NTMultiChannelBuilder</b>.
*/
shared_pointer value(epics::pvData::UnionConstPtr valuePtr);
/**
* Add descriptor field to the NTMultiChannel.
* @return this instance of a {@code NTMultiChannelBuilder}.
* Adds descriptor field to the NTMultiChannel.
* @return this instance of <b>NTMultiChannelBuilder</b>.
*/
shared_pointer addDescriptor();
/**
* Add alarm structure to the NTMultiChannel.
* @return this instance of a {@code NTMultiChannelBuilder}.
* Adds alarm field to the NTMultiChannel.
* @return this instance of <b>NTMultiChannelBuilder</b>.
*/
shared_pointer addAlarm();
/**
* Add timeStamp structure to the NTMultiChannel.
* @return this instance of a {@code NTMultiChannelBuilder}.
* Adds timeStamp field to the NTMultiChannel.
* @return this instance of <b>NTMultiChannelBuilder</b>.
*/
shared_pointer addTimeStamp();
/**
* Add severity array to the NTMultiChannel.
* @return this instance of a {@code NTMultiChannelBuilder}.
* Adds severity array to the NTMultiChannel.
* @return this instance of <b>NTMultiChannelBuilder</b>.
*/
shared_pointer addSeverity();
/**
* Add status array to the NTMultiChannel.
* @return this instance of a {@code NTMultiChannelBuilder}.
* Adds status array to the NTMultiChannel.
* @return this instance of <b>NTMultiChannelBuilder</b>.
*/
shared_pointer addStatus();
/**
* Add message array to the NTMultiChannel.
* @return this instance of a {@code NTMultiChannelBuilder}.
* Adds message array to the NTMultiChannel.
* @return this instance of <b>NTMultiChannelBuilder</b>.
*/
shared_pointer addMessage();
/**
* Add secondsPastEpoch array to the NTMultiChannel.
* @return this instance of a {@code NTMultiChannelBuilder}.
* Adds secondsPastEpoch array to the NTMultiChannel.
* @return this instance of <b>NTMultiChannelBuilder</b>.
*/
shared_pointer addSecondsPastEpoch();
/**
* Add nanoseconds array to the NTMultiChannel.
* @return this instance of a {@code NTMultiChannelBuilder}.
* Adds nanoseconds array to the NTMultiChannel.
* @return this instance of <b>NTMultiChannelBuilder</b>.
*/
shared_pointer addNanoseconds();
/**
* Add userTag array to the NTMultiChannel.
* @return this instance of a {@code NTMultiChannelBuilder}.
* Adds userTag array to the NTMultiChannel.
* @return this instance of <b>NTMultiChannelBuilder</b>.
*/
shared_pointer addUserTag();
/**
* Create a {@code Structure} that represents NTMultiChannel.
* Adds isConnected array to the NTMultiChannel.
* @return this instance of <b>NTMultiChannelBuilder</b>.
*/
shared_pointer addIsConnected();
/**
* Creates a <b>Structure</b> that represents NTMultiChannel.
* This resets this instance state and allows new instance to be created.
* @return a new instance of a {@code Structure}.
* @return a new instance of a <b>Structure</b>.
*/
epics::pvData::StructureConstPtr createStructure();
/**
* Create a {@code PVStructure} that represents NTMultiChannel.
* This resets this instance state and allows new {@code instance to be created.}
* @return a new instance of a {@code PVStructure}
* Creates a <b>PVStructure</b> that represents NTMultiChannel.
* This resets this instance state and allows new instance to be created.
* @return a new instance of a <b>PVStructure</b>
*/
epics::pvData::PVStructurePtr createPVStructure();
/**
* Create a {@code NTMultiChannel} instance.
* This resets this instance state and allows new {@code instance to be created.}
* @return a new instance of a {@code NTMultiChannel}
* Creates a <b>NTMultiChannel</b> instance.
* This resets this instance state and allows new instance to be created.
* @return a new instance of a <b>NTMultiChannel</b>
*/
NTMultiChannelPtr create();
/**
* Add extra {@code Field} to the type.
* @param name name of the field.
* @param field a field to add.
* @return this instance of a {@code NTMultiChannelBuilder}.
* Adds extra <b>Field</b> to the type.
* @param name the name of the field.
* @param field the field to be added.
* @return this instance of a <b>NTMultiChannelBuilder</b>
*/
shared_pointer add(std::string const & name, epics::pvData::FieldConstPtr const & field);
private:
NTMultiChannelBuilder();
@@ -127,6 +159,7 @@ namespace detail {
bool secondsPastEpoch;
bool nanoseconds;
bool userTag;
bool isConnected;
// NOTE: this preserves order, however it does not handle duplicates
epics::pvData::StringArray extraFieldNames;
@@ -140,7 +173,13 @@ namespace detail {
typedef std::tr1::shared_ptr<detail::NTMultiChannelBuilder> NTMultiChannelBuilderPtr;
class NTMultiChannel
/**
* @brief Convenience Class for NTMultiChannel
*
* @author mrk
*
*/
class epicsShareClass NTMultiChannel
{
public:
POINTER_DEFINITIONS(NTMultiChannel);
@@ -148,38 +187,92 @@ public:
static const std::string URI;
/**
* Wrap (aka dynamic cast, or wrap) the structure to NTMultiChannel.
* First isCompatible is called.
* This method will nullptr if the structure is is not compatible.
* @param structure The structure to wrap-ed (dynamic cast, wrapped) to NTMultiChannel.
* @return NTMultiChannel instance on success, nullptr otherwise.
* Creates an NTMultiChannel wrapping the specified PVStructure if the latter is compatible.
* <p>
* Checks the supplied PVStructure is compatible with NTMultiChannel
* and if so returns an NTMultiChannel which wraps it.
* This method will return null if the structure is is not compatible
* or is null.
*
* @param pvStructure the PVStructure to be wrapped
* @return NTMultiChannel instance wrapping pvStructure on success, null otherwise
*/
static shared_pointer wrap(epics::pvData::PVStructurePtr const & structure);
static shared_pointer wrap(epics::pvData::PVStructurePtr const & pvStructure);
/**
* Wrap (aka dynamic cast, or wrap) the structure to NTMultiChannel without checking for isCompatible
* @param structure The structure to wrap-ed (dynamic cast, wrapped) to NTMultiChannel.
* @return NTMultiChannel instance.
* Creates an NTMultiChannel wrapping the specified PVStructure, regardless of the latter's compatibility.
* <p>
* No checks are made as to whether the specified PVStructure
* is compatible with NTMultiChannel or is non-null.
*
* @param pvStructure the PVStructure to be wrapped
* @return NTMultiChannel instance wrapping pvStructure
*/
static shared_pointer wrapUnsafe(epics::pvData::PVStructurePtr const & structure);
static shared_pointer wrapUnsafe(epics::pvData::PVStructurePtr const & pvStructure);
/**
* Is the Structure an NTMultiChannel.
* This method structure->getID() and checks if it is the same as the URI.
* @param structure The structure to test.
* @return (false,true) if (is not, is) an NTMultiChannel.
* Returns whether the specified Structure reports to be a compatible NTMultiChannel.
* <p>
* Checks whether the specified Structure reports compatibility with this
* version of NTMultiChannel through its type ID, including checking version numbers.
* The return value does not depend on whether the structure is actually
* compatible in terms of its introspection type.
*
* @param structure the Structure to test
* @return (false,true) if the specified Structure (is not, is) a compatible NTMultiChannel
*/
static bool is_a(
static bool is_a(epics::pvData::StructureConstPtr const & structure);
/**
* Returns whether the specified PVStructure reports to be a compatible NTMultiChannel.
* <p>
* Checks whether the specified PVStructure reports compatibility with this
* version of NTMultiChannel through its type ID, including checking version numbers.
* The return value does not depend on whether the structure is actually
* compatible in terms of its introspection type.
*
* @param pvStructure the PVStructure to test
* @return (false,true) if the specified PVStructure (is not, is) a compatible NTMultiChannel
*/
static bool is_a(epics::pvData::PVStructurePtr const & pvStructure);
/**
* Returns whether the specified Structure is compatible with NTMultiChannel.
* <p>
* Checks whether the specified Structure is compatible with this version
* of NTMultiChannel through the introspection interface.
*
* @param structure the Structure to test
* @return (false,true) if the specified Structure (is not, is) a compatible NTMultiChannel
*/
static bool isCompatible(
epics::pvData::StructureConstPtr const &structure);
/**
* Is the pvStructure compatible with NTMultiChannel.
* This method introspects the fields to see if they are compatible.
* @param pvStructure The pvStructure to test.
* @return (false,true) if (is not, is) an NTMultiChannel.
* Returns whether the specified PVStructure is compatible with NTMultiChannel.
* <p>
* Checks whether the specified PVStructure is compatible with this version
* of NTMultiChannel through the introspection interface.
*
* @param pvStructure the PVStructure to test
* @return (false,true) if the specified PVStructure (is not, is) a compatible NTMultiChannel
*/
static bool isCompatible(
epics::pvData::PVStructurePtr const &pvStructure);
/**
* Create a NTMultiChannelBuilder instance
* Checks whether the wrapped PVStructure is valid with respect to this
* version of NTMultiChannel.
* <p>
* Unlike isCompatible(), isValid() may perform checks on the value
* data as well as the introspection data.
*
* @return (false,true) if the wrapped PVStructure (is not, is) a valid NTMultiChannel
*/
bool isValid();
/**
* Creates an NTMultiChannelBuilder instance
* @return builder instance.
*/
static NTMultiChannelBuilderPtr createBuilder();
@@ -189,95 +282,112 @@ public:
*/
~NTMultiChannel() {}
/**
* Attach a pvTimeStamp.
* @param pvTimeStamp The pvTimeStamp that will be attached.
* Does nothing if no timeStamp
* Attaches a PVTimeStamp to the wrapped PVStructure.
* Does nothing if no timeStamp field.
* @param pvTimeStamp the PVTimeStamp that will be attached.
* @return true if the operation was successfull (i.e. this instance has a timeStamp field), otherwise false.
*/
void attachTimeStamp(epics::pvData::PVTimeStamp &pvTimeStamp) const;
bool attachTimeStamp(epics::pvData::PVTimeStamp &pvTimeStamp) const;
/**
* Attach a pvAlarm.
* @param pvAlarm The pvAlarm that will be attached.
* Does nothing if no alarm
* Attaches a PVAlarm to the wrapped PVStructure.
* Does nothing if no alarm field.
* @param pvAlarm the PVAlarm that will be attached.
* @return true if the operation was successfull (i.e. this instance has an alarm field), otherwise false.
*/
void attachAlarm(epics::pvData::PVAlarm &pvAlarm) const;
bool attachAlarm(epics::pvData::PVAlarm &pvAlarm) const;
/**
* Get the pvStructure.
* @return PVStructurePtr.
* Returns the PVStructure wrapped by this instance.
* @return the PVStructure wrapped by this instance.
*/
epics::pvData::PVStructurePtr getPVStructure() const
{return pvNTMultiChannel;}
/**
* Get the timeStamp.
* @return PVStructurePtr which may be null.
*/
epics::pvData::PVStructurePtr getTimeStamp() const
{return pvTimeStamp;}
/**
* Get the alarm.
* @return PVStructurePtr which may be null.
*/
epics::pvData::PVStructurePtr getAlarm() const
{return pvAlarm;}
/**
* Get the value of each channel.
* @return PVUnionArrayPtr
*/
epics::pvData::PVUnionArrayPtr getValue() const
{return pvValue;}
/**
* Get the channelName of each channel.
* @return PVStringArrayPtr
*/
epics::pvData::PVStringArrayPtr getChannelName() const
{ return pvChannelName;};
/**
* Get the connection state of each channel.
* @return PVBooleanArrayPtr
*/
epics::pvData::PVBooleanArrayPtr getIsConnected() const
{ return pvIsConnected;};
/**
* Get the severity of each channel.
* @return PVIntArrayPtr which may be null.
*/
epics::pvData::PVIntArrayPtr getSeverity() const
{return pvSeverity;}
/**
* Get the status of each channel.
* @return PVIntArrayPtr which may be null.
*/
epics::pvData::PVIntArrayPtr getStatus() const
{return pvStatus;}
/**
* Get the message of each chnnel.
* @return PVStringArrayPtr which may be null.
*/
epics::pvData::PVStringArrayPtr getMessage() const
{return pvMessage;}
/**
* Get the secondsPastEpoch of each channel.
* @return PVLongArrayPtr which may be null.
*/
epics::pvData::PVLongArrayPtr getSecondsPastEpoch() const
{return pvSecondsPastEpoch;}
/**
* Get the nanoseconds of each channel.
* @return PVIntArrayPtr which may be null.
*/
epics::pvData::PVIntArrayPtr getNanoseconds() const
{return pvNanoseconds;}
/**
* Get the userTag of each channel.
* @return PVIntArrayPtr which may be null.
*/
epics::pvData::PVIntArrayPtr getUserTag() const
{return pvUserTag;}
/**
* Get the descriptor.
* @return PVStringPtr which may be null.
* Return the descriptor field.
* @return the descriptor field or null if no descriptor field.
*/
epics::pvData::PVStringPtr getDescriptor() const
{return pvDescriptor;}
/**
* Returns the timeStamp field.
* @return the timeStamp field or null if no such field.
*/
epics::pvData::PVStructurePtr getTimeStamp() const
{return pvTimeStamp;}
/**
* Returns the alarm field.
* @return the alarm field or null if no such field.
*/
epics::pvData::PVStructurePtr getAlarm() const
{return pvAlarm;}
/**
* Returns the field with the value of each channel.
* @return the value field.
*/
epics::pvData::PVUnionArrayPtr getValue() const
{return pvValue;}
/**
* Returns the field with the channelName of each channel.
* @return the channelName field
*/
epics::pvData::PVStringArrayPtr getChannelName() const
{ return pvChannelName;};
/**
* Returns the field with the connection state of each channel.
* @return the isConnected field or null if no such field
*/
epics::pvData::PVBooleanArrayPtr getIsConnected() const
{ return pvIsConnected;};
/**
* Returns the field with the severity of each channel.
* @return the severity field or null if no such field.
*/
epics::pvData::PVIntArrayPtr getSeverity() const
{return pvSeverity;}
/**
* Returns the field with the status of each channel.
* @return the status field or null if no such field
*/
epics::pvData::PVIntArrayPtr getStatus() const
{return pvStatus;}
/**
* Returns the field with the message of each channel.
* @return message field or null if no such field.
*/
epics::pvData::PVStringArrayPtr getMessage() const
{return pvMessage;}
/**
* Returns the field with the secondsPastEpoch of each channel.
* @return the secondsPastEpoch field or null if no such field.
*/
epics::pvData::PVLongArrayPtr getSecondsPastEpoch() const
{return pvSecondsPastEpoch;}
/**
* Returns the field with the nanoseconds of each channel.
* @return nanoseconds field or null if no such field.
*/
epics::pvData::PVIntArrayPtr getNanoseconds() const
{return pvNanoseconds;}
/**
* Returns the field with the userTag of each channel.
* @return the userTag field or null if no such field.
*/
epics::pvData::PVIntArrayPtr getUserTag() const
{return pvUserTag;}
private:
NTMultiChannel(epics::pvData::PVStructurePtr const & pvStructure);
epics::pvData::PVStructurePtr pvNTMultiChannel;

View File

@@ -1,11 +1,13 @@
/* ntnameValue.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* This software is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#define epicsExportSharedSymbols
#include <pv/ntnameValue.h>
#include <pv/ntutils.h>
using namespace std;
using namespace epics::pvData;
@@ -110,10 +112,10 @@ NTNameValueBuilder::shared_pointer NTNameValueBuilder::add(string const & name,
const std::string NTNameValue::URI("epics:nt/NTNameValue:1.0");
NTNameValue::shared_pointer NTNameValue::wrap(PVStructurePtr const & structure)
NTNameValue::shared_pointer NTNameValue::wrap(PVStructurePtr const & pvStructure)
{
if(!isCompatible(structure)) return shared_pointer();
return wrapUnsafe(structure);
if(!isCompatible(pvStructure)) return shared_pointer();
return wrapUnsafe(pvStructure);
}
NTNameValue::shared_pointer NTNameValue::wrapUnsafe(PVStructurePtr const & structure)
@@ -123,23 +125,52 @@ NTNameValue::shared_pointer NTNameValue::wrapUnsafe(PVStructurePtr const & struc
bool NTNameValue::is_a(StructureConstPtr const & structure)
{
return structure->getID() == URI;
return NTUtils::is_a(structure->getID(), URI);
}
bool NTNameValue::isCompatible(StructureConstPtr const & structure)
{
if (structure.get() == 0) return false;
ScalarArrayConstPtr nameField = structure->getField<ScalarArray>("name");
if (nameField.get() == 0 || nameField->getElementType() != pvString)
return false;
ScalarArrayConstPtr valueField = structure->getField<ScalarArray>("value");
if (valueField.get() == 0)
return false;
FieldConstPtr field = structure->getField("descriptor");
if (field.get())
{
ScalarConstPtr descriptorField = structure->getField<Scalar>("descriptor");
if (!descriptorField || descriptorField->getScalarType() != pvString)
return false;
}
NTFieldPtr ntField = NTField::get();
field = structure->getField("alarm");
if (field && !ntField->isAlarm(field))
return false;
field = structure->getField("timeStamp");
if (field && !ntField->isTimeStamp(field))
return false;
return true;
}
bool NTNameValue::isCompatible(PVStructurePtr const & pvStructure)
{
if(!pvStructure) return false;
PVStringArrayPtr pvName = pvStructure->getSubField<PVStringArray>("name");
if(!pvName) return false;
PVFieldPtr pvValue = pvStructure->getSubField("value");
if(!pvValue) return false;
PVFieldPtr pvField = pvStructure->getSubField("descriptor");
if(pvField && !pvStructure->getSubField<PVString>("descriptor")) return false;
pvField = pvStructure->getSubField("alarm");
if(pvField && !ntField->isAlarm(pvField->getField())) return false;
pvField = pvStructure->getSubField("timeStamp");
if(pvField && !ntField->isTimeStamp(pvField->getField())) return false;
return true;
return isCompatible(pvStructure->getStructure());
}
bool NTNameValue::isValid()
{
return (getValue<PVScalarArray>()->getLength() == getName()->getLength());
}
NTNameValueBuilderPtr NTNameValue::createBuilder()

View File

@@ -1,14 +1,29 @@
/* ntnameValue.h */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* This software is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#ifndef NTNAMEVALUE_H
#define NTNAMEVALUE_H
#ifdef epicsExportSharedSymbols
# define ntnameValueEpicsExportSharedSymbols
# undef epicsExportSharedSymbols
#endif
#include <pv/pvDisplay.h>
#include <pv/pvControl.h>
#ifdef ntnameValueEpicsExportSharedSymbols
# define epicsExportSharedSymbols
# undef ntnameValueEpicsExportSharedSymbols
#endif
#include <pv/ntfield.h>
#include <shareLib.h>
namespace epics { namespace nt {
class NTNameValue;
@@ -17,7 +32,8 @@ typedef std::tr1::shared_ptr<NTNameValue> NTNameValuePtr;
namespace detail {
/**
* Interface for in-line creating of NTNameValue.
* @brief Interface for in-line creating of NTNameValue.
*
* One instance can be used to create multiple instances.
* An instance of this object must not be used concurrently (an object has a state).
* @author mse
@@ -29,56 +45,56 @@ namespace detail {
POINTER_DEFINITIONS(NTNameValueBuilder);
/**
* Set a value array {@code Scalar} type.
* @param scalarType value array scalar array.
* @return this instance of a {@code NTTableBuilder}.
* Sets the value array <b>Scalar</b> type.
* @param scalarType the value field element ScalarType
* @return this instance of <b>NTTableBuilder</b>.
*/
shared_pointer value(epics::pvData::ScalarType scalarType);
/**
* Add descriptor field to the NTNameValue.
* @return this instance of a {@code NTNameValueBuilder}.
* Adds descriptor field to the NTNameValue.
* @return this instance of <b>NTTableBuilder</b>.
*/
shared_pointer addDescriptor();
/**
* Add alarm structure to the NTNameValue.
* @return this instance of a {@code NTNameValueBuilder}.
* Adds alarm field to the NTNameValue.
* @return this instance of <b>NTTableBuilder</b>.
*/
shared_pointer addAlarm();
/**
* Add timeStamp structure to the NTNameValue.
* @return this instance of a {@code NTNameValueBuilder}.
* Adds timeStamp field to the NTNameValue.
* @return this instance of <b>NTTableBuilder</b>.
*/
shared_pointer addTimeStamp();
/**
* Create a {@code Structure} that represents NTNameValue.
* Creates a <b>Structure</b> that represents NTNameValue.
* This resets this instance state and allows new instance to be created.
* @return a new instance of a {@code Structure}.
* @return a new instance of <b>Structure</b>.
*/
epics::pvData::StructureConstPtr createStructure();
/**
* Create a {@code PVStructure} that represents NTNameValue.
* This resets this instance state and allows new {@code instance to be created.
* @return a new instance of a {@code PVStructure}
* Creates a <b>PVStructure</b> that represents NTNameValue.
* This resets this instance state and allows new instance to be created.
* @return a new instance of <b>PVStructure</b>
*/
epics::pvData::PVStructurePtr createPVStructure();
/**
* Create a {@code NTNameValue} instance.
* This resets this instance state and allows new {@code instance to be created.
* @return a new instance of a {@code NTNameValue}
* Creates a <b>NTNameValue</b> instance.
* This resets this instance state and allows new instance to be created.
* @return a new instance of <b>NTNameValue</b>
*/
NTNameValuePtr create();
/**
* Add extra {@code Field} to the type.
* @param name name of the field.
* @param field a field to add.
* @return this instance of a {@code NTNameValueBuilder}.
* Adds extra <b>Field</b> to the type.
* @param name the name of the field.
* @param field the field to be added.
* @return this instance of <b>NTTableBuilder</b>.
*/
shared_pointer add(std::string const & name, epics::pvData::FieldConstPtr const & field);
@@ -105,13 +121,12 @@ namespace detail {
typedef std::tr1::shared_ptr<detail::NTNameValueBuilder> NTNameValueBuilderPtr;
/**
* Convenience Class for NTNameValue
* @brief Convenience Class for NTNameValue
*
* @author mrk
*/
class NTNameValue
class epicsShareClass NTNameValue
{
public:
POINTER_DEFINITIONS(NTNameValue);
@@ -119,38 +134,90 @@ public:
static const std::string URI;
/**
* Wrap (aka dynamic cast, or wrap) the structure to NTNameValue.
* First isCompatible is called.
* This method will nullptr if the structure is is not compatible.
* This method will nullptr if the structure is nullptr.
* @param structure The structure to wrap-ed (dynamic cast, wrapped) to NTNameValue.
* @return NTNameValue instance on success, nullptr otherwise.
* Creates an NTNameValue wrapping the specified PVStructure if the latter is compatible.
* <p>
* Checks the supplied PVStructure is compatible with NTNameValue
* and if so returns an NTNameValue which wraps it.
* This method will return null if the structure is is not compatible
* or is null.
*
* @param pvStructure the PVStructure to be wrapped.
* @return NTNameValue instance wrapping pvStructure on success, null otherwise.
*/
static shared_pointer wrap(epics::pvData::PVStructurePtr const & structure);
static shared_pointer wrap(epics::pvData::PVStructurePtr const & pvStructure);
/**
* Wrap (aka dynamic cast, or wrap) the structure to NTMultiChannel without checking for isCompatible
* @param structure The structure to wrap-ed (dynamic cast, wrapped) to NTNameValue.
* @return NTNameValue instance.
* Creates an NTNameValue wrapping the specified PVStructure, regardless of the latter's compatibility.
* <p>
* No checks are made as to whether the specified PVStructure
* is compatible with NTNameValue or is non-null.
*
* @param pvStructure the PVStructure to be wrapped.
* @return NTNameValue instance wrapping pvStructure.
*/
static shared_pointer wrapUnsafe(epics::pvData::PVStructurePtr const & structure);
static shared_pointer wrapUnsafe(epics::pvData::PVStructurePtr const & pvStructure);
/**
* Is the structure an NTNameValue.
* @param structure The structure to test.
* @return (false,true) if (is not, is) an NTNameValue.
* Returns whether the specified Structure reports to be a compatible NTNameValue.
* <p>
* Checks if the specified Structure reports compatibility with this
* version of NTNameValue through its type ID, including checking version numbers.
* The return value does not depend on whether the structure is actually
* compatible in terms of its introspection type.
*
* @param structure the Structure to test.
* @return (false,true) if the specified Structure (is not, is) a compatible NTNameValue.
*/
static bool is_a(epics::pvData::StructureConstPtr const & structure);
/**
* Is the pvStructure compatible with NTNameValue..
* This method introspects the fields to see if they are compatible.
* @param pvStructure The pvStructure to test.
* @return (false,true) if (is not, is) an NTMultiChannel.
* Returns whether the specified PVStructure reports to be a compatible NTNameValue.
* <p>
* Checks if the specified PVStructure reports compatibility with this
* version of NTNameValue through its type ID, including checking version numbers.
* The return value does not depend on whether the structure is actually
* compatible in terms of its introspection type
* @param pvStructure The PVStructure to test.
* @return (false,true) if the specified PVStructure (is not, is) a compatible NTNameValue.
*/
static bool is_a(epics::pvData::PVStructurePtr const & pvStructure);
/**
* Returns whether the specified Structure is compatible with NTNameValue.
* <p>
* Checks if the specified PVStructure is compatible with this version
* of NTNameValue through the introspection interface.
* @param structure the Structure to test.
* @return (false,true) if the specified Structure (is not, is) a compatible NTNameValue.
*/
static bool isCompatible(
epics::pvData::StructureConstPtr const &structure);
/**
* Returns whether the specified PVStructure is compatible with NTNameValue.
* <p>
* Checks if the specified PVStructure is compatible with this version
* of NTNameValue through the introspection interface.
*
* @param pvStructure the PVStructure to test
* @return (false,true) if the specified PVStructure (is not, is) a compatible NTNameValue
*/
static bool isCompatible(
epics::pvData::PVStructurePtr const &pvStructure);
/**
* Create a NTNameValue builder instance.
* Returns whether the wrapped PVStructure is valid with respect to this
* version of NTNameValue.
* <p>
* Unlike isCompatible(), isValid() may perform checks on the value
* data as well as the introspection data.
*
* @return (false,true) if the wrapped PVStructure (is not, is) a valid NTNameValue
*/
bool isValid();
/**
* Creates an NTNameValue builder instance.
* @return builder instance.
*/
static NTNameValueBuilderPtr createBuilder();
@@ -161,60 +228,63 @@ public:
~NTNameValue() {}
/**
* Attach a pvTimeStamp.
* @param pvTimeStamp The pvTimeStamp that will be attached.
* Does nothing if no timeStamp.
* Attaches a PVTimeStamp to the wrapped PVStructure.
* Does nothing if no timeStamp field.
* @param pvTimeStamp the PVTimeStamp that will be attached.
* @return true if the operation was successfull (i.e. this instance has a timeStamp field), otherwise false.
*/
bool attachTimeStamp(epics::pvData::PVTimeStamp &pvTimeStamp) const;
/**
* Attach an pvAlarm.
* @param pvAlarm The pvAlarm that will be attached.
* Does nothing if no alarm.
* @return true if the operation was successfull (i.e. this instance has a timeStamp field), otherwise false.
* Attaches a PVAlarm to the wrapped PVStructure.
* Does nothing if no alarm field.
* @param pvAlarm the PVAlarm that will be attached.
* @return true if the operation was successfull (i.e. this instance has an alarm field), otherwise false.
*/
bool attachAlarm(epics::pvData::PVAlarm &pvAlarm) const;
/**
* Get the pvStructure.
* @return PVStructurePtr.
* Returns the PVStructure wrapped by this instance.
* @return the PVStructure wrapped by this instance.
*/
epics::pvData::PVStructurePtr getPVStructure() const;
/**
* Get the descriptor field.
* @return The pvString or null if no function field.
* Returns the descriptor field.
* @return the descriptor field or null if no descriptor field.
*/
epics::pvData::PVStringPtr getDescriptor() const;
/**
* Get the timeStamp.
* @return PVStructurePtr which may be null.
* Returns the timeStamp field.
* @return the timStamp field or null if no timeStamp field.
*/
epics::pvData::PVStructurePtr getTimeStamp() const;
/**
* Get the alarm.
* @return PVStructurePtr which may be null.
* Returns the alarm field.
* @return the alarm field or null if no alarm field.
*/
epics::pvData::PVStructurePtr getAlarm() const;
/**
* Get the name array field.
* Returns the name array field.
* @return The PVStringArray for the name.
*/
epics::pvData::PVStringArrayPtr getName() const;
/**
* Get the value array field.
* Returns the value array field.
* @return The PVField for the value.
*/
epics::pvData::PVFieldPtr getValue() const;
/**
* Get the value array field of a specified type (e.g. PVDoubleArray).
* @return The <PVT> array for the value.
* Returns the value array field of a specified expected type (e.g. PVDoubleArray).
*
* @tparam PVT The expected type of the value field which should be
* be PVScalarArray or a derived class.
* @return The PVT array for the value.
*/
template<typename PVT>
std::tr1::shared_ptr<PVT> getValue() const

View File

@@ -1,13 +1,16 @@
/* ntndarray.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* This software is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#include <algorithm>
#define epicsExportSharedSymbols
#include <pv/ntndarray.h>
#include <pv/ntndarrayAttribute.h>
#include <pv/ntutils.h>
using namespace std;
using namespace epics::pvData;
@@ -16,13 +19,14 @@ namespace epics { namespace nt {
static NTFieldPtr ntField = NTField::get();
namespace detail {
const std::string ntAttrStr("epics:nt/NTAttribute:1.0");
namespace detail {
static FieldCreatePtr fieldCreate = getFieldCreate();
static PVDataCreatePtr pvDataCreate = getPVDataCreate();
static Mutex mutex;
StructureConstPtr NTNDArrayBuilder::createStructure()
{
enum
@@ -36,16 +40,14 @@ StructureConstPtr NTNDArrayBuilder::createStructure()
const size_t NUMBER_OF_INDICES = DISPLAY_INDEX+1;
const size_t NUMBER_OF_STRUCTURES = 1 << NUMBER_OF_INDICES;
Lock xx(mutex);
static StructureConstPtr ntndarrayStruc[NUMBER_OF_STRUCTURES];
static UnionConstPtr valueType;
static StructureConstPtr codecStruc;
static StructureConstPtr dimensionStruc;
static StructureConstPtr attributeStruc;
static Mutex mutex;
Lock xx(mutex);
StructureConstPtr returnedStruc;
size_t index = 0;
@@ -92,13 +94,7 @@ StructureConstPtr NTNDArrayBuilder::createStructure()
if (!attributeStruc)
{
attributeStruc = fb->setId(ntAttrStr)->
add("name", pvString)->
add("value", fieldCreate->createVariantUnion())->
add("descriptor", pvString)->
add("sourceType", pvInt)->
add("source", pvString)->
createStructure();
attributeStruc = NTNDArrayAttribute::createBuilder()->createStructure();
}
fb->setId(NTNDArray::URI)->
@@ -114,12 +110,12 @@ StructureConstPtr NTNDArrayBuilder::createStructure()
if (descriptor)
fb->add("descriptor", pvString);
if (timeStamp)
fb->add("timeStamp", standardField->timeStamp());
if (alarm)
fb->add("alarm", standardField->alarm());
if (timeStamp)
fb->add("timeStamp", standardField->timeStamp());
if (display)
fb->add("display", standardField->display());
@@ -204,52 +200,279 @@ const std::string ntAttrStr("epics:nt/NTAttribute:1.0");
static FieldCreatePtr fieldCreate = getFieldCreate();
static PVDataCreatePtr pvDataCreate = getPVDataCreate();
NTNDArray::shared_pointer NTNDArray::wrap(PVStructurePtr const & structure)
class NTValueType
{
if(!isCompatible(structure)) return shared_pointer();
return wrapUnsafe(structure);
public:
static bool isCompatible(UnionConstPtr const &u)
{
if(!u.get()) return false;
if (u->getID() != Union::defaultId()) return false;
if (u->isVariant()) return false;
for (int i = pvBoolean; i != pvString; ++i)
{
ScalarType scalarType = static_cast<ScalarType>(i);
std::string name(ScalarTypeFunc::name(scalarType));
name += "Value";
ScalarArrayConstPtr scalarField = u->getField<ScalarArray>(name);
if (scalarField.get() == 0 ||
scalarField->getElementType() != scalarType)
return false;
}
return true;
}
};
class NTCodec
{
public:
static bool isCompatible(StructureConstPtr const &structure)
{
if(!structure.get()) return false;
if (structure->getID() != "codec_t") return false;
ScalarConstPtr scalarField = structure->getField<Scalar>("name");
if (scalarField.get() == 0 || scalarField->getScalarType() != pvString)
return false;
UnionConstPtr paramField = structure->getField<Union>("parameters");
if (paramField.get() == 0 || !paramField->isVariant())
return false;
return true;
}
};
class NTDimension
{
public:
static bool isCompatible(StructureConstPtr const &structure)
{
if(!structure.get()) return false;
if (structure->getID() != "dimension_t") return false;
ScalarConstPtr scalarField = structure->getField<Scalar>("size");
if (scalarField.get() == 0 || scalarField->getScalarType() != pvInt)
return false;
scalarField = structure->getField<Scalar>("offset");
if (scalarField.get() == 0 || scalarField->getScalarType() != pvInt)
return false;
scalarField = structure->getField<Scalar>("fullSize");
if (scalarField.get() == 0 || scalarField->getScalarType() != pvInt)
return false;
scalarField = structure->getField<Scalar>("binning");
if (scalarField.get() == 0 || scalarField->getScalarType() != pvInt)
return false;
scalarField = structure->getField<Scalar>("reverse");
if (scalarField.get() == 0 || scalarField->getScalarType() != pvBoolean)
return false;
return true;
}
};
NTNDArray::shared_pointer NTNDArray::wrap(PVStructurePtr const & pvStructure)
{
if(!isCompatible(pvStructure)) return shared_pointer();
return wrapUnsafe(pvStructure);
}
NTNDArray::shared_pointer NTNDArray::wrapUnsafe(PVStructurePtr const & structure)
NTNDArray::shared_pointer NTNDArray::wrapUnsafe(PVStructurePtr const & pvStructure)
{
return shared_pointer(new NTNDArray(structure));
return shared_pointer(new NTNDArray(pvStructure));
}
bool NTNDArray::is_a(StructureConstPtr const & structure)
{
return structure->getID() == URI;
return NTUtils::is_a(structure->getID(), URI);
}
bool NTNDArray::isCompatible(PVStructurePtr const & pvStructure)
bool NTNDArray::isCompatible(StructureConstPtr const &structure)
{
if(!pvStructure) return false;
PVUnionPtr pvValue = pvStructure->getSubField<PVUnion>("value");
if(!pvValue) return false;
PVFieldPtr pvField = pvStructure->getSubField("descriptor");
if(pvField && !pvStructure->getSubField<PVString>("descriptor")) return false;
pvField = pvStructure->getSubField("alarm");
if(pvField && !ntField->isAlarm(pvField->getField())) return false;
pvField = pvStructure->getSubField("timeStamp");
if(pvField && !ntField->isTimeStamp(pvField->getField())) return false;
pvField = pvStructure->getSubField("display");
if(pvField && !ntField->isDisplay(pvField->getField())) return false;
if(!pvStructure->getSubField<PVLong>("compressedSize")) return false;
if(!pvStructure->getSubField<PVLong>("uncompressedSize")) return false;
PVStructurePtr pvCodec = pvStructure->getSubField<PVStructure>("codec");
if(!pvCodec) return false;
if(!pvCodec->getSubField<PVString>("name")) return false;
if(!pvCodec->getSubField<PVUnion>("parameters")) return false;
PVStructureArrayPtr pvDimension = pvStructure->getSubField<PVStructureArray>("dimension");
if(pvDimension->getStructureArray()->getStructure()->getID().compare("dimension_t")!=0) return false;
if(!pvStructure->getSubField<PVInt>("uniqueId")) return false;
pvField = pvStructure->getSubField("dataTimeStamp");
if(pvField && !ntField->isTimeStamp(pvField->getField())) return false;
PVStructureArrayPtr pvAttribute = pvStructure->getSubField<PVStructureArray>("attribute");
if(pvAttribute->getStructureArray()->getStructure()->getID().compare(ntAttrStr)!=0) return false;
if(!structure.get()) return false;
UnionConstPtr valueField = structure->getField<Union>("value");
if(!NTValueType::isCompatible(valueField)) return false;
StructureConstPtr codecField = structure->getField<Structure>("codec");
if(!NTCodec::isCompatible(codecField)) return false;
ScalarConstPtr compressedSizeField = structure->getField<Scalar>("compressedSize");
if (compressedSizeField.get() == 0)
return false;
if (compressedSizeField->getScalarType() != pvLong)
return false;
ScalarConstPtr uncompressedSizeField = structure->getField<Scalar>("uncompressedSize");
if (uncompressedSizeField.get() == 0)
return false;
if (uncompressedSizeField->getScalarType() != pvLong)
return false;
StructureArrayConstPtr dimensionField = structure->getField<StructureArray>("dimension");
if (dimensionField.get() == 0)
return false;
StructureConstPtr dimElementStruc = dimensionField->getStructure();
if(!NTDimension::isCompatible(dimElementStruc))
return false;
NTFieldPtr ntField = NTField::get();
StructureConstPtr dataTimeStampField = structure->getField<Structure>(
"dataTimeStamp");
if (dataTimeStampField.get() == 0 || !ntField->isTimeStamp(dataTimeStampField))
return false;
ScalarConstPtr uniqueIdField = structure->getField<Scalar>("uniqueId");
if (uniqueIdField.get() == 0)
return false;
if (uniqueIdField->getScalarType() != pvInt)
return false;
StructureArrayConstPtr attributeField = structure->getField<StructureArray>( "attribute");
StructureConstPtr attributeElementStruc = attributeField->getStructure();
if (!NTNDArrayAttribute::isCompatible(attributeElementStruc))
return false;
FieldConstPtr field = structure->getField("descriptor");
if (field.get())
{
ScalarConstPtr descriptorField = structure->getField<Scalar>("descriptor");
if (!descriptorField.get() || descriptorField->getScalarType() != pvString)
return false;
}
field = structure->getField("alarm");
if (field.get() && !ntField->isAlarm(field))
return false;
field = structure->getField("timeStamp");
if (field.get() && !ntField->isTimeStamp(field))
return false;
field = structure->getField("display");
if (field.get() && !ntField->isDisplay(field))
return false;
return true;
}
bool NTNDArray::isCompatible(PVStructurePtr const & pvStructure)
{
if(!pvStructure.get()) return false;
return isCompatible(pvStructure->getStructure());
}
bool NTNDArray::isValid()
{
int64 valueSize = getValueSize();
int64 compressedSize = getCompressedDataSize()->get();
if (valueSize != compressedSize)
return false;
long expectedUncompressed = getExpectedUncompressedSize();
long uncompressedSize = getUncompressedDataSize()->get();
if (uncompressedSize != expectedUncompressed)
return false;
std::string codecName = getCodec()->getSubField<PVString>("name")->get();
if (codecName == "" && valueSize < uncompressedSize)
return false;
return true;
}
int64 NTNDArray::getExpectedUncompressedSize()
{
int64 size = 0;
PVStructureArrayPtr pvDim = getDimension();
if (pvDim->getLength() != 0)
{
PVStructureArray::const_svector data = pvDim->view();
size = getValueTypeSize();
for (PVStructureArray::const_svector::const_iterator it = data.begin();
it != data.end(); ++it )
{
PVStructurePtr dim = *it;
size *= dim->getSubField<PVInt>("size")->get();
}
}
return size;
}
int64 NTNDArray::getValueSize()
{
int64 size = 0;
PVScalarArrayPtr storedValue = getValue()->get<PVScalarArray>();
if (!storedValue.get())
{
size = storedValue->getLength()*getValueTypeSize();
}
return size;
}
int64 NTNDArray::getValueTypeSize()
{
int64 typeSize = 0;
PVScalarArrayPtr storedValue = getValue()->get<PVScalarArray>();
if (storedValue.get())
{
switch (storedValue->getScalarArray()->getElementType())
{
case pvBoolean:
case pvByte:
case pvUByte:
typeSize = 1;
break;
case pvShort:
case pvUShort:
typeSize = 2;
break;
case pvInt:
case pvUInt:
case pvFloat:
typeSize = 4;
break;
case pvLong:
case pvULong:
case pvDouble:
typeSize = 8;
break;
default:
break;
}
}
return typeSize;
}
NTNDArrayBuilderPtr NTNDArray::createBuilder()
{
return NTNDArrayBuilderPtr(new detail::NTNDArrayBuilder());
@@ -283,6 +506,15 @@ bool NTNDArray::attachAlarm(PVAlarm &pvAlarm) const
return false;
}
bool NTNDArray::attachDisplay(PVDisplay &pvDisplay) const
{
PVStructurePtr dp = getDisplay();
if (dp)
return pvDisplay.attach(dp);
else
return false;
}
PVStructurePtr NTNDArray::getPVStructure() const
{
return pvNTNDArray;
@@ -308,21 +540,26 @@ PVLongPtr NTNDArray::getUncompressedDataSize() const
return pvNTNDArray->getSubField<PVLong>("uncompressedSize");
}
PVStructureArrayPtr NTNDArray::getAttribute() const
{
return pvNTNDArray->getSubField<PVStructureArray>("attribute");
}
PVStructureArrayPtr NTNDArray::getDimension() const
{
return pvNTNDArray->getSubField<PVStructureArray>("dimension");
}
PVIntPtr NTNDArray::getUniqueId() const
{
return pvNTNDArray->getSubField<PVInt>("uniqueId");
}
PVStructurePtr NTNDArray::getDataTimeStamp() const
{
return pvNTNDArray->getSubField<PVStructure>("dataTimeStamp");
}
PVStructureArrayPtr NTNDArray::getAttribute() const
{
return pvNTNDArray->getSubField<PVStructureArray>("attribute");
}
PVStringPtr NTNDArray::getDescriptor() const
{
return pvNTNDArray->getSubField<PVString>("descriptor");

View File

@@ -1,17 +1,32 @@
/* ntndarray.h */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* This software is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#ifndef NTNDARRAY_H
#define NTNDARRAY_H
#include <pv/ntfield.h>
#include <vector>
#include <string>
#ifdef epicsExportSharedSymbols
# define ntscalarArrayEpicsExportSharedSymbols
# undef epicsExportSharedSymbols
#endif
#include <pv/pvDisplay.h>
#include <pv/pvControl.h>
#ifdef ntscalarArrayEpicsExportSharedSymbols
# define epicsExportSharedSymbols
# undef ntscalarArrayEpicsExportSharedSymbols
#endif
#include <pv/ntfield.h>
#include <shareLib.h>
namespace epics { namespace nt {
class NTNDArray;
@@ -20,7 +35,8 @@ typedef std::tr1::shared_ptr<NTNDArray> NTNDArrayPtr;
namespace detail {
/**
* Interface for in-line creating of NTNDArray.
* @brief Interface for in-line creating of NTNDArray.
*
* One instance can be used to create multiple instances.
* An instance of this object must not be used concurrently (an object has a state).
* @author mse
@@ -32,54 +48,55 @@ namespace detail {
POINTER_DEFINITIONS(NTNDArrayBuilder);
/**
* Add descriptor field to the NTNDArray.
* @return this instance of a {@code NTNDArrayBuilder}.
* Adds descriptor field to the NTNDArray.
* @return this instance of <b>NTNDArrayBuilder</b>.
*/
shared_pointer addDescriptor();
/**
* Add alarm structure to the NTNDArray.
* @return this instance of a {@code NTNDArrayBuilder}.
* Adds alarm field to the NTNDArray.
* @return this instance of <b>NTNDArrayBuilder</b>.
*/
shared_pointer addAlarm();
/**
* Add timeStamp structure to the NTNDArray.
* @return this instance of a {@code NTNDArrayBuilder}.
* Adds timeStamp field to the NTNDArray.
* @return this instance of <b>NTNDArrayBuilder</b>.
*/
shared_pointer addTimeStamp();
/**
* Add display structure to the NTNDArray.
* @return this instance of a {@code NTNDArrayBuilder}.
* Adds display field to the NTNDArray.
* @return this instance of <b>NTNDArrayBuilder</b>.
*/
shared_pointer addDisplay();
/**
* Create a {@code Structure} that represents NTNDArray.
* Creates a <b>Structure</b> that represents NTNDArray.
* This resets this instance state and allows new instance to be created.
* @return a new instance of a {@code Structure}.
* @return a new instance of a <b>Structure</b>.
*/
epics::pvData::StructureConstPtr createStructure();
/**
* Create a {@code PVStructure} that represents NTNDArray.
* This resets this instance state and allows new {@code instance to be created.
* @return a new instance of a {@code PVStructure}
* Creates a <b>PVStructure</b> that represents NTNDArray.
* This resets this instance state and allows new instance to be created.
* @return a new instance of a <b>PVStructure</b>
*/
epics::pvData::PVStructurePtr createPVStructure();
/**
* Create a {@code NTNDArray} instance.
* This resets this instance state and allows new {@code instance to be created.
* @return a new instance of a {@code NTNDArray}
* Creates a <b>NTNDArray</b> instance.
* This resets this instance state and allows new instance to be created.
* @return a new instance of a <b>NTNDArray</b>
*/
NTNDArrayPtr create();
/**
* Add extra {@code Field} to the type.
* @param name name of the field.
* @param field a field to add.
* @return this instance of a {@code NTArrayBuilder}.
* Adds extra <b>Field</b> to the type.
* @param name the name of the field.
* @param field the field to be added.
* @return this instance of a <b>NTArrayBuilder</b>.
*/
shared_pointer add(std::string const & name, epics::pvData::FieldConstPtr const & field);
@@ -105,10 +122,11 @@ namespace detail {
typedef std::tr1::shared_ptr<detail::NTNDArrayBuilder> NTNDArrayBuilderPtr;
/**
* Convenience Class for NTNDArray
* @brief Convenience Class for NTNDArray
*
* @author dgh
*/
class NTNDArray
class epicsShareClass NTNDArray
{
public:
POINTER_DEFINITIONS(NTNDArray);
@@ -116,39 +134,91 @@ public:
static const std::string URI;
/**
* Wrap (aka dynamic cast, or wrap) the structure to NTNDArray.
* First isCompatible is called.
* This method will nullptr if the structure is is not compatible.
* This method will nullptr if the structure is nullptr.
* @param structure The structure to wrap-ed (dynamic cast, wrapped) to NTNDArray.
* @return NTNDArray instance on success, nullptr otherwise.
* Creates an NTScalarArray wrapping the specified PVStructure if the latter is compatible.
* <p>
* Checks the supplied PVStructure is compatible with NTScalarArray
* and if so returns an NTScalarArray which wraps it.
* This method will return null if the structure is is not compatible
* or is null.
*
* @param pvStructure the PVStructure to be wrapped
* @return NTScalarArray instance wrapping pvStructure on success, null otherwise
*/
static shared_pointer wrap(epics::pvData::PVStructurePtr const & structure);
static shared_pointer wrap(epics::pvData::PVStructurePtr const & pvStructure);
/**
* Wrap (aka dynamic cast, or wrap) the structure to NTMultiChannel without checking for isCompatible
* @param structure The structure to wrap-ed (dynamic cast, wrapped) to NTNDArray.
* @return NTNDArray instance.
* Creates an NTNDArray wrapping the specified PVStructure, regardless of the latter's compatibility.
* <p>
* No checks are made as to whether the specified PVStructure
* is compatible with NTNDArray or is non-null.
*
* @param pvStructure the PVStructure to be wrapped
* @return NTNDArray instance wrapping pvStructure
*/
static shared_pointer wrapUnsafe(epics::pvData::PVStructurePtr const & structure);
static shared_pointer wrapUnsafe(epics::pvData::PVStructurePtr const & pvStructure);
/**
* Is the structure an NTNDArray.
* @param structure The structure to test.
* @return (false,true) if (is not, is) an NTNDArray.
* Returns whether the specified Structure reports to be a compatible NTNDArray.
* <p>
* Checks if the specified Structure reports compatibility with this
* version of NTNDArray through its type ID, including checking version numbers.
* The return value does not depend on whether the structure is actually
* compatible in terms of its introspection type.
*
* @param structure the pvStructure to test
* @return (false,true) if the specified Structure (is not, is) a compatible NTNDArray
*/
static bool is_a(epics::pvData::StructureConstPtr const & structure);
/**
* Is the pvStructure compatible with NTNDArray..
* This method introspects the fields to see if they are compatible.
* @param pvStructure The pvStructure to test.
* @return (false,true) if (is not, is) an NTMultiChannel.
* Returns whether the specified PVStructure reports to be a compatible NTNDArray.
*
* Checks if the specified PVStructure reports compatibility with this
* version of NTNDArray through its type ID, including checking version numbers.
* The return value does not depend on whether the structure is actually
* compatible in terms of its introspection type.
*
* @param pvStructure the PVStructure to test
* @return (false,true) if the specified PVStructure (is not, is) a compatible NTNDArray
*/
static bool is_a(epics::pvData::PVStructurePtr const & pvStructure);
/**
* Returns whether the specified Structure is compatible with NTNDArray.
* <p>
* Checks if the specified Structure is compatible with this version
* of NTNDArray through the introspection interface.
*
* @param structure the Structure to test
* @return (false,true) if the specified Structure (is not, is) a compatible NTNDArray
*/
static bool isCompatible(
epics::pvData::StructureConstPtr const &structure);
/**
* Returns whether the specified PVStructure is compatible with NTNDArray.
* <p>
* Checks if the specified PVStructure is compatible with this version
* of NTNDArray through the introspection interface.
* @param pvStructure the PVStructure to test
* @return (false,true) if the specified PVStructure (is not, is) a compatible NTNDArray
*/
static bool isCompatible(
epics::pvData::PVStructurePtr const &pvStructure);
/**
* Create a NTNDArrayBuilder instance
* Returns whether the wrapped PVStructure is valid with respect to this
* version of NTNDArray.
* <p>
* Unlike isCompatible(), isValid() may perform checks on the value
* data as well as the introspection data.
*
* @return (false,true) if the wrapped PVStructure (is not, is) a valid NTNDArray
*/
bool isValid();
/**
* Creates an NTNDArrayBuilder instance
* @return builder instance.
*/
static NTNDArrayBuilderPtr createBuilder();
@@ -159,15 +229,15 @@ public:
~NTNDArray() {}
/**
* Attach a pvTimeStamp to timeStamp field.
* @param pvTimeStamp The pvTimeStamp that will be attached.
* Does nothing if no timeStamp.
* Attaches a PVTimeStamp to the wrapped PVStructure.
* Does nothing if no timeStamp field.
* @param pvTimeStamp the PVTimeStamp that will be attached.
* @return true if the operation was successfull (i.e. this instance has a timeStamp field), otherwise false.
*/
bool attachTimeStamp(epics::pvData::PVTimeStamp &pvTimeStamp) const;
/**
* Attach a pvTimeStamp to dataTimeStamp field.
* Attaches a pvTimeStamp to dataTimeStamp field.
* @param pvTimeStamp The pvTimeStamp that will be attached.
* Does nothing if no timeStamp.
* @return true if the operation was successfull (i.e. this instance has a timeStamp field), otherwise false.
@@ -175,93 +245,106 @@ public:
bool attachDataTimeStamp(epics::pvData::PVTimeStamp &pvTimeStamp) const;
/**
* Attach an pvAlarm.
* @param pvAlarm The pvAlarm that will be attached.
* Does nothing if no alarm.
* @return true if the operation was successfull (i.e. this instance has a timeStamp field), otherwise false.
* Attaches a PVAlarm to the wrapped PVStructure.
* Does nothing if no alarm field.
* @param pvAlarm the PVAlarm that will be attached.
* @return true if the operation was successfull (i.e. this instance has an alarm field), otherwise false.
*/
bool attachAlarm(epics::pvData::PVAlarm &pvAlarm) const;
/**
* Get the pvStructure.
* @return PVStructurePtr.
* Returns the PVStructure wrapped by this instance.
* @return the PVStructure wrapped by this instance.
*/
epics::pvData::PVStructurePtr getPVStructure() const;
/**
* Get the value field.
* @return The PVField for the values.
* Returns the value field.
* Returns the value field.
*/
epics::pvData::PVUnionPtr getValue() const;
/**
* Get the codec field.
* @return the PVStructurePtr.
* Returns the codec field.
* @return the codec field.
*/
epics::pvData::PVStructurePtr getCodec() const;
/**
* Get the compressedDataSize field.
* @return PVStructurePtr.
* Returns the compressedDataSize field.
* @return the compressedDataSize field.
*/
epics::pvData::PVLongPtr getCompressedDataSize() const;
/**
* Get the uncompressedDataSize field.
* @return PVStructurePtr.
* Returns the uncompressedDataSize field.
* @return the uncompressedDataSize field.
*/
epics::pvData::PVLongPtr getUncompressedDataSize() const;
/**
* Get the attribute field.
* @return the PVStructurePtr.
*/
epics::pvData::PVStructureArrayPtr getAttribute() const;
/**
* Get the dimension field.
* @return the PVStructurePtr.
* Returns the dimension field.
* @return the dimension field.
*/
epics::pvData::PVStructureArrayPtr getDimension() const;
/**
* Get the uniqueId field.
* @return PVStructurePtr.
* Returns the uniqueId field.
* @return the uniqueId field.
*/
epics::pvData::PVIntPtr getUniqueId() const;
/**
* Get the data timeStamp field.
* @return PVStructurePtr.
* Returns the dataTimeStamp field.
* @return the dataTimeStamp field.
*/
epics::pvData::PVStructurePtr getDataTimeStamp() const;
/**
* Get the descriptor field.
* @return The pvString or null if no function field.
* Returns the attribute field.
* @return the attribute field.
*/
epics::pvData::PVStructureArrayPtr getAttribute() const;
/**
* Returns the descriptor field.
* @return the descriptor field or null if no descriptor field.
*/
epics::pvData::PVStringPtr getDescriptor() const;
/**
* Get the timeStamp field.
* @return PVStructurePtr which may be null.
* Returns the timeStamp field.
* @return the timStamp field or null if no timeStamp field.
*/
epics::pvData::PVStructurePtr getTimeStamp() const;
/**
* Get the alarm field.
* @return PVStructurePtr which may be null.
* Returns the alarm field.
* @return the alarm field or null if no alarm field.
*/
epics::pvData::PVStructurePtr getAlarm() const;
/**
* Get the display field.
* @return PVStructurePtr which may be null.
* Attaches a PVDisplay to the wrapped PVStructure.
* Does nothing if no display.
* @param pvDisplay the PVDisplay that will be attached.
* @return true if the operation was successfull (i.e. this instance has a display field), otherwise false.
*/
bool attachDisplay(epics::pvData::PVDisplay &pvDisplay) const;
/**
* Returns the display field.
* @return PVStructurePtr or null if no alarm field.
*/
epics::pvData::PVStructurePtr getDisplay() const;
private:
NTNDArray(epics::pvData::PVStructurePtr const & pvStructure);
epics::pvData::int64 getExpectedUncompressedSize();
epics::pvData::int64 getValueSize();
epics::pvData::int64 getValueTypeSize();
epics::pvData::PVStructurePtr pvNTNDArray;
friend class detail::NTNDArrayBuilder;

View File

@@ -0,0 +1,237 @@
/* ntndarrayAttribute.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* This software is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#define epicsExportSharedSymbols
#include <pv/ntndarrayAttribute.h>
#include <pv/ntattribute.h>
#include <pv/ntutils.h>
using namespace std;
using namespace epics::pvData;
namespace epics { namespace nt {
static NTFieldPtr ntField = NTField::get();
namespace detail {
StructureConstPtr NTNDArrayAttributeBuilder::createStructure()
{
FieldBuilderPtr builder =
getFieldCreate()->createFieldBuilder()->
setId(NTNDArrayAttribute::URI)->
add("name", pvString)->
add("value", getFieldCreate()->createVariantUnion());
if (tags)
builder->addArray("tags", pvString);
builder->add("descriptor", pvString);
builder->add("sourceType", pvInt);
builder->add("source", pvString);
if (alarm)
builder->add("alarm", ntField->createAlarm());
if (timeStamp)
builder->add("timeStamp", ntField->createTimeStamp());
size_t extraCount = extraFieldNames.size();
for (size_t i = 0; i< extraCount; i++)
builder->add(extraFieldNames[i], extraFields[i]);
StructureConstPtr s = builder->createStructure();
reset();
return s;
}
NTNDArrayAttributeBuilder::shared_pointer NTNDArrayAttributeBuilder::addTags()
{
tags = true;
return shared_from_this();
}
NTNDArrayAttributeBuilder::shared_pointer NTNDArrayAttributeBuilder::addDescriptor()
{
descriptor = true;
return shared_from_this();
}
NTNDArrayAttributeBuilder::shared_pointer NTNDArrayAttributeBuilder::addAlarm()
{
alarm = true;
return shared_from_this();
}
NTNDArrayAttributeBuilder::shared_pointer NTNDArrayAttributeBuilder::addTimeStamp()
{
timeStamp = true;
return shared_from_this();
}
PVStructurePtr NTNDArrayAttributeBuilder::createPVStructure()
{
return getPVDataCreate()->createPVStructure(createStructure());
}
NTNDArrayAttributePtr NTNDArrayAttributeBuilder::create()
{
return NTNDArrayAttributePtr(new NTNDArrayAttribute(createPVStructure()));
}
NTNDArrayAttributeBuilder::NTNDArrayAttributeBuilder()
{
reset();
}
void NTNDArrayAttributeBuilder::reset()
{
descriptor = false;
alarm = false;
timeStamp = false;
extraFieldNames.clear();
extraFields.clear();
}
NTNDArrayAttributeBuilder::shared_pointer NTNDArrayAttributeBuilder::add(string const & name, FieldConstPtr const & field)
{
extraFields.push_back(field); extraFieldNames.push_back(name);
return shared_from_this();
}
}
const std::string NTNDArrayAttribute::URI("epics:nt/NTAttribute:1.0");
NTNDArrayAttribute::shared_pointer NTNDArrayAttribute::wrap(PVStructurePtr const & pvStructure)
{
if(!isCompatible(pvStructure)) return shared_pointer();
return wrapUnsafe(pvStructure);
}
NTNDArrayAttribute::shared_pointer NTNDArrayAttribute::wrapUnsafe(PVStructurePtr const & pvStructure)
{
return shared_pointer(new NTNDArrayAttribute(pvStructure));
}
bool NTNDArrayAttribute::is_a(StructureConstPtr const & structure)
{
return NTUtils::is_a(structure->getID(), URI);
}
bool NTNDArrayAttribute::isCompatible(StructureConstPtr const & structure)
{
if (!NTAttribute::isCompatible(structure)) return false;
// descriptor required field for attibute in an ndarray
ScalarConstPtr descriptorField = structure->getField<Scalar>("descriptor");
if (descriptorField.get() == 0 || descriptorField->getScalarType() != pvString)
return false;
ScalarConstPtr sourcedTypeField = structure->getField<Scalar>("sourceType");
if (sourcedTypeField.get() == 0 || sourcedTypeField->getScalarType() != pvInt)
return false;
ScalarConstPtr sourcedField = structure->getField<Scalar>("source");
if (sourcedField.get() == 0 || sourcedField->getScalarType() != pvString)
return false;
return true;
}
bool NTNDArrayAttribute::isCompatible(PVStructurePtr const & pvStructure)
{
if(!pvStructure) return false;
return isCompatible(pvStructure->getStructure());
}
bool NTNDArrayAttribute::isValid()
{
return true;
}
NTNDArrayAttributeBuilderPtr NTNDArrayAttribute::createBuilder()
{
return NTNDArrayAttributeBuilderPtr(new detail::NTNDArrayAttributeBuilder());
}
bool NTNDArrayAttribute::attachTimeStamp(PVTimeStamp &pvTimeStamp) const
{
PVStructurePtr ts = getTimeStamp();
if (ts)
return pvTimeStamp.attach(ts);
else
return false;
}
bool NTNDArrayAttribute::attachAlarm(PVAlarm &pvAlarm) const
{
PVStructurePtr al = getAlarm();
if (al)
return pvAlarm.attach(al);
else
return false;
}
PVStructurePtr NTNDArrayAttribute::getPVStructure() const
{
return pvNTNDArrayAttribute;
}
PVStringPtr NTNDArrayAttribute::getDescriptor() const
{
return pvNTNDArrayAttribute->getSubField<PVString>("descriptor");
}
PVStructurePtr NTNDArrayAttribute::getTimeStamp() const
{
return pvNTNDArrayAttribute->getSubField<PVStructure>("timeStamp");
}
PVStructurePtr NTNDArrayAttribute::getAlarm() const
{
return pvNTNDArrayAttribute->getSubField<PVStructure>("alarm");
}
PVStringPtr NTNDArrayAttribute::getName() const
{
return pvNTNDArrayAttribute->getSubField<PVString>("name");
}
PVUnionPtr NTNDArrayAttribute::getValue() const
{
return pvValue;
}
PVStringArrayPtr NTNDArrayAttribute::getTags() const
{
return pvNTNDArrayAttribute->getSubField<PVStringArray>("tags");
}
PVIntPtr NTNDArrayAttribute::getSourceType() const
{
return pvNTNDArrayAttribute->getSubField<PVInt>("sourceType");
}
PVStringPtr NTNDArrayAttribute::getSource() const
{
return pvNTNDArrayAttribute->getSubField<PVString>("source");
}
NTNDArrayAttribute::NTNDArrayAttribute(PVStructurePtr const & pvStructure) :
pvNTNDArrayAttribute(pvStructure), pvValue(pvNTNDArrayAttribute->getSubField<PVUnion>("value"))
{
}
}}

313
src/nt/ntndarrayAttribute.h Normal file
View File

@@ -0,0 +1,313 @@
/* ntndarrayAttribute.h */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* This software is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#ifndef NTNDARRAYATTRIBUTE_H
#define NTNDARRAYATTRIBUTE_H
#ifdef epicsExportSharedSymbols
# define ntndarrayAttributeEpicsExportSharedSymbols
# undef epicsExportSharedSymbols
#endif
#ifdef ntndarrayAttributeEpicsExportSharedSymbols
# define epicsExportSharedSymbols
# undef ntndarrayAttributeEpicsExportSharedSymbols
#endif
#include <pv/ntfield.h>
#include <shareLib.h>
namespace epics { namespace nt {
class NTNDArrayAttribute;
typedef std::tr1::shared_ptr<NTNDArrayAttribute> NTNDArrayAttributePtr;
namespace detail {
/**
* @brief Interface for in-line creating of NTAttribute extended as required by NTNDArray
*
* One instance can be used to create multiple instances.
* An instance of this object must not be used concurrently (an object has a state).
* @author dgh
*/
class epicsShareClass NTNDArrayAttributeBuilder :
public std::tr1::enable_shared_from_this<NTNDArrayAttributeBuilder>
{
public:
POINTER_DEFINITIONS(NTNDArrayAttributeBuilder);
/**
* Adds tags field to the NTNDArrayAttribute.
* @return this instance of <b>NTNDArrayAttributeBuilder</b>.
*/
virtual shared_pointer addTags();
/**
* Adds descriptor field to the NTNDArrayAttribute.
* @return this instance of <b>NTNDArrayAttributeBuilder</b>.
*/
shared_pointer addDescriptor();
/**
* Adds alarm field to the NTNDArrayAttribute.
* @return this instance of <b>NTNDArrayAttributeBuilder</b>.
*/
shared_pointer addAlarm();
/**
* Adds timeStamp field to the NTNDArrayAttribute.
* @return this instance of <b>NTNDArrayAttributeBuilder</b>.
*/
shared_pointer addTimeStamp();
/**
* Creates a <b>Structure</b> that represents NTNDArrayAttribute.
* This resets this instance state and allows new instance to be created.
* @return a new instance of a <b>Structure</b>.
*/
epics::pvData::StructureConstPtr createStructure();
/**
* Creates a <b>PVStructure</b> that represents NTNDArrayAttribute.
* This resets this instance state and allows new instance to be created.
* @return a new instance of a <b>PVStructure</b>.
*/
epics::pvData::PVStructurePtr createPVStructure();
/**
* Creates a <b>NTNDArrayAttribute</b> instance.
* This resets this instance state and allows new instance to be created.
* @return a new instance of a <b>NTNDArrayAttribute</b>.
*/
NTNDArrayAttributePtr create();
/**
* Adds extra <b>Field</b> to the type.
* @param name the name of the field.
* @param field the field to be added.
* @return this instance of <b>NTNDArrayAttributeBuilder</b>.
*/
shared_pointer add(std::string const & name, epics::pvData::FieldConstPtr const & field);
protected://private:
NTNDArrayAttributeBuilder();
void reset();
bool tags;
bool descriptor;
bool alarm;
bool timeStamp;
// NOTE: this preserves order, however it does not handle duplicates
epics::pvData::StringArray extraFieldNames;
epics::pvData::FieldConstPtrArray extraFields;
friend class ::epics::nt::NTNDArrayAttribute;
};
}
typedef std::tr1::shared_ptr<detail::NTNDArrayAttributeBuilder> NTNDArrayAttributeBuilderPtr;
/**
* @brief Convenience Class for NTNDArrayAttribute
*
* @author dgh
*/
class epicsShareClass NTNDArrayAttribute
{
public:
POINTER_DEFINITIONS(NTNDArrayAttribute);
static const std::string URI;
/**
* Creates an NTNDArrayAttribute wrapping the specified PVStructure if the latter is compatible.
* <p>
* Checks the supplied PVStructure is compatible with NTAttribute
* extended as required by NTNDArray and if so returns an
* NTNDArrayAttribute which wraps it.
* This method will return null if the structure is is not compatible
* or is null.
*
* @param pvStructure the PVStructure to be wrapped
* @return NTAttribute instance wrapping pvStructure on success, null otherwise
*/
static shared_pointer wrap(epics::pvData::PVStructurePtr const & pvStructure);
/**
* Creates an NTNDArrayAttribute wrapping the specified PVStructure, regardless of the latter's compatibility.
* <p>
* No checks are made as to whether the specified PVStructure
* is compatible with NTAttribute extended as required by NTNDArray
* or is non-null.
*
* @param pvStructure the PVStructure to be wrapped
* @return NTAttribute instance wrapping pvStructure
*/
static shared_pointer wrapUnsafe(epics::pvData::PVStructurePtr const & pvStructure);
/**
* Returns whether the specified Structure reports to be a compatible NTAttribute.
* <p>
* Checks if the specified Structure reports compatibility with this
* version of NTAttribute through its type ID, including checking version numbers.
* The return value does not depend on whether the structure is actually
* compatible in terms of its introspection type.
*
* @param structure the Structure to test
* @return (false,true) if the specified Structure (is not, is) a compatible NTAttribute
*/
static bool is_a(epics::pvData::StructureConstPtr const & structure);
/**
* Returns whether the specified PVStructure reports to be a compatible NTAttribute.
* <p>
* Checks if the specified PVStructure reports compatibility with this
* version of NTAttribute through its type ID, including checking version numbers.
* The return value does not depend on whether the structure is actually
* compatible in terms of its introspection type.
*
* @param pvStructure the PVStructure to test
* @return (false,true) if the specified PVStructure (is not, is) a compatible NTAttribute
*/
static bool is_a(epics::pvData::PVStructurePtr const & pvStructure);
/**
* Returns whether the specified Structure is compatible with NTAttribute
* extended as required by NTNDArray.
* <p>
* Checks if the specified Structure is compatible with this version
* of NTAttribute extended as required by this version of NTNDArray
* through the introspection interface.
*
* @param structure the Structure to test
* @return (false,true) if the specified Structure (is not, is) a compatible NTAttribute
*/
static bool isCompatible(
epics::pvData::StructureConstPtr const &structure);
/**
* Returns whether the specified PVStructure is compatible with NTAttribute
* extended as required by NTNDArray.
* <p>
* Checks if the specified PVStructure is compatible with this version
* of NTAttribute extended as required by this version of NTNDArray
* through the introspection interface.
* @param pvStructure the PVStructure to test
* @return (false,true) if the specified PVStructure (is not, is) a compatible NTAttribute
*/
static bool isCompatible(
epics::pvData::PVStructurePtr const &pvStructure);
/**
* Returns whether the wrapped PVStructure is valid with respect to this
* version of NTAttribute extended as per this version of NTNDArray.
* <p>
* Unlike isCompatible(), isValid() may perform checks on the value
* data as well as the introspection data.
*
* @return (false,true) if the wrapped PVStructure (is not, is) a valid NTNDArrayAttribute
*/
bool isValid();
/**
* Creates an NTNDArrayAttribute builder instance.
* @return builder instance.
*/
static NTNDArrayAttributeBuilderPtr createBuilder();
/**
* Destructor.
*/
~NTNDArrayAttribute() {}
/**
* Attaches a PVTimeStamp to the wrapped PVStructure.
* Does nothing if no timeStamp field.
* @param pvTimeStamp the PVTimeStamp that will be attached.
* @return true if the operation was successfull (i.e. this instance has a timeStamp field), otherwise false.
*/
bool attachTimeStamp(epics::pvData::PVTimeStamp &pvTimeStamp) const;
/**
* Attaches a PVAlarm to the wrapped PVStructure.
* Does nothing if no alarm field.
* @param pvAlarm the PVAlarm that will be attached.
* @return true if the operation was successfull (i.e. this instance has an alarm field), otherwise false.
*/
bool attachAlarm(epics::pvData::PVAlarm &pvAlarm) const;
/**
* Returns the PVStructure wrapped by this instance.
* @return the PVStructure wrapped by this instance.
*/
epics::pvData::PVStructurePtr getPVStructure() const;
/**
* Returns the descriptor field.
* @return the descriptor field.
*/
epics::pvData::PVStringPtr getDescriptor() const;
/**
* Returns the timeStamp field.
* @return the timStamp field or null if no such field.
*/
epics::pvData::PVStructurePtr getTimeStamp() const;
/**
* Returns the alarm field.
* @return the alarm field or null if no alarm field.
*/
epics::pvData::PVStructurePtr getAlarm() const;
/**
* Returns the name field.
* @return the name field.
*/
epics::pvData::PVStringPtr getName() const;
/**
* Returns the value field.
* @return the value field.
*/
epics::pvData::PVUnionPtr getValue() const;
/**
* Returns the tags field.
* @return the tags field or null if no such field.
*/
epics::pvData::PVStringArrayPtr getTags() const;
/**
* Returns the sourceType field.
* @return the sourceType field.
*/
epics::pvData::PVIntPtr getSourceType() const;
/**
* Returns the source field.
* @return the source field.
*/
epics::pvData::PVStringPtr getSource() const;
private:
NTNDArrayAttribute(epics::pvData::PVStructurePtr const & pvStructure);
epics::pvData::PVStructurePtr pvNTNDArrayAttribute;
epics::pvData::PVUnionPtr pvValue;
friend class detail::NTNDArrayAttributeBuilder;
};
}}
#endif /* NTNDARRAYATTRIBUTE_H */

View File

@@ -1,11 +1,13 @@
/* ntscalar.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* This software is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#define epicsExportSharedSymbols
#include <pv/ntscalar.h>
#include <pv/ntutils.h>
using namespace std;
using namespace epics::pvData;
@@ -16,8 +18,6 @@ static NTFieldPtr ntField = NTField::get();
namespace detail {
static NTFieldPtr ntField = NTField::get();
NTScalarBuilder::shared_pointer NTScalarBuilder::value(
epics::pvData::ScalarType scalarType
)
@@ -130,37 +130,69 @@ NTScalarBuilder::shared_pointer NTScalarBuilder::add(string const & name, FieldC
const std::string NTScalar::URI("epics:nt/NTScalar:1.0");
NTScalar::shared_pointer NTScalar::wrap(PVStructurePtr const & structure)
NTScalar::shared_pointer NTScalar::wrap(PVStructurePtr const & pvStructure)
{
if(!isCompatible(structure)) return shared_pointer();
return wrapUnsafe(structure);
if(!isCompatible(pvStructure)) return shared_pointer();
return wrapUnsafe(pvStructure);
}
NTScalar::shared_pointer NTScalar::wrapUnsafe(PVStructurePtr const & structure)
NTScalar::shared_pointer NTScalar::wrapUnsafe(PVStructurePtr const & pvStructure)
{
return shared_pointer(new NTScalar(structure));
return shared_pointer(new NTScalar(pvStructure));
}
bool NTScalar::is_a(StructureConstPtr const & structure)
{
return structure->getID() == URI;
return NTUtils::is_a(structure->getID(), URI);
}
bool NTScalar::isCompatible(StructureConstPtr const &structure)
{
if (structure.get() == 0) return false;
ScalarConstPtr valueField = structure->getField<Scalar>("value");
if (valueField.get() == 0)
return false;
FieldConstPtr field = structure->getField("descriptor");
if (field.get())
{
ScalarConstPtr descriptorField = structure->getField<Scalar>("descriptor");
if (!descriptorField.get() || descriptorField->getScalarType() != pvString)
return false;
}
NTFieldPtr ntField = NTField::get();
field = structure->getField("alarm");
if (field.get() && !ntField->isAlarm(field))
return false;
field = structure->getField("timeStamp");
if (field.get() && !ntField->isTimeStamp(field))
return false;
field = structure->getField("display");
if (field.get() && !ntField->isDisplay(field))
return false;
field = structure->getField("control");
if (field.get() && !ntField->isControl(field))
return false;
return true;
}
bool NTScalar::isCompatible(PVStructurePtr const & pvStructure)
{
if(!pvStructure) return false;
PVScalarPtr pvValue = pvStructure->getSubField<PVScalar>("value");
if(!pvValue) return false;
PVFieldPtr pvField = pvStructure->getSubField("descriptor");
if(pvField && !pvStructure->getSubField<PVString>("descriptor")) return false;
pvField = pvStructure->getSubField("alarm");
if(pvField && !ntField->isAlarm(pvField->getField())) return false;
pvField = pvStructure->getSubField("timeStamp");
if(pvField && !ntField->isTimeStamp(pvField->getField())) return false;
pvField = pvStructure->getSubField("display");
if(pvField && !ntField->isDisplay(pvField->getField())) return false;
pvField = pvStructure->getSubField("control");
if(pvField && !ntField->isControl(pvField->getField())) return false;
return isCompatible(pvStructure->getStructure());
}
bool NTScalar::isValid()
{
return true;
}

View File

@@ -1,16 +1,29 @@
/* ntscalar.h */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* This software is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#ifndef NTSCALAR_H
#define NTSCALAR_H
#include <pv/ntfield.h>
#ifdef epicsExportSharedSymbols
# define ntscalarEpicsExportSharedSymbols
# undef epicsExportSharedSymbols
#endif
#include <pv/pvDisplay.h>
#include <pv/pvControl.h>
#ifdef ntscalarEpicsExportSharedSymbols
# define epicsExportSharedSymbols
# undef ntscalarEpicsExportSharedSymbols
#endif
#include <pv/ntfield.h>
#include <shareLib.h>
namespace epics { namespace nt {
class NTScalar;
@@ -19,7 +32,8 @@ typedef std::tr1::shared_ptr<NTScalar> NTScalarPtr;
namespace detail {
/**
* Interface for in-line creating of NTScalar.
* @brief Interface for in-line creating of NTScalar.
*
* One instance can be used to create multiple instances.
* An instance of this object must not be used concurrently (an object has a state).
* @author mse
@@ -31,67 +45,68 @@ namespace detail {
POINTER_DEFINITIONS(NTScalarBuilder);
/**
* Set a value type of a NTScalar.
* Sets the value type of an NTScalar.
* @param scalarType the value type.
* @return this instance of a {@code NTTableBuilder}.
* @return this instance of <b>NTScalarBuilder</b>.
*/
shared_pointer value(epics::pvData::ScalarType scalarType);
/**
* Add descriptor field to the NTScalar.
* @return this instance of a {@code NTScalarBuilder}.
* Adds descriptor field to the NTScalar.
* @return this instance of <b>NTScalarBuilder</b>.
*/
shared_pointer addDescriptor();
/**
* Add alarm structure to the NTScalar.
* @return this instance of a {@code NTScalarBuilder}.
* Adds alarm field to the NTScalar.
* @return this instance of <b>NTScalarBuilder</b>.
*/
shared_pointer addAlarm();
/**
* Add timeStamp structure to the NTScalar.
* @return this instance of a {@code NTScalarBuilder}.
* Adds timeStamp field to the NTScalar.
* @return this instance of <b>NTScalarBuilder</b>.
*/
shared_pointer addTimeStamp();
/**
* Add display structure to the NTScalar.
* @return this instance of a {@code NTScalarBuilder}.
* Adds display field to the NTScalar.
* @return this instance of <b>NTScalarBuilder</b>.
*/
shared_pointer addDisplay();
/**
* Add control structure to the NTScalar.
* @return this instance of a {@code NTScalarBuilder}.
* Adds control field to the NTScalar.
* @return this instance of <b>NTScalarBuilder</b>.
*/
shared_pointer addControl();
/**
* Create a {@code Structure} that represents NTScalar.
* Creates a <b>Structure</b> that represents NTScalar.
* This resets this instance state and allows new instance to be created.
* @return a new instance of a {@code Structure}.
* @return a new instance of a <b>Structure</b>.
*/
epics::pvData::StructureConstPtr createStructure();
/**
* Create a {@code PVStructure} that represents NTScalar.
* This resets this instance state and allows new {@code instance to be created.
* @return a new instance of a {@code PVStructure}
* Creates a <b>PVStructure</b> that represents NTScalar.
* This resets this instance state and allows new instance to be created.
* @return a new instance of a <b>PVStructure</b>.
*/
epics::pvData::PVStructurePtr createPVStructure();
/**
* Create a {@code NTScalar} instance.
* This resets this instance state and allows new {@code instance to be created.
* @return a new instance of a {@code NTScalar}
* Creates a <b>NTScalar</b> instance.
* This resets this instance state and allows new instance to be created.
* @return a new instance of a <b>NTScalar</b>.
*/
NTScalarPtr create();
/**
* Add extra {@code Field} to the type.
* @param name name of the field.
* @param field a field to add.
* @return this instance of a {@code NTScalarBuilder}.
* Adds extra <b>Field</b> to the type.
* @param name the name of the field.
* @param field the field to be added.
* @return this instance of <b>NTScalarBuilder</b>.
*/
shared_pointer add(std::string const & name, epics::pvData::FieldConstPtr const & field);
@@ -123,10 +138,11 @@ typedef std::tr1::shared_ptr<detail::NTScalarBuilder> NTScalarBuilderPtr;
/**
* Convenience Class for NTScalar
* @brief Convenience Class for NTScalar
*
* @author mrk
*/
class NTScalar
class epicsShareClass NTScalar
{
public:
POINTER_DEFINITIONS(NTScalar);
@@ -134,38 +150,92 @@ public:
static const std::string URI;
/**
* Wrap (aka dynamic cast, or wrap) the structure to NTScalar.
* First isCompatible is called.
* This method will nullptr if the structure is is not compatible.
* This method will nullptr if the structure is nullptr.
* @param structure The structure to wrap-ed (dynamic cast, wrapped) to NTScalar.
* @return NTScalar instance on success, nullptr otherwise.
* Creates an NTScalar wrapping the specified PVStructure if the latter is compatible.
* <p>
* Checks the supplied PVStructure is compatible with NTScalar
* and if so returns an NTScalar which wraps it.
* This method will return null if the structure is is not compatible
* or is null.
*
* @param pvStructure the PVStructure to be wrapped
* @return NTScalar instance wrapping pvStructure on success, null otherwise
*/
static shared_pointer wrap(epics::pvData::PVStructurePtr const & structure);
static shared_pointer wrap(epics::pvData::PVStructurePtr const & pvStructure);
/**
* Wrap (aka dynamic cast, or wrap) the structure to NTMultiChannel without checking for isCompatible
* @param structure The structure to wrap-ed (dynamic cast, wrapped) to NTScalar.
* @return NTScalar instance.
* Creates an NTScalar wrapping the specified PVStructure, regardless of the latter's compatibility.
* <p>
* No checks are made as to whether the specified PVStructure
* is compatible with NTScalar or is non-null.
*
* @param pvStructure the PVStructure to be wrapped
* @return NTScalar instance wrapping pvStructure
*/
static shared_pointer wrapUnsafe(epics::pvData::PVStructurePtr const & structure);
static shared_pointer wrapUnsafe(epics::pvData::PVStructurePtr const & pvStructure);
/**
* Is the structure an NTScalar.
* @param structure The structure to test.
* @return (false,true) if (is not, is) an NTScalar.
* Returns whether the specified Structure reports to be a compatible NTScalar.
* <p>
* Checks if the specified Structure reports compatibility with this
* version of NTScalar through its type ID, including checking version numbers.
* The return value does not depend on whether the structure is actually
* compatible in terms of its introspection type.
*
* @param structure the Structure to test
* @return (false,true) if the specified Structure (is not, is) a compatible NTScalar
*/
static bool is_a(epics::pvData::StructureConstPtr const & structure);
/**
* Is the pvStructure compatible with NTScalar.
* This method introspects the fields to see if they are compatible.
* @param pvStructure The pvStructure to test.
* @return (false,true) if (is not, is) an NTMultiChannel.
* Returns whether the specified PVStructure reports to be a compatible NTScalar.
* <p>
* Checks if the specified PVStructure reports compatibility with this
* version of NTScalar through its type ID, including checking version numbers.
* The return value does not depend on whether the structure is actually
* compatible in terms of its introspection type.
*
* @param pvStructure the PVStructure to test
* @return (false,true) if the specified PVStructure (is not, is) a compatible NTScalar
*/
static bool is_a(epics::pvData::PVStructurePtr const & pvStructure);
/**
* Returns whether the specified Structure is compatible with NTScalar.
* <p>
* Checks if the specified Structure is compatible with this version
* of NTScalar through the introspection interface.
*
* @param structure the Structure to test
* @return (false,true) if the specified Structure (is not, is) a compatible NTScalar
*/
static bool isCompatible(
epics::pvData::StructureConstPtr const &structure);
/**
* Returns whether the specified PVStructure is compatible with NTScalar.
* <p>
* Checks if the specified PVStructure is compatible with this version
* of NTScalar through the introspection interface.
*
* @param pvStructure the PVStructure to test
* @return (false,true) if the specified PVStructure (is not, is) a compatible NTScalar
*/
static bool isCompatible(
epics::pvData::PVStructurePtr const &pvStructure);
/**
* Create a NTScalar builder instance.
* Returns whether the wrapped PVStructure is valid with respect to this
* version of NTScalar.
* <p>
* Unlike isCompatible(), isValid() may perform checks on the value
* data as well as the introspection data.
*
* @return (false,true) if wrapped PVStructure (is not, is) a valid NTScalar
*/
bool isValid();
/**
* Creates an NTScalar builder instance.
* @return builder instance.
*/
static NTScalarBuilderPtr createBuilder();
@@ -176,82 +246,84 @@ public:
~NTScalar() {}
/**
* Attach a pvTimeStamp.
* @param pvTimeStamp The pvTimeStamp that will be attached.
* Does nothing if no timeStamp.
* Attaches a PVTimeStamp to the wrapped PVStructure.
* Does nothing if no timeStamp field.
* @param pvTimeStamp the PVTimeStamp that will be attached.
* @return true if the operation was successfull (i.e. this instance has a timeStamp field), otherwise false.
*/
bool attachTimeStamp(epics::pvData::PVTimeStamp &pvTimeStamp) const;
/**
* Attach an pvAlarm.
* @param pvAlarm The pvAlarm that will be attached.
* Does nothing if no alarm.
* @return true if the operation was successfull (i.e. this instance has a timeStamp field), otherwise false.
* Attaches a PVAlarm to the wrapped PVStructure.
* Does nothing if no alarm field.
* @param pvAlarm the PVAlarm that will be attached.
* @return true if the operation was successfull (i.e. this instance has an alarm field), otherwise false.
*/
bool attachAlarm(epics::pvData::PVAlarm &pvAlarm) const;
/**
* Attach an pvDisplay.
* @param pvDisplay The pvDisplay that will be attached.
* Does nothing if no display.
* @return true if the operation was successfull (i.e. this instance has a display field), otherwise false.
* Attaches a PVDisplay to the wrapped PVStructure.
* Does nothing if no display field.
* @param pvDisplay the PVDisplay that will be attached.
* @return true if the operation was successfull (i.e. this instance has a display field), otherwise false.
*/
bool attachDisplay(epics::pvData::PVDisplay &pvDisplay) const;
/**
* Attach an pvControl.
* @param pvControl The pvControl that will be attached.
* Does nothing if no control.
* @return true if the operation was successfull (i.e. this instance has a control field), otherwise false.
* Attaches an PVControl to the wrapped PVStructure.
* Does nothing if no control field.
* @param pvControl The PVControl that will be attached.
* @return true if the operation was successfull (i.e. this instance has a control field), otherwise false.
*/
bool attachControl(epics::pvData::PVControl &pvControl) const;
/**
* Get the pvStructure.
* @return PVStructurePtr.
* Returns the PVStructure wrapped by this instance.
* @return the PVStructure wrapped by this instance.
*/
epics::pvData::PVStructurePtr getPVStructure() const;
/**
* Get the descriptor field.
* @return The pvString or null if no function field.
* Returns the descriptor field.
* @return the descriptor field or null if no descriptor field.
*/
epics::pvData::PVStringPtr getDescriptor() const;
/**
* Get the timeStamp.
* @return PVStructurePtr which may be null.
* Returns the timeStamp field.
* @return the timStamp field or null if no timeStamp field.
*/
epics::pvData::PVStructurePtr getTimeStamp() const;
/**
* Get the alarm.
* @return PVStructurePtr which may be null.
* Returns the alarm field.
* @return the alarm field or null if no alarm field.
*/
epics::pvData::PVStructurePtr getAlarm() const;
/**
* Get the display.
* Returns the display.
* @return PVStructurePtr which may be null.
*/
epics::pvData::PVStructurePtr getDisplay() const;
/**
* Get the control.
* Returns the control.
* @return PVStructurePtr which may be null.
*/
epics::pvData::PVStructurePtr getControl() const;
/**
* Get the value field.
* Returns the value field.
* @return The PVField for the values.
*/
epics::pvData::PVFieldPtr getValue() const;
/**
* Get the value field of a specified type (e.g. PVDouble).
* @return The <PVT> field for the values.
* Returns the value field of a specified type (for example, PVDouble).
* @tparam PVT the expected type of the value field which should be
* be PVScalar or a derived class.
* @return the value field or null if it is not of the expected type.
*/
template<typename PVT>
std::tr1::shared_ptr<PVT> getValue() const
@@ -268,4 +340,4 @@ private:
};
}}
#endif /* NTScalar_H */
#endif /* NTSCALAR_H */

View File

@@ -1,11 +1,13 @@
/* ntscalarArray.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* This software is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#define epicsExportSharedSymbols
#include <pv/ntscalarArray.h>
#include <pv/ntutils.h>
using namespace std;
using namespace epics::pvData;
@@ -16,6 +18,16 @@ static NTFieldPtr ntField = NTField::get();
namespace detail {
NTScalarArrayBuilder::shared_pointer NTScalarArrayBuilder::value(
epics::pvData::ScalarType elementType
)
{
valueType = elementType;
valueTypeSet = true;
return shared_from_this();
}
NTScalarArrayBuilder::shared_pointer NTScalarArrayBuilder::arrayValue(
epics::pvData::ScalarType elementType
)
@@ -127,40 +139,70 @@ NTScalarArrayBuilder::shared_pointer NTScalarArrayBuilder::add(string const & na
const std::string NTScalarArray::URI("epics:nt/NTScalarArray:1.0");
NTScalarArray::shared_pointer NTScalarArray::wrap(PVStructurePtr const & structure)
NTScalarArray::shared_pointer NTScalarArray::wrap(PVStructurePtr const & pvStructure)
{
if(!isCompatible(structure)) return shared_pointer();
return wrapUnsafe(structure);
if(!isCompatible(pvStructure)) return shared_pointer();
return wrapUnsafe(pvStructure);
}
NTScalarArray::shared_pointer NTScalarArray::wrapUnsafe(PVStructurePtr const & structure)
NTScalarArray::shared_pointer NTScalarArray::wrapUnsafe(PVStructurePtr const & pvStructure)
{
return shared_pointer(new NTScalarArray(structure));
return shared_pointer(new NTScalarArray(pvStructure));
}
bool NTScalarArray::is_a(StructureConstPtr const & structure)
{
return structure->getID() == URI;
return NTUtils::is_a(structure->getID(), URI);
}
bool NTScalarArray::isCompatible(StructureConstPtr const & structure)
{
if (structure.get() == 0) return false;
ScalarArrayConstPtr valueField = structure->getField<ScalarArray>("value");
if (valueField.get() == 0)
return false;
FieldConstPtr field = structure->getField("descriptor");
if (field.get())
{
ScalarConstPtr descriptorField = structure->getField<Scalar>("descriptor");
if (!descriptorField.get() || descriptorField->getScalarType() != pvString)
return false;
}
NTFieldPtr ntField = NTField::get();
field = structure->getField("alarm");
if (field.get() && !ntField->isAlarm(field))
return false;
field = structure->getField("timeStamp");
if (field.get() && !ntField->isTimeStamp(field))
return false;
field = structure->getField("display");
if (field.get() && !ntField->isDisplay(field))
return false;
field = structure->getField("control");
if (field.get() && !ntField->isControl(field))
return false;
return true;
}
bool NTScalarArray::isCompatible(PVStructurePtr const & pvStructure)
{
if(!pvStructure) return false;
PVScalarArrayPtr pvValue = pvStructure->getSubField<PVScalarArray>("value");
if(!pvValue) return false;
PVFieldPtr pvField = pvStructure->getSubField("descriptor");
if(pvField && !pvStructure->getSubField<PVString>("descriptor")) return false;
pvField = pvStructure->getSubField("alarm");
if(pvField && !ntField->isAlarm(pvField->getField())) return false;
pvField = pvStructure->getSubField("timeStamp");
if(pvField && !ntField->isTimeStamp(pvField->getField())) return false;
pvField = pvStructure->getSubField("display");
if(pvField && !ntField->isDisplay(pvField->getField())) return false;
pvField = pvStructure->getSubField("control");
if(pvField && !ntField->isControl(pvField->getField())) return false;
return true;
return isCompatible(pvStructure->getStructure());
}
bool NTScalarArray::isValid()
{
return true;
}
NTScalarArrayBuilderPtr NTScalarArray::createBuilder()
{

View File

@@ -1,16 +1,30 @@
/* ntscalarArray.h */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* This software is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#ifndef NTSCALARARRAY_H
#define NTSCALARARRAY_H
#include <pv/ntfield.h>
#ifdef epicsExportSharedSymbols
# define ntscalarArrayEpicsExportSharedSymbols
# undef epicsExportSharedSymbols
#endif
#include <pv/pvDisplay.h>
#include <pv/pvControl.h>
#ifdef ntscalarArrayEpicsExportSharedSymbols
# define epicsExportSharedSymbols
# undef ntscalarArrayEpicsExportSharedSymbols
#endif
#include <pv/ntfield.h>
#include <shareLib.h>
namespace epics { namespace nt {
class NTScalarArray;
@@ -19,7 +33,8 @@ typedef std::tr1::shared_ptr<NTScalarArray> NTScalarArrayPtr;
namespace detail {
/**
* Interface for in-line creating of NTScalarArray.
* @brief Interface for in-line creating of NTScalarArray.
*
* One instance can be used to create multiple instances.
* An instance of this object must not be used concurrently (an object has a state).
* @author mse
@@ -31,67 +46,76 @@ namespace detail {
POINTER_DEFINITIONS(NTScalarArrayBuilder);
/**
* Set a value type of a NTScalarArray.
* @param elementType the value array element type.
* @return this instance of a {@code NTTableBuilder}.
* Sets the value type of the NTScalarArray.
* @param elementType the value field element ScalarType.
* @return this instance of <b>NTScalarArrayBuilder</b>.
*/
shared_pointer value(epics::pvData::ScalarType elementType);
/**
* Sets the value type of the NTScalarArray.
* @param elementType the value field element ScalarType.
* @return this instance of <b>NTScalarArrayBuilder</b>.
* @deprecated use value instead.
*/
shared_pointer arrayValue(epics::pvData::ScalarType elementType);
/**
* Add descriptor field to the NTScalarArray.
* @return this instance of a {@code NTScalarArrayBuilder}.
* Adds descriptor field to the NTScalarArray.
* @return this instance of <b>NTScalarArrayBuilder</b>.
*/
shared_pointer addDescriptor();
/**
* Add alarm structure to the NTScalarArray.
* @return this instance of a {@code NTScalarArrayBuilder}.
* Adds alarm field to the NTScalarArray.
* @return this instance of <b>NTScalarArrayBuilder</b>.
*/
shared_pointer addAlarm();
/**
* Add timeStamp structure to the NTScalarArray.
* @return this instance of a {@code NTScalarArrayBuilder}.
* Adds timeStamp field to the NTScalarArray.
* @return this instance of <b>NTScalarArrayBuilder</b>.
*/
shared_pointer addTimeStamp();
/**
* Add display structure to the NTScalarArray.
* @return this instance of a {@code NTScalarArrayBuilder}.
* Adds display field to the NTScalarArray.
* @return this instance of <b>NTScalarArrayBuilder</b>.
*/
shared_pointer addDisplay();
/**
* Add control structure to the NTScalarArray.
* @return this instance of a {@code NTScalarArrayBuilder}.
* Adds control field to the NTScalarArray.
* @return this instance of <b>NTScalarArrayBuilder</b>.
*/
shared_pointer addControl();
/**
* Create a {@code Structure} that represents NTScalarArray.
* Creates a <b>Structure</b> that represents NTScalarArray.
* This resets this instance state and allows new instance to be created.
* @return a new instance of a {@code Structure}.
* @return a new instance of <b>Structure</b>.
*/
epics::pvData::StructureConstPtr createStructure();
/**
* Create a {@code PVStructure} that represents NTScalarArray.
* This resets this instance state and allows new {@code instance to be created.
* @return a new instance of a {@code PVStructure}
* Creates a <b>PVStructure</b> that represents NTScalarArray.
* This resets this instance state and allows new instance to be created.
* @return a new instance of <b>PVStructure</b>.
*/
epics::pvData::PVStructurePtr createPVStructure();
/**
* Create a {@code NTScalarArray} instance.
* This resets this instance state and allows new {@code instance to be created.
* @return a new instance of a {@code NTScalarArray}
* Creates a <b>NTScalarArray</b> instance.
* This resets this instance state and allows new instance to be created.
* @return a new instance of <b>NTScalarArray</b>.
*/
NTScalarArrayPtr create();
/**
* Add extra {@code Field} to the type.
* @param name name of the field.
* @param field a field to add.
* @return this instance of a {@code NTScalarArrayBuilder}.
* Adds extra <b>Field</b> to the type.
* @param name the name of the field.
* @param field the field to be added.
* @return this instance of <b>NTScalarArrayBuilder</b>.
*/
shared_pointer add(std::string const & name, epics::pvData::FieldConstPtr const & field);
@@ -123,10 +147,11 @@ typedef std::tr1::shared_ptr<detail::NTScalarArrayBuilder> NTScalarArrayBuilderP
/**
* Convenience Class for NTScalarArray
* @brief Convenience Class for NTScalarArray
*
* @author mrk
*/
class NTScalarArray
class epicsShareClass NTScalarArray
{
public:
POINTER_DEFINITIONS(NTScalarArray);
@@ -134,40 +159,91 @@ public:
static const std::string URI;
/**
* Wrap (aka dynamic cast, or wrap) the structure to NTScalarArray.
* First isCompatible is called.
* This method will nullptr if the structure is is not compatible.
* This method will nullptr if the structure is nullptr.
* @param structure The structure to wrap-ed (dynamic cast, wrapped) to NTScalarArray.
* @return NTScalarArray instance on success, nullptr otherwise.
* Creates an NTScalarArray wrapping the specified PVStructure if the latter is compatible.
* <p>
* Checks the supplied PVStructure is compatible with NTScalarArray
* and if so returns an NTScalarArray which wraps it.
* This method will return null if the structure is is not compatible
* or is null.
*
* @param pvStructure the PVStructure to be wrapped
* @return NTScalarArray instance wrapping pvStructure on success, null otherwise
*/
static shared_pointer wrap(epics::pvData::PVStructurePtr const & structure);
static shared_pointer wrap(epics::pvData::PVStructurePtr const & pvStructure);
/**
* Wrap (aka dynamic cast, or wrap) the structure to NTMultiChannel without checking for isCompatible
* @param structure The structure to wrap-ed (dynamic cast, wrapped) to NTScalarArray.
* @return NTScalarArray instance.
* Creates an NTScalarArray wrapping the specified PVStructure, regardless of the latter's compatibility.
* <p>
* No checks are made as to whether the specified PVStructure
* is compatible with NTScalarArray or is non-null.
*
* @param pvStructure the PVStructure to be wrapped
* @return NTScalarArray instance wrapping pvStructure
*/
static shared_pointer wrapUnsafe(epics::pvData::PVStructurePtr const & structure);
static shared_pointer wrapUnsafe(epics::pvData::PVStructurePtr const & pvStructure);
/**
* Is the structure an NTScalarArray.
* @param structure The structure to test.
* @return (false,true) if (is not, is) an NTScalarArray.
* Returns whether the specified Structure reports to be a compatible NTScalarArray.
* <p>
* Checks if the specified Structure reports compatibility with this
* version of NTScalarArray through its type ID, including checking version numbers.
* The return value does not depend on whether the structure is actually
* compatible in terms of its introspection type.
*
* @param structure the Structure to test
* @return (false,true) if the specified Structure (is not, is) a compatible NTScalarArray
*/
static bool is_a(epics::pvData::StructureConstPtr const & structure);
/**
* Is the pvStructure compatible with NTScalarArray..
* This method introspects the fields to see if they are compatible.
* @param pvStructure The pvStructure to test.
* @return (false,true) if (is not, is) an NTMultiChannel.
* Returns whether the specified PVStructure reports to be a compatible NTScalarArray.
* <p>
* Checks if the specified PVStructure reports compatibility with this
* version of NTScalarArray through its type ID, including checking version numbers.
* The return value does not depend on whether the structure is actually
* compatible in terms of its introspection type.
*
* @param pvStructure the PVStructure to test
* @return (false,true) if the specified PVStructure (is not, is) a compatible NTScalarArray
*/
static bool is_a(epics::pvData::PVStructurePtr const & pvStructure);
/**
* Returns whether the specified Structure is compatible with NTScalarArray.
* <p>
* Checks if the specified Structure is compatible with this version
* of NTScalarArray through the introspection interface.
*
* @param structure the Structure to test.
* @return (false,true) if the specified Structure (is not, is) a compatible NTScalarArray
*/
static bool isCompatible(
epics::pvData::StructureConstPtr const &structure);
/**
* Returns whether the specified PVStructure is compatible with NTScalarArray.
* <p>
* Checks if the specified PVStructure is compatible with this version
* of NTScalarArray through the introspection interface.
*
* @param pvStructure the PVStructure to test
* @return (false,true) if the specified PVStructure (is not, is) a compatible NTScalarArray
*/
static bool isCompatible(
epics::pvData::PVStructurePtr const &pvStructure);
/**
* Create a NTScalarArray builder instance.
* Returns whether the wrapped PVStructure is a valid NTScalarArray.
* <p>
* Unlike isCompatible(), isValid() may perform checks on the value
* data as well as the introspection data.
*
* @return (false,true) if the wrapped PVStructure (is not, is) a valid NTScalarArray.
*/
bool isValid();
/**
* Creates an NTScalarArray builder instance.
* @return builder instance.
*/
static NTScalarArrayBuilderPtr createBuilder();
@@ -178,82 +254,84 @@ public:
~NTScalarArray() {}
/**
* Attach a pvTimeStamp.
* @param pvTimeStamp The pvTimeStamp that will be attached.
* Does nothing if no timeStamp.
* Attaches a PVTimeStamp to the wrapped PVStructure.
* Does nothing if no timeStamp field.
* @param pvTimeStamp the PVTimeStamp that will be attached.
* @return true if the operation was successfull (i.e. this instance has a timeStamp field), otherwise false.
*/
bool attachTimeStamp(epics::pvData::PVTimeStamp &pvTimeStamp) const;
/**
* Attach an pvAlarm.
* @param pvAlarm The pvAlarm that will be attached.
* Does nothing if no alarm.
* @return true if the operation was successfull (i.e. this instance has a timeStamp field), otherwise false.
* Attaches a PVAlarm to the wrapped PVStructure.
* Does nothing if no alarm field.
* @param pvAlarm the PVAlarm that will be attached.
* @return true if the operation was successfull (i.e. this instance has an alarm field), otherwise false.
*/
bool attachAlarm(epics::pvData::PVAlarm &pvAlarm) const;
/**
* Attach an pvDisplay.
* @param pvDisplay The pvDisplay that will be attached.
* Does nothing if no display.
* @return true if the operation was successfull (i.e. this instance has a display field), otherwise false.
* Attaches a PVDisplay to the wrapped PVStructure.
* Does nothing if no display field.
* @param pvDisplay the PVDisplay that will be attached.
* @return true if the operation was successfull (i.e. this instance has a display field), otherwise false.
*/
bool attachDisplay(epics::pvData::PVDisplay &pvDisplay) const;
/**
* Attach an pvControl.
* Attaches an pvControl.
* @param pvControl The pvControl that will be attached.
* Does nothing if no control.
* Does nothing if no control field.
* @return true if the operation was successfull (i.e. this instance has a control field), otherwise false.
*/
bool attachControl(epics::pvData::PVControl &pvControl) const;
/**
* Get the pvStructure.
* @return PVStructurePtr.
* Returns the PVStructure wrapped by this instance.
* @return the PVStructure wrapped by this instance.
*/
epics::pvData::PVStructurePtr getPVStructure() const;
/**
* Get the descriptor field.
* @return The pvString or null if no function field.
* Returns the descriptor field.
* @return the descriptor field or null if no descriptor field.
*/
epics::pvData::PVStringPtr getDescriptor() const;
/**
* Get the timeStamp.
* @return PVStructurePtr which may be null.
* Returns the timeStamp field.
* @return the timStamp field or null if no timeStamp field.
*/
epics::pvData::PVStructurePtr getTimeStamp() const;
/**
* Get the alarm.
* @return PVStructurePtr which may be null.
* Returns the alarm field.
* @return the alarm field or null if no alarm field.
*/
epics::pvData::PVStructurePtr getAlarm() const;
/**
* Get the display.
* Returns the display.
* @return PVStructurePtr which may be null.
*/
epics::pvData::PVStructurePtr getDisplay() const;
/**
* Get the control.
* Returns the control.
* @return PVStructurePtr which may be null.
*/
epics::pvData::PVStructurePtr getControl() const;
/**
* Get the value field.
* Returns the value field.
* @return The PVField for the values.
*/
epics::pvData::PVFieldPtr getValue() const;
/**
* Get the value field of a specified type (e.g. PVDoubleArray).
* @return The <PVT> field for the values.
* Returns the value field of a specified type (e.g. PVDoubleArray).
* @tparam PVT the expected type of the value field which should be
* be PVScalarArray or a derived class.
* @return the value field or null if it is not of the expected type.
*/
template<typename PVT>
std::tr1::shared_ptr<PVT> getValue() const
@@ -270,4 +348,4 @@ private:
};
}}
#endif /* NTScalarArray_H */
#endif /* NTSCALARARRAY_H */

View File

@@ -0,0 +1,377 @@
/* ntscalarMultiChannel.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* This software is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#include <algorithm>
#define epicsExportSharedSymbols
#include <pv/ntscalarMultiChannel.h>
#include <pv/ntutils.h>
using namespace std;
using namespace epics::pvData;
namespace epics { namespace nt {
static FieldCreatePtr fieldCreate = getFieldCreate();
static PVDataCreatePtr pvDataCreate = getPVDataCreate();
static NTFieldPtr ntField = NTField::get();
namespace detail {
NTScalarMultiChannelBuilder::shared_pointer NTScalarMultiChannelBuilder::value(ScalarType scalarType)
{
valueType = scalarType;
return shared_from_this();
}
NTScalarMultiChannelBuilder::shared_pointer NTScalarMultiChannelBuilder::addDescriptor()
{
descriptor = true;
return shared_from_this();
}
NTScalarMultiChannelBuilder::shared_pointer NTScalarMultiChannelBuilder::addAlarm()
{
alarm = true;
return shared_from_this();
}
NTScalarMultiChannelBuilder::shared_pointer NTScalarMultiChannelBuilder::addTimeStamp()
{
timeStamp = true;
return shared_from_this();
}
NTScalarMultiChannelBuilder::shared_pointer NTScalarMultiChannelBuilder::addSeverity()
{
severity = true;
return shared_from_this();
}
NTScalarMultiChannelBuilder::shared_pointer NTScalarMultiChannelBuilder::addStatus()
{
status = true;
return shared_from_this();
}
NTScalarMultiChannelBuilder::shared_pointer NTScalarMultiChannelBuilder::addMessage()
{
message = true;
return shared_from_this();
}
NTScalarMultiChannelBuilder::shared_pointer NTScalarMultiChannelBuilder::addSecondsPastEpoch()
{
secondsPastEpoch = true;
return shared_from_this();
}
NTScalarMultiChannelBuilder::shared_pointer NTScalarMultiChannelBuilder::addNanoseconds()
{
nanoseconds = true;
return shared_from_this();
}
NTScalarMultiChannelBuilder::shared_pointer NTScalarMultiChannelBuilder::addUserTag()
{
userTag = true;
return shared_from_this();
}
NTScalarMultiChannelBuilder::shared_pointer NTScalarMultiChannelBuilder::addIsConnected()
{
isConnected = true;
return shared_from_this();
}
StructureConstPtr NTScalarMultiChannelBuilder::createStructure()
{
StandardFieldPtr standardField = getStandardField();
size_t nfields = 2;
size_t extraCount = extraFieldNames.size();
nfields += extraCount;
if(descriptor) ++nfields;
if(alarm) ++nfields;
if(timeStamp) ++nfields;
if(severity) ++nfields;
if(status) ++nfields;
if(message) ++nfields;
if(secondsPastEpoch) ++nfields;
if(nanoseconds) ++nfields;
if(userTag) ++nfields;
if(isConnected) ++nfields;
FieldConstPtrArray fields(nfields);
StringArray names(nfields);
size_t ind = 0;
names[ind] = "value";
fields[ind++] = fieldCreate->createScalarArray(valueType);
names[ind] = "channelName";
fields[ind++] = fieldCreate->createScalarArray(pvString);
if(descriptor) {
names[ind] = "descriptor";
fields[ind++] = fieldCreate->createScalar(pvString);
}
if(alarm) {
names[ind] = "alarm";
fields[ind++] = standardField->alarm();
}
if(timeStamp) {
names[ind] = "timeStamp";
fields[ind++] = standardField->timeStamp();
}
if(severity) {
names[ind] = "severity";
fields[ind++] = fieldCreate->createScalarArray(pvInt);
}
if(status) {
names[ind] = "status";
fields[ind++] = fieldCreate->createScalarArray(pvInt);
}
if(message) {
names[ind] = "message";
fields[ind++] = fieldCreate->createScalarArray(pvString);
}
if(secondsPastEpoch) {
names[ind] = "secondsPastEpoch";
fields[ind++] = fieldCreate->createScalarArray(pvLong);
}
if(nanoseconds) {
names[ind] = "nanoseconds";
fields[ind++] = fieldCreate->createScalarArray(pvInt);
}
if(userTag) {
names[ind] = "userTag";
fields[ind++] = fieldCreate->createScalarArray(pvInt);
}
if(isConnected) {
names[ind] = "isConnected";
fields[ind++] = fieldCreate->createScalarArray(pvBoolean);
}
for (size_t i = 0; i< extraCount; i++) {
names[ind] = extraFieldNames[i];
fields[ind++] = extraFields[i];
}
StructureConstPtr st = fieldCreate->createStructure(NTScalarMultiChannel::URI,names,fields);
reset();
return st;
}
PVStructurePtr NTScalarMultiChannelBuilder::createPVStructure()
{
return pvDataCreate->createPVStructure(createStructure());
}
NTScalarMultiChannelPtr NTScalarMultiChannelBuilder::create()
{
return NTScalarMultiChannelPtr(new NTScalarMultiChannel(createPVStructure()));
}
NTScalarMultiChannelBuilder::NTScalarMultiChannelBuilder()
: valueType(pvDouble)
{
reset();
}
void NTScalarMultiChannelBuilder::reset()
{
extraFieldNames.clear();
extraFields.clear();
valueType = pvDouble;
descriptor = false;
alarm = false;
timeStamp = false;
severity = false;
status = false;
message = false;
secondsPastEpoch = false;
nanoseconds = false;
userTag = false;
isConnected = false;
}
NTScalarMultiChannelBuilder::shared_pointer NTScalarMultiChannelBuilder::add(string const & name, FieldConstPtr const & field)
{
extraFields.push_back(field); extraFieldNames.push_back(name);
return shared_from_this();
}
}
const std::string NTScalarMultiChannel::URI("epics:nt/NTScalarMultiChannel:1.0");
NTScalarMultiChannel::shared_pointer NTScalarMultiChannel::wrap(PVStructurePtr const & pvStructure)
{
if(!isCompatible(pvStructure)) return shared_pointer();
return wrapUnsafe(pvStructure);
}
NTScalarMultiChannel::shared_pointer NTScalarMultiChannel::wrapUnsafe(PVStructurePtr const & pvStructure)
{
return shared_pointer(new NTScalarMultiChannel(pvStructure));
}
bool NTScalarMultiChannel::is_a(StructureConstPtr const &structure)
{
return NTUtils::is_a(structure->getID(), URI);
}
bool NTScalarMultiChannel::isCompatible(StructureConstPtr const & structure)
{
if (!structure.get()) return false;
ScalarArrayConstPtr valueField = structure->getField<ScalarArray>("value");
if (!valueField.get()) return false;
ScalarArrayConstPtr channelNameField = structure->getField<ScalarArray>(
"channelName");
if (!channelNameField.get()) return false;
if (channelNameField->getElementType() != pvString) return false;
FieldConstPtr field = structure->getField("severity");
if (field.get())
{
ScalarArrayConstPtr severityField = structure->getField<ScalarArray>("severity");
if (!severityField.get() || severityField->getElementType() != pvInt)
return false;
}
field = structure->getField("status");
if (field.get())
{
ScalarArrayConstPtr statusField = structure->getField<ScalarArray>("status");
if (!statusField.get() || statusField->getElementType() != pvInt)
return false;
}
field = structure->getField("message");
if (field.get())
{
ScalarArrayConstPtr messageField = structure->getField<ScalarArray>("message");
if (!messageField.get() || messageField->getElementType() != pvString)
return false;
}
field = structure->getField("secondsPastEpoch");
if (field.get())
{
ScalarArrayConstPtr secondsPastEpochField = structure->getField<ScalarArray>("secondsPastEpoch");
if (!secondsPastEpochField.get() || secondsPastEpochField->getElementType() != pvLong)
return false;
}
field = structure->getField("nanoseconds");
if (field.get())
{
ScalarArrayConstPtr nanosecondsField = structure->getField<ScalarArray>("nanoseconds");
if (!nanosecondsField.get() || nanosecondsField->getElementType() != pvInt)
return false;
}
field = structure->getField("userTag");
if (field.get())
{
ScalarArrayConstPtr userTagField = structure->getField<ScalarArray>("userTag");
if (!userTagField.get() || userTagField->getElementType() != pvInt)
return false;
}
field = structure->getField("descriptor");
if (field.get())
{
ScalarConstPtr descriptorField = structure->getField<Scalar>("descriptor");
if (!descriptorField.get() || descriptorField->getScalarType() != pvString)
return false;
}
NTFieldPtr ntField = NTField::get();
field = structure->getField("alarm");
if (field.get() && !ntField->isAlarm(field))
return false;
field = structure->getField("timeStamp");
if (field.get() && !ntField->isTimeStamp(field))
return false;
return true;
}
bool NTScalarMultiChannel::isCompatible(PVStructurePtr const &pvStructure)
{
if(!pvStructure.get()) return false;
return isCompatible(pvStructure->getStructure());
}
bool NTScalarMultiChannel::isValid()
{
size_t valueLength = getValue()->getLength();
if (getChannelName()->getLength() != valueLength) return false;
PVScalarArrayPtr arrayFields[] = {
getSeverity(), getStatus(), getMessage(),
getSecondsPastEpoch(), getNanoseconds(), getUserTag()
};
size_t N = sizeof(arrayFields)/sizeof(arrayFields[0]);
PVScalarArrayPtr arrayField;
for (PVScalarArrayPtr * pa = arrayFields; pa != arrayFields+N; ++pa)
{
arrayField = *pa;
if (arrayField.get() && arrayField->getLength() != valueLength)
return false;
}
return true;
}
NTScalarMultiChannelBuilderPtr NTScalarMultiChannel::createBuilder()
{
return NTScalarMultiChannelBuilderPtr(new detail::NTScalarMultiChannelBuilder());
}
NTScalarMultiChannel::NTScalarMultiChannel(PVStructurePtr const & pvStructure)
: pvNTScalarMultiChannel(pvStructure),
pvTimeStamp(pvStructure->getSubField<PVStructure>("timeStamp")),
pvAlarm(pvStructure->getSubField<PVStructure>("alarm")),
pvValue(pvStructure->getSubField<PVScalarArray>("value")),
pvChannelName(pvStructure->getSubField<PVStringArray>("channelName")),
pvIsConnected(pvStructure->getSubField<PVBooleanArray>("isConnected")),
pvSeverity(pvStructure->getSubField<PVIntArray>("severity")),
pvStatus(pvStructure->getSubField<PVIntArray>("status")),
pvMessage(pvStructure->getSubField<PVStringArray>("message")),
pvSecondsPastEpoch(pvStructure->getSubField<PVLongArray>("secondsPastEpoch")),
pvNanoseconds(pvStructure->getSubField<PVIntArray>("nanoseconds")),
pvUserTag(pvStructure->getSubField<PVIntArray>("userTag")),
pvDescriptor(pvStructure->getSubField<PVString>("descriptor"))
{
}
bool NTScalarMultiChannel::attachTimeStamp(PVTimeStamp &pv) const
{
if (pvTimeStamp)
return pv.attach(pvTimeStamp);
else
return false;
}
bool NTScalarMultiChannel::attachAlarm(PVAlarm &pv) const
{
if (pvAlarm)
return pv.attach(pvAlarm);
else
return false;
}
}}

View File

@@ -0,0 +1,424 @@
/* ntscalarMultiChannel.h */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* This software is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#ifndef NTSCALARMULTICHANNEL_H
#define NTSCALARMULTICHANNEL_H
#include <vector>
#include <string>
#ifdef epicsExportSharedSymbols
# define ntscalarMultiChannelEpicsExportSharedSymbols
# undef epicsExportSharedSymbols
#endif
#include <pv/pvDisplay.h>
#include <pv/pvControl.h>
#ifdef ntscalarMultiChannelEpicsExportSharedSymbols
# define epicsExportSharedSymbols
# undef ntscalarMultiChannelEpicsExportSharedSymbols
#endif
#include <pv/ntfield.h>
#include <shareLib.h>
namespace epics { namespace nt {
class NTScalarMultiChannel;
typedef std::tr1::shared_ptr<NTScalarMultiChannel> NTScalarMultiChannelPtr;
namespace detail {
/**
* @brief Interface for in-line creating of NTScalarMultiChannel.
*
* One instance can be used to create multiple instances.
* An instance of this object must not be used concurrently (an object has a state).
* @author dgh
* @author mse
*/
class epicsShareClass NTScalarMultiChannelBuilder :
public std::tr1::enable_shared_from_this<NTScalarMultiChannelBuilder>
{
public:
POINTER_DEFINITIONS(NTScalarMultiChannelBuilder);
/**
* Sets the scalar type for the value field.
* If this is not called then pvDouble is the default.
* @param scalarType the value field element ScalarType.
* @return this instance of <b>NTScalarMultiChannelBuilder</b>.
*/
shared_pointer value(epics::pvData::ScalarType scalarType);
/**
* Adds descriptor field to the NTScalarMultiChannel.
* @return this instance of <b>NTScalarMultiChannelBuilder</b>.
*/
shared_pointer addDescriptor();
/**
* Adds alarm field to the NTScalarMultiChannel.
* @return this instance of <b>NTScalarMultiChannelBuilder</b>.
*/
shared_pointer addAlarm();
/**
* Adds timeStamp field to the NTScalarMultiChannel.
* @return this instance of <b>NTScalarMultiChannelBuilder</b>.
*/
shared_pointer addTimeStamp();
/**
* Adds severity array to the NTScalarMultiChannel.
* @return this instance of <b>NTScalarMultiChannelBuilder</b>.
*/
shared_pointer addSeverity();
/**
* Adds status array to the NTScalarMultiChannel.
* @return this instance of <b>NTScalarMultiChannelBuilder</b>.
*/
shared_pointer addStatus();
/**
* Adds message array to the NTScalarMultiChannel.
* @return this instance of <b>NTScalarMultiChannelBuilder</b>.
*/
shared_pointer addMessage();
/**
* Adds secondsPastEpoch array to the NTScalarMultiChannel.
* @return this instance of <b>NTScalarMultiChannelBuilder</b>.
*/
shared_pointer addSecondsPastEpoch();
/**
* Adds nanoseconds array to the NTScalarMultiChannel.
* @return this instance of <b>NTScalarMultiChannelBuilder</b>.
*/
shared_pointer addNanoseconds();
/**
* Adds userTag array to the NTScalarMultiChannel.
* @return this instance of <b>NTScalarMultiChannelBuilder</b>.
*/
shared_pointer addUserTag();
/**
* Adds isConnected array to the NTScalarMultiChannel.
* @return this instance of <b>NTScalarMultiChannelBuilder</b>.
*/
shared_pointer addIsConnected();
/**
* Creates a <b>Structure</b> that represents NTScalarMultiChannel.
* This resets this instance state and allows new instance to be created.
* @return a new instance of a <b>Structure</b>.
*/
epics::pvData::StructureConstPtr createStructure();
/**
* Creates a <b>PVStructure</b> that represents NTScalarMultiChannel.
* This resets this instance state and allows new instance to be created.
* @return a new instance of a <b>PVStructure</b>
*/
epics::pvData::PVStructurePtr createPVStructure();
/**
* Creates a <b>NTScalarMultiChannel</b> instance.
* This resets this instance state and allows new instance to be created.
* @return a new instance of a <b>NTScalarMultiChannel</b>
*/
NTScalarMultiChannelPtr create();
/**
* Adds extra <b>Field</b> to the type.
* @param name the name of the field.
* @param field the field to be added.
* @return this instance of a <b>NTScalarMultiChannelBuilder</b>
*/
shared_pointer add(std::string const & name, epics::pvData::FieldConstPtr const & field);
private:
NTScalarMultiChannelBuilder();
void reset();
epics::pvData::ScalarType valueType;
bool descriptor;
bool alarm;
bool timeStamp;
bool severity;
bool status;
bool message;
bool secondsPastEpoch;
bool nanoseconds;
bool userTag;
bool isConnected;
// NOTE: this preserves order, however it does not handle duplicates
epics::pvData::StringArray extraFieldNames;
epics::pvData::FieldConstPtrArray extraFields;
friend class ::epics::nt::NTScalarMultiChannel;
};
}
typedef std::tr1::shared_ptr<detail::NTScalarMultiChannelBuilder> NTScalarMultiChannelBuilderPtr;
/**
* @brief Convenience Class for NTScalarMultiChannel
* @author dgh
* @author mrk
*
*/
class epicsShareClass NTScalarMultiChannel
{
public:
POINTER_DEFINITIONS(NTScalarMultiChannel);
static const std::string URI;
/**
* Creates an NTScalarMultiChannel wrapping the specified PVStructure if the latter is compatible.
* <p>
* Checks the supplied PVStructure is compatible with NTScalarMultiChannel
* and if so returns an NTScalarMultiChannel which wraps it.
* This method will return null if the structure is is not compatible
* or is null.
*
* @param pvStructure the PVStructure to be wrapped
* @return NTScalarMultiChannel instance wrapping pvStructure on success, null otherwise
*/
static shared_pointer wrap(epics::pvData::PVStructurePtr const & pvStructure);
/**
* Creates an NTScalarMultiChannel wrapping the specified PVStructure, regardless of the latter's compatibility.
* <p>
* No checks are made as to whether the specified PVStructure
* is compatible with NTScalarMultiChannel or is non-null.
*
* @param pvStructure the PVStructure to be wrapped
* @return NTScalarMultiChannel instance wrapping pvStructure
*/
static shared_pointer wrapUnsafe(epics::pvData::PVStructurePtr const & pvStructure);
/**
* Returns whether the specified Structure reports to be a compatible NTScalarMultiChannel.
* <p>
* Checks if the specified Structure reports compatibility with this
* version of NTScalarMultiChannel through its type ID, including checking version numbers.
* The return value does not depend on whether the structure is actually
* compatible in terms of its introspection type.
*
* @param structure the Structure to test
* @return (false,true) if the specified Structure (is not, is) a compatible NTScalarMultiChannel
*/
static bool is_a(epics::pvData::StructureConstPtr const & structure);
/**
* Returns whether the specified PVStructure reports to be a compatible NTScalarMultiChannel.
* <p>
* Checks if the specified PVStructure reports compatibility with this
* version of NTScalarMultiChannel through its type ID, including checking version numbers.
* The return value does not depend on whether the structure is actually
* compatible in terms of its introspection type.
*
* @param pvStructure the PVStructure to test
* @return (false,true) if the specified PVStructure (is not, is) a compatible NTScalarMultiChannel
*/
static bool is_a(epics::pvData::PVStructurePtr const & pvStructure);
/**
* Returns whether the specified Structure is compatible with NTScalarMultiChannel.
* <p>
* Checks if the specified Structure is compatible with this version
* of NTScalarMultiChannel through the introspection interface.
*
* @param structure the Structure to test
* @return (false,true) if the specified Structure (is not, is) a compatible NTScalarMultiChannel
*/
static bool isCompatible(
epics::pvData::StructureConstPtr const &structure);
/**
* Returns whether the wrapped PVStructure is a valid NTScalarMultiChannel.
* <p>
* Unlike isCompatible(), isValid() may perform checks on the value
* data as well as the introspection data.
*
* @return (false,true) if wrapped PVStructure (is not, is) a valid NTScalarMultiChannel
*/
static bool isCompatible(
epics::pvData::PVStructurePtr const &pvStructure);
/**
* Returns whether the specified PVStructure is a valid NTScalarMultiChannel.
* <p>
* Unlike isCompatible(), isValid() may perform checks on the value
* data as well as the introspection data.
*
* @return (false,true) if wrapped PVStructure (is not, is) a valid NTScalarMultiChannel.
*/
bool isValid();
/**
* Creates an NTScalarMultiChannelBuilder instance
* @return builder instance.
*/
static NTScalarMultiChannelBuilderPtr createBuilder();
/**
* Destructor
*/
~NTScalarMultiChannel() {}
/**
* Attaches a PVTimeStamp to the wrapped PVStructure.
* Does nothing if no timeStamp field.
* @param pvTimeStamp the PVTimeStamp that will be attached.
* @return true if the operation was successfull (i.e. this instance has a timeStamp field), otherwise false.
*/
bool attachTimeStamp(epics::pvData::PVTimeStamp &pvTimeStamp) const;
/**
* Attaches a PVAlarm to the wrapped PVStructure.
* Does nothing if no alarm field.
* @param pvAlarm the PVAlarm that will be attached.
* @return true if the operation was successfull (i.e. this instance has an alarm field), otherwise false.
*/
bool attachAlarm(epics::pvData::PVAlarm &pvAlarm) const;
/**
* Returns the PVStructure wrapped by this instance.
* @return the PVStructure wrapped by this instance.
*/
epics::pvData::PVStructurePtr getPVStructure() const
{return pvNTScalarMultiChannel;}
/**
* Return the descriptor field.
* @return the descriptor field or null if no descriptor field.
*/
epics::pvData::PVStringPtr getDescriptor() const
{return pvDescriptor;}
/**
* Returns the timeStamp field.
* @return the timeStamp field or null if no such field.
*/
epics::pvData::PVStructurePtr getTimeStamp() const
{return pvTimeStamp;}
/**
* Returns the alarm field.
* @return the alarm field or null if no such field.
*/
epics::pvData::PVStructurePtr getAlarm() const
{return pvAlarm;}
/**
* Returns the field with the value of each channel.
* @return the value field.
*/
epics::pvData::PVScalarArrayPtr getValue() const
{return pvValue;}
/**
* Returns the value of each channel of a specified expected type
* (for example, PVDoubleArray).
* @tparam PVT the expected type of the value field which should be
* be PVScalarArray or a derived class.
* @return the value field or null if it is not of the expected type.
*/
template<typename PVT>
std::tr1::shared_ptr<PVT> getValue() const
{
return std::tr1::dynamic_pointer_cast<PVT>(pvValue);
}
/**
* Returns the field with the channelName of each channel.
* @return the channelName field
*/
epics::pvData::PVStringArrayPtr getChannelName() const
{ return pvChannelName;};
/**
* Returns the field with the connection state of each channel.
* @return the isConnected field or null if no such field
*/
epics::pvData::PVBooleanArrayPtr getIsConnected() const
{ return pvIsConnected;};
/**
* Returns the field with the severity of each channel.
* @return the severity field or null if no such field
*/
epics::pvData::PVIntArrayPtr getSeverity() const
{return pvSeverity;}
/**
* Returns the field with the status of each channel.
* @return the status field or null if no such field
*/
epics::pvData::PVIntArrayPtr getStatus() const
{return pvStatus;}
/**
* Returns the field with the message of each channel.
* @return message field or null if no such field.
*/
epics::pvData::PVStringArrayPtr getMessage() const
{return pvMessage;}
/**
* Returns the field with the secondsPastEpoch of each channel.
* @return the secondsPastEpoch field or null if no such field.
*/
epics::pvData::PVLongArrayPtr getSecondsPastEpoch() const
{return pvSecondsPastEpoch;}
/**
* Returns the field with the nanoseconds of each channel.
* @return nanoseconds field or null if no such field.
*/
epics::pvData::PVIntArrayPtr getNanoseconds() const
{return pvNanoseconds;}
/**
* Returns the field with the userTag of each channel.
* @return the userTag field or null if no such field.
*/
epics::pvData::PVIntArrayPtr getUserTag() const
{return pvUserTag;}
private:
NTScalarMultiChannel(epics::pvData::PVStructurePtr const & pvStructure);
epics::pvData::PVStructurePtr pvNTScalarMultiChannel;
epics::pvData::PVStructurePtr pvTimeStamp;
epics::pvData::PVStructurePtr pvAlarm;
epics::pvData::PVScalarArrayPtr pvValue;
epics::pvData::PVStringArrayPtr pvChannelName;
epics::pvData::PVBooleanArrayPtr pvIsConnected;
epics::pvData::PVIntArrayPtr pvSeverity;
epics::pvData::PVIntArrayPtr pvStatus;
epics::pvData::PVStringArrayPtr pvMessage;
epics::pvData::PVLongArrayPtr pvSecondsPastEpoch;
epics::pvData::PVIntArrayPtr pvNanoseconds;
epics::pvData::PVIntArrayPtr pvUserTag;
epics::pvData::PVStringPtr pvDescriptor;
friend class detail::NTScalarMultiChannelBuilder;
};
}}
#endif /* NTSCALARMULTICHANNEL_H */

View File

@@ -1,13 +1,15 @@
/* nttable.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* This software is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#include <algorithm>
#define epicsExportSharedSymbols
#include <pv/nttable.h>
#include <pv/ntutils.h>
using namespace std;
using namespace epics::pvData;
@@ -18,14 +20,14 @@ static NTFieldPtr ntField = NTField::get();
namespace detail {
NTTableBuilder::shared_pointer NTTableBuilder::add(
NTTableBuilder::shared_pointer NTTableBuilder::addColumn(
std::string const & name, epics::pvData::ScalarType scalarType
)
{
if (std::find(labels.begin(), labels.end(), name) != labels.end())
if (std::find(columnNames.begin(), columnNames.end(), name) != columnNames.end())
throw std::runtime_error("duplicate column name");
labels.push_back(name);
columnNames.push_back(name);
types.push_back(scalarType);
return shared_from_this();
@@ -41,9 +43,9 @@ StructureConstPtr NTTableBuilder::createStructure()
addArray("labels", pvString)->
addNestedStructure("value");
vector<string>::size_type len = labels.size();
vector<string>::size_type len = columnNames.size();
for (vector<string>::size_type i = 0; i < len; i++)
nestedBuilder->addArray(labels[i], types[i]);
nestedBuilder->addArray(columnNames[i], types[i]);
builder = nestedBuilder->endNested();
@@ -56,12 +58,11 @@ StructureConstPtr NTTableBuilder::createStructure()
if (timeStamp)
builder->add("timeStamp", ntField->createTimeStamp());
StructureConstPtr s = builder->createStructure();
size_t extraCount = extraFieldNames.size();
for (size_t i = 0; i< extraCount; i++)
builder->add(extraFieldNames[i], extraFields[i]);
StructureConstPtr s = builder->createStructure();
reset();
return s;
@@ -87,9 +88,10 @@ NTTableBuilder::shared_pointer NTTableBuilder::addTimeStamp()
PVStructurePtr NTTableBuilder::createPVStructure()
{
size_t len = labels.size();
// fill in labels with default values (the column names)
size_t len = columnNames.size();
shared_vector<string> l(len);
for(size_t i=0; i<len; ++i) l[i] = labels[i];
for(size_t i=0; i<len; ++i) l[i] = columnNames[i];
PVStructurePtr s = getPVDataCreate()->createPVStructure(createStructure());
s->getSubField<PVStringArray>("labels")->replace(freeze(l));
return s;
@@ -107,7 +109,7 @@ NTTableBuilder::NTTableBuilder()
void NTTableBuilder::reset()
{
labels.clear();
columnNames.clear();
types.clear();
descriptor = false;
alarm = false;
@@ -125,34 +127,95 @@ NTTableBuilder::shared_pointer NTTableBuilder::add(string const & name, FieldCon
const std::string NTTable::URI("epics:nt/NTTable:1.0");
NTTable::shared_pointer NTTable::wrap(PVStructurePtr const & structure)
NTTable::shared_pointer NTTable::wrap(PVStructurePtr const & pvStructure)
{
if(!isCompatible(structure)) return shared_pointer();
return wrapUnsafe(structure);
if(!isCompatible(pvStructure)) return shared_pointer();
return wrapUnsafe(pvStructure);
}
NTTable::shared_pointer NTTable::wrapUnsafe(PVStructurePtr const & structure)
NTTable::shared_pointer NTTable::wrapUnsafe(PVStructurePtr const & pvStructure)
{
return shared_pointer(new NTTable(structure));
return shared_pointer(new NTTable(pvStructure));
}
bool NTTable::is_a(StructureConstPtr const & structure)
{
return structure->getID() == URI;
return NTUtils::is_a(structure->getID(), URI);
}
bool NTTable::isCompatible(StructureConstPtr const & structure)
{
if (!structure.get()) return false;
StructureConstPtr valueField = structure->getField<Structure>("value");
if (!valueField.get())
return false;
FieldConstPtrArray const & fields = valueField->getFields();
for (FieldConstPtrArray::const_iterator it = fields.begin();
it != fields.end(); ++it)
{
if ((*it)->getType() != scalarArray) return false;
}
ScalarArrayConstPtr labelsField = structure->getField<ScalarArray>("labels");
if (!labelsField.get() || labelsField->getElementType() != pvString)
return false;
FieldConstPtr field = structure->getField("descriptor");
if (field.get())
{
ScalarConstPtr descriptorField = structure->getField<Scalar>("descriptor");
if (!descriptorField.get() || descriptorField->getScalarType() != pvString)
return false;
}
NTFieldPtr ntField = NTField::get();
field = structure->getField("alarm");
if (field.get() && !ntField->isAlarm(field))
return false;
field = structure->getField("timeStamp");
if (field.get() && !ntField->isTimeStamp(field))
return false;
return true;
}
bool NTTable::isCompatible(PVStructurePtr const & pvStructure)
{
if(!pvStructure) return false;
PVFieldPtr pvField = pvStructure->getSubField("alarm");
if(pvField && !ntField->isAlarm(pvField->getField())) return false;
pvField = pvStructure->getSubField("timeStamp");
if(pvField && !ntField->isTimeStamp(pvField->getField())) return false;
PVStringArrayPtr pvLabel = pvStructure->getSubField<PVStringArray>("labels");
if(!pvLabel) return false;
return isCompatible(pvStructure->getStructure());
}
bool NTTable::isValid()
{
PVFieldPtrArray const & columns = pvValue->getPVFields();
if (getLabels()->getLength() != columns.size()) return false;
bool first = true;
int length = 0;
for (PVFieldPtrArray::const_iterator it = columns.begin();
it != columns.end();++it)
{
PVScalarArrayPtr column = std::tr1::dynamic_pointer_cast<PVScalarArray>(*it);
if (!column.get()) return false;
int colLength = column->getLength();
if (first)
{
length = colLength;
first = false;
}
else if (length != colLength)
return false;
}
return true;
}
NTTableBuilderPtr NTTable::createBuilder()
{
return NTTableBuilderPtr(new detail::NTTableBuilder());
@@ -201,13 +264,18 @@ PVStringArrayPtr NTTable::getLabels() const
return pvNTTable->getSubField<PVStringArray>("labels");
}
StringArray const & NTTable::getColumnNames() const
{
return pvNTTable->getStructure()->getFieldNames();
}
PVFieldPtr NTTable::getColumn(std::string const & columnName) const
{
return pvNTTable->getSubField("value." + columnName);
return pvValue->getSubField(columnName);
}
NTTable::NTTable(PVStructurePtr const & pvStructure) :
pvNTTable(pvStructure)
pvNTTable(pvStructure), pvValue(pvNTTable->getSubField<PVStructure>("value"))
{}

View File

@@ -1,17 +1,32 @@
/* nttable.h */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* This software is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#ifndef NTTABLE_H
#define NTTABLE_H
#include <pv/ntfield.h>
#include <vector>
#include <string>
#ifdef epicsExportSharedSymbols
# define nttableEpicsExportSharedSymbols
# undef epicsExportSharedSymbols
#endif
#include <pv/pvDisplay.h>
#include <pv/pvControl.h>
#ifdef nttableEpicsExportSharedSymbols
# define epicsExportSharedSymbols
# undef nttableEpicsExportSharedSymbols
#endif
#include <pv/ntfield.h>
#include <shareLib.h>
namespace epics { namespace nt {
class NTTable;
@@ -20,7 +35,8 @@ typedef std::tr1::shared_ptr<NTTable> NTTablePtr;
namespace detail {
/**
* Interface for in-line creating of NTTable.
* @brief Interface for in-line creating of NTTable.
*
* One instance can be used to create multiple instances.
* An instance of this object must not be used concurrently (an object has a state).
* @author mse
@@ -32,56 +48,60 @@ namespace detail {
POINTER_DEFINITIONS(NTTableBuilder);
/**
* Add a column of given {@code Scalar} type.
* Adds a column of given <b>Scalar</b> type.
* @param name name of the column.
* @param elementType column type, a scalar array.
* @return this instance of a {@code NTTableBuilder}.
* @return this instance of <b>NTTableBuilder</b>.
*/
shared_pointer add(std::string const & name, epics::pvData::ScalarType elememtType);
shared_pointer addColumn(std::string const & name, epics::pvData::ScalarType elementType);
/**
* Add descriptor field to the NTTable.
* @return this instance of a {@code NTTableBuilder}.
* Adds descriptor field to the NTTable.
* @return this instance of <b>NTTableBuilder</b>.
*/
shared_pointer addDescriptor();
/**
* Add alarm structure to the NTTable.
* @return this instance of a {@code NTTableBuilder}.
* Adds alarm field to the NTTable.
* @return this instance of <b>NTTableBuilder</b>.
*/
shared_pointer addAlarm();
/**
* Add timeStamp structure to the NTTable.
* @return this instance of a {@code NTTableBuilder}.
* Adds timeStamp field to the NTTable.
* @return this instance of <b>NTTableBuilder</b>.
*/
shared_pointer addTimeStamp();
/**
* Create a {@code Structure} that represents NTTable.
* Creates a <b>Structure</b> that represents NTTable.
* This resets this instance state and allows new instance to be created.
* @return a new instance of a {@code Structure}.
* @return a new instance of <b>Structure</b>.
*/
epics::pvData::StructureConstPtr createStructure();
/**
* Create a {@code PVStructure} that represents NTTable.
* This resets this instance state and allows new {@code instance to be created.
* @return a new instance of a {@code PVStructure}
* Creates a <b>PVStructure</b> that represents NTTable.
* The returned PVStructure will have labels equal to the column names.
* This resets this instance state and allows new instance to be created.
* @return a new instance of <b>PVStructure</b>.
*/
epics::pvData::PVStructurePtr createPVStructure();
/**
* Create a {@code NTTable} instance.
* This resets this instance state and allows new {@code instance to be created.
* @return a new instance of a {@code NTTable}
* Creates a <b>NTTable</b> instance.
* The returned NTTable will wrap a PVStructure which will have
* labels equal to the column names.
* This resets this instance state and allows new instance to be created.
* @return a new instance of <b>NTTable</b>.
*/
NTTablePtr create();
/**
* Add extra {@code Field} to the type.
* @param name name of the field.
* @param field a field to add.
* @return this instance of a {@code NTTableBuilder}.
* Adds extra <b>Field</b> to the type.
* @param name the name of the field.
* @param field the field to be added.
* @return this instance of <b>NTTableBuilder</b>.
*/
shared_pointer add(std::string const & name, epics::pvData::FieldConstPtr const & field);
@@ -90,7 +110,7 @@ namespace detail {
void reset();
std::vector<std::string> labels;
std::vector<std::string> columnNames;
std::vector<epics::pvData::ScalarType> types;
bool descriptor;
@@ -111,10 +131,11 @@ typedef std::tr1::shared_ptr<detail::NTTableBuilder> NTTableBuilderPtr;
/**
* Convenience Class for NTTable
* @brief Convenience Class for NTTable
*
* @author mrk
*/
class NTTable
class epicsShareClass NTTable
{
public:
POINTER_DEFINITIONS(NTTable);
@@ -122,38 +143,91 @@ public:
static const std::string URI;
/**
* Wrap (aka dynamic cast, or wrap) the structure to NTTable.
* First isCompatible is called.
* This method will nullptr if the structure is is not compatible.
* This method will nullptr if the structure is nullptr.
* @param structure The structure to wrap-ed (dynamic cast, wrapped) to NTTable.
* @return NTTable instance on success, nullptr otherwise.
* Creates an NTTable wrapping the specified PVStructure if the latter is compatible.
* <p>
* Checks the supplied PVStructure is compatible with NTTable
* and if so returns an NTTable which wraps it.
* This method will return null if the structure is is not compatible
* or is null.
*
* @param pvStructure the PVStructure to be wrapped
* @return NTTable instance wrapping pvStructure on success, null otherwise
*/
static shared_pointer wrap(epics::pvData::PVStructurePtr const & structure);
static shared_pointer wrap(epics::pvData::PVStructurePtr const & pvStructure);
/**
* Wrap (aka dynamic cast, or wrap) the structure to NTMultiChannel without checking for isCompatible
* @param structure The structure to wrap-ed (dynamic cast, wrapped) to NTTable.
* @return NTTable instance.
* Creates an NTTable wrapping the specified PVStructure, regardless of the latter's compatibility.
* <p>
* No checks are made as to whether the specified PVStructure
* is compatible with NTTable or is non-null.
*
* @param pvStructure the PVStructure to be wrapped
* @return NTTable instance wrapping pvStructure
*/
static shared_pointer wrapUnsafe(epics::pvData::PVStructurePtr const & structure);
static shared_pointer wrapUnsafe(epics::pvData::PVStructurePtr const & pvStructure);
/**
* Is the structure an NTTable.
* @param structure The structure to test.
* @return (false,true) if (is not, is) an NTTable.
* Returns whether the specified Structure reports to be a compatible NTTable.
* <p>
* Checks if the specified Structure reports compatibility with this
* version of NTTable through its type ID, including checking version numbers.
* The return value does not depend on whether the structure is actually
* compatible in terms of its introspection type.
*
* @param structure the Structure to test
* @return (false,true) if the specified Structure (is not, is) a compatible NTTable
*/
static bool is_a(epics::pvData::StructureConstPtr const & structure);
/**
* Is the pvStructure compatible with NTTable.
* This method introspects the fields to see if they are compatible.
* @param pvStructure The pvStructure to test.
* @return (false,true) if (is not, is) an NTMultiChannel.
* Returns whether the specified PVStructure reports to be a compatible NTTable.
* <p>
* Checks if the specified PVStructure reports compatibility with this
* version of NTTable through its type ID, including checking version numbers.
* The return value does not depend on whether the structure is actually
* compatible in terms of its introspection type.
*
* @param pvStructure the PVStructure to test
* @return (false,true) if the specified PVStructure (is not, is) a compatible NTTable
*/
static bool is_a(epics::pvData::PVStructurePtr const & pvStructure);
/**
* Returns whether the specified Structure is compatible with NTTable.
* <p>
* Checks if the specified Structure is compatible with this version
* of NTTable through the introspection interface.
*
* @param structure the Structure to test
* @return (false,true) if the specified Structure (is not, is) a compatible NTTable
*/
static bool isCompatible(
epics::pvData::StructureConstPtr const &structure);
/**
* Returns whether the specified PVStructure is compatible with NTTable.
*
* Checks if the specified PVStructure is compatible with this version
* of NTTable through the introspection interface.
*
* @param pvStructure the PVStructure to test
* @return (false,true) if the specified PVStructure (is not, is) a compatible NTTable
*/
static bool isCompatible(
epics::pvData::PVStructurePtr const &pvStructure);
/**
* Create a NTTable builder instance.
* Returns whether the specified structure is a valid NTTable.
* <p>
* Unlike isCompatible(), isValid() may perform checks on the value
* data as well as the introspection data.
*
* @return (false,true) if wrapped PVStructure (is not, is) a valid NTTable
*/
bool isValid();
/**
* Creates an NTTable builder instance.
* @return builder instance.
*/
static NTTableBuilderPtr createBuilder();
@@ -164,62 +238,73 @@ public:
~NTTable() {}
/**
* Attach a pvTimeStamp.
* @param pvTimeStamp The pvTimeStamp that will be attached.
* Does nothing if no timeStamp.
* Attaches a PVTimeStamp to the wrapped PVStructure.
* Does nothing if no timeStamp field.
* @param pvTimeStamp the PVTimeStamp that will be attached.
* @return true if the operation was successfull (i.e. this instance has a timeStamp field), otherwise false.
*/
bool attachTimeStamp(epics::pvData::PVTimeStamp &pvTimeStamp) const;
/**
* Attach an pvAlarm.
* @param pvAlarm The pvAlarm that will be attached.
* Does nothing if no alarm.
* @return true if the operation was successfull (i.e. this instance has a timeStamp field), otherwise false.
* Attaches a PVAlarm to the wrapped PVStructure.
* Does nothing if no alarm field.
* @param pvAlarm the PVAlarm that will be attached.
* @return true if the operation was successfull (i.e. this instance has an alarm field), otherwise false.
*/
bool attachAlarm(epics::pvData::PVAlarm &pvAlarm) const;
/**
* Get the pvStructure.
* @return PVStructurePtr.
* Returns the PVStructure wrapped by this instance.
* @return the PVStructure wrapped by this instance.
*/
epics::pvData::PVStructurePtr getPVStructure() const;
/**
* Get the descriptor field.
* @return The pvString or null if no function field.
* Returns the descriptor field.
* @return the descriptor field or null if no descriptor field.
*/
epics::pvData::PVStringPtr getDescriptor() const;
/**
* Get the timeStamp.
* @return PVStructurePtr which may be null.
* Returns the timeStamp field.
* @return the timStamp field or null if no such field.
*/
epics::pvData::PVStructurePtr getTimeStamp() const;
/**
* Get the alarm.
* @return PVStructurePtr which may be null.
* Returns the alarm field.
* @return the alarm field or null if no such field.
*/
epics::pvData::PVStructurePtr getAlarm() const;
/**
* Get the labels field.
* @return The pvStringArray for the labels.
* Returns the labels field.
* @return the labels field.
*/
epics::pvData::PVStringArrayPtr getLabels() const;
/**
* Get the PVField (column) for a field that follows the label field.
* @param columnName The name of the column.
* @return The PVFieldPtr for the field.
* Returns the column names for the table.
* For each name, calling getColumn should return the column, which should not be null.
* @return the column names.
*/
epics::pvData::StringArray const & getColumnNames() const;
/**
* Returns the PVField for the column with the specified colum name.
* @param columnName the name of the column.
* @return the field for the column or null if column does not exist.
*/
epics::pvData::PVFieldPtr getColumn(std::string const & columnName) const;
/**
* Get the PVField (column) for a field that follows the label field of a specified type (e.g. PVDoubleArray).
* @param columnName The name of the column.
* @return The <PVT> field.
* Returns the column with the specified column name and of a specified
* expected type (for example, PVDoubleArray).
* @tparam PVT the expected type of the column which should be
* be PVScalarArray or a derived class.
* @param columnName the name of the column.
* @return the field for the column or null if column does not exist
* or is not of the specified type.
*/
template<typename PVT>
std::tr1::shared_ptr<PVT> getColumn(std::string const & columnName) const
@@ -234,6 +319,7 @@ public:
private:
NTTable(epics::pvData::PVStructurePtr const & pvStructure);
epics::pvData::PVStructurePtr pvNTTable;
epics::pvData::PVStructurePtr pvValue;
friend class detail::NTTableBuilder;
};

213
src/nt/ntunion.cpp Normal file
View File

@@ -0,0 +1,213 @@
/* ntunion.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* This software is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#define epicsExportSharedSymbols
#include <pv/ntunion.h>
#include <pv/ntutils.h>
using namespace std;
using namespace epics::pvData;
namespace epics { namespace nt {
static NTFieldPtr ntField = NTField::get();
namespace detail {
StructureConstPtr NTUnionBuilder::createStructure()
{
FieldBuilderPtr builder =
getFieldCreate()->createFieldBuilder()->
setId(NTUnion::URI)->
add("value", valueType);
if (descriptor)
builder->add("descriptor", pvString);
if (alarm)
builder->add("alarm", ntField->createAlarm());
if (timeStamp)
builder->add("timeStamp", ntField->createTimeStamp());
size_t extraCount = extraFieldNames.size();
for (size_t i = 0; i< extraCount; i++)
builder->add(extraFieldNames[i], extraFields[i]);
StructureConstPtr s = builder->createStructure();
reset();
return s;
}
NTUnionBuilder::shared_pointer NTUnionBuilder::addDescriptor()
{
descriptor = true;
return shared_from_this();
}
NTUnionBuilder::shared_pointer NTUnionBuilder::addAlarm()
{
alarm = true;
return shared_from_this();
}
NTUnionBuilder::shared_pointer NTUnionBuilder::addTimeStamp()
{
timeStamp = true;
return shared_from_this();
}
PVStructurePtr NTUnionBuilder::createPVStructure()
{
return getPVDataCreate()->createPVStructure(createStructure());
}
NTUnionPtr NTUnionBuilder::create()
{
return NTUnionPtr(new NTUnion(createPVStructure()));
}
NTUnionBuilder::NTUnionBuilder()
{
reset();
}
void NTUnionBuilder::reset()
{
valueType = getFieldCreate()->createVariantUnion();
descriptor = false;
alarm = false;
timeStamp = false;
extraFieldNames.clear();
extraFields.clear();
}
NTUnionBuilder::shared_pointer NTUnionBuilder::add(string const & name, FieldConstPtr const & field)
{
extraFields.push_back(field); extraFieldNames.push_back(name);
return shared_from_this();
}
}
const std::string NTUnion::URI("epics:nt/NTUnion:1.0");
NTUnion::shared_pointer NTUnion::wrap(PVStructurePtr const & pvStructure)
{
if(!isCompatible(pvStructure)) return shared_pointer();
return wrapUnsafe(pvStructure);
}
NTUnion::shared_pointer NTUnion::wrapUnsafe(PVStructurePtr const & pvStructure)
{
return shared_pointer(new NTUnion(pvStructure));
}
bool NTUnion::is_a(StructureConstPtr const & structure)
{
return NTUtils::is_a(structure->getID(), URI);
}
bool NTUnion::isCompatible(StructureConstPtr const &structure)
{
if (structure.get() == 0) return false;
UnionConstPtr valueField = structure->getField<Union>("value");
if (valueField.get() == 0)
return false;
FieldConstPtr field = structure->getField("descriptor");
if (field.get())
{
ScalarConstPtr descriptorField = structure->getField<Scalar>("descriptor");
if (!descriptorField.get() || descriptorField->getScalarType() != pvString)
return false;
}
NTFieldPtr ntField = NTField::get();
field = structure->getField("alarm");
if (field.get() && !ntField->isAlarm(field))
return false;
field = structure->getField("timeStamp");
if (field.get() && !ntField->isTimeStamp(field))
return false;
return true;
}
bool NTUnion::isCompatible(PVStructurePtr const & pvStructure)
{
if(!pvStructure) return false;
return isCompatible(pvStructure->getStructure());
}
bool NTUnion::isValid()
{
return true;
}
NTUnionBuilderPtr NTUnion::createBuilder()
{
return NTUnionBuilderPtr(new detail::NTUnionBuilder());
}
bool NTUnion::attachTimeStamp(PVTimeStamp &pvTimeStamp) const
{
PVStructurePtr ts = getTimeStamp();
if (ts)
return pvTimeStamp.attach(ts);
else
return false;
}
bool NTUnion::attachAlarm(PVAlarm &pvAlarm) const
{
PVStructurePtr al = getAlarm();
if (al)
return pvAlarm.attach(al);
else
return false;
}
PVStructurePtr NTUnion::getPVStructure() const
{
return pvNTUnion;
}
PVStringPtr NTUnion::getDescriptor() const
{
return pvNTUnion->getSubField<PVString>("descriptor");
}
PVStructurePtr NTUnion::getTimeStamp() const
{
return pvNTUnion->getSubField<PVStructure>("timeStamp");
}
PVStructurePtr NTUnion::getAlarm() const
{
return pvNTUnion->getSubField<PVStructure>("alarm");
}
PVUnionPtr NTUnion::getValue() const
{
return pvValue;
}
NTUnion::NTUnion(PVStructurePtr const & pvStructure) :
pvNTUnion(pvStructure), pvValue(pvNTUnion->getSubField<PVUnion>("value"))
{}
}}

273
src/nt/ntunion.h Normal file
View File

@@ -0,0 +1,273 @@
/* ntunion.h */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* This software is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#ifndef NTUNION_H
#define NTUNION_H
#ifdef epicsExportSharedSymbols
# define ntunionEpicsExportSharedSymbols
# undef epicsExportSharedSymbols
#endif
#ifdef ntunionEpicsExportSharedSymbols
# define epicsExportSharedSymbols
# undef ntunionEpicsExportSharedSymbols
#endif
#include <pv/ntfield.h>
#include <shareLib.h>
namespace epics { namespace nt {
class NTUnion;
typedef std::tr1::shared_ptr<NTUnion> NTUnionPtr;
namespace detail {
/**
* @brief Interface for in-line creating of NTUnion.
*
* One instance can be used to create multiple instances.
* An instance of this object must not be used concurrently (an object has a state).
* @author dgh
*/
class epicsShareClass NTUnionBuilder :
public std::tr1::enable_shared_from_this<NTUnionBuilder>
{
public:
POINTER_DEFINITIONS(NTUnionBuilder);
/**
* Adds descriptor field to the NTUnion.
* @return this instance of <b>NTUnionBuilder</b>.
*/
shared_pointer addDescriptor();
/**
* Adds alarm field to the NTUnion.
* @return this instance of <b>NTUnionBuilder</b>.
*/
shared_pointer addAlarm();
/**
* Adds timeStamp field to the NTUnion.
* @return this instance of <b>NTUnionBuilder</b>.
*/
shared_pointer addTimeStamp();
/**
* Creates a <b>Structure</b> that represents NTUnion.
* This resets this instance state and allows new instance to be created.
* @return a new instance of a <b>Structure</b>.
*/
epics::pvData::StructureConstPtr createStructure();
/**
* Creates a <b>PVStructure</b> that represents NTUnion.
* This resets this instance state and allows new instance to be created.
* @return a new instance of a <b>PVStructure</b>.
*/
epics::pvData::PVStructurePtr createPVStructure();
/**
* Creates a <b>NTUnion</b> instance.
* This resets this instance state and allows new instance to be created.
* @return a new instance of a <b>NTUnion</b>.
*/
NTUnionPtr create();
/**
* Adds extra <b>Field</b> to the type.
* @param name the name of the field.
* @param field the field to be added.
* @return this instance of <b>NTUnionBuilder</b>.
*/
shared_pointer add(std::string const & name, epics::pvData::FieldConstPtr const & field);
private:
NTUnionBuilder();
epics::pvData::UnionConstPtr valueType;
void reset();
bool descriptor;
bool alarm;
bool timeStamp;
// NOTE: this preserves order, however it does not handle duplicates
epics::pvData::StringArray extraFieldNames;
epics::pvData::FieldConstPtrArray extraFields;
friend class ::epics::nt::NTUnion;
};
}
typedef std::tr1::shared_ptr<detail::NTUnionBuilder> NTUnionBuilderPtr;
/**
* @brief Convenience Class for NTUnion
*
* @author dgh
*/
class epicsShareClass NTUnion
{
public:
POINTER_DEFINITIONS(NTUnion);
static const std::string URI;
/**
* Creates an NTUnion wrapping the specified PVStructure if the latter is compatible.
* <p>
* Checks the supplied PVStructure is compatible with NTUnion
* and if so returns an NTUnion which wraps it.
* This method will return null if the structure is is not compatible
* or is null.
*
* @param pvStructure the PVStructure to be wrapped
* @return NTUnion instance wrapping pvStructure on success, null otherwise
*/
static shared_pointer wrap(epics::pvData::PVStructurePtr const & pvStructure);
/**
* Creates an NTUnion wrapping the specified PVStructure, regardless of the latter's compatibility.
* <p>
* No checks are made as to whether the specified PVStructure
* is compatible with NTUnion or is non-null.
* @param pvStructure the PVStructure to be wrapped
* @return NTUnion instance wrapping pvStructure
*/
static shared_pointer wrapUnsafe(epics::pvData::PVStructurePtr const & pvStructure);
/**
* Returns whether the specified Structure reports to be a compatible NTUnion.
* <p>
* Checks if the specified Structure reports compatibility with this
* version of NTUnion through its type ID, including checking version numbers.
* The return value does not depend on whether the structure is actually
* compatible in terms of its introspection type.
*
* @param structure the Structure to test
* @return (false,true) if the specified Structure (is not, is) a compatible NTUnion
*/
static bool is_a(epics::pvData::StructureConstPtr const & structure);
/**
* Returns whether the specified PVStructure reports to be a compatible NTUnion.
*
* Checks if the specified PVStructure reports compatibility with this
* version of NTUnion through its type ID, including checking version numbers.
* The return value does not depend on whether the structure is actually
* compatible in terms of its introspection type.
*
* @param pvStructure the PVStructure to test
* @return (false,true) if the specified PVStructure (is not, is) a compatible NTUnion
*/
static bool is_a(epics::pvData::PVStructurePtr const & pvStructure);
/**
* Returns whether the specified Structure is compatible with NTUnion.
* <p>
* Checks if the specified Structure is compatible with this version
* of NTUnion through the introspection interface.
* @param structure the Structure to test
* @return (false,true) if the specified Structure (is not, is) a compatible NTUnion
*/
static bool isCompatible(
epics::pvData::StructureConstPtr const &structure);
/**
* Returns whether the specified PVStructure is compatible with NTUnion.
* <p>
* Checks if the specified PVStructure is compatible with this version
* of NTUnion through the introspection interface
* @param pvStructure the PVStructure to test
* @return (false,true) if the specified PVStructure (is not, is) a compatible NTUnion
*/
static bool isCompatible(
epics::pvData::PVStructurePtr const &pvStructure);
/**
* Returns whether the wrapped PVStructure is a valid NTUnion.
* <p>
* Unlike isCompatible(), isValid() may perform checks on the value
* data as well as the introspection data.
*
* @return (false,true) if wrapped PVStructure (is not, is) a valid NTUnion
*/
bool isValid();
/**
* Creates an NTUnion builder instance.
* @return builder instance.
*/
static NTUnionBuilderPtr createBuilder();
/**
* Destructor.
*/
~NTUnion() {}
/**
* Attaches a PVTimeStamp to the wrapped PVStructure.
* Does nothing if no timeStamp field.
* @param pvTimeStamp the PVTimeStamp that will be attached.
* @return true if the operation was successfull (i.e. this instance has a timeStamp field), otherwise false.
*/
bool attachTimeStamp(epics::pvData::PVTimeStamp &pvTimeStamp) const;
/**
* Attaches a PVAlarm to the wrapped PVStructure.
* Does nothing if no alarm field.
* @param pvAlarm the PVAlarm that will be attached.
* @return true if the operation was successfull (i.e. this instance has an alarm field), otherwise false.
*/
bool attachAlarm(epics::pvData::PVAlarm &pvAlarm) const;
/**
* Returns the PVStructure wrapped by this instance.
* @return the PVStructure wrapped by this instance.
*/
epics::pvData::PVStructurePtr getPVStructure() const;
/**
* Returns the descriptor field.
* @return the descriptor field or null if no descriptor field.
*/
epics::pvData::PVStringPtr getDescriptor() const;
/**
* Returns the timeStamp field.
* @return the timStamp field or null if no timeStamp field.
*/
epics::pvData::PVStructurePtr getTimeStamp() const;
/**
* Returns the alarm field.
* @return the alarm field or null if no alarm field.
*/
epics::pvData::PVStructurePtr getAlarm() const;
/**
* Returns the value field.
* @return the value field.
*/
epics::pvData::PVUnionPtr getValue() const;
private:
NTUnion(epics::pvData::PVStructurePtr const & pvStructure);
epics::pvData::PVStructurePtr pvNTUnion;
epics::pvData::PVUnionPtr pvValue;
friend class detail::NTUnionBuilder;
};
}}
#endif /* NTUNION_H */

249
src/nt/nturi.cpp Normal file
View File

@@ -0,0 +1,249 @@
/* nturi.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* This software is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#include <algorithm>
#define epicsExportSharedSymbols
#include <pv/nturi.h>
#include <pv/ntutils.h>
using namespace std;
using namespace epics::pvData;
namespace epics { namespace nt {
static NTFieldPtr ntField = NTField::get();
namespace detail {
NTURIBuilder::shared_pointer NTURIBuilder::addQueryString(std::string const & name)
{
if (std::find(queryFieldNames.begin(), queryFieldNames.end(), name) != queryFieldNames.end())
throw std::runtime_error("duplicate query field name");
queryFieldNames.push_back(name);
queryTypes.push_back(pvString);
return shared_from_this();
}
NTURIBuilder::shared_pointer NTURIBuilder::addQueryDouble(std::string const & name)
{
if (std::find(queryFieldNames.begin(), queryFieldNames.end(), name) != queryFieldNames.end())
throw std::runtime_error("duplicate query field name");
queryFieldNames.push_back(name);
queryTypes.push_back(pvDouble);
return shared_from_this();
}
NTURIBuilder::shared_pointer NTURIBuilder::addQueryInt(std::string const & name)
{
if (std::find(queryFieldNames.begin(), queryFieldNames.end(), name) != queryFieldNames.end())
throw std::runtime_error("duplicate query field name");
queryFieldNames.push_back(name);
queryTypes.push_back(pvInt);
return shared_from_this();
}
StructureConstPtr NTURIBuilder::createStructure()
{
FieldBuilderPtr builder = getFieldCreate()->
createFieldBuilder()->
setId(NTURI::URI)->
add("scheme", pvString);
if (authority)
builder->add("authority", pvString);
builder->add("path", pvString);
if (!queryFieldNames.empty())
{
FieldBuilderPtr nestedBuilder = builder->
addNestedStructure("query");
vector<string>::size_type len = queryFieldNames.size();
for (vector<string>::size_type i = 0; i < len; i++)
nestedBuilder->add(queryFieldNames[i], queryTypes[i]);
builder = nestedBuilder->endNested();
}
size_t extraCount = extraFieldNames.size();
for (size_t i = 0; i< extraCount; i++)
builder->add(extraFieldNames[i], extraFields[i]);
StructureConstPtr s = builder->createStructure();
reset();
return s;
}
NTURIBuilder::shared_pointer NTURIBuilder::addAuthority()
{
authority = true;
return shared_from_this();
}
PVStructurePtr NTURIBuilder::createPVStructure()
{
return getPVDataCreate()->createPVStructure(createStructure());
}
NTURIPtr NTURIBuilder::create()
{
return NTURIPtr(new NTURI(createPVStructure()));
}
NTURIBuilder::NTURIBuilder()
{
reset();
}
void NTURIBuilder::reset()
{
queryFieldNames.clear();
queryTypes.clear();
authority = false;
}
NTURIBuilder::shared_pointer NTURIBuilder::add(string const & name, FieldConstPtr const & field)
{
extraFields.push_back(field);
extraFieldNames.push_back(name);
return shared_from_this();
}
}
const std::string NTURI::URI("epics:nt/NTURI:1.0");
NTURI::shared_pointer NTURI::wrap(PVStructurePtr const & pvStructure)
{
if(!isCompatible(pvStructure)) return shared_pointer();
return wrapUnsafe(pvStructure);
}
NTURI::shared_pointer NTURI::wrapUnsafe(PVStructurePtr const & pvStructure)
{
return shared_pointer(new NTURI(pvStructure));
}
bool NTURI::is_a(StructureConstPtr const & structure)
{
return NTUtils::is_a(structure->getID(), URI);
}
bool NTURI::isCompatible(StructureConstPtr const & structure)
{
if (!structure.get()) return false;
ScalarConstPtr schemeField = structure->getField<Scalar>("scheme");
if (schemeField.get() == 0 || schemeField->getScalarType() != pvString)
return false;
ScalarConstPtr pathField = structure->getField<Scalar>("path");
if (pathField.get() == 0 || pathField->getScalarType() != pvString)
return false;
FieldConstPtr field = structure->getField("authority");
if (field.get())
{
ScalarConstPtr authorityField = structure->getField<Scalar>("authority");
if (!authorityField.get() || authorityField->getScalarType() != pvString)
return false;
}
field = structure->getField("query");
if (field.get())
{
StructureConstPtr queryField = structure->getField<Structure>("query");
if (!queryField.get())
return false;
FieldConstPtrArray const & fields = queryField->getFields();
for (FieldConstPtrArray::const_iterator it = fields.begin();
it != fields.end(); ++it)
{
if ((*it)->getType() != scalar) return false;
ScalarType scalarType = std::tr1::dynamic_pointer_cast<const Scalar>(
(*it))->getScalarType();
if (scalarType != pvString &&
scalarType != pvInt &&
scalarType != pvDouble) return false;
}
}
return true;
}
bool NTURI::isCompatible(PVStructurePtr const & pvStructure)
{
if(!pvStructure) return false;
return isCompatible(pvStructure->getStructure());
}
bool NTURI::isValid()
{
return true;
}
NTURIBuilderPtr NTURI::createBuilder()
{
return NTURIBuilderPtr(new detail::NTURIBuilder());
}
PVStructurePtr NTURI::getPVStructure() const
{
return pvNTURI;
}
PVStringPtr NTURI::getScheme() const
{
return pvNTURI->getSubField<PVString>("scheme");
}
PVStringPtr NTURI::getAuthority() const
{
return pvNTURI->getSubField<PVString>("authority");
}
PVStringPtr NTURI::getPath() const
{
return pvNTURI->getSubField<PVString>("path");
}
PVStructurePtr NTURI::getQuery() const
{
return pvNTURI->getSubField<PVStructure>("query");
}
StringArray const & NTURI::getQueryNames() const
{
return pvNTURI->getSubField<PVStructure>("query")->getStructure()->getFieldNames();
}
PVFieldPtr NTURI::getQueryField(std::string const & name) const
{
return pvNTURI->getSubField("query." + name);
}
NTURI::NTURI(PVStructurePtr const & pvStructure) :
pvNTURI(pvStructure)
{}
}}

310
src/nt/nturi.h Normal file
View File

@@ -0,0 +1,310 @@
/* nturi.h */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* This software is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#ifndef NTURI_H
#define NTURI_H
#include <vector>
#include <string>
#ifdef epicsExportSharedSymbols
# define nturiEpicsExportSharedSymbols
# undef epicsExportSharedSymbols
#endif
#ifdef nturiEpicsExportSharedSymbols
# define epicsExportSharedSymbols
# undef nturiEpicsExportSharedSymbols
#endif
#include <pv/ntfield.h>
#include <shareLib.h>
namespace epics { namespace nt {
class NTURI;
typedef std::tr1::shared_ptr<NTURI> NTURIPtr;
namespace detail {
/**
* @brief Interface for in-line creating of NTURI.
*
* One instance can be used to create multiple instances.
* An instance of this object must not be used concurrently (an object has a state).
* @author dgh
*/
class epicsShareClass NTURIBuilder :
public std::tr1::enable_shared_from_this<NTURIBuilder>
{
public:
POINTER_DEFINITIONS(NTURIBuilder);
/**
* Adds authority field to the NTURI.
* @return this instance of <b>NTURIBuilder</b>.
*/
shared_pointer addAuthority();
/**
* Adds extra <b>Scalar</b> of ScalarType pvString
* to the query field of the type.
* @param name name of the field.
* @return this instance of <b>NTURIBuilder</b>.
*/
shared_pointer addQueryString(std::string const & name);
/**
* Adds extra <b>Scalar</b> of ScalarType pvDouble
* to the query field of the type.
* @param name name of the field.
* @return this instance of <b>NTURIBuilder</b>.
*/
shared_pointer addQueryDouble(std::string const & name);
/**
* Adds extra <b>Scalar</b> of ScalarType pvInt
* to the query field of the type.
* @param name name of the field.
* @return this instance of <b>NTURIBuilder</b>.
*/
shared_pointer addQueryInt(std::string const & name);
/**
* Creates a <b>Structure</b> that represents NTURI.
* This resets this instance state and allows new instance to be created.
* @return a new instance of <b>Structure</b>.
*/
epics::pvData::StructureConstPtr createStructure();
/**
* Creates a <b>PVStructure</b> that represents NTURI.
* The returned PVStructure will have labels equal to the column names.
* This resets this instance state and allows new instance to be created.
* @return a new instance of <b>PVStructure</b>.
*/
epics::pvData::PVStructurePtr createPVStructure();
/**
* Creates a <b>NTURI</b> instance.
* The returned NTURI will wrap a PVStructure which will have
* labels equal to the column names.
* This resets this instance state and allows new instance to be created.
* @return a new instance of <b>NTURI</b>.
*/
NTURIPtr create();
/**
* Adds extra <b>Field</b> to the type.
* @param name the name of the field.
* @param field the field to be added.
* @return this instance of <b>NTURIBuilder</b>.
*/
shared_pointer add(std::string const & name, epics::pvData::FieldConstPtr const & field);
private:
NTURIBuilder();
void reset();
std::vector<std::string> queryFieldNames;
std::vector<epics::pvData::ScalarType> queryTypes;
bool authority;
// NOTE: this preserves order, however it does not handle duplicates
epics::pvData::StringArray extraFieldNames;
epics::pvData::FieldConstPtrArray extraFields;
friend class ::epics::nt::NTURI;
};
}
typedef std::tr1::shared_ptr<detail::NTURIBuilder> NTURIBuilderPtr;
/**
* @brief Convenience Class for NTURI
*
* @author dgh
*/
class epicsShareClass NTURI
{
public:
POINTER_DEFINITIONS(NTURI);
static const std::string URI;
/**
* Creates an NTURI wrapping the specified PVStructure if the latter is compatible.
* <p>
* Checks the supplied PVStructure is compatible with NTURI
* and if so returns an NTURI which wraps it.
* This method will return null if the structure is is not compatible
* or is null.
*
* @param pvStructure the PVStructure to be wrapped
* @return NTURI instance wrapping pvStructure on success, null otherwise
*/
static shared_pointer wrap(epics::pvData::PVStructurePtr const & pvStructure);
/**
* Creates an NTScalar wrapping the specified PVStructure, regardless of the latter's compatibility.
* <p>
* No checks are made as to whether the specified PVStructure
* is compatible with NTScalar or is non-null.
*
* @param pvStructure the PVStructure to be wrapped
* @return NTScalar instance wrapping pvStructure
*/
static shared_pointer wrapUnsafe(epics::pvData::PVStructurePtr const & pvStructure);
/**
* Returns whether the specified Structure reports to be a compatible NTScalar.
* <p>
* Checks if the specified Structure reports compatibility with this
* version of NTScalar through its type ID, including checking version numbers.
* The return value does not depend on whether the structure is actually
* compatible in terms of its introspection type.
*
* @param structure the Structure to test
* @return (false,true) if (is not, is) a compatible NTScalar
*/
static bool is_a(epics::pvData::StructureConstPtr const & structure);
/**
* Returns whether the specified PVStructure reports to be a compatible NTURI.
* <p>
* Checks if the specified PVStructure reports compatibility with this
* version of NTURI through its type ID, including checking version numbers.
* The return value does not depend on whether the structure is actually
* compatible in terms of its introspection type.
*
* @param pvStructure the PVStructure to test.
* @return (false,true) if the specified PVStructure (is not, is) a compatible NTURI.
*/
static bool is_a(epics::pvData::PVStructurePtr const & pvStructure);
/**
* Returns whether the specified Structure is compatible with NTURI.
* <p>
* Checks if the specified Structure is compatible with this version
* of NTURI through the introspection interface.
*
* @param structure the Structure to test
* @return (false,true) if the specified Structure (is not, is) a compatible NTURI
*/
static bool isCompatible(
epics::pvData::StructureConstPtr const &structure);
/**
* Returns whether the specified PVStructure is compatible with NTURI.
* <p>
* Checks if the specified PVStructure is compatible with this version
* of NTURI through the introspection interface.
*
* @param pvStructure the PVStructure to test
* @return (false,true) if the specified PVStructure (is not, is) a compatible NTURI
*/
static bool isCompatible(
epics::pvData::PVStructurePtr const &pvStructure);
/**
* Returns whether the wrapped PVStructure is a valid NTURI.
* <p>
* Unlike isCompatible(), isValid() may perform checks on the value
* data as well as the introspection data.
*
* @return (false,true) if wrapped PVStructure (is not, is) a valid NTURI.
*/
bool isValid();
/**
* Creates an NTURI builder instance.
* @return builder instance.
*/
static NTURIBuilderPtr createBuilder();
/**
* Destructor.
*/
~NTURI() {}
/**
* Returns the PVStructure wrapped by this instance.
* @return the PVStructure wrapped by this instance.
*/
epics::pvData::PVStructurePtr getPVStructure() const;
/**
* Returns the scheme field.
* @return the scheme field.
*/
epics::pvData::PVStringPtr getScheme() const;
/**
* Returns the authority field.
* @return the authority field or null if no such field.
*/
epics::pvData::PVStringPtr getAuthority() const;
/**
* Returns the path field.
* @return the path field.
*/
epics::pvData::PVStringPtr getPath() const;
/**
* Returns the query field.
* @return the query field or null if no such field.
*/
epics::pvData::PVStructurePtr getQuery() const;
/**
* Returns the names of the query fields for the URI.
* For each name, calling getQueryField should return
* the query field, which should not be null.
* @return The query field names.
*/
epics::pvData::StringArray const & getQueryNames() const;
/**
* Returns the subfield of the query field with the specified name.
* @param name the name of the subfield.
* @return the the subfield of the query field or null if the field does not exist.
*/
epics::pvData::PVFieldPtr getQueryField(std::string const & name) const;
/**
* Returns the subfield of the query field (parameter) with the specified
* name and of a specified expected type (for example, PVString).
* @tparam PVT the expected type of the subfield which should be
* be PVString, PVInt pr PVDouble.
* @param name the subfield of the query field or null if the field does
* not exist or is not of the expected type.
* @return The PVT field.
*/
template<typename PVT>
std::tr1::shared_ptr<PVT> getQueryField(std::string const & name) const
{
epics::pvData::PVFieldPtr pvField = getQueryField(name);
if (pvField.get())
return std::tr1::dynamic_pointer_cast<PVT>(pvField);
else
return std::tr1::shared_ptr<PVT>();
}
private:
NTURI(epics::pvData::PVStructurePtr const & pvStructure);
epics::pvData::PVStructurePtr pvNTURI;
friend class detail::NTURIBuilder;
};
}}
#endif /* NTURI_H */

28
src/nt/ntutils.cpp Normal file
View File

@@ -0,0 +1,28 @@
/* ntutils.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* This software is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#define epicsExportSharedSymbols
#include <pv/ntutils.h>
using namespace std;
namespace epics { namespace nt {
bool NTUtils::is_a(const std::string &u1, const std::string &u2)
{
// remove minor for the u1
size_t pos1 = u1.find_last_of('.');
std::string su1 = (pos1 == string::npos) ? u1 : u1.substr(0, pos1);
// remove minor for the u2
size_t pos2 = u2.find_last_of('.');
std::string su2 = (pos2 == string::npos) ? u2 : u2.substr(0, pos2);
return su2 == su1;
}
}}

40
src/nt/ntutils.h Normal file
View File

@@ -0,0 +1,40 @@
/* ntutils.h */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* This software is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#ifndef NTUTILS_H
#define NTUTILS_H
#include <string>
#include <shareLib.h>
namespace epics { namespace nt {
/**
* @brief Utility methods for NT types.
*
* @author mse
*/
class epicsShareClass NTUtils {
public:
/**
* Checks whether NT types are compatible by checking their IDs,
* i.e. their names and major version must match.
* @param u1 the first URI.
* @param u2 the second URI.
* @return true if URIs are compatible, false otherwise.
*/
static bool is_a(const std::string &u1, const std::string &u2);
private:
// disable object creation
NTUtils() {}
};
}}
#endif /* NTUTILS_H */

View File

@@ -24,6 +24,10 @@ TESTPROD_HOST += ntmultiChannelTest
ntmultiChannelTest_SRCS += ntmultiChannelTest.cpp
TESTS += ntmultiChannelTest
TESTPROD_HOST += ntscalarMultiChannelTest
ntscalarMultiChannelTest_SRCS += ntscalarMultiChannelTest.cpp
TESTS += ntscalarMultiChannelTest
TESTPROD_HOST += nttableTest
nttableTest_SRCS = nttableTest.cpp
TESTS += nttableTest
@@ -32,6 +36,42 @@ TESTPROD_HOST += ntndarrayTest
ntndarrayTest_SRCS = ntndarrayTest.cpp
TESTS += ntndarrayTest
TESTPROD_HOST += ntmatrixTest
ntmatrixTest_SRCS = ntmatrixTest.cpp
TESTS += ntmatrixTest
TESTPROD_HOST += ntenumTest
ntenumTest_SRCS = ntenumTest.cpp
TESTS += ntenumTest
TESTPROD_HOST += ntunionTest
ntunionTest_SRCS = ntunionTest.cpp
TESTS += ntunionTest
TESTPROD_HOST += ntaggregateTest
ntaggregateTest_SRCS = ntaggregateTest.cpp
TESTS += ntaggregateTest
TESTPROD_HOST += ntattributeTest
ntattributeTest_SRCS = ntattributeTest.cpp
TESTS += ntattributeTest
TESTPROD_HOST += ntndarrayAttributeTest
ntndarrayAttributeTest_SRCS = ntndarrayAttributeTest.cpp
TESTS += ntndarrayAttributeTest
TESTPROD_HOST += ntcontinuumTest
ntattributeTest_SRCS = ntcontinuumTest.cpp
TESTS += ntcontinuumTest
TESTPROD_HOST += nthistogramTest
ntattributeTest_SRCS = nthistogramTest.cpp
TESTS += nthistogramTest
TESTPROD_HOST += ntutilsTest
ntutilsTest_SRCS = ntutilsTest.cpp
TESTS += ntutilsTest
TESTSCRIPTS_HOST += $(TESTS:%=%.t)
include $(TOP)/configure/RULES

175
test/nt/ntaggregateTest.cpp Normal file
View File

@@ -0,0 +1,175 @@
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* This software 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/nt.h>
using namespace epics::nt;
using namespace epics::pvData;
using std::tr1::dynamic_pointer_cast;
static FieldCreatePtr fieldCreate = getFieldCreate();
static StandardFieldPtr standardField = getStandardField();
static NTFieldPtr ntField = NTField::get();
void test_builder()
{
testDiag("test_builder");
NTAggregateBuilderPtr builder = NTAggregate::createBuilder();
testOk(builder.get() != 0, "Got builder");
StructureConstPtr structure = builder->
addDescriptor()->
addAlarm()->
addTimeStamp()->
add("valueAlarm",standardField->doubleAlarm()) ->
add("extra",fieldCreate->createScalarArray(pvString)) ->
createStructure();
testOk1(structure.get() != 0);
if (!structure)
return;
testOk1(NTAggregate::is_a(structure));
testOk1(structure->getID() == NTAggregate::URI);
testOk1(structure->getNumberFields() == 7);
testOk1(structure->getField("value").get() != 0);
testOk1(structure->getField("descriptor").get() != 0);
testOk1(structure->getField("alarm").get() != 0);
testOk1(structure->getField("timeStamp").get() != 0);
ScalarConstPtr valueField = structure->getField<Scalar>("value");
testOk(valueField.get() != 0, "value is scalar");
std::cout << *structure << std::endl;
}
void test_ntaggregate()
{
testDiag("test_ntaggregate");
NTAggregateBuilderPtr builder = NTAggregate::createBuilder();
testOk(builder.get() != 0, "Got builder");
NTAggregatePtr ntAggregate = builder->
addDescriptor()->
addAlarm()->
addTimeStamp()->
add("valueAlarm",standardField->intAlarm()) ->
create();
testOk1(ntAggregate.get() != 0);
testOk1(ntAggregate->getPVStructure().get() != 0);
testOk1(ntAggregate->getValue().get() != 0);
testOk1(ntAggregate->getDescriptor().get() != 0);
testOk1(ntAggregate->getAlarm().get() != 0);
testOk1(ntAggregate->getTimeStamp().get() != 0);
//
// example how to set a value
//
ntAggregate->getValue()->put(1.0);
//
// example how to get a value
//
double value = ntAggregate->getValue()->get();
testOk1(value == 1.0);
//
// timeStamp ops
//
PVTimeStamp pvTimeStamp;
if (ntAggregate->attachTimeStamp(pvTimeStamp))
{
testPass("timeStamp attach");
// example how to set current time
TimeStamp ts;
ts.getCurrent();
pvTimeStamp.set(ts);
// example how to get EPICS time
TimeStamp ts2;
pvTimeStamp.get(ts2);
testOk1(ts2.getEpicsSecondsPastEpoch() != 0);
}
else
testFail("timeStamp attach fail");
//
// alarm ops
//
PVAlarm pvAlarm;
if (ntAggregate->attachAlarm(pvAlarm))
{
testPass("alarm attach");
// example how to set an alarm
Alarm alarm;
alarm.setStatus(deviceStatus);
alarm.setSeverity(minorAlarm);
alarm.setMessage("simulation alarm");
pvAlarm.set(alarm);
}
else
testFail("alarm attach fail");
//
// set descriptor
//
ntAggregate->getDescriptor()->put("This is a test NTAggregate");
// dump ntAggregate
std::cout << *ntAggregate->getPVStructure() << std::endl;
}
void test_wrap()
{
testDiag("test_wrap");
NTAggregatePtr nullPtr = NTAggregate::wrap(PVStructurePtr());
testOk(nullPtr.get() == 0, "nullptr wrap");
nullPtr = NTAggregate::wrap(
getPVDataCreate()->createPVStructure(
NTField::get()->createTimeStamp()
)
);
testOk(nullPtr.get() == 0, "wrong type wrap");
NTAggregateBuilderPtr builder = NTAggregate::createBuilder();
testOk(builder.get() != 0, "Got builder");
PVStructurePtr pvStructure = builder->
createPVStructure();
testOk1(pvStructure.get() != 0);
if (!pvStructure)
return;
testOk1(NTAggregate::isCompatible(pvStructure)==true);
NTAggregatePtr ptr = NTAggregate::wrap(pvStructure);
testOk(ptr.get() != 0, "wrap OK");
ptr = NTAggregate::wrapUnsafe(pvStructure);
testOk(ptr.get() != 0, "wrapUnsafe OK");
}
MAIN(testNTAggregate) {
testPlan(28);
test_builder();
test_ntaggregate();
test_wrap();
return testDone();
}

176
test/nt/ntattributeTest.cpp Normal file
View File

@@ -0,0 +1,176 @@
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* This software 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/nt.h>
using namespace epics::nt;
using namespace epics::pvData;
using std::tr1::dynamic_pointer_cast;
static FieldCreatePtr fieldCreate = getFieldCreate();
static StandardFieldPtr standardField = getStandardField();
static NTFieldPtr ntField = NTField::get();
void test_builder()
{
testDiag("test_builder");
NTAttributeBuilderPtr builder = NTAttribute::createBuilder();
testOk(builder.get() != 0, "Got builder");
StructureConstPtr structure = builder->
addTags()->
addDescriptor()->
addAlarm()->
addTimeStamp()->
add("extra",fieldCreate->createScalar(pvString)) ->
createStructure();
testOk1(structure.get() != 0);
if (!structure)
return;
testOk1(NTAttribute::is_a(structure));
testOk1(structure->getID() == NTAttribute::URI);
testOk1(structure->getNumberFields() == 7);
testOk1(structure->getField("name").get() != 0);
testOk1(structure->getField("value").get() != 0);
testOk1(structure->getField("tags").get() != 0);
testOk1(structure->getField("descriptor").get() != 0);
testOk1(structure->getField("alarm").get() != 0);
testOk1(structure->getField("timeStamp").get() != 0);
ScalarConstPtr nameField = structure->getField<Scalar>("name");
testOk(nameField.get() != 0 && nameField->getScalarType() == pvString,
"name is string");
UnionConstPtr valueField = structure->getField<Union>("value");
testOk(valueField.get() != 0, "value is enum");
ScalarArrayConstPtr tagsField = structure->getField<ScalarArray>("tags");
testOk(tagsField.get() != 0 && tagsField->getElementType() == pvString,
"tags is string[]");
std::cout << *structure << std::endl;
}
void test_ntattribute()
{
testDiag("test_ntattribute");
NTAttributeBuilderPtr builder = NTAttribute::createBuilder();
testOk(builder.get() != 0, "Got builder");
NTAttributePtr ntAttribute = builder->
addTags()->
addDescriptor()->
addAlarm()->
addTimeStamp()->
create();
testOk1(ntAttribute.get() != 0);
testOk1(ntAttribute->getPVStructure().get() != 0);
testOk1(ntAttribute->getName().get() != 0);
testOk1(ntAttribute->getValue().get() != 0);
testOk1(ntAttribute->getTags().get() != 0);
testOk1(ntAttribute->getDescriptor().get() != 0);
testOk1(ntAttribute->getAlarm().get() != 0);
testOk1(ntAttribute->getTimeStamp().get() != 0);
//
// timeStamp ops
//
PVTimeStamp pvTimeStamp;
if (ntAttribute->attachTimeStamp(pvTimeStamp))
{
testPass("timeStamp attach");
// example how to set current time
TimeStamp ts;
ts.getCurrent();
pvTimeStamp.set(ts);
// example how to get EPICS time
TimeStamp ts2;
pvTimeStamp.get(ts2);
testOk1(ts2.getEpicsSecondsPastEpoch() != 0);
}
else
testFail("timeStamp attach fail");
//
// alarm ops
//
PVAlarm pvAlarm;
if (ntAttribute->attachAlarm(pvAlarm))
{
testPass("alarm attach");
// example how to set an alarm
Alarm alarm;
alarm.setStatus(deviceStatus);
alarm.setSeverity(minorAlarm);
alarm.setMessage("simulation alarm");
pvAlarm.set(alarm);
}
else
testFail("alarm attach fail");
//
// set descriptor
//
ntAttribute->getDescriptor()->put("This is a test NTAttribute");
// dump ntAttribute
std::cout << *ntAttribute->getPVStructure() << std::endl;
}
void test_wrap()
{
testDiag("test_wrap");
NTAttributePtr nullPtr = NTAttribute::wrap(PVStructurePtr());
testOk(nullPtr.get() == 0, "nullptr wrap");
nullPtr = NTAttribute::wrap(
getPVDataCreate()->createPVStructure(
NTField::get()->createTimeStamp()
)
);
testOk(nullPtr.get() == 0, "wrong type wrap");
NTAttributeBuilderPtr builder = NTAttribute::createBuilder();
testOk(builder.get() != 0, "Got builder");
PVStructurePtr pvStructure = builder->
createPVStructure();
testOk1(pvStructure.get() != 0);
if (!pvStructure)
return;
testOk1(NTAttribute::isCompatible(pvStructure)==true);
NTAttributePtr ptr = NTAttribute::wrap(pvStructure);
testOk(ptr.get() != 0, "wrap OK");
ptr = NTAttribute::wrapUnsafe(pvStructure);
testOk(ptr.get() != 0, "wrapUnsafe OK");
}
MAIN(testNTAttribute) {
testPlan(33);
test_builder();
test_ntattribute();
test_wrap();
return testDone();
}

276
test/nt/ntcontinuumTest.cpp Normal file
View File

@@ -0,0 +1,276 @@
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* This software 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/nt.h>
using namespace epics::nt;
using namespace epics::pvData;
using std::tr1::dynamic_pointer_cast;
static FieldCreatePtr fieldCreate = getFieldCreate();
void test_builder()
{
testDiag("test_builder");
NTContinuumBuilderPtr builder = NTContinuum::createBuilder();
testOk(builder.get() != 0, "Got builder");
StructureConstPtr structure = builder->
addDescriptor()->
addAlarm()->
addTimeStamp()->
add("extra1",fieldCreate->createScalar(pvString)) ->
add("extra2",fieldCreate->createScalarArray(pvString)) ->
createStructure();
testOk1(structure.get() != 0);
if (!structure)
return;
testOk1(NTContinuum::is_a(structure));
testOk1(structure->getID() == NTContinuum::URI);
testOk1(structure->getNumberFields() == 8);
testOk1(structure->getField("base").get() != 0);
testOk1(structure->getField("value").get() != 0);
testOk1(structure->getField("units").get() != 0);
testOk1(structure->getField("descriptor").get() != 0);
testOk1(structure->getField("alarm").get() != 0);
testOk1(structure->getField("timeStamp").get() != 0);
testOk(dynamic_pointer_cast<const ScalarArray>(structure->getField("base")).get() != 0 &&
dynamic_pointer_cast<const ScalarArray>(structure->getField("base"))->getElementType() == pvDouble, "base array element type");
testOk(dynamic_pointer_cast<const ScalarArray>(structure->getField("value")).get() != 0 &&
dynamic_pointer_cast<const ScalarArray>(structure->getField("value"))->getElementType() == pvDouble, "value array element type");
testOk(dynamic_pointer_cast<const ScalarArray>(structure->getField("units")).get() != 0 &&
dynamic_pointer_cast<const ScalarArray>(structure->getField("units"))->getElementType() == pvString, "units array element type");
std::cout << *structure << std::endl;
}
void test_ntcontinuum()
{
testDiag("test_ntcontinuum");
NTContinuumBuilderPtr builder = NTContinuum::createBuilder();
testOk(builder.get() != 0, "Got builder");
NTContinuumPtr ntContinuum = builder->
addDescriptor()->
addAlarm()->
addTimeStamp()->
add("extra1",fieldCreate->createScalar(pvString)) ->
add("extra2",fieldCreate->createScalarArray(pvString)) ->
create();
testOk1(ntContinuum.get() != 0);
testOk1(ntContinuum->getPVStructure().get() != 0);
testOk1(ntContinuum->getDescriptor().get() != 0);
testOk1(ntContinuum->getAlarm().get() != 0);
testOk1(ntContinuum->getTimeStamp().get() != 0);
testOk1(ntContinuum->getBase().get() != 0);
testOk1(ntContinuum->getValue().get() != 0);
//
// example how to set base
//
PVDoubleArray::svector newBase;
newBase.push_back(1.0);
newBase.push_back(2.0);
PVDoubleArrayPtr pvBaseField = ntContinuum->getBase();
pvBaseField->replace(freeze(newBase));
//
// example how to get bases
//
PVDoubleArray::const_svector base(pvBaseField->view());
testOk1(base.size() == 2);
testOk1(base[0] == 1.0);
testOk1(base[1] == 2.0);
//
// example how to set values
//
PVDoubleArray::svector newValue;
newValue.push_back(1.0);
newValue.push_back(2.0);
newValue.push_back(10.0);
newValue.push_back(20.0);
newValue.push_back(100.0);
newValue.push_back(200.0);
PVDoubleArrayPtr pvValueField = ntContinuum->getValue();
pvValueField->replace(freeze(newValue));
//
// example how to get values
//
PVDoubleArray::const_svector value(pvValueField->view());
testOk1(value.size() == 6);
testOk1(value[0] == 1.0);
testOk1(value[1] == 2.0);
testOk1(value[2] == 10.0);
testOk1(value[3] == 20.0);
testOk1(value[4] == 100.0);
testOk1(value[5] == 200.0);
//
// example how to set units
//
PVStringArray::svector newUnits;
newUnits.push_back("s");
newUnits.push_back("ms");
newUnits.push_back("us");
newUnits.push_back("s");
PVStringArrayPtr pvUnitsField = ntContinuum->getUnits();
pvUnitsField->replace(freeze(newUnits));
//
// example how to get units
//
PVStringArray::const_svector units(pvUnitsField->view());
testOk1(units.size() == 4);
testOk1(units[0] == "s");
testOk1(units[1] == "ms");
testOk1(units[2] == "us");
testOk1(units[3] == "s");
//
// test isValid
//
testOk1(ntContinuum->isValid());
//
// timeStamp ops
//
PVTimeStamp pvTimeStamp;
if (ntContinuum->attachTimeStamp(pvTimeStamp))
{
testPass("timeStamp attach");
// example how to set current time
TimeStamp ts;
ts.getCurrent();
pvTimeStamp.set(ts);
// example how to get EPICS time
TimeStamp ts2;
pvTimeStamp.get(ts2);
testOk1(ts2.getEpicsSecondsPastEpoch() != 0);
}
else
testFail("timeStamp attach fail");
//
// alarm ops
//
PVAlarm pvAlarm;
if (ntContinuum->attachAlarm(pvAlarm))
{
testPass("alarm attach");
// example how to set an alarm
Alarm alarm;
alarm.setStatus(deviceStatus);
alarm.setSeverity(minorAlarm);
alarm.setMessage("simulation alarm");
pvAlarm.set(alarm);
}
else
testFail("alarm attach fail");
//
// set descriptor
//
ntContinuum->getDescriptor()->put("This is a test NTContinuum");
// dump NTContinuum
std::cout << *ntContinuum->getPVStructure() << std::endl;
}
void test_wrap()
{
testDiag("test_wrap");
NTContinuumPtr nullPtr = NTContinuum::wrap(PVStructurePtr());
testOk(nullPtr.get() == 0, "nullptr wrap");
nullPtr = NTContinuum::wrap(
getPVDataCreate()->createPVStructure(
NTField::get()->createTimeStamp()
)
);
testOk(nullPtr.get() == 0, "wrong type wrap");
NTContinuumBuilderPtr builder = NTContinuum::createBuilder();
testOk(builder.get() != 0, "Got builder");
PVStructurePtr pvStructure = builder->
createPVStructure();
testOk1(pvStructure.get() != 0);
if (!pvStructure)
return;
testOk1(NTContinuum::isCompatible(pvStructure)==true);
NTContinuumPtr ptr = NTContinuum::wrap(pvStructure);
testOk(ptr.get() != 0, "wrap OK");
ptr = NTContinuum::wrapUnsafe(pvStructure);
testOk(ptr.get() != 0, "wrapUnsafe OK");
}
void test_extra()
{
testDiag("test_extra");
NTContinuumBuilderPtr builder = NTContinuum::createBuilder();
testOk(builder.get() != 0, "Got builder");
StructureConstPtr structure = builder->
addTimeStamp()->
add("function", getFieldCreate()->createScalar(pvString))->
createStructure();
testOk1(structure.get() != 0);
if (!structure)
return;
testOk1(NTContinuum::is_a(structure));
testOk1(structure->getID() == NTContinuum::URI);
testOk1(structure->getNumberFields() == 5);
testOk1(structure->getField("base").get() != 0);
testOk1(structure->getField("value").get() != 0);
testOk1(structure->getField("units").get() != 0);
testOk1(structure->getField("timeStamp").get() != 0);
testOk1(structure->getField("function").get() != 0);
testOk(dynamic_pointer_cast<const Scalar>(structure->getField("function")).get() != 0 &&
dynamic_pointer_cast<const Scalar>(structure->getField("function"))->getScalarType() == pvString, "function type");
std::cout << *structure << std::endl;
}
MAIN(testNTContinuum) {
testPlan(59);
test_builder();
test_ntcontinuum();
test_wrap();
test_extra();
return testDone();
}

188
test/nt/ntenumTest.cpp Normal file
View File

@@ -0,0 +1,188 @@
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* This software 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/nt.h>
using namespace epics::nt;
using namespace epics::pvData;
using std::tr1::dynamic_pointer_cast;
static FieldCreatePtr fieldCreate = getFieldCreate();
static StandardFieldPtr standardField = getStandardField();
static NTFieldPtr ntField = NTField::get();
void test_builder()
{
testDiag("test_builder");
NTEnumBuilderPtr builder = NTEnum::createBuilder();
testOk(builder.get() != 0, "Got builder");
StructureConstPtr structure = builder->
addDescriptor()->
addAlarm()->
addTimeStamp()->
add("valueAlarm",standardField->doubleAlarm()) ->
add("extra",fieldCreate->createScalarArray(pvString)) ->
createStructure();
testOk1(structure.get() != 0);
if (!structure)
return;
testOk1(NTEnum::is_a(structure));
testOk1(structure->getID() == NTEnum::URI);
testOk1(structure->getNumberFields() == 6);
testOk1(structure->getField("value").get() != 0);
testOk1(structure->getField("descriptor").get() != 0);
testOk1(structure->getField("alarm").get() != 0);
testOk1(structure->getField("timeStamp").get() != 0);
FieldConstPtr valueField = structure->getField("value");
testOk(valueField.get() != 0 &&
ntField->isEnumerated(valueField), "value is enum");
std::cout << *structure << std::endl;
}
void test_ntenum()
{
testDiag("test_ntenum");
NTEnumBuilderPtr builder = NTEnum::createBuilder();
testOk(builder.get() != 0, "Got builder");
NTEnumPtr ntEnum = builder->
addDescriptor()->
addAlarm()->
addTimeStamp()->
add("valueAlarm",standardField->intAlarm()) ->
create();
testOk1(ntEnum.get() != 0);
testOk1(ntEnum->getPVStructure().get() != 0);
testOk1(ntEnum->getValue().get() != 0);
testOk1(ntEnum->getDescriptor().get() != 0);
testOk1(ntEnum->getAlarm().get() != 0);
testOk1(ntEnum->getTimeStamp().get() != 0);
//
// example how to set a value
//
PVStructurePtr pvValue = ntEnum->getValue();
//PVStringArray pvChoices = pvValue->getSubField<PVStringArray>("choices");
PVStringArray::svector choices(2);
choices[0] = "Off";
choices[1] = "On";
pvValue->getSubField<PVStringArray>("choices")->replace(freeze(choices));
pvValue->getSubField<PVInt>("index")->put(1);
//
// example how to get a value
//
int32 value = ntEnum->getValue()->getSubField<PVInt>("index")->get();
testOk1(value == 1);
PVStringArrayPtr pvChoices = ntEnum->getValue()->getSubField<PVStringArray>("choices");
std::string choice0 = pvChoices->view()[0];
std::string choice1 = pvChoices->view()[1];
testOk1(choice0 == "Off");
testOk1(choice1 == "On");
//
// timeStamp ops
//
PVTimeStamp pvTimeStamp;
if (ntEnum->attachTimeStamp(pvTimeStamp))
{
testPass("timeStamp attach");
// example how to set current time
TimeStamp ts;
ts.getCurrent();
pvTimeStamp.set(ts);
// example how to get EPICS time
TimeStamp ts2;
pvTimeStamp.get(ts2);
testOk1(ts2.getEpicsSecondsPastEpoch() != 0);
}
else
testFail("timeStamp attach fail");
//
// alarm ops
//
PVAlarm pvAlarm;
if (ntEnum->attachAlarm(pvAlarm))
{
testPass("alarm attach");
// example how to set an alarm
Alarm alarm;
alarm.setStatus(deviceStatus);
alarm.setSeverity(minorAlarm);
alarm.setMessage("simulation alarm");
pvAlarm.set(alarm);
}
else
testFail("alarm attach fail");
//
// set descriptor
//
ntEnum->getDescriptor()->put("This is a test NTEnum");
// dump ntEnum
std::cout << *ntEnum->getPVStructure() << std::endl;
}
void test_wrap()
{
testDiag("test_wrap");
NTEnumPtr nullPtr = NTEnum::wrap(PVStructurePtr());
testOk(nullPtr.get() == 0, "nullptr wrap");
nullPtr = NTEnum::wrap(
getPVDataCreate()->createPVStructure(
NTField::get()->createTimeStamp()
)
);
testOk(nullPtr.get() == 0, "wrong type wrap");
NTEnumBuilderPtr builder = NTEnum::createBuilder();
testOk(builder.get() != 0, "Got builder");
PVStructurePtr pvStructure = builder->
createPVStructure();
testOk1(pvStructure.get() != 0);
if (!pvStructure)
return;
testOk1(NTEnum::isCompatible(pvStructure)==true);
NTEnumPtr ptr = NTEnum::wrap(pvStructure);
testOk(ptr.get() != 0, "wrap OK");
ptr = NTEnum::wrapUnsafe(pvStructure);
testOk(ptr.get() != 0, "wrapUnsafe OK");
}
MAIN(testNTEnum) {
testPlan(30);
test_builder();
test_ntenum();
test_wrap();
return testDone();
}

View File

@@ -1,6 +1,6 @@
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* This software is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
/*
@@ -15,6 +15,7 @@
#include <pv/nt.h>
using namespace epics::nt;
using namespace epics::pvData;
using std::string;
using std::cout;

261
test/nt/nthistogramTest.cpp Normal file
View File

@@ -0,0 +1,261 @@
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* This software 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/nt.h>
using namespace epics::nt;
using namespace epics::pvData;
using std::tr1::dynamic_pointer_cast;
static FieldCreatePtr fieldCreate = getFieldCreate();
void test_builder()
{
testDiag("test_builder");
NTHistogramBuilderPtr builder = NTHistogram::createBuilder();
testOk(builder.get() != 0, "Got builder");
StructureConstPtr structure = builder->
value(pvLong)->
addDescriptor()->
addAlarm()->
addTimeStamp()->
add("extra1",fieldCreate->createScalar(pvString)) ->
add("extra2",fieldCreate->createScalarArray(pvString)) ->
createStructure();
testOk1(structure.get() != 0);
if (!structure)
return;
testOk1(NTHistogram::is_a(structure));
testOk1(structure->getID() == NTHistogram::URI);
testOk1(structure->getNumberFields() == 7);
testOk1(structure->getField("ranges").get() != 0);
testOk1(structure->getField("value").get() != 0);
testOk1(structure->getField("descriptor").get() != 0);
testOk1(structure->getField("alarm").get() != 0);
testOk1(structure->getField("timeStamp").get() != 0);
testOk(dynamic_pointer_cast<const ScalarArray>(structure->getField("ranges")).get() != 0 &&
dynamic_pointer_cast<const ScalarArray>(structure->getField("ranges"))->getElementType() == pvDouble, "ranges array element type");
testOk(dynamic_pointer_cast<const ScalarArray>(structure->getField("value")).get() != 0 &&
dynamic_pointer_cast<const ScalarArray>(structure->getField("value"))->getElementType() == pvLong, "value array element type");
std::cout << *structure << std::endl;
// no value set
try
{
structure = builder->
addDescriptor()->
addAlarm()->
addTimeStamp()->
add("extra1",fieldCreate->createScalar(pvString)) ->
add("extra2",fieldCreate->createScalarArray(pvString)) ->
createStructure();
testFail("no value type set");
} catch (std::runtime_error &) {
testPass("no value type set");
}
}
void test_nthistogram()
{
testDiag("test_nthistogram");
NTHistogramBuilderPtr builder = NTHistogram::createBuilder();
testOk(builder.get() != 0, "Got builder");
NTHistogramPtr ntHistogram = builder->
value(pvInt)->
addDescriptor()->
addAlarm()->
addTimeStamp()->
add("extra1",fieldCreate->createScalar(pvString)) ->
add("extra2",fieldCreate->createScalarArray(pvString)) ->
create();
testOk1(ntHistogram.get() != 0);
testOk1(ntHistogram->getPVStructure().get() != 0);
testOk1(ntHistogram->getDescriptor().get() != 0);
testOk1(ntHistogram->getAlarm().get() != 0);
testOk1(ntHistogram->getTimeStamp().get() != 0);
testOk1(ntHistogram->getRanges().get() != 0);
testOk1(ntHistogram->getValue().get() != 0);
testOk1(ntHistogram->getValue<PVIntArray>().get() != 0);
//
// example how to set ranges
//
PVDoubleArray::svector newRanges;
newRanges.push_back(-100.0);
newRanges.push_back(0.0);
newRanges.push_back(100.0);
PVDoubleArrayPtr pvRangesField = ntHistogram->getRanges();
pvRangesField->replace(freeze(newRanges));
//
// example how to get ranges
//
PVDoubleArray::const_svector ranges(pvRangesField->view());
testOk1(ranges.size() == 3);
testOk1(ranges[0] == -100.0);
testOk1(ranges[1] == 0.0);
testOk1(ranges[2] == 100.0);
//
// example how to set value
//
PVIntArray::svector newValue;
newValue.push_back(1);
newValue.push_back(2);
PVIntArrayPtr pvValueField = ntHistogram->getValue<PVIntArray>();
pvValueField->replace(freeze(newValue));
//
// example how to get values for each bin
//
PVIntArray::const_svector value(pvValueField->view());
testOk1(value.size() == 2);
testOk1(value[0] == 1);
testOk1(value[1] == 2);
//
// test isValid
//
testOk1(ntHistogram->isValid());
//
// timeStamp ops
//
PVTimeStamp pvTimeStamp;
if (ntHistogram->attachTimeStamp(pvTimeStamp))
{
testPass("timeStamp attach");
// example how to set current time
TimeStamp ts;
ts.getCurrent();
pvTimeStamp.set(ts);
// example how to get EPICS time
TimeStamp ts2;
pvTimeStamp.get(ts2);
testOk1(ts2.getEpicsSecondsPastEpoch() != 0);
}
else
testFail("timeStamp attach fail");
//
// alarm ops
//
PVAlarm pvAlarm;
if (ntHistogram->attachAlarm(pvAlarm))
{
testPass("alarm attach");
// example how to set an alarm
Alarm alarm;
alarm.setStatus(deviceStatus);
alarm.setSeverity(minorAlarm);
alarm.setMessage("simulation alarm");
pvAlarm.set(alarm);
}
else
testFail("alarm attach fail");
//
// set descriptor
//
ntHistogram->getDescriptor()->put("This is a test NTHistogram");
// dump NTHistogram
std::cout << *ntHistogram->getPVStructure() << std::endl;
}
void test_wrap()
{
testDiag("test_wrap");
NTHistogramPtr nullPtr = NTHistogram::wrap(PVStructurePtr());
testOk(nullPtr.get() == 0, "nullptr wrap");
nullPtr = NTHistogram::wrap(
getPVDataCreate()->createPVStructure(
NTField::get()->createTimeStamp()
)
);
testOk(nullPtr.get() == 0, "wrong type wrap");
NTHistogramBuilderPtr builder = NTHistogram::createBuilder();
testOk(builder.get() != 0, "Got builder");
PVStructurePtr pvStructure = builder->
value(pvInt)->
createPVStructure();
testOk1(pvStructure.get() != 0);
if (!pvStructure)
return;
testOk1(NTHistogram::isCompatible(pvStructure)==true);
NTHistogramPtr ptr = NTHistogram::wrap(pvStructure);
testOk(ptr.get() != 0, "wrap OK");
ptr = NTHistogram::wrapUnsafe(pvStructure);
testOk(ptr.get() != 0, "wrapUnsafe OK");
}
void test_extra()
{
testDiag("test_extra");
NTHistogramBuilderPtr builder = NTHistogram::createBuilder();
testOk(builder.get() != 0, "Got builder");
StructureConstPtr structure = builder->
value(pvInt)->
addTimeStamp()->
add("function", getFieldCreate()->createScalar(pvString))->
createStructure();
testOk1(structure.get() != 0);
if (!structure)
return;
testOk1(NTHistogram::is_a(structure));
testOk1(structure->getID() == NTHistogram::URI);
testOk1(structure->getNumberFields() == 4);
testOk1(structure->getField("ranges").get() != 0);
testOk1(structure->getField("value").get() != 0);
testOk1(structure->getField("timeStamp").get() != 0);
testOk1(structure->getField("function").get() != 0);
testOk(dynamic_pointer_cast<const Scalar>(structure->getField("function")).get() != 0 &&
dynamic_pointer_cast<const Scalar>(structure->getField("function"))->getScalarType() == pvString, "function type");
std::cout << *structure << std::endl;
}
MAIN(testNTHistogram) {
testPlan(50);
test_builder();
test_nthistogram();
test_wrap();
test_extra();
return testDone();
}

211
test/nt/ntmatrixTest.cpp Normal file
View File

@@ -0,0 +1,211 @@
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* This software 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/nt.h>
using namespace epics::nt;
using namespace epics::pvData;
using std::tr1::dynamic_pointer_cast;
static FieldCreatePtr fieldCreate = getFieldCreate();
void test_builder()
{
testDiag("test_builder");
NTMatrixBuilderPtr builder = NTMatrix::createBuilder();
testOk(builder.get() != 0, "Got builder");
StructureConstPtr structure = builder->
//arrayValue(pvDouble)->
addDim()->
addDescriptor()->
addAlarm()->
addTimeStamp()->
addDisplay()->
add("extra1",fieldCreate->createScalar(pvString)) ->
add("extra2",fieldCreate->createScalarArray(pvString)) ->
createStructure();
testOk1(structure.get() != 0);
if (!structure)
return;
testOk1(NTMatrix::is_a(structure));
testOk1(structure->getID() == NTMatrix::URI);
testOk1(structure->getNumberFields() == 8);
testOk1(structure->getField("value").get() != 0);
testOk1(structure->getField("dim").get() != 0);
testOk1(structure->getField("descriptor").get() != 0);
testOk1(structure->getField("alarm").get() != 0);
testOk1(structure->getField("timeStamp").get() != 0);
testOk1(structure->getField("display").get() != 0);
testOk(dynamic_pointer_cast<const ScalarArray>(structure->getField("value")).get() != 0 &&
dynamic_pointer_cast<const ScalarArray>(structure->getField("value"))->getElementType() == pvDouble, "value type");
std::cout << *structure << std::endl;
}
void test_ntmatrix()
{
testDiag("test_ntmatrix");
NTMatrixBuilderPtr builder = NTMatrix::createBuilder();
testOk(builder.get() != 0, "Got builder");
NTMatrixPtr ntScalarArray = builder->
//arrayValue(pvInt)->
addDim()->
addDescriptor()->
addAlarm()->
addTimeStamp()->
addDisplay()->
create();
testOk1(ntScalarArray.get() != 0);
testOk1(ntScalarArray->getPVStructure().get() != 0);
testOk1(ntScalarArray->getValue().get() != 0);
testOk1(ntScalarArray->getDim().get() != 0);
testOk1(ntScalarArray->getDescriptor().get() != 0);
testOk1(ntScalarArray->getAlarm().get() != 0);
testOk1(ntScalarArray->getTimeStamp().get() != 0);
testOk1(ntScalarArray->getDisplay().get() != 0);
//
// example how to set values
//
PVDoubleArray::svector newValues;
newValues.push_back(1.0);
newValues.push_back(2.0);
newValues.push_back(8.0);
PVDoubleArrayPtr pvValueField = ntScalarArray->getValue();
pvValueField->replace(freeze(newValues));
//
// example how to get values
//
PVDoubleArray::const_svector values(pvValueField->view());
testOk1(values.size() == 3);
testOk1(values[0] == 1.0);
testOk1(values[1] == 2.0);
testOk1(values[2] == 8.0);
//
// timeStamp ops
//
PVTimeStamp pvTimeStamp;
if (ntScalarArray->attachTimeStamp(pvTimeStamp))
{
testPass("timeStamp attach");
// example how to set current time
TimeStamp ts;
ts.getCurrent();
pvTimeStamp.set(ts);
// example how to get EPICS time
TimeStamp ts2;
pvTimeStamp.get(ts2);
testOk1(ts2.getEpicsSecondsPastEpoch() != 0);
}
else
testFail("timeStamp attach fail");
//
// alarm ops
//
PVAlarm pvAlarm;
if (ntScalarArray->attachAlarm(pvAlarm))
{
testPass("alarm attach");
// example how to set an alarm
Alarm alarm;
alarm.setStatus(deviceStatus);
alarm.setSeverity(minorAlarm);
alarm.setMessage("simulation alarm");
pvAlarm.set(alarm);
}
else
testFail("alarm attach fail");
//
// display ops
//
PVDisplay pvDisplay;
if (ntScalarArray->attachDisplay(pvDisplay))
{
testPass("display attach");
// example how to set an display
Display display;
display.setLow(-15);
display.setHigh(15);
display.setDescription("This is a test scalar array");
display.setFormat("%d");
display.setUnits("A");
pvDisplay.set(display);
}
else
testFail("display attach fail");
//
// set descriptor
//
ntScalarArray->getDescriptor()->put("This is a test NTMatrix");
// dump ntScalarArray
std::cout << *ntScalarArray->getPVStructure() << std::endl;
}
void test_wrap()
{
testDiag("test_wrap");
NTMatrixPtr nullPtr = NTMatrix::wrap(PVStructurePtr());
testOk(nullPtr.get() == 0, "nullptr wrap");
nullPtr = NTMatrix::wrap(
getPVDataCreate()->createPVStructure(
NTField::get()->createTimeStamp()
)
);
testOk(nullPtr.get() == 0, "wrong type wrap");
NTMatrixBuilderPtr builder = NTMatrix::createBuilder();
testOk(builder.get() != 0, "Got builder");
PVStructurePtr pvStructure = builder->
createPVStructure();
testOk1(pvStructure.get() != 0);
if (!pvStructure)
return;
testOk1(NTMatrix::isCompatible(pvStructure)==true);
NTMatrixPtr ptr = NTMatrix::wrap(pvStructure);
testOk(ptr.get() != 0, "wrap OK");
ptr = NTMatrix::wrapUnsafe(pvStructure);
testOk(ptr.get() != 0, "wrapUnsafe OK");
}
MAIN(testNTMatrix) {
testPlan(36);
test_builder();
test_ntmatrix();
test_wrap();
return testDone();
}

View File

@@ -1,6 +1,6 @@
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* This software is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
/*
@@ -77,6 +77,7 @@ static void test()
addAlarm()->
addTimeStamp()->
addSeverity() ->
addIsConnected() ->
create();
testOk1(multiChannel.get() != 0);
pvStructure = multiChannel->getPVStructure();
@@ -106,7 +107,7 @@ static void test()
pvSeverity->replace(freeze(severities));
if(debug) {cout << *pvStructure << endl;}
PVBooleanArrayPtr pvIsConnected = multiChannel->getIsConnected();
shared_vector<const boolean> isConnected = pvIsConnected->view();
shared_vector<const epics::pvData::boolean> isConnected = pvIsConnected->view();
multiChannel = builder->
value(unionPtr) ->
addDescriptor()->
@@ -118,6 +119,7 @@ static void test()
addSecondsPastEpoch() ->
addNanoseconds() ->
addUserTag() ->
addIsConnected() ->
create();
testOk1(multiChannel.get() != 0);
pvStructure = multiChannel->getPVStructure();

View File

@@ -1,6 +1,6 @@
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* This software is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/

View File

@@ -0,0 +1,178 @@
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* This software 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/nt.h>
using namespace epics::nt;
using namespace epics::pvData;
using std::tr1::dynamic_pointer_cast;
static FieldCreatePtr fieldCreate = getFieldCreate();
static StandardFieldPtr standardField = getStandardField();
static NTFieldPtr ntField = NTField::get();
void test_builder()
{
testDiag("test_builder");
NTNDArrayAttributeBuilderPtr builder = NTNDArrayAttribute::createBuilder();
testOk(builder.get() != 0, "Got builder");
StructureConstPtr structure = builder->
addTags()->
addAlarm()->
addTimeStamp()->
add("extra",fieldCreate->createScalar(pvString)) ->
createStructure();
testOk1(structure.get() != 0);
if (!structure)
return;
testOk1(NTNDArrayAttribute::is_a(structure));
testOk1(structure->getID() == NTNDArrayAttribute::URI);
testOk1(structure->getNumberFields() == 9);
testOk1(structure->getField("name").get() != 0);
testOk1(structure->getField("value").get() != 0);
testOk1(structure->getField("tags").get() != 0);
testOk1(structure->getField("descriptor").get() != 0);
testOk1(structure->getField("alarm").get() != 0);
testOk1(structure->getField("timeStamp").get() != 0);
testOk1(structure->getField("sourceType").get() != 0);
testOk1(structure->getField("source").get() != 0);
ScalarConstPtr nameField = structure->getField<Scalar>("name");
testOk(nameField.get() != 0 && nameField->getScalarType() == pvString,
"name is string");
UnionConstPtr valueField = structure->getField<Union>("value");
testOk(valueField.get() != 0, "value is enum");
ScalarArrayConstPtr tagsField = structure->getField<ScalarArray>("tags");
testOk(tagsField.get() != 0 && tagsField->getElementType() == pvString,
"tags is string[]");
std::cout << *structure << std::endl;
}
void test_ntndarrayAttribute()
{
testDiag("test_ntndarrayAttribute");
NTNDArrayAttributeBuilderPtr builder = NTNDArrayAttribute::createBuilder();
testOk(builder.get() != 0, "Got builder");
NTNDArrayAttributePtr ntNDArrayAttribute = builder->
addTags()->
addAlarm()->
addTimeStamp()->
create();
testOk1(ntNDArrayAttribute.get() != 0);
testOk1(ntNDArrayAttribute->getPVStructure().get() != 0);
testOk1(ntNDArrayAttribute->getName().get() != 0);
testOk1(ntNDArrayAttribute->getValue().get() != 0);
testOk1(ntNDArrayAttribute->getTags().get() != 0);
testOk1(ntNDArrayAttribute->getDescriptor().get() != 0);
testOk1(ntNDArrayAttribute->getAlarm().get() != 0);
testOk1(ntNDArrayAttribute->getTimeStamp().get() != 0);
testOk1(ntNDArrayAttribute->getSourceType().get() != 0);
testOk1(ntNDArrayAttribute->getSource().get() != 0);
//
// timeStamp ops
//
PVTimeStamp pvTimeStamp;
if (ntNDArrayAttribute->attachTimeStamp(pvTimeStamp))
{
testPass("timeStamp attach");
// example how to set current time
TimeStamp ts;
ts.getCurrent();
pvTimeStamp.set(ts);
// example how to get EPICS time
TimeStamp ts2;
pvTimeStamp.get(ts2);
testOk1(ts2.getEpicsSecondsPastEpoch() != 0);
}
else
testFail("timeStamp attach fail");
//
// alarm ops
//
PVAlarm pvAlarm;
if (ntNDArrayAttribute->attachAlarm(pvAlarm))
{
testPass("alarm attach");
// example how to set an alarm
Alarm alarm;
alarm.setStatus(deviceStatus);
alarm.setSeverity(minorAlarm);
alarm.setMessage("simulation alarm");
pvAlarm.set(alarm);
}
else
testFail("alarm attach fail");
//
// set descriptor
//
ntNDArrayAttribute->getDescriptor()->put("This is a test NTNDArrayAttribute");
// dump ntNDArrayAttribute
std::cout << *ntNDArrayAttribute->getPVStructure() << std::endl;
}
void test_wrap()
{
testDiag("test_wrap");
NTNDArrayAttributePtr nullPtr = NTNDArrayAttribute::wrap(PVStructurePtr());
testOk(nullPtr.get() == 0, "nullptr wrap");
nullPtr = NTNDArrayAttribute::wrap(
getPVDataCreate()->createPVStructure(
NTField::get()->createTimeStamp()
)
);
testOk(nullPtr.get() == 0, "wrong type wrap");
NTNDArrayAttributeBuilderPtr builder = NTNDArrayAttribute::createBuilder();
testOk(builder.get() != 0, "Got builder");
PVStructurePtr pvStructure = builder->
createPVStructure();
testOk1(pvStructure.get() != 0);
if (!pvStructure)
return;
testOk1(NTNDArrayAttribute::isCompatible(pvStructure)==true);
NTNDArrayAttributePtr ptr = NTNDArrayAttribute::wrap(pvStructure);
testOk(ptr.get() != 0, "wrap OK");
ptr = NTNDArrayAttribute::wrapUnsafe(pvStructure);
testOk(ptr.get() != 0, "wrapUnsafe OK");
}
MAIN(testNTNDArrayAttribute) {
testPlan(37);
test_builder();
test_ntndarrayAttribute();
test_wrap();
return testDone();
}

View File

@@ -1,6 +1,6 @@
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* This software is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/

View File

@@ -1,6 +1,6 @@
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* This software is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
@@ -23,7 +23,7 @@ void test_builder()
testOk(builder.get() != 0, "Got builder");
StructureConstPtr structure = builder->
arrayValue(pvDouble)->
value(pvDouble)->
addDescriptor()->
addAlarm()->
addTimeStamp()->
@@ -75,7 +75,7 @@ void test_ntscalarArray()
testOk(builder.get() != 0, "Got builder");
NTScalarArrayPtr ntScalarArray = builder->
arrayValue(pvInt)->
value(pvInt)->
addDescriptor()->
addAlarm()->
addTimeStamp()->
@@ -220,7 +220,7 @@ void test_wrap()
testOk(builder.get() != 0, "Got builder");
PVStructurePtr pvStructure = builder->
arrayValue(pvDouble)->
value(pvDouble)->
createPVStructure();
testOk1(pvStructure.get() != 0);
if (!pvStructure)

View File

@@ -0,0 +1,181 @@
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* This software is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
/*
* ntscalarMultiChannelTest.cpp
*
* Created on: 2015.08
* Authors: Marty Kraimer, Dave Hickin
*/
#include <cstddef>
#include <cstdlib>
#include <cstddef>
#include <string>
#include <list>
#include <iostream>
#include <epicsUnitTest.h>
#include <testMain.h>
#include <pv/nt.h>
#include <pv/sharedVector.h>
#include <pv/ntscalarMultiChannel.h>
using namespace epics::pvData;
using namespace epics::nt;
using std::string;
using std::cout;
using std::endl;
using std::vector;
static bool debug = false;
static FieldCreatePtr fieldCreate = getFieldCreate();
static PVDataCreatePtr pvDataCreate = getPVDataCreate();
static NTFieldPtr ntField = NTField::get();
static PVNTFieldPtr pvntField = PVNTField::get();
static void test()
{
NTScalarMultiChannelBuilderPtr builder = NTScalarMultiChannel::createBuilder();
testOk(builder.get() != 0, "Got builder");
NTScalarMultiChannelPtr multiChannel = builder->
addDescriptor()->
addAlarm()->
addTimeStamp()->
addSeverity() ->
add("extra1",fieldCreate->createScalar(pvString)) ->
add("extra2",fieldCreate->createScalarArray(pvString)) ->
create();
testOk1(multiChannel.get() != 0);
PVStructurePtr pvStructure = multiChannel->getPVStructure();
testOk1(pvStructure.get()!=NULL);
testOk1(NTScalarMultiChannel::is_a(pvStructure->getStructure()));
size_t nchan = 3;
shared_vector<string> names(nchan);
names[0] = "channel 0";
names[1] = "channel 1";
names[2] = "channel 2";
shared_vector<const string> channelNames(freeze(names));
PVStringArrayPtr pvChannelName = multiChannel->getChannelName();
pvChannelName->replace(channelNames);
if(debug) {cout << *pvStructure << endl;}
multiChannel = builder->
value(pvDouble) ->
addDescriptor()->
addAlarm()->
addTimeStamp()->
addSeverity() ->
addIsConnected() ->
create();
testOk1(multiChannel.get() != 0);
pvStructure = multiChannel->getPVStructure();
if(debug) {cout << *pvStructure << endl;}
pvChannelName = multiChannel->getChannelName();
pvChannelName->replace(channelNames);
PVDoubleArrayPtr pvValue = multiChannel->getValue<PVDoubleArray>();
PVDoubleArray::svector doubles(nchan);
doubles.resize(nchan);
doubles[0] = 3.14159;
doubles[1] = 2.71828;
doubles[2] = 137.036;
pvValue->replace(freeze(doubles));
shared_vector<int32> severities(nchan);
severities[0] = 0;
severities[1] = 1;
severities[2] = 2;
PVIntArrayPtr pvSeverity = multiChannel->getSeverity();
pvSeverity->replace(freeze(severities));
if(debug) {cout << *pvStructure << endl;}
PVBooleanArrayPtr pvIsConnected = multiChannel->getIsConnected();
shared_vector<const epics::pvData::boolean> isConnected = pvIsConnected->view();
multiChannel = builder->
value(pvDouble) ->
addDescriptor()->
addAlarm()->
addTimeStamp()->
addSeverity() ->
addStatus() ->
addMessage() ->
addSecondsPastEpoch() ->
addNanoseconds() ->
addUserTag() ->
addIsConnected() ->
create();
testOk1(multiChannel.get() != 0);
pvStructure = multiChannel->getPVStructure();
if(debug) {cout << *pvStructure << endl;}
testOk1(NTScalarMultiChannel::isCompatible(pvStructure)==true);
PVStructurePtr pvTimeStamp = multiChannel->getTimeStamp();
testOk1(pvTimeStamp.get() !=0);
PVStructurePtr pvAlarm = multiChannel->getAlarm();
testOk1(pvAlarm.get() !=0);
pvValue = multiChannel->getValue<PVDoubleArray>();
testOk1(pvValue.get() !=0);
pvChannelName = multiChannel->getChannelName();
testOk1(pvChannelName.get() !=0);
pvIsConnected = multiChannel->getIsConnected();
testOk1(pvIsConnected.get() !=0);
pvSeverity = multiChannel->getSeverity();
testOk1(pvSeverity.get() !=0);
PVIntArrayPtr pvStatus = multiChannel->getStatus();
testOk1(pvStatus.get() !=0);
PVStringArrayPtr pvMessage = multiChannel->getMessage();
testOk1(pvMessage.get() !=0);
PVLongArrayPtr pvSecondsPastEpoch = multiChannel->getSecondsPastEpoch();
testOk1(pvSecondsPastEpoch.get() !=0);
PVIntArrayPtr pvNanoseconds = multiChannel->getNanoseconds();
testOk1(pvNanoseconds.get() !=0);
PVIntArrayPtr pvUserTag = multiChannel->getUserTag();
testOk1(pvUserTag.get() !=0);
PVStringPtr pvDescriptor = multiChannel->getDescriptor();
testOk1(pvDescriptor.get() !=0);
}
void test_wrap()
{
testDiag("test_wrap");
NTScalarMultiChannelPtr nullPtr = NTScalarMultiChannel::wrap(PVStructurePtr());
testOk(nullPtr.get() == 0, "nullptr wrap");
nullPtr = NTScalarMultiChannel::wrap(
getPVDataCreate()->createPVStructure(
NTField::get()->createTimeStamp()
)
);
testOk(nullPtr.get() == 0, "wrong type wrap");
NTScalarMultiChannelBuilderPtr builder = NTScalarMultiChannel::createBuilder();
testOk(builder.get() != 0, "Got builder");
PVStructurePtr pvStructure = builder->
createPVStructure();
testOk1(pvStructure.get() != 0);
if (!pvStructure)
return;
NTScalarMultiChannelPtr ptr = NTScalarMultiChannel::wrap(pvStructure);
testOk(ptr.get() != 0, "wrap OK");
builder = NTScalarMultiChannel::createBuilder();
ptr = NTScalarMultiChannel::wrapUnsafe(pvStructure);
testOk(ptr.get() != 0, "wrapUnsafe OK");
}
MAIN(testCreateRequest)
{
testPlan(25);
test();
test_wrap();
return testDone();
}

View File

@@ -1,6 +1,6 @@
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* This software is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/

View File

@@ -1,6 +1,6 @@
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* This software is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
@@ -22,9 +22,9 @@ void test_builder()
testOk(builder.get() != 0, "Got builder");
StructureConstPtr structure = builder->
add("column0", pvDouble)->
add("column1", pvString)->
add("column2", pvInt)->
addColumn("column0", pvDouble)->
addColumn("column1", pvString)->
addColumn("column2", pvInt)->
addDescriptor()->
addAlarm()->
addTimeStamp()->
@@ -37,12 +37,14 @@ void test_builder()
testOk1(NTTable::is_a(structure));
testOk1(structure->getID() == NTTable::URI);
testOk1(structure->getNumberFields() == 5);
testOk1(structure->getNumberFields() == 7);
testOk1(structure->getField("labels").get() != 0);
testOk1(structure->getField("value").get() != 0);
testOk1(structure->getField("descriptor").get() != 0);
testOk1(structure->getField("alarm").get() != 0);
testOk1(structure->getField("timeStamp").get() != 0);
testOk1(structure->getField("extra1").get() != 0);
testOk1(structure->getField("extra2").get() != 0);
StructureConstPtr s = dynamic_pointer_cast<const Structure>(structure->getField("value"));
#define TEST_COLUMN(name, type) \
@@ -62,8 +64,8 @@ void test_builder()
try
{
structure = builder->
add("column0", pvDouble)->
add("column0", pvString)->
addColumn("column0", pvDouble)->
addColumn("column0", pvString)->
createStructure();
testFail("duplicate column name");
} catch (std::runtime_error &) {
@@ -79,9 +81,9 @@ void test_labels()
testOk(builder.get() != 0, "Got builder");
PVStructurePtr pvStructure = builder->
add("column0", pvDouble)->
add("column1", pvString)->
add("column2", pvInt)->
addColumn("column0", pvDouble)->
addColumn("column1", pvString)->
addColumn("column2", pvInt)->
createPVStructure();
testOk1(pvStructure.get() != 0);
if (!pvStructure)
@@ -108,9 +110,9 @@ void test_nttable()
testOk(builder.get() != 0, "Got builder");
NTTablePtr ntTable = builder->
add("column0", pvDouble)->
add("column1", pvString)->
add("column2", pvInt)->
addColumn("column0", pvDouble)->
addColumn("column1", pvString)->
addColumn("column2", pvInt)->
addDescriptor()->
addAlarm()->
addTimeStamp()->
@@ -218,9 +220,9 @@ void test_wrap()
testOk(builder.get() != 0, "Got builder");
PVStructurePtr pvStructure = builder->
add("column0", pvDouble)->
add("column1", pvString)->
add("column2", pvInt)->
addColumn("column0", pvDouble)->
addColumn("column1", pvString)->
addColumn("column2", pvInt)->
createPVStructure();
testOk1(pvStructure.get() != 0);
if (!pvStructure)
@@ -234,7 +236,7 @@ void test_wrap()
}
MAIN(testNTTable) {
testPlan(46);
testPlan(48);
test_builder();
test_labels();
test_nttable();

167
test/nt/ntunionTest.cpp Normal file
View File

@@ -0,0 +1,167 @@
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* This software 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/nt.h>
using namespace epics::nt;
using namespace epics::pvData;
using std::tr1::dynamic_pointer_cast;
static FieldCreatePtr fieldCreate = getFieldCreate();
static StandardFieldPtr standardField = getStandardField();
static NTFieldPtr ntField = NTField::get();
void test_builder()
{
testDiag("test_builder");
NTUnionBuilderPtr builder = NTUnion::createBuilder();
testOk(builder.get() != 0, "Got builder");
StructureConstPtr structure = builder->
addDescriptor()->
addAlarm()->
addTimeStamp()->
add("valueAlarm",standardField->doubleAlarm()) ->
add("extra",fieldCreate->createScalarArray(pvString)) ->
createStructure();
testOk1(structure.get() != 0);
if (!structure)
return;
testOk1(NTUnion::is_a(structure));
testOk1(structure->getID() == NTUnion::URI);
testOk1(structure->getNumberFields() == 6);
testOk1(structure->getField("value").get() != 0);
testOk1(structure->getField("descriptor").get() != 0);
testOk1(structure->getField("alarm").get() != 0);
testOk1(structure->getField("timeStamp").get() != 0);
UnionConstPtr valueField = structure->getField<Union>("value");
testOk(valueField.get() != 0, "value is enum");
std::cout << *structure << std::endl;
}
void test_ntunion()
{
testDiag("test_ntunion");
NTUnionBuilderPtr builder = NTUnion::createBuilder();
testOk(builder.get() != 0, "Got builder");
NTUnionPtr ntUnion = builder->
addDescriptor()->
addAlarm()->
addTimeStamp()->
create();
testOk1(ntUnion.get() != 0);
testOk1(ntUnion->getPVStructure().get() != 0);
testOk1(ntUnion->getValue().get() != 0);
testOk1(ntUnion->getDescriptor().get() != 0);
testOk1(ntUnion->getAlarm().get() != 0);
testOk1(ntUnion->getTimeStamp().get() != 0);
// TODO
// 1. Variant union example.
// 2. set the union value.
//
// timeStamp ops
//
PVTimeStamp pvTimeStamp;
if (ntUnion->attachTimeStamp(pvTimeStamp))
{
testPass("timeStamp attach");
// example how to set current time
TimeStamp ts;
ts.getCurrent();
pvTimeStamp.set(ts);
// example how to get EPICS time
TimeStamp ts2;
pvTimeStamp.get(ts2);
testOk1(ts2.getEpicsSecondsPastEpoch() != 0);
}
else
testFail("timeStamp attach fail");
//
// alarm ops
//
PVAlarm pvAlarm;
if (ntUnion->attachAlarm(pvAlarm))
{
testPass("alarm attach");
// example how to set an alarm
Alarm alarm;
alarm.setStatus(deviceStatus);
alarm.setSeverity(minorAlarm);
alarm.setMessage("simulation alarm");
pvAlarm.set(alarm);
}
else
testFail("alarm attach fail");
//
// set descriptor
//
ntUnion->getDescriptor()->put("This is a test NTUnion");
// dump ntUnion
std::cout << *ntUnion->getPVStructure() << std::endl;
}
void test_wrap()
{
testDiag("test_wrap");
NTUnionPtr nullPtr = NTUnion::wrap(PVStructurePtr());
testOk(nullPtr.get() == 0, "nullptr wrap");
nullPtr = NTUnion::wrap(
getPVDataCreate()->createPVStructure(
NTField::get()->createTimeStamp()
)
);
testOk(nullPtr.get() == 0, "wrong type wrap");
NTUnionBuilderPtr builder = NTUnion::createBuilder();
testOk(builder.get() != 0, "Got builder");
PVStructurePtr pvStructure = builder->
createPVStructure();
testOk1(pvStructure.get() != 0);
if (!pvStructure)
return;
testOk1(NTUnion::isCompatible(pvStructure)==true);
NTUnionPtr ptr = NTUnion::wrap(pvStructure);
testOk(ptr.get() != 0, "wrap OK");
ptr = NTUnion::wrapUnsafe(pvStructure);
testOk(ptr.get() != 0, "wrapUnsafe OK");
}
MAIN(testNTUnion) {
testPlan(27);
test_builder();
test_ntunion();
test_wrap();
return testDone();
}

38
test/nt/ntutilsTest.cpp Normal file
View File

@@ -0,0 +1,38 @@
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* This software 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/ntutils.h>
using namespace epics::nt;
void test_is_a()
{
testDiag("test_is_a");
testOk1(NTUtils::is_a("epics:nt/NTTable:1.0", "epics:nt/NTTable:1.0"));
testOk1(NTUtils::is_a("epics:nt/NTTable:2.0", "epics:nt/NTTable:2.0"));
testOk1(NTUtils::is_a("epics:nt/NTTable:1.0", "epics:nt/NTTable:1.1"));
testOk1(NTUtils::is_a("epics:nt/NTTable:1.1", "epics:nt/NTTable:1.0"));
testOk1(!NTUtils::is_a("epics:nt/NTTable:1.0", "epics:nt/NTTable:2.0"));
testOk1(!NTUtils::is_a("epics:nt/NTTable:2.0", "epics:nt/NTTable:1.0"));
testOk1(!NTUtils::is_a("epics:nt/NTTable:1.3", "epics:nt/NTTable:2.3"));
testOk1(!NTUtils::is_a("epics:nt/NTTable:1.0", "epics:nt/NTTable:11.0"));
testOk1(!NTUtils::is_a("epics:nt/NTTable:11.0", "epics:nt/NTTable:1.0"));
testOk1(!NTUtils::is_a("epics:nt/NTTable:1.0", "epics:nt/NTMatrix:1.0"));
}
MAIN(testNTUtils) {
testPlan(10);
test_is_a();
return testDone();
}