78 Commits
4.0.2 ... 5.0.0

Author SHA1 Message Date
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
68 changed files with 10534 additions and 1283 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,9 +0,0 @@
b9a943e6828731a8a89e811818b2d91faff69d86 1.0-BETA
aaa5f5840b7eea8afaafb4d13a49bf78975aac0f 4.0.0
aaa5f5840b7eea8afaafb4d13a49bf78975aac0f 4.0.0
df4c65e13c2cfaa92e42f84a7afc97c81b5f3888 4.0.0
df4c65e13c2cfaa92e42f84a7afc97c81b5f3888 4.0.0
ec29bda853f50fa501cbcf3ffd836a1ef2adcdd4 4.0.0
0daade17a7440f970750db4a8388e0cee2d04f17 4.0.1
0daade17a7440f970750db4a8388e0cee2d04f17 4.0.1
1c140dd0e1993ac0a2798e8148b90ccce44ad407 4.0.1

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

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

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=""
PVDATA_BRANCH=""
###########################################
# 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

46
jenkins/cloudbees_doc Normal file
View File

@@ -0,0 +1,46 @@
# 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.
###########################################
# Determine EPICS Base version
DEFAULT_BASE=3.14.12.5
BASE=${1:-${DEFAULT_BASE}}
###########################################
# Fetch and unpack dependencies
export STUFF=/tmp/stuff
rm -fr ${STUFF}
mkdir -p ${STUFF}
cd ${STUFF}
wget -nv https://openepics.ci.cloudbees.com/job/Doxygen-1.8.3_Build/lastSuccessfulBuild/artifact/doxygen-1.8.3.CB-dist.tar.gz
tar -xzf doxygen-1.8.3.CB-dist.tar.gz
###########################################
# Generate
cd ${WORKSPACE}
wget -nv https://openepics.ci.cloudbees.com/job/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
rsync -aqP --delete -e ssh documentation epics-jenkins@web.sourceforge.net:/home/project-web/epics-pvdata/htdocs/docbuild/normativeTypesCPP/tip

View File

@@ -1,30 +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,7 +1,7 @@
/* 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
@@ -17,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 & structure)
{
if(!isCompatible(structure)) return shared_pointer();
return wrapUnsafe(structure);
}
NTAggregate::shared_pointer NTAggregate::wrapUnsafe(PVStructurePtr const & structure)
{
return shared_pointer(new NTAggregate(structure));
}
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"))
{}
}}

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

@@ -0,0 +1,345 @@
/* 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);
/**
* Add dispersion field to the NTAggregate.
* @return this instance of <b>NTAggregateBuilder</b>.
*/
shared_pointer addDispersion();
/**
* Add first field to the NTAggregate.
* @return this instance of <b>NTAggregateBuilder</b>.
*/
shared_pointer addFirst();
/**
* Add firstTimeStamp field to the NTAggregate.
* @return this instance of <b>NTAggregateBuilder</b>.
*/
shared_pointer addFirstTimeStamp();
/**
* Add last field to the NTAggregate.
* @return this instance of <b>NTAggregateBuilder</b>.
*/
shared_pointer addLast();
/**
* Add lastTimeStamp field to the NTAggregate.
* @return this instance of <b>NTAggregateBuilder</b>.
*/
shared_pointer addLastTimeStamp();
/**
* Add max field to the NTAggregate.
* @return this instance of <b>NTAggregateBuilder</b>.
*/
shared_pointer addMax();
/**
* Add min field to the NTAggregate.
* @return this instance of <b>NTAggregateBuilder</b>.
*/
shared_pointer addMin();
/**
* Add descriptor field to the NTAggregate.
* @return this instance of <b>NTAggregateBuilder</b>.
*/
shared_pointer addDescriptor();
/**
* Add alarm structure to the NTAggregate.
* @return this instance of <b>NTAggregateBuilder</b>.
*/
shared_pointer addAlarm();
/**
* Add timeStamp structure to the NTAggregate.
* @return this instance of <b>NTAggregateBuilder</b>.
*/
shared_pointer addTimeStamp();
/**
* Create 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();
/**
* Create 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();
/**
* Create 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();
/**
* Add extra <b>Field</b> to the type.
* @param name name of the field.
* @param field a field to add.
* @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;
/**
* Wrap (aka dynamic cast, or wrap) the structure to NTAggregate.
* 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 NTAggregate.
* @return NTAggregate instance on success, nullptr otherwise.
*/
static shared_pointer wrap(epics::pvData::PVStructurePtr const & structure);
/**
* Wrap (aka dynamic cast, or wrap) the structure to NTAggregate without checking for isCompatible
* @param structure The structure to wrap-ed (dynamic cast, wrapped) to NTAggregate.
* @return NTAggregate instance.
*/
static shared_pointer wrapUnsafe(epics::pvData::PVStructurePtr const & structure);
/**
* Is the structure an NTAggregate.
* @param structure The structure to test.
* @return (false,true) if (is not, is) an NTAggregate.
*/
static bool is_a(epics::pvData::StructureConstPtr const & structure);
/**
* Is the structure an NTAggregate.
* @param pvStructure The PVStructure to test.
* @return (false,true) if (is not, is) an NTAggregate.
*/
static bool is_a(epics::pvData::PVStructurePtr const & pvStructure);
/**
* Is the Structure compatible with NTAggregate.
* This method introspects the fields to see if they are compatible.
* @param structure The Structure to test.
* @return (false,true) if (is not, is) an NTAggregate.
*/
static bool isCompatible(
epics::pvData::StructureConstPtr const &structure);
/**
* Is the PVStructure compatible with NTAggregate.
* 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 NTAggregate.
*/
static bool isCompatible(
epics::pvData::PVStructurePtr const &pvStructure);
/**
* Checks if the specified structure is a valid NTAggregate.
*
* Checks whether the wrapped structure is valid with respect to this
* version of NTAggregate
* @return (false,true) if (is not, is) a valid NTAggregate.
*/
bool isValid();
/**
* Create a NTAggregate builder instance.
* @return builder instance.
*/
static NTAggregateBuilderPtr createBuilder();
/**
* Destructor.
*/
~NTAggregate() {}
/**
* Attach a pvTimeStamp.
* @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.
*/
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.
*/
bool attachAlarm(epics::pvData::PVAlarm &pvAlarm) const;
/**
* Get the pvStructure.
* @return PVStructurePtr.
*/
epics::pvData::PVStructurePtr getPVStructure() const;
/**
* Get the descriptor field.
* @return The pvString or null if no function field.
*/
epics::pvData::PVStringPtr getDescriptor() const;
/**
* Get the timeStamp.
* @return PVStructurePtr which may be null.
*/
epics::pvData::PVStructurePtr getTimeStamp() const;
/**
* Get the alarm.
* @return PVStructurePtr which may be null.
*/
epics::pvData::PVStructurePtr getAlarm() const;
/**
* Get the value field.
* @return The PVDouble for the value.
*/
epics::pvData::PVDoublePtr getValue() const;
/**
* Get the N field.
* @return The PVLong for the N field.
*/
epics::pvData::PVLongPtr getN() const;
/**
* Get the dispersion field.
* @return The PVDouble for the dispersion which may be null
*/
epics::pvData::PVDoublePtr getDispersion() const;
/**
* Get the first field.
* @return The PVDouble for the first field which may be null
*/
epics::pvData::PVDoublePtr getFirst() const;
/**
* Get the firstTimeStamp field.
* @return PVStructurePtr which may be null.
*/
epics::pvData::PVStructurePtr getFirstTimeStamp() const;
/**
* Get the last field.
* @return The PVDouble for the last field which may be null
*/
epics::pvData::PVDoublePtr getLast() const;
/**
* Get the lastTimeStamp field.
* @return PVStructurePtr which may be null.
*/
epics::pvData::PVStructurePtr getLastTimeStamp() const;
/**
* Get the max field.
* @return The PVDouble for the max field which may be null
*/
epics::pvData::PVDoublePtr getMax() const;
/**
* Get the min field.
* @return The PVDouble for the max field which may be null
*/
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 & structure)
{
if(!isCompatible(structure)) return shared_pointer();
return wrapUnsafe(structure);
}
NTAttribute::shared_pointer NTAttribute::wrapUnsafe(PVStructurePtr const & structure)
{
return shared_pointer(new NTAttribute(structure));
}
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"))
{
}
}}

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

@@ -0,0 +1,267 @@
/* 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);
/**
* Add tags field to the NTAttribute.
* @return this instance of <b>NTAttributeBuilder</b>.
*/
virtual shared_pointer addTags();
/**
* Add descriptor field to the NTAttribute.
* @return this instance of <b>NTAttributeBuilder</b>.
*/
shared_pointer addDescriptor();
/**
* Add alarm structure to the NTAttribute.
* @return this instance of <b>NTAttributeBuilder</b>.
*/
shared_pointer addAlarm();
/**
* Add timeStamp structure to the NTAttribute.
* @return this instance of <b>NTAttributeBuilder</b>.
*/
shared_pointer addTimeStamp();
/**
* Create 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();
/**
* Create 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();
/**
* Create 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();
/**
* Add extra <b>Field</b> to the type.
* @param name name of the field.
* @param field a field to add.
* @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;
/**
* Wrap (aka dynamic cast, or wrap) the structure to NTAttribute.
* 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 NTAttribute.
* @return NTAttribute instance on success, nullptr otherwise.
*/
static shared_pointer wrap(epics::pvData::PVStructurePtr const & structure);
/**
* Wrap (aka dynamic cast, or wrap) the structure to NTAttribute without checking for isCompatible
* @param structure The structure to wrap-ed (dynamic cast, wrapped) to NTAttribute.
* @return NTAttribute instance.
*/
static shared_pointer wrapUnsafe(epics::pvData::PVStructurePtr const & structure);
/**
* Is the structure an NTAttribute.
* @param structure The structure to test.
* @return (false,true) if (is not, is) an NTAttribute.
*/
static bool is_a(epics::pvData::StructureConstPtr const & structure);
/**
* Is the structure an NTAttribute.
* @param pvStructure The PVStructure to test.
* @return (false,true) if (is not, is) an NTAttribute.
*/
static bool is_a(epics::pvData::PVStructurePtr const & pvStructure);
/**
* Is the Structure compatible with NTAttribute.
* This method introspects the fields to see if they are compatible.
* @param structure The Structure to test.
* @return (false,true) if (is not, is) an NTAttribute.
*/
static bool isCompatible(
epics::pvData::StructureConstPtr const &structure);
/**
* Is the PVStructure compatible with NTAttribute.
* 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 NTAttribute.
*/
static bool isCompatible(
epics::pvData::PVStructurePtr const &pvStructure);
/**
* Checks if the specified structure is a valid NTAttribute.
*
* Checks whether the wrapped structure is valid with respect to this
* version of NTAttribute
* @return (false,true) if (is not, is) a valid NTAttribute.
*/
bool isValid();
/**
* Create a NTAttribute builder instance.
* @return builder instance.
*/
static NTAttributeBuilderPtr createBuilder();
/**
* Destructor.
*/
~NTAttribute() {}
/**
* Attach a pvTimeStamp.
* @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.
*/
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.
*/
bool attachAlarm(epics::pvData::PVAlarm &pvAlarm) const;
/**
* Get the pvStructure.
* @return PVStructurePtr.
*/
epics::pvData::PVStructurePtr getPVStructure() const;
/**
* Get the descriptor field.
* @return The pvString or null if no function field.
*/
epics::pvData::PVStringPtr getDescriptor() const;
/**
* Get the timeStamp.
* @return PVStructurePtr which may be null.
*/
epics::pvData::PVStructurePtr getTimeStamp() const;
/**
* Get the alarm.
* @return PVStructurePtr which may be null.
*/
epics::pvData::PVStructurePtr getAlarm() const;
/**
* Get the name field.
* @return The PVString for the name.
*/
epics::pvData::PVStringPtr getName() const;
/**
* Get the value field.
* @return The PVUnion for the values.
*/
epics::pvData::PVUnionPtr getValue() const;
/**
* Get the tags field.
* @return The PVStringArray for the tags, which may be null.
*/
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 & structure)
{
if(!isCompatible(structure)) return shared_pointer();
return wrapUnsafe(structure);
}
NTContinuum::shared_pointer NTContinuum::wrapUnsafe(PVStructurePtr const & structure)
{
return shared_pointer(new NTContinuum(structure));
}
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"))
{}
}}

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

@@ -0,0 +1,262 @@
/* 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);
/**
* Add descriptor field to the NTContinuum.
* @return this instance of <b>NTContinuumBuilder</b>.
*/
shared_pointer addDescriptor();
/**
* Add alarm structure to the NTContinuum.
* @return this instance of <b>NTContinuumBuilder</b>.
*/
shared_pointer addAlarm();
/**
* Add timeStamp structure to the NTContinuum.
* @return this instance of <b>NTContinuumBuilder</b>.
*/
shared_pointer addTimeStamp();
/**
* Create 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();
/**
* Create 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();
/**
* Create 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();
/**
* Add extra <b>Field</b> to the type.
* @param name name of the field.
* @param field a field to add.
* @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;
/**
* Wrap (aka dynamic cast, or wrap) the structure to NTContinuum.
* 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 NTContinuum.
* @return NTContinuum instance on success, nullptr otherwise.
*/
static shared_pointer wrap(epics::pvData::PVStructurePtr const & structure);
/**
* Wrap (aka dynamic cast, or wrap) the structure to NTContinuum without checking for isCompatible
* @param structure The structure to wrap-ed (dynamic cast, wrapped) to NTContinuum.
* @return NTContinuum instance.
*/
static shared_pointer wrapUnsafe(epics::pvData::PVStructurePtr const & structure);
/**
* Is the structure an NTContinuum.
* @param structure The structure to test.
* @return (false,true) if (is not, is) an NTContinuum.
*/
static bool is_a(epics::pvData::StructureConstPtr const & structure);
/**
* Is the structure an NTContinuum.
* @param pvStructure The PVStructure to test.
* @return (false,true) if (is not, is) an NTContinuum.
*/
static bool is_a(epics::pvData::PVStructurePtr const & pvStructure);
/**
* Is the Structure compatible with NTContinuum.
* This method introspects the fields to see if they are compatible.
* @param structure The Structure to test.
* @return (false,true) if (is not, is) an NTContinuum.
*/
static bool isCompatible(
epics::pvData::StructureConstPtr const &structure);
/**
* Is the PVStructure compatible with NTContinuum.
* 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 NTContinuum.
*/
static bool isCompatible(
epics::pvData::PVStructurePtr const &pvStructure);
/**
* Checks if the specified structure is a valid NTContinuum.
*
* Checks whether the wrapped structure is valid with respect to this
* version of NTContinuum
* @return (false,true) if (is not, is) a valid NTContinuum.
*/
bool isValid();
/**
* Create a NTContinuum builder instance.
* @return builder instance.
*/
static NTContinuumBuilderPtr createBuilder();
/**
* Destructor.
*/
~NTContinuum() {}
/**
* Attach a pvTimeStamp.
* @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.
*/
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.
*/
bool attachAlarm(epics::pvData::PVAlarm &pvAlarm) const;
/**
* Get the pvStructure.
* @return PVStructurePtr.
*/
epics::pvData::PVStructurePtr getPVStructure() const;
/**
* Get the descriptor field.
* @return The pvString or null if no function field.
*/
epics::pvData::PVStringPtr getDescriptor() const;
/**
* Get the timeStamp.
* @return PVStructurePtr which may be null.
*/
epics::pvData::PVStructurePtr getTimeStamp() const;
/**
* Get the alarm.
* @return PVStructurePtr which may be null.
*/
epics::pvData::PVStructurePtr getAlarm() const;
/**
* Get the base field.
* @return The PVDoubleArray for the base.
*/
epics::pvData::PVDoubleArrayPtr getBase() const;
/**
* Get the value field.
* @return The PVDoubleArray for the values.
*/
epics::pvData::PVDoubleArrayPtr getValue() const;
/**
* Get the units field.
* @return The PVStringArray for the units.
*/
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 & structure)
{
if(!isCompatible(structure)) return shared_pointer();
return wrapUnsafe(structure);
}
NTEnum::shared_pointer NTEnum::wrapUnsafe(PVStructurePtr const & structure)
{
return shared_pointer(new NTEnum(structure));
}
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"))
{}
}}

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

@@ -0,0 +1,248 @@
/* 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);
/**
* Add descriptor field to the NTEnum.
* @return this instance of <b>NTEnumBuilder</b>.
*/
shared_pointer addDescriptor();
/**
* Add alarm structure to the NTEnum.
* @return this instance of <b>NTEnumBuilder</b>.
*/
shared_pointer addAlarm();
/**
* Add timeStamp structure to the NTEnum.
* @return this instance of <b>NTEnumBuilder</b>.
*/
shared_pointer addTimeStamp();
/**
* Create 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();
/**
* Create 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();
/**
* Create 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();
/**
* Add extra <b>Field</b> to the type.
* @param name name of the field.
* @param field a field to add.
* @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;
/**
* Wrap (aka dynamic cast, or wrap) the structure to NTEnum.
* 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 NTEnum.
* @return NTEnum instance on success, nullptr otherwise.
*/
static shared_pointer wrap(epics::pvData::PVStructurePtr const & structure);
/**
* Wrap (aka dynamic cast, or wrap) the structure to NTEnum without checking for isCompatible
* @param structure The structure to wrap-ed (dynamic cast, wrapped) to NTEnum.
* @return NTEnum instance.
*/
static shared_pointer wrapUnsafe(epics::pvData::PVStructurePtr const & structure);
/**
* Is the structure an NTEnum.
* @param structure The structure to test.
* @return (false,true) if (is not, is) an NTEnum.
*/
static bool is_a(epics::pvData::StructureConstPtr const & structure);
/**
* Is the structure an NTEnum.
* @param pvStructure The PVStructure to test.
* @return (false,true) if (is not, is) an NTEnum.
*/
static bool is_a(epics::pvData::PVStructurePtr const & pvStructure);
/**
* Is the Structure compatible with NTEnum.
* This method introspects the fields to see if they are compatible.
* @param structure The Structure to test.
* @return (false,true) if (is not, is) an NTEnum.
*/
static bool isCompatible(
epics::pvData::StructureConstPtr const &structure);
/**
* Is the PVStructure compatible with NTEnum.
* 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 NTEnum.
*/
static bool isCompatible(
epics::pvData::PVStructurePtr const &pvStructure);
/**
* Checks if the specified structure is a valid NTEnum.
*
* Checks whether the wrapped structure is valid with respect to this
* version of NTEnum
* @return (false,true) if (is not, is) a valid NTEnum.
*/
bool isValid();
/**
* Create a NTEnum builder instance.
* @return builder instance.
*/
static NTEnumBuilderPtr createBuilder();
/**
* Destructor.
*/
~NTEnum() {}
/**
* Attach a pvTimeStamp.
* @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.
*/
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.
*/
bool attachAlarm(epics::pvData::PVAlarm &pvAlarm) const;
/**
* Get the pvStructure.
* @return PVStructurePtr.
*/
epics::pvData::PVStructurePtr getPVStructure() const;
/**
* Get the descriptor field.
* @return The pvString or null if no function field.
*/
epics::pvData::PVStringPtr getDescriptor() const;
/**
* Get the timeStamp.
* @return PVStructurePtr which may be null.
*/
epics::pvData::PVStructurePtr getTimeStamp() const;
/**
* Get the alarm.
* @return PVStructurePtr which may be null.
*/
epics::pvData::PVStructurePtr getAlarm() const;
/**
* Get the value field.
* @return The PVStructure for the values.
*/
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,7 +1,7 @@
/* 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.
*/

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
@@ -30,11 +30,6 @@
#include <shareLib.h>
namespace epics { namespace nt {
/**
* Convenience Class for introspection fields of a Normative Type
* @author mrk
*
*/
class NTField;
typedef std::tr1::shared_ptr<NTField> NTFieldPtr;
@@ -42,6 +37,12 @@ typedef std::tr1::shared_ptr<NTField> NTFieldPtr;
class PVNTField;
typedef std::tr1::shared_ptr<PVNTField> PVNTFieldPtr;
/**
* @brief Convenience Class for introspection fields of a Normative Type
*
* @author mrk
*
*/
class epicsShareClass NTField {
public:
POINTER_DEFINITIONS(NTField);
@@ -139,7 +140,8 @@ private:
};
/**
* Convenience Class for data fields of a Normative Type
* @brief Convenience Class for data fields of a Normative Type
*
* @author mrk
*
*/
@@ -212,4 +214,5 @@ private:
};
}}
#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 & structure)
{
if(!isCompatible(structure)) return shared_pointer();
return wrapUnsafe(structure);
}
NTHistogram::shared_pointer NTHistogram::wrapUnsafe(PVStructurePtr const & structure)
{
return shared_pointer(new NTHistogram(structure));
}
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"))
{}
}}

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

@@ -0,0 +1,277 @@
/* 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);
/**
* Set a scalar type of value field array.
* @param scalarType the value type.
* @return this instance of <b>NTHistogramBuilder</b>.
*/
shared_pointer value(epics::pvData::ScalarType scalarType);
/**
* Add descriptor field to the NTHistogram.
* @return this instance of <b>NTHistogramBuilder</b>.
*/
shared_pointer addDescriptor();
/**
* Add alarm structure to the NTHistogram.
* @return this instance of <b>NTHistogramBuilder</b>.
*/
shared_pointer addAlarm();
/**
* Add timeStamp structure to the NTHistogram.
* @return this instance of <b>NTHistogramBuilder</b>.
*/
shared_pointer addTimeStamp();
/**
* Create 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();
/**
* Create 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();
/**
* Create 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();
/**
* Add extra <b>Field</b> to the type.
* @param name name of the field.
* @param field a field to add.
* @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;
/**
* Wrap (aka dynamic cast, or wrap) the structure to NTHistogram.
* 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 NTHistogram.
* @return NTHistogram instance on success, nullptr otherwise.
*/
static shared_pointer wrap(epics::pvData::PVStructurePtr const & structure);
/**
* Wrap (aka dynamic cast, or wrap) the structure to NTHistogram without checking for isCompatible
* @param structure The structure to wrap-ed (dynamic cast, wrapped) to NTHistogram.
* @return NTHistogram instance.
*/
static shared_pointer wrapUnsafe(epics::pvData::PVStructurePtr const & structure);
/**
* Is the structure an NTHistogram.
* @param structure The structure to test.
* @return (false,true) if (is not, is) an NTHistogram.
*/
static bool is_a(epics::pvData::StructureConstPtr const & structure);
/**
* Is the structure an NTHistogram.
* @param pvStructure The PVStructure to test.
* @return (false,true) if (is not, is) an NTHistogram.
*/
static bool is_a(epics::pvData::PVStructurePtr const & pvStructure);
/**
* Is the Structure compatible with NTHistogram.
* This method introspects the fields to see if they are compatible.
* @param structure The Structure to test.
* @return (false,true) if (is not, is) an NTHistogram.
*/
static bool isCompatible(
epics::pvData::StructureConstPtr const &structure);
/**
* Is the PVStructure compatible with NTHistogram.
* 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 NTHistogram.
*/
static bool isCompatible(
epics::pvData::PVStructurePtr const &pvStructure);
/**
* Checks if the specified structure is a valid NTHistogram.
*
* Checks whether the wrapped structure is valid with respect to this
* version of NTHistogram
* @return (false,true) if (is not, is) a valid NTHistogram.
*/
bool isValid();
/**
* Create a NTHistogram builder instance.
* @return builder instance.
*/
static NTHistogramBuilderPtr createBuilder();
/**
* Destructor.
*/
~NTHistogram() {}
/**
* Attach a pvTimeStamp.
* @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.
*/
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.
*/
bool attachAlarm(epics::pvData::PVAlarm &pvAlarm) const;
/**
* Get the pvStructure.
* @return PVStructurePtr.
*/
epics::pvData::PVStructurePtr getPVStructure() const;
/**
* Get the descriptor field.
* @return The pvString or null if no function field.
*/
epics::pvData::PVStringPtr getDescriptor() const;
/**
* Get the timeStamp.
* @return PVStructurePtr which may be null.
*/
epics::pvData::PVStructurePtr getTimeStamp() const;
/**
* Get the alarm.
* @return PVStructurePtr which may be null.
*/
epics::pvData::PVStructurePtr getAlarm() const;
/**
* Get the base field.
* @return The PVDoubleArray for the base.
*/
epics::pvData::PVDoubleArrayPtr getRanges() const;
/**
* Get the value field.
* @return The PVScalarArray for the values.
*/
epics::pvData::PVScalarArrayPtr getValue() const;
/**
* Get the value field of a specified type (e.g. PVIntArray).
* @return The <PVT> field for the values.
*/
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;
}
}}

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

@@ -0,0 +1,147 @@
/**
* 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 {
/**
* Utility class for parsing an ID following the NT type ID conventions
*
* An NT type ID will be of the from epics:nt/<type-name>:<Major>.<Minor>,
* e.g. epics:nt/NTNDArray:1.2
* @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);
/**
* Get the full name of the id, i.e. the original ID
*
* For example above returns "epics:nt/NTNDArray:1.2"
* @return the full name
*/
std::string getFullName();
/**
* Get the fully qualified name including namespaces, but excluding version numbers
*
* For example above return "epics:nt/NTNDArray"
* @return the fully qualified name
*/
std::string getQualifiedName();
/**
* Get the namespace
*
* For example above return "epics:nt"
* @return the namespace
*/
std::string getNamespace();
/**
* Get the unqualified name, without namespace or version
*
* For example above return "NTNDArray"
* @return the unqualified name
*/
std::string getName();
/**
* Get the unqualified name, without namespace or version
*
* For example above return "NTNDArray"
* @return the unqualified name
*/
std::string getVersion();
/**
* Get the Major version as a string
*
* For example above return "1"
* @return the Major string
*/
std::string getMajorVersionString();
/**
* Does the ID contain a major version and is it a number
*
* @return true if it contains a major version number
*/
bool hasMajorVersion();
/**
* Get the Major version as an integer
*
* For example above return 1
* @return the Major string
*/
int getMajorVersion();
/**
* Get the Major version as a string
*
* For example above return "1"
* @return the Major string
*/
std::string getMinorVersionString();
/**
* Does the ID contain a minor version and is it a number
*
* @return true if it contains a minor version number
*/
bool hasMinorVersion();
/**
* Get the Minor version as an integer
*
* 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 & structure)
{
if(!isCompatible(structure)) return shared_pointer();
return wrapUnsafe(structure);
}
NTMatrix::shared_pointer NTMatrix::wrapUnsafe(PVStructurePtr const & structure)
{
return shared_pointer(new NTMatrix(structure));
}
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"))
{}
}}

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

@@ -0,0 +1,285 @@
/* 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);
/**
* Add dimensionfield to the NTMatrix.
* @return this instance of <b>NTMatrixBuilder</b>.
*/
shared_pointer addDim();
/**
* Add descriptor field to the NTMatrix.
* @return this instance of <b>NTMatrixBuilder</b>.
*/
shared_pointer addDescriptor();
/**
* Add alarm structure to the NTMatrix.
* @return this instance of <b>NTMatrixBuilder</b>.
*/
shared_pointer addAlarm();
/**
* Add timeStamp structure to the NTMatrix.
* @return this instance of <b>NTMatrixBuilder</b>.
*/
shared_pointer addTimeStamp();
/**
* Add display structure to the NTMatrix.
* @return this instance of <b>NTMatrixBuilder</b>.
*/
shared_pointer addDisplay();
/**
* Create 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();
/**
* Create 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();
/**
* Create 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();
/**
* Add extra <b>Field</b> to the type.
* @param name name of the field.
* @param field a field to add.
* @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;
/**
* Wrap (aka dynamic cast, or wrap) the structure to NTMatrix.
* 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 NTMatrix.
* @return NTMatrix instance on success, nullptr otherwise.
*/
static shared_pointer wrap(epics::pvData::PVStructurePtr const & structure);
/**
* Wrap (aka dynamic cast, or wrap) the structure to NTMatrix without checking for isCompatible
* @param structure The structure to wrap-ed (dynamic cast, wrapped) to NTMatrix.
* @return NTMatrix instance.
*/
static shared_pointer wrapUnsafe(epics::pvData::PVStructurePtr const & structure);
/**
* Is the structure an NTMatrix.
* @param structure The structure to test.
* @return (false,true) if (is not, is) an NTMatrix.
*/
static bool is_a(epics::pvData::StructureConstPtr const & structure);
/**
* Is the structure an NTMatrix.
* @param pvStructure The PVStructure to test.
* @return (false,true) if (is not, is) an NTMatrix.
*/
static bool is_a(epics::pvData::PVStructurePtr const & pvStructure);
/**
* Is the Structure compatible with NTMatrix.
* This method introspects the fields to see if they are compatible.
* @param structure The Structure to test.
* @return (false,true) if (is not, is) an NTMatrix.
*/
static bool isCompatible(
epics::pvData::StructureConstPtr const &structure);
/**
* Is the PVStructure compatible with NTMatrix.
* 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 NTMatrix.
*/
static bool isCompatible(
epics::pvData::PVStructurePtr const &pvStructure);
/**
* Checks if the specified structure is a valid NTMatrix.
*
* Checks whether the wrapped structure is valid with respect to this
* version of NTMatrix
* @return (false,true) if (is not, is) a valid NTMatrix.
*/
bool isValid();
/**
* Create a NTMatrix builder instance.
* @return builder instance.
*/
static NTMatrixBuilderPtr createBuilder();
/**
* Destructor.
*/
~NTMatrix() {}
/**
* Attach a pvTimeStamp.
* @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.
*/
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.
*/
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.
*/
bool attachDisplay(epics::pvData::PVDisplay &pvDisplay) const;
/**
* Get the pvStructure.
* @return PVStructurePtr.
*/
epics::pvData::PVStructurePtr getPVStructure() const;
/**
* Get the descriptor field.
* @return The pvString or null if no function field.
*/
epics::pvData::PVStringPtr getDescriptor() const;
/**
* Get the timeStamp.
* @return PVStructurePtr which may be null.
*/
epics::pvData::PVStructurePtr getTimeStamp() const;
/**
* Get the alarm.
* @return PVStructurePtr which may be null.
*/
epics::pvData::PVStructurePtr getAlarm() const;
/**
* Get the display.
* @return PVStructurePtr which may be null.
*/
epics::pvData::PVStructurePtr getDisplay() const;
/**
* Get the value field.
* @return The PVDoubleArray for the values.
*/
epics::pvData::PVDoubleArrayPtr getValue() const;
/**
* Get the dim field.
* @return The PVIntArray for the dim which may be null.
*/
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,7 +1,7 @@
/* 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.
*/
@@ -84,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;
@@ -99,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;
@@ -110,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";
@@ -148,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];
@@ -187,6 +196,7 @@ void NTMultiChannelBuilder::reset()
secondsPastEpoch = false;
nanoseconds = false;
userTag = false;
isConnected = false;
}
@@ -216,38 +226,124 @@ bool NTMultiChannel::is_a(StructureConstPtr const &structure)
return NTUtils::is_a(structure->getID(), URI);
}
bool NTMultiChannel::isCompatible(PVStructurePtr const &pvStructure)
bool NTMultiChannel::isCompatible(StructureConstPtr const & structure)
{
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;
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.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")),
@@ -266,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,7 +1,7 @@
/* 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
@@ -30,11 +30,6 @@
namespace epics { namespace nt {
/**
* Convenience Class for NTMultiChannel
* @author mrk
*
*/
class NTMultiChannel;
typedef std::tr1::shared_ptr<NTMultiChannel> NTMultiChannelPtr;
@@ -42,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
@@ -55,77 +51,82 @@ 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}.
* @return this instance of <b>NTMultiChannelBuilder</b>.
*/
shared_pointer addDescriptor();
/**
* Add alarm structure to the NTMultiChannel.
* @return this instance of a {@code NTMultiChannelBuilder}.
* @return this instance of <b>NTMultiChannelBuilder</b>.
*/
shared_pointer addAlarm();
/**
* Add timeStamp structure to the NTMultiChannel.
* @return this instance of a {@code NTMultiChannelBuilder}.
* @return this instance of <b>NTMultiChannelBuilder</b>.
*/
shared_pointer addTimeStamp();
/**
* Add severity array to the NTMultiChannel.
* @return this instance of a {@code NTMultiChannelBuilder}.
* @return this instance of <b>NTMultiChannelBuilder</b>.
*/
shared_pointer addSeverity();
/**
* Add status array to the NTMultiChannel.
* @return this instance of a {@code NTMultiChannelBuilder}.
* @return this instance of <b>NTMultiChannelBuilder</b>.
*/
shared_pointer addStatus();
/**
* Add message array to the NTMultiChannel.
* @return this instance of a {@code NTMultiChannelBuilder}.
* @return this instance of <b>NTMultiChannelBuilder</b>.
*/
shared_pointer addMessage();
/**
* Add secondsPastEpoch array to the NTMultiChannel.
* @return this instance of a {@code NTMultiChannelBuilder}.
* @return this instance of <b>NTMultiChannelBuilder</b>.
*/
shared_pointer addSecondsPastEpoch();
/**
* Add nanoseconds array to the NTMultiChannel.
* @return this instance of a {@code NTMultiChannelBuilder}.
* @return this instance of <b>NTMultiChannelBuilder</b>.
*/
shared_pointer addNanoseconds();
/**
* Add userTag array to the NTMultiChannel.
* @return this instance of a {@code NTMultiChannelBuilder}.
* @return this instance of <b>NTMultiChannelBuilder</b>.
*/
shared_pointer addUserTag();
/**
* Create a {@code Structure} that represents NTMultiChannel.
* Add isConnected array to the NTMultiChannel.
* @return this instance of <b>NTMultiChannelBuilder</b>.
*/
shared_pointer addIsConnected();
/**
* Create 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.
* Create a <b>PVStructure</b> that represents NTMultiChannel.
* This resets this instance state and allows new {@code instance to be created.}
* @return a new instance of a {@code PVStructure}
* @return a new instance of a <b>PVStructure</b>
*/
epics::pvData::PVStructurePtr createPVStructure();
/**
* Create a {@code NTMultiChannel} instance.
* Create a <b>NTMultiChannel</b> instance.
* This resets this instance state and allows new {@code instance to be created.}
* @return a new instance of a {@code NTMultiChannel}
* @return a new instance of a <b>NTMultiChannel</b>
*/
NTMultiChannelPtr create();
/**
* Add extra {@code Field} to the type.
* Add extra <b>Field</b> to the type.
* @param name name of the field.
* @param field a field to add.
* @return this instance of a {@code NTMultiChannelBuilder}.
* @return this instance of a <b>NTMultiChannelBuilder</b>
*/
shared_pointer add(std::string const & name, epics::pvData::FieldConstPtr const & field);
private:
@@ -143,6 +144,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;
@@ -156,6 +158,12 @@ namespace detail {
typedef std::tr1::shared_ptr<detail::NTMultiChannelBuilder> NTMultiChannelBuilderPtr;
/**
* @brief Convenience Class for NTMultiChannel
*
* @author mrk
*
*/
class epicsShareClass NTMultiChannel
{
public:
@@ -178,22 +186,48 @@ public:
* @return NTMultiChannel instance.
*/
static shared_pointer wrapUnsafe(epics::pvData::PVStructurePtr const & structure);
/**
* Is the Structure an NTMultiChannel.
* This method structure->getID() and checks if it is the same as the URI.
* Is the structure an NTMultiChannel.
* @param structure The structure to test.
* @return (false,true) if (is not, is) an NTMultiChannel.
*/
static bool is_a(
epics::pvData::StructureConstPtr const &structure);
static bool is_a(epics::pvData::StructureConstPtr const & structure);
/**
* Is the pvStructure compatible with NTMultiChannel.
* Is the structure an NTMultiChannel.
* @param pvStructure The PVStructure to test.
* @return (false,true) if (is not, is) an NTMultiChannel.
*/
static bool is_a(epics::pvData::PVStructurePtr const & pvStructure);
/**
* Is the Structure compatible with NTMultiChannel.
* This method introspects the fields to see if they are compatible.
* @param pvStructure The pvStructure to test.
* @param structure The Structure to test.
* @return (false,true) if (is not, is) an 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.
*/
static bool isCompatible(
epics::pvData::PVStructurePtr const &pvStructure);
/**
* Checks if the specified structure is a valid NTMultiChannel.
*
* Checks whether the wrapped structure is valid with respect to this
* version of NTMultiChannel
* @return (false,true) if (is not, is) a valid NTMultiChannel.
*/
bool isValid();
/**
* Create a NTMultiChannelBuilder instance
* @return builder instance.
@@ -204,18 +238,21 @@ public:
* Destructor
*/
~NTMultiChannel() {}
/**
* Attach a pvTimeStamp.
* @param pvTimeStamp The pvTimeStamp that will be attached.
* Does nothing if no timeStamp
*/
void attachTimeStamp(epics::pvData::PVTimeStamp &pvTimeStamp) const;
/**
* Attach a pvTimeStamp.
* @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.
*/
bool attachTimeStamp(epics::pvData::PVTimeStamp &pvTimeStamp) const;
/**
* Attach a pvAlarm.
* @param pvAlarm The pvAlarm that will be attached.
* Does nothing if no alarm
* Does nothing if no alarm.
* @return true if the operation was successfull (i.e. this instance has a timeStamp field), otherwise false.
*/
void attachAlarm(epics::pvData::PVAlarm &pvAlarm) const;
bool attachAlarm(epics::pvData::PVAlarm &pvAlarm) const;
/**
* Get the pvStructure.
* @return PVStructurePtr.

View File

@@ -1,7 +1,7 @@
/* 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.
*/
@@ -128,20 +128,49 @@ bool NTNameValue::is_a(StructureConstPtr const & structure)
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,7 +1,7 @@
/* 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
@@ -32,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
@@ -44,56 +45,56 @@ namespace detail {
POINTER_DEFINITIONS(NTNameValueBuilder);
/**
* Set a value array {@code Scalar} type.
* Set a value array <b>Scalar</b> type.
* @param scalarType value array scalar array.
* @return this instance of a {@code NTTableBuilder}.
* @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}.
* @return this instance of <b>NTTableBuilder</b>.
*/
shared_pointer addDescriptor();
/**
* Add alarm structure to the NTNameValue.
* @return this instance of a {@code NTNameValueBuilder}.
* @return this instance of <b>NTTableBuilder</b>.
*/
shared_pointer addAlarm();
/**
* Add timeStamp structure to the NTNameValue.
* @return this instance of a {@code NTNameValueBuilder}.
* @return this instance of <b>NTTableBuilder</b>.
*/
shared_pointer addTimeStamp();
/**
* Create a {@code Structure} that represents NTNameValue.
* Create 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}
* Create 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}
* Create 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.
* Add extra <b>Field</b> to the type.
* @param name name of the field.
* @param field a field to add.
* @return this instance of a {@code NTNameValueBuilder}.
* @return this instance of <b>NTTableBuilder</b>.
*/
shared_pointer add(std::string const & name, epics::pvData::FieldConstPtr const & field);
@@ -120,10 +121,9 @@ namespace detail {
typedef std::tr1::shared_ptr<detail::NTNameValueBuilder> NTNameValueBuilderPtr;
/**
* Convenience Class for NTNameValue
* @brief Convenience Class for NTNameValue
*
* @author mrk
*/
class epicsShareClass NTNameValue
@@ -144,7 +144,7 @@ public:
static shared_pointer wrap(epics::pvData::PVStructurePtr const & structure);
/**
* Wrap (aka dynamic cast, or wrap) the structure to NTMultiChannel without checking for isCompatible
* Wrap (aka dynamic cast, or wrap) the structure to NTNameValue without checking for isCompatible
* @param structure The structure to wrap-ed (dynamic cast, wrapped) to NTNameValue.
* @return NTNameValue instance.
*/
@@ -156,14 +156,41 @@ public:
* @return (false,true) if (is not, is) an NTNameValue.
*/
static bool is_a(epics::pvData::StructureConstPtr const & structure);
/**
* Is the pvStructure compatible with NTNameValue..
* Is the structure an NTNameValue.
* @param pvStructure The PVStructure to test.
* @return (false,true) if (is not, is) an NTNameValue.
*/
static bool is_a(epics::pvData::PVStructurePtr const & pvStructure);
/**
* Is the Structure 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.
* @param structure The Structure to test.
* @return (false,true) if (is not, is) an NTNameValue.
*/
static bool isCompatible(
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 NTNameValue.
*/
static bool isCompatible(
epics::pvData::PVStructurePtr const &pvStructure);
/**
* Checks if the specified structure is a valid NTNameValue.
*
* Checks whether the wrapped structure is valid with respect to this
* version of NTNameValue
* @return (false,true) if (is not, is) a valid NTNameValue.
*/
bool isValid();
/**
* Create a NTNameValue builder instance.
* @return builder instance.

View File

@@ -1,7 +1,7 @@
/* 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.
*/
@@ -9,6 +9,7 @@
#define epicsExportSharedSymbols
#include <pv/ntndarray.h>
#include <pv/ntndarrayAttribute.h>
#include <pv/ntutils.h>
using namespace std;
@@ -18,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
@@ -38,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;
@@ -94,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)->
@@ -116,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());
@@ -206,6 +200,86 @@ const std::string ntAttrStr("epics:nt/NTAttribute:1.0");
static FieldCreatePtr fieldCreate = getFieldCreate();
static PVDataCreatePtr pvDataCreate = getPVDataCreate();
class NTValueType
{
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 & structure)
{
if(!isCompatible(structure)) return shared_pointer();
@@ -222,36 +296,183 @@ bool NTNDArray::is_a(StructureConstPtr const & structure)
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());
@@ -310,21 +531,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,7 +1,7 @@
/* 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
@@ -35,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
@@ -48,53 +49,53 @@ namespace detail {
/**
* Add descriptor field to the NTNDArray.
* @return this instance of a {@code NTNDArrayBuilder}.
* @return this instance of <b>NTNDArrayBuilder</b>.
*/
shared_pointer addDescriptor();
/**
* Add alarm structure to the NTNDArray.
* @return this instance of a {@code NTNDArrayBuilder}.
* @return this instance of <b>NTNDArrayBuilder</b>.
*/
shared_pointer addAlarm();
/**
* Add timeStamp structure to the NTNDArray.
* @return this instance of a {@code NTNDArrayBuilder}.
* @return this instance of <b>NTNDArrayBuilder</b>.
*/
shared_pointer addTimeStamp();
/**
* Add display structure to the NTNDArray.
* @return this instance of a {@code NTNDArrayBuilder}.
* @return this instance of <b>NTNDArrayBuilder</b>.
*/
shared_pointer addDisplay();
/**
* Create a {@code Structure} that represents NTNDArray.
* Create 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}
* Create 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}
* Create 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.
* Add extra <b>Field</b> to the type.
* @param name name of the field.
* @param field a field to add.
* @return this instance of a {@code NTArrayBuilder}.
* @return this instance of a <b>NTArrayBuilder</b>.
*/
shared_pointer add(std::string const & name, epics::pvData::FieldConstPtr const & field);
@@ -120,7 +121,8 @@ namespace detail {
typedef std::tr1::shared_ptr<detail::NTNDArrayBuilder> NTNDArrayBuilderPtr;
/**
* Convenience Class for NTNDArray
* @brief Convenience Class for NTNDArray
*
* @author dgh
*/
class epicsShareClass NTNDArray
@@ -141,7 +143,7 @@ public:
static shared_pointer wrap(epics::pvData::PVStructurePtr const & structure);
/**
* Wrap (aka dynamic cast, or wrap) the structure to NTMultiChannel without checking for isCompatible
* Wrap (aka dynamic cast, or wrap) the structure to NTNDArray without checking for isCompatible
* @param structure The structure to wrap-ed (dynamic cast, wrapped) to NTNDArray.
* @return NTNDArray instance.
*/
@@ -155,13 +157,39 @@ public:
static bool is_a(epics::pvData::StructureConstPtr const & structure);
/**
* Is the pvStructure compatible with NTNDArray..
* Is the structure an NTNDArray.
* @param pvStructure The PVStructure to test.
* @return (false,true) if (is not, is) an NTNDArray.
*/
static bool is_a(epics::pvData::PVStructurePtr const & pvStructure);
/**
* Is the Structure 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.
* @param structure The Structure to test.
* @return (false,true) if (is not, is) an NTNDArray.
*/
static bool isCompatible(
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 NTNDArray.
*/
static bool isCompatible(
epics::pvData::PVStructurePtr const &pvStructure);
/**
* Checks if the specified structure is a valid NTNDArray.
*
* Checks whether the wrapped structure is valid with respect to this
* version of NTNDArray
* @return (false,true) if (is not, is) a valid NTNDArray.
*/
bool isValid();
/**
* Create a NTNDArrayBuilder instance
* @return builder instance.
@@ -227,12 +255,6 @@ public:
*/
epics::pvData::PVLongPtr getUncompressedDataSize() const;
/**
* Get the attribute field.
* @return the PVStructurePtr.
*/
epics::pvData::PVStructureArrayPtr getAttribute() const;
/**
* Get the dimension field.
* @return the PVStructurePtr.
@@ -251,6 +273,12 @@ public:
*/
epics::pvData::PVStructurePtr getDataTimeStamp() const;
/**
* Get the attribute field.
* @return the PVStructurePtr.
*/
epics::pvData::PVStructureArrayPtr getAttribute() const;
/**
* Get the descriptor field.
* @return The pvString or null if no function field.
@@ -277,6 +305,11 @@ public:
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 & structure)
{
if(!isCompatible(structure)) return shared_pointer();
return wrapUnsafe(structure);
}
NTNDArrayAttribute::shared_pointer NTNDArrayAttribute::wrapUnsafe(PVStructurePtr const & structure)
{
return shared_pointer(new NTNDArrayAttribute(structure));
}
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"))
{
}
}}

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

@@ -0,0 +1,279 @@
/* 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);
/**
* Add tags field to the NTNDArrayAttribute.
* @return this instance of <b>NTNDArrayAttributeBuilder</b>.
*/
virtual shared_pointer addTags();
/**
* Add descriptor field to the NTNDArrayAttribute.
* @return this instance of <b>NTNDArrayAttributeBuilder</b>.
*/
shared_pointer addDescriptor();
/**
* Add alarm structure to the NTNDArrayAttribute.
* @return this instance of <b>NTNDArrayAttributeBuilder</b>.
*/
shared_pointer addAlarm();
/**
* Add timeStamp structure to the NTNDArrayAttribute.
* @return this instance of <b>NTNDArrayAttributeBuilder</b>.
*/
shared_pointer addTimeStamp();
/**
* Create 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();
/**
* Create 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();
/**
* Create 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();
/**
* Add extra <b>Field</b> to the type.
* @param name name of the field.
* @param field a field to add.
* @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;
/**
* @briVIntPtref Convenience Class for NTNDArrayAttribute
*
* @author dgh
*/
class epicsShareClass NTNDArrayAttribute
{
public:
POINTER_DEFINITIONS(NTNDArrayAttribute);
static const std::string URI;
/**
* Wrap (aka dynamic cast, or wrap) the structure to NTNDArrayAttribute.
* 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 NTNDArrayAttribute.
* @return NTNDArrayAttribute instance on success, nullptr otherwise.
*/
static shared_pointer wrap(epics::pvData::PVStructurePtr const & structure);
/**
* Wrap (aka dynamic cast, or wrap) the structure to NTNDArrayAttribute without checking for isCompatible
* @param structure The structure to wrap-ed (dynamic cast, wrapped) to NTNDArrayAttribute.
* @return NTNDArrayAttribute instance.
*/
static shared_pointer wrapUnsafe(epics::pvData::PVStructurePtr const & structure);
/**
* Is the structure an NTNDArrayAttribute.
* @param structure The structure to test.
* @return (false,true) if (is not, is) an NTNDArrayAttribute.
*/
static bool is_a(epics::pvData::StructureConstPtr const & structure);
/**
* Is the structure an NTNDArrayAttribute.
* @param pvStructure The PVStructure to test.
* @return (false,true) if (is not, is) an NTNDArrayAttribute.
*/
static bool is_a(epics::pvData::PVStructurePtr const & pvStructure);
/**
* Is the Structure compatible with NTNDArrayAttribute.
* This method introspects the fields to see if they are compatible.
* @param structure The Structure to test.
* @return (false,true) if (is not, is) an NTNDArrayAttribute.
*/
static bool isCompatible(
epics::pvData::StructureConstPtr const &structure);
/**
* Is the PVStructure compatible with NTNDArrayAttribute.
* 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 NTNDArrayAttribute.
*/
static bool isCompatible(
epics::pvData::PVStructurePtr const &pvStructure);
/**
* Checks if the specified structure is a valid NTNDArrayAttribute.
*
* Checks whether the wrapped structure is valid with respect to this
* version of NTNDArrayAttribute
* @return (false,true) if (is not, is) a valid NTNDArrayAttribute.
*/
bool isValid();
/**
* Create a NTNDArrayAttribute builder instance.
* @return builder instance.
*/
static NTNDArrayAttributeBuilderPtr createBuilder();
/**
* Destructor.
*/
~NTNDArrayAttribute() {}
/**
* Attach a pvTimeStamp.
* @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.
*/
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.
*/
bool attachAlarm(epics::pvData::PVAlarm &pvAlarm) const;
/**
* Get the pvStructure.
* @return PVStructurePtr.
*/
epics::pvData::PVStructurePtr getPVStructure() const;
/**
* Get the descriptor field.
* @return The pvString
*/
epics::pvData::PVStringPtr getDescriptor() const;
/**
* Get the timeStamp.
* @return PVStructurePtr which may be null.
*/
epics::pvData::PVStructurePtr getTimeStamp() const;
/**
* Get the alarm.
* @return PVStructurePtr which may be null.
*/
epics::pvData::PVStructurePtr getAlarm() const;
/**
* Get the name field.
* @return The PVString for the name.
*/
epics::pvData::PVStringPtr getName() const;
/**
* Get the value field.
* @return The PVUnion for the values.
*/
epics::pvData::PVUnionPtr getValue() const;
/**
* Get the tags field.
* @return The PVStringArray for the tags, which may be null.
*/
epics::pvData::PVStringArrayPtr getTags() const;
/**
* Get the sourceType field.
* @return The PVInt for the sourceType field.
*/
epics::pvData::PVIntPtr getSourceType() const;
/**
* Get the source field.
* @return The PVString for the source field, which may be null.
*/
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,7 +1,7 @@
/* 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.
*/
@@ -18,8 +18,6 @@ static NTFieldPtr ntField = NTField::get();
namespace detail {
static NTFieldPtr ntField = NTField::get();
NTScalarBuilder::shared_pointer NTScalarBuilder::value(
epics::pvData::ScalarType scalarType
)
@@ -148,21 +146,53 @@ bool NTScalar::is_a(StructureConstPtr const & structure)
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,7 +1,7 @@
/* 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
@@ -32,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
@@ -46,65 +47,65 @@ namespace detail {
/**
* Set a value type of a 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}.
* @return this instance of <b>NTScalarBuilder</b>.
*/
shared_pointer addDescriptor();
/**
* Add alarm structure to the NTScalar.
* @return this instance of a {@code NTScalarBuilder}.
* @return this instance of <b>NTScalarBuilder</b>.
*/
shared_pointer addAlarm();
/**
* Add timeStamp structure to the NTScalar.
* @return this instance of a {@code NTScalarBuilder}.
* @return this instance of <b>NTScalarBuilder</b>.
*/
shared_pointer addTimeStamp();
/**
* Add display structure to the NTScalar.
* @return this instance of a {@code NTScalarBuilder}.
* @return this instance of <b>NTScalarBuilder</b>.
*/
shared_pointer addDisplay();
/**
* Add control structure to the NTScalar.
* @return this instance of a {@code NTScalarBuilder}.
* @return this instance of <b>NTScalarBuilder</b>.
*/
shared_pointer addControl();
/**
* Create a {@code Structure} that represents NTScalar.
* Create 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}
* Create 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}
* Create 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.
* Add extra <b>Field</b> to the type.
* @param name name of the field.
* @param field a field to add.
* @return this instance of a {@code NTScalarBuilder}.
* @return this instance of <b>NTScalarBuilder</b>.
*/
shared_pointer add(std::string const & name, epics::pvData::FieldConstPtr const & field);
@@ -136,7 +137,8 @@ typedef std::tr1::shared_ptr<detail::NTScalarBuilder> NTScalarBuilderPtr;
/**
* Convenience Class for NTScalar
* @brief Convenience Class for NTScalar
*
* @author mrk
*/
class epicsShareClass NTScalar
@@ -169,14 +171,41 @@ public:
* @return (false,true) if (is not, is) an NTScalar.
*/
static bool is_a(epics::pvData::StructureConstPtr const & structure);
/**
* Is the pvStructure compatible with NTScalar.
* Is the structure an NTScalar.
* @param pvStructure The PVStructure to test.
* @return (false,true) if (is not, is) an NTScalar.
*/
static bool is_a(epics::pvData::PVStructurePtr const & pvStructure);
/**
* Is the Structure 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.
* @param structure The Structure to test.
* @return (false,true) if (is not, is) an NTScalar.
*/
static bool isCompatible(
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 NTScalar.
*/
static bool isCompatible(
epics::pvData::PVStructurePtr const &pvStructure);
/**
* Checks if the specified structure is a valid NTScalar.
*
* Checks whether the wrapped structure is valid with respect to this
* version of NTScalar
* @return (false,true) if (is not, is) a valid NTScalar.
*/
bool isValid();
/**
* Create a NTScalar builder instance.
* @return builder instance.
@@ -281,4 +310,4 @@ private:
};
}}
#endif /* NTScalar_H */
#endif /* NTSCALAR_H */

View File

@@ -1,7 +1,7 @@
/* 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.
*/
@@ -145,24 +145,54 @@ bool NTScalarArray::is_a(StructureConstPtr const & structure)
return NTUtils::is_a(structure->getID(), URI);
}
bool NTScalarArray::isCompatible(PVStructurePtr const & pvStructure)
bool NTScalarArray::isCompatible(StructureConstPtr const & structure)
{
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;
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;
return isCompatible(pvStructure->getStructure());
}
bool NTScalarArray::isValid()
{
return true;
}
NTScalarArrayBuilderPtr NTScalarArray::createBuilder()
{

View File

@@ -1,7 +1,7 @@
/* 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
@@ -33,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
@@ -47,65 +48,65 @@ namespace detail {
/**
* Set a value type of a NTScalarArray.
* @param elementType the value array element type.
* @return this instance of a {@code NTTableBuilder}.
* @return this instance of <b>NTScalarArrayBuilder</b>.
*/
shared_pointer arrayValue(epics::pvData::ScalarType elementType);
/**
* Add descriptor field to the NTScalarArray.
* @return this instance of a {@code NTScalarArrayBuilder}.
* @return this instance of <b>NTScalarArrayBuilder</b>.
*/
shared_pointer addDescriptor();
/**
* Add alarm structure to the NTScalarArray.
* @return this instance of a {@code NTScalarArrayBuilder}.
* @return this instance of <b>NTScalarArrayBuilder</b>.
*/
shared_pointer addAlarm();
/**
* Add timeStamp structure to the NTScalarArray.
* @return this instance of a {@code NTScalarArrayBuilder}.
* @return this instance of <b>NTScalarArrayBuilder</b>.
*/
shared_pointer addTimeStamp();
/**
* Add display structure to the NTScalarArray.
* @return this instance of a {@code NTScalarArrayBuilder}.
* @return this instance of <b>NTScalarArrayBuilder</b>.
*/
shared_pointer addDisplay();
/**
* Add control structure to the NTScalarArray.
* @return this instance of a {@code NTScalarArrayBuilder}.
* @return this instance of <b>NTScalarArrayBuilder</b>.
*/
shared_pointer addControl();
/**
* Create a {@code Structure} that represents NTScalarArray.
* Create 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}
* Create 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}
* Create 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.
* Add extra <b>Field</b> to the type.
* @param name name of the field.
* @param field a field to add.
* @return this instance of a {@code NTScalarArrayBuilder}.
* @return this instance of <b>NTScalarArrayBuilder</b>.
*/
shared_pointer add(std::string const & name, epics::pvData::FieldConstPtr const & field);
@@ -137,7 +138,8 @@ typedef std::tr1::shared_ptr<detail::NTScalarArrayBuilder> NTScalarArrayBuilderP
/**
* Convenience Class for NTScalarArray
* @brief Convenience Class for NTScalarArray
*
* @author mrk
*/
class epicsShareClass NTScalarArray
@@ -158,28 +160,53 @@ public:
static shared_pointer wrap(epics::pvData::PVStructurePtr const & structure);
/**
* Wrap (aka dynamic cast, or wrap) the structure to NTMultiChannel without checking for isCompatible
* Wrap (aka dynamic cast, or wrap) the structure to NTMatrix without checking for isCompatible
* @param structure The structure to wrap-ed (dynamic cast, wrapped) to NTScalarArray.
* @return NTScalarArray instance.
*/
static shared_pointer wrapUnsafe(epics::pvData::PVStructurePtr const & structure);
/**
* Is the structure an NTScalarArray.
* @param structure The structure to test.
* @return (false,true) if (is not, is) an NTScalarArray.
*/
static bool is_a(epics::pvData::StructureConstPtr const & structure);
/**
* Is the pvStructure compatible with NTScalarArray..
* Is the structure an NTScalarArray.
* @param pvStructure The PVStructure to test.
* @return (false,true) if (is not, is) an NTScalarArray.
*/
static bool is_a(epics::pvData::PVStructurePtr const & pvStructure);
/**
* Is the Structure 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.
* @param structure The Structure to test.
* @return (false,true) if (is not, is) an NTScalarArray.
*/
static bool isCompatible(
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 NTScalarArray.
*/
static bool isCompatible(
epics::pvData::PVStructurePtr const &pvStructure);
/**
* Checks if the specified structure is a valid NTScalarArray.
*
* Checks whether the wrapped structure is valid with respect to this
* version of NTScalarArray
* @return (false,true) if (is not, is) a valid NTScalarArray.
*/
bool isValid();
/**
* Create a NTScalarArray builder instance.
* @return builder instance.
@@ -284,4 +311,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 & structure)
{
if(!isCompatible(structure)) return shared_pointer();
return wrapUnsafe(structure);
}
NTScalarMultiChannel::shared_pointer NTScalarMultiChannel::wrapUnsafe(PVStructurePtr const & structure)
{
return shared_pointer(new NTScalarMultiChannel(structure));
}
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,362 @@
/* 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);
/**
* specify the scalar type for the value field.
* If this is not called then pvDouble is the default.
* @return this instance of <b>NTScalarMultiChannelBuilder</b>.
*/
shared_pointer value(epics::pvData::ScalarType scalarType);
/**
* Add descriptor field to the NTScalarMultiChannel.
* @return this instance of <b>NTScalarMultiChannelBuilder</b>.
*/
shared_pointer addDescriptor();
/**
* Add alarm structure to the NTScalarMultiChannel.
* @return this instance of <b>NTScalarMultiChannelBuilder</b>.
*/
shared_pointer addAlarm();
/**
* Add timeStamp structure to the NTScalarMultiChannel.
* @return this instance of <b>NTScalarMultiChannelBuilder</b>.
*/
shared_pointer addTimeStamp();
/**
* Add severity array to the NTScalarMultiChannel.
* @return this instance of <b>NTScalarMultiChannelBuilder</b>.
*/
shared_pointer addSeverity();
/**
* Add status array to the NTScalarMultiChannel.
* @return this instance of <b>NTScalarMultiChannelBuilder</b>.
*/
shared_pointer addStatus();
/**
* Add message array to the NTScalarMultiChannel.
* @return this instance of <b>NTScalarMultiChannelBuilder</b>.
*/
shared_pointer addMessage();
/**
* Add secondsPastEpoch array to the NTScalarMultiChannel.
* @return this instance of <b>NTScalarMultiChannelBuilder</b>.
*/
shared_pointer addSecondsPastEpoch();
/**
* Add nanoseconds array to the NTScalarMultiChannel.
* @return this instance of <b>NTScalarMultiChannelBuilder</b>.
*/
shared_pointer addNanoseconds();
/**
* Add userTag array to the NTScalarMultiChannel.
* @return this instance of <b>NTScalarMultiChannelBuilder</b>.
*/
shared_pointer addUserTag();
/**
* Add isConnected array to the NTScalarMultiChannel.
* @return this instance of <b>NTScalarMultiChannelBuilder</b>.
*/
shared_pointer addIsConnected();
/**
* Create 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();
/**
* Create a <b>PVStructure</b> that represents NTScalarMultiChannel.
* This resets this instance state and allows new {@code instance to be created.}
* @return a new instance of a <b>PVStructure</b>
*/
epics::pvData::PVStructurePtr createPVStructure();
/**
* Create a <b>NTScalarMultiChannel</b> instance.
* This resets this instance state and allows new {@code instance to be created.}
* @return a new instance of a <b>NTScalarMultiChannel</b>
*/
NTScalarMultiChannelPtr create();
/**
* Add extra <b>Field</b> to the type.
* @param name name of the field.
* @param field a field to add.
* @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;
/**
* Wrap (aka dynamic cast, or wrap) the structure to NTScalarMultiChannel.
* 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 NTScalarMultiChannel.
* @return NTScalarMultiChannel instance on success, nullptr otherwise.
*/
static shared_pointer wrap(epics::pvData::PVStructurePtr const & structure);
/**
* Wrap (aka dynamic cast, or wrap) the structure to NTScalarMultiChannel without checking for isCompatible
* @param structure The structure to wrap-ed (dynamic cast, wrapped) to NTScalarMultiChannel.
* @return NTScalarMultiChannel instance.
*/
static shared_pointer wrapUnsafe(epics::pvData::PVStructurePtr const & structure);
/**
* Is the structure an NTScalarMultiChannel.
* @param structure The structure to test.
* @return (false,true) if (is not, is) an NTScalarMultiChannel.
*/
static bool is_a(epics::pvData::StructureConstPtr const & structure);
/**
* Is the structure an NTScalarMultiChannel.
* @param pvStructure The PVStructure to test.
* @return (false,true) if (is not, is) an NTScalarMultiChannel.
*/
static bool is_a(epics::pvData::PVStructurePtr const & pvStructure);
/**
* Is the Structure compatible with NTScalarMultiChannel.
* This method introspects the fields to see if they are compatible.
* @param structure The Structure to test.
* @return (false,true) if (is not, is) an NTScalarMultiChannel.
*/
static bool isCompatible(
epics::pvData::StructureConstPtr const &structure);
/**
* Is the PVStructure compatible with NTScalarMultiChannel.
* 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 NTScalarMultiChannel.
*/
static bool isCompatible(
epics::pvData::PVStructurePtr const &pvStructure);
/**
* Checks if the specified structure is a valid NTScalarMultiChannel.
*
* Checks whether the wrapped structure is valid with respect to this
* version of NTScalarMultiChannel
* @return (false,true) if (is not, is) a valid NTScalarMultiChannel.
*/
bool isValid();
/**
* Create a NTScalarMultiChannelBuilder instance
* @return builder instance.
*/
static NTScalarMultiChannelBuilderPtr createBuilder();
/**
* Destructor
*/
~NTScalarMultiChannel() {}
/**
* Attach a pvTimeStamp.
* @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.
*/
bool attachTimeStamp(epics::pvData::PVTimeStamp &pvTimeStamp) const;
/**
* Attach a 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.
*/
bool attachAlarm(epics::pvData::PVAlarm &pvAlarm) const;
/**
* Get the pvStructure.
* @return PVStructurePtr.
*/
epics::pvData::PVStructurePtr getPVStructure() const
{return pvNTScalarMultiChannel;}
/**
* 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 PVScalarArrayPtr
*/
epics::pvData::PVScalarArrayPtr getValue() const
{return pvValue;}
/**
* Get the value field of a specified type (e.g. PVDoubleArray).
* @return The <PVT> field for the values.
*/
template<typename PVT>
std::tr1::shared_ptr<PVT> getValue() const
{
return std::tr1::dynamic_pointer_cast<PVT>(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.
*/
epics::pvData::PVStringPtr getDescriptor() const
{return pvDescriptor;}
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,7 +1,7 @@
/* 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.
*/
@@ -20,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();
@@ -43,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();
@@ -58,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;
@@ -89,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;
@@ -109,7 +109,7 @@ NTTableBuilder::NTTableBuilder()
void NTTableBuilder::reset()
{
labels.clear();
columnNames.clear();
types.clear();
descriptor = false;
alarm = false;
@@ -143,18 +143,79 @@ bool NTTable::is_a(StructureConstPtr const & structure)
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());
@@ -203,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,7 +1,7 @@
/* 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
@@ -35,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
@@ -47,56 +48,59 @@ namespace detail {
POINTER_DEFINITIONS(NTTableBuilder);
/**
* Add a column of given {@code Scalar} type.
* Add 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 elememtType);
/**
* Add descriptor field to the NTTable.
* @return this instance of a {@code NTTableBuilder}.
* @return this instance of <b>NTTableBuilder</b>.
*/
shared_pointer addDescriptor();
/**
* Add alarm structure to the NTTable.
* @return this instance of a {@code NTTableBuilder}.
* @return this instance of <b>NTTableBuilder</b>.
*/
shared_pointer addAlarm();
/**
* Add timeStamp structure to the NTTable.
* @return this instance of a {@code NTTableBuilder}.
* @return this instance of <b>NTTableBuilder</b>.
*/
shared_pointer addTimeStamp();
/**
* Create a {@code Structure} that represents NTTable.
* Create 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}
* Create 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}
* Create 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.
* Add extra <b>Field</b> to the type.
* @param name name of the field.
* @param field a field to add.
* @return this instance of a {@code NTTableBuilder}.
* @return this instance of <b>NTTableBuilder</b>.
*/
shared_pointer add(std::string const & name, epics::pvData::FieldConstPtr const & field);
@@ -105,7 +109,7 @@ namespace detail {
void reset();
std::vector<std::string> labels;
std::vector<std::string> columnNames;
std::vector<epics::pvData::ScalarType> types;
bool descriptor;
@@ -126,7 +130,8 @@ typedef std::tr1::shared_ptr<detail::NTTableBuilder> NTTableBuilderPtr;
/**
* Convenience Class for NTTable
* @brief Convenience Class for NTTable
*
* @author mrk
*/
class epicsShareClass NTTable
@@ -159,14 +164,41 @@ public:
* @return (false,true) if (is not, is) an NTTable.
*/
static bool is_a(epics::pvData::StructureConstPtr const & structure);
/**
* Is the pvStructure compatible with NTTable.
* Is the structure an NTTable.
* @param pvStructure The PVStructure to test.
* @return (false,true) if (is not, is) an NTTable.
*/
static bool is_a(epics::pvData::PVStructurePtr const & pvStructure);
/**
* Is the Structure 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.
* @param structure The Structure to test.
* @return (false,true) if (is not, is) an NTTable.
*/
static bool isCompatible(
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 NTTable.
*/
static bool isCompatible(
epics::pvData::PVStructurePtr const &pvStructure);
/**
* Checks if the specified structure is a valid NTTable.
*
* Checks whether the wrapped structure is valid with respect to this
* version of NTTable
* @return (false,true) if (is not, is) a valid NTTable.
*/
bool isValid();
/**
* Create a NTTable builder instance.
* @return builder instance.
@@ -190,7 +222,7 @@ public:
* 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.
* @return true if the operation was successfull (i.e. this instance has a timeStamp field), otherwise false.
*/
bool attachAlarm(epics::pvData::PVAlarm &pvAlarm) const;
@@ -224,6 +256,13 @@ public:
*/
epics::pvData::PVStringArrayPtr getLabels() const;
/**
* Get 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;
/**
* Get the PVField (column) for a field that follows the label field.
* @param columnName The name of the column.
@@ -249,6 +288,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 & structure)
{
if(!isCompatible(structure)) return shared_pointer();
return wrapUnsafe(structure);
}
NTUnion::shared_pointer NTUnion::wrapUnsafe(PVStructurePtr const & structure)
{
return shared_pointer(new NTUnion(structure));
}
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"))
{}
}}

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

@@ -0,0 +1,250 @@
/* 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);
/**
* Add descriptor field to the NTUnion.
* @return this instance of <b>NTUnionBuilder</b>.
*/
shared_pointer addDescriptor();
/**
* Add alarm structure to the NTUnion.
* @return this instance of <b>NTUnionBuilder</b>.
*/
shared_pointer addAlarm();
/**
* Add timeStamp structure to the NTUnion.
* @return this instance of <b>NTUnionBuilder</b>.
*/
shared_pointer addTimeStamp();
/**
* Create 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();
/**
* Create 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();
/**
* Create 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();
/**
* Add extra <b>Field</b> to the type.
* @param name name of the field.
* @param field a field to add.
* @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;
/**
* Wrap (aka dynamic cast, or wrap) the structure to NTUnion.
* 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 NTUnion.
* @return NTUnion instance on success, nullptr otherwise.
*/
static shared_pointer wrap(epics::pvData::PVStructurePtr const & structure);
/**
* Wrap (aka dynamic cast, or wrap) the structure to NTUnion without checking for isCompatible
* @param structure The structure to wrap-ed (dynamic cast, wrapped) to NTUnion.
* @return NTUnion instance.
*/
static shared_pointer wrapUnsafe(epics::pvData::PVStructurePtr const & structure);
/**
* Is the structure an NTUnion.
* @param structure The structure to test.
* @return (false,true) if (is not, is) an NTUnion.
*/
static bool is_a(epics::pvData::StructureConstPtr const & structure);
/**
* Is the structure an NTUnion.
* @param pvStructure The PVStructure to test.
* @return (false,true) if (is not, is) an NTUnion.
*/
static bool is_a(epics::pvData::PVStructurePtr const & pvStructure);
/**
* Is the Structure compatible with NTUnion.
* This method introspects the fields to see if they are compatible.
* @param structure The Structure to test.
* @return (false,true) if (is not, is) an NTUnion.
*/
static bool isCompatible(
epics::pvData::StructureConstPtr const &structure);
/**
* Is the PVStructure compatible with NTUnion.
* 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 NTUnion.
*/
static bool isCompatible(
epics::pvData::PVStructurePtr const &pvStructure);
/**
* Checks if the specified structure is a valid NTUnion.
*
* Checks whether the wrapped structure is valid with respect to this
* version of NTUnion
* @return (false,true) if (is not, is) a valid NTUnion.
*/
bool isValid();
/**
* Create a NTUnion builder instance.
* @return builder instance.
*/
static NTUnionBuilderPtr createBuilder();
/**
* Destructor.
*/
~NTUnion() {}
/**
* Attach a pvTimeStamp.
* @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.
*/
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.
*/
bool attachAlarm(epics::pvData::PVAlarm &pvAlarm) const;
/**
* Get the pvStructure.
* @return PVStructurePtr.
*/
epics::pvData::PVStructurePtr getPVStructure() const;
/**
* Get the descriptor field.
* @return The pvString or null if no function field.
*/
epics::pvData::PVStringPtr getDescriptor() const;
/**
* Get the timeStamp.
* @return PVStructurePtr which may be null.
*/
epics::pvData::PVStructurePtr getTimeStamp() const;
/**
* Get the alarm.
* @return PVStructurePtr which may be null.
*/
epics::pvData::PVStructurePtr getAlarm() const;
/**
* Get the value field.
* @return The PVUnion for the values.
*/
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 & structure)
{
if(!isCompatible(structure)) return shared_pointer();
return wrapUnsafe(structure);
}
NTURI::shared_pointer NTURI::wrapUnsafe(PVStructurePtr const & structure)
{
return shared_pointer(new NTURI(structure));
}
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)
{}
}}

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

@@ -0,0 +1,287 @@
/* 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);
/**
* Add authority field to the NTURI.
* @return this instance of <b>NTURIBuilder</b>.
*/
shared_pointer addAuthority();
/**
* Add 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);
/**
* Add 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);
/**
* Add 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);
/**
* Add 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 <b>NTURIBuilder</b>.
*/
//shared_pointer addColumn(std::string const & name, epics::pvData::ScalarType elememtType);
/**
* Create 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();
/**
* Create 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();
/**
* Create 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();
/**
* Add extra <b>Field</b> to the type.
* @param name name of the field.
* @param field a field to add.
* @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;
/**
* Wrap (aka dynamic cast, or wrap) the structure to NTURI.
* 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 NTURI.
* @return NTURI instance on success, nullptr otherwise.
*/
static shared_pointer wrap(epics::pvData::PVStructurePtr const & structure);
/**
* 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 NTURI.
* @return NTURI instance.
*/
static shared_pointer wrapUnsafe(epics::pvData::PVStructurePtr const & structure);
/**
* Is the structure an NTURI.
* @param structure The structure to test.
* @return (false,true) if (is not, is) an NTURI.
*/
static bool is_a(epics::pvData::StructureConstPtr const & structure);
/**
* Is the structure an NTURI.
* @param pvStructure The PVStructure to test.
* @return (false,true) if (is not, is) an NTURI.
*/
static bool is_a(epics::pvData::PVStructurePtr const & pvStructure);
/**
* Is the Structure compatible with NTURI.
* This method introspects the fields to see if they are compatible.
* @param structure The Structure to test.
* @return (false,true) if (is not, is) an NTURI.
*/
static bool isCompatible(
epics::pvData::StructureConstPtr const &structure);
/**
* Is the PVStructure compatible with NTURI.
* 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 NTURI.
*/
static bool isCompatible(
epics::pvData::PVStructurePtr const &pvStructure);
/**
* Checks if the specified structure is a valid NTURI.
*
* Checks whether the wrapped structure is valid with respect to this
* version of NTURI
* @return (false,true) if (is not, is) a valid NTURI.
*/
bool isValid();
/**
* Create a NTURI builder instance.
* @return builder instance.
*/
static NTURIBuilderPtr createBuilder();
/**
* Destructor.
*/
~NTURI() {}
/**
* Get the pvStructure.
* @return PVStructurePtr.
*/
epics::pvData::PVStructurePtr getPVStructure() const;
/**
* Get the scheme field.
* @return The PVString for the scheme.
*/
epics::pvData::PVStringPtr getScheme() const;
/**
* Get the authority field.
* @return The PVString for the authority.
*/
epics::pvData::PVStringPtr getAuthority() const;
/**
* Get the path field.
* @return The PVString for the path.
*/
epics::pvData::PVStringPtr getPath() const;
/**
* Get the query field.
* @return The PVStructure for the query.
*/
epics::pvData::PVStructurePtr getQuery() const;
/**
* Get 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;
/**
* 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.
*/
epics::pvData::PVFieldPtr getQueryField(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.
*/
template<typename PVT>
std::tr1::shared_ptr<PVT> getQueryField(std::string const & columnName) const
{
epics::pvData::PVFieldPtr pvField = getQueryField(columnName);
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 */

View File

@@ -1,7 +1,7 @@
/* ntutils.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.
*/
@@ -14,12 +14,15 @@ namespace epics { namespace nt {
bool NTUtils::is_a(const std::string &u1, const std::string &u2)
{
// remove minor for the u2
size_t pos = u2.find_last_of('.');
std::string su2 = (pos == string::npos) ? u2 : u2.substr(0, pos);
// remove minor for the u1
size_t pos1 = u1.find_last_of('.');
std::string su1 = (pos1 == string::npos) ? u1 : u1.substr(0, pos1);
// "starts with comparison"
return su2.size() <= u1.size() && u1.compare(0, su2.size(), su2) == 0;
// 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;
}
}}

View File

@@ -1,7 +1,7 @@
/* ntutils.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 NTUTILS_H
@@ -13,7 +13,8 @@
namespace epics { namespace nt {
/**
* Utility methods for NT types.
* @brief Utility methods for NT types.
*
* @author mse
*/
class epicsShareClass NTUtils {

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

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

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

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

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.
*/
@@ -24,11 +24,13 @@ void test_is_a()
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(8);
testPlan(10);
test_is_a();
return testDone();
}