139 Commits

Author SHA1 Message Date
Ralph Lange
bcaac0163a jenkins: adapt doc script to new CloudBees jenkins job 2015-09-14 15:17:55 +02:00
Dave Hickin
f9d27b2d74 Merge branch 'master' into release/5.0 2015-09-05 07:38:15 +01:00
Dave Hickin
2bc01a482e Doxygen fixes 2015-09-05 07:34:18 +01:00
Ralph Lange
392cc7426d jenkins: update dependencies pvCommonCPP/4.1 pvDataCPP/5.0 2015-09-04 11:55:29 +02:00
Dave Hickin
dd955ea81e Ammend license notice in unit tests
Replaced references to "EPICS pvData" with "this software" in per-file
copyright notice - consistent with other files.
2015-09-04 09:41:08 +01:00
Dave Hickin
a0a19bcfd9 Fix bug in NTUtils::is_a
Previous implementation matches <type-name>:1x.0 and <type-name>:1.0,
depending on the order of the arguments, e.g.
NTUtils::is_a("epics:nt/NTTable:11.0", "epics:nt/NTTable:1.0") returned
true. Fix this and add unit tests to cover this.
2015-09-04 09:39:27 +01:00
Dave Hickin
16b46448c0 License and copyright
Replaced references to "EPICS pvData" and "EPICS JavaIOC" with "this
software" in per-file copyright notice - consistent with other files.
Add BNL and DLS to copyright and legal disclaimers.
2015-09-04 09:24:54 +01:00
Dave Hickin
e5947aa0a2 Add unit tests for NTNDArrayAttribute 2015-09-04 08:37:09 +01:00
Dave Hickin
3c30598a56 Add unit test for NTHistogram 2015-09-04 00:34:41 +01:00
Dave Hickin
85673cadad Add unit test for NTContinuum 2015-09-04 00:33:57 +01:00
Dave Hickin
db0d1e8f9e Fix for NTHistogram::isCompatible()
Correct null pointer check - logic was inverted
2015-09-04 00:33:06 +01:00
Dave Hickin
99f9e0429f Remove duplicate NTField 2015-09-03 14:10:08 +01:00
Dave Hickin
3dc852e2b7 Delete commented out code 2015-09-03 14:09:36 +01:00
Dave Hickin
d9c3dfcf26 Use NTNDArrayAttribute in constructing NTNDArray
Use NTNDArrayAttribute wrapper to construct NTAttributes in NTNDArray.
Delete unused attribute string.
2015-09-03 14:08:56 +01:00
Ralph Lange
38f7d6bea1 jenkins: add configurable dependent branch versions 2015-09-03 13:44:17 +02:00
Matej Sekoranja
4f38e7904d fixed rtems/vxworks compilation 2015-09-01 21:12:47 +02:00
Matej Sekoranja
ad03935c5b Merge pull request #4 from anjohnson/add-license-file
Add license and copyright files
2015-09-01 20:06:49 +02:00
Dave Hickin
5574452b08 Call addIsConnected() in unit tests
for multi-channel types
2015-09-01 16:50:46 +01:00
Dave Hickin
649cd6800d Make isConnected optional in multi channel types 2015-09-01 15:55:21 +01:00
Dave Hickin
05a7a6923f Implement NTNDArray::isValid() 2015-09-01 15:53:52 +01:00
Dave Hickin
f5226f23dc Implement NTNDArray::isCompatible(Structure)
Add implementation of NTNDArray::isCompatible(Structure). Implement
NTNDArray::isCompatible(PVStructure) in terms of this.
2015-09-01 15:53:09 +01:00
Dave Hickin
e1fdcfcab0 Add implementation of NTID 2015-09-01 15:50:18 +01:00
Dave Hickin
5ec16a1772 Fix build error
boolean replaced by bool
2015-09-01 02:40:14 +01:00
Dave Hickin
ba64c6a6a5 Add isValid() implementations
for NTMultiChannel, NTScalarMultiChannel, NTTable and NTURI.
2015-08-31 23:53:10 +01:00
Dave Hickin
ed9a707f14 More efficient implementation of NTTable
Cache the value field. Allows simpler implementation of getColumn().
2015-08-31 23:50:51 +01:00
Dave Hickin
6ec5fb6ef9 Add implentations of isValid()
for NTAggregate, NTAttibute, NTContinuum, NTEnum, NTHistogram, NTMatrix,
NTNameValue, NTNDArrayAttribute, NTScalar, NTScalarArray and NTUnion.
2015-08-30 23:46:02 +01:00
Dave Hickin
ddab44823f Use NTAttribute wrapper in NTNDArray
Use the wrapper NTAttribute wrapper NTNDArrayAttribute to test the
attribute field in implementation of NTNDArray::isCompatible(Structure).
2015-08-29 11:09:32 +01:00
Dave Hickin
d54060576a Add implementation of isCompatible(Structure)
for all types except NTNDArray and implement isCompatible(PVStructure)
in terms of it.
2015-08-29 11:06:37 +01:00
Dave Hickin
e8a9beec07 Remove excess blank lines 2015-08-29 11:00:40 +01:00
Dave Hickin
84304d9b4e Add utility class for parsing NT IDs 2015-08-21 14:46:26 +01:00
Dave Hickin
b62cb22818 Added NTNDArrayAttribute
Added wrapper for NTAttributes extended as required by NTNDArray.
2015-08-21 07:45:16 +01:00
Dave Hickin
1e6fb17e92 Add NTURI 2015-08-21 06:47:52 +01:00
Dave Hickin
bc2622f70a Add getColumnNames() to NTTable 2015-08-21 06:46:17 +01:00
Dave Hickin
da81f8db83 Add NTHistogram 2015-08-21 03:55:35 +01:00
Dave Hickin
7c58eae97e Add NTContinuum 2015-08-21 03:55:04 +01:00
Dave Hickin
0b3e1c9fd1 Add isValid() and overloads of is_a() and isCompatible()
Add convenience methods is_a(PVStructure). Add overloads of isCompatible
taking a Structure since implementation of isCompatible(PVStructure)
only uses introspection interface. Implement for NTScalar and
NTScalarArray. Add isValid() function that checks NT is valid through data
interface.
2015-08-21 01:15:40 +01:00
Dave Hickin
59afc5335a Fixed unit NTTable test failure 2015-08-20 18:32:18 +01:00
Dave Hickin
399a39a20a Tell git to ignore build output of unit tests 2015-08-20 17:26:03 +01:00
Dave Hickin
000dde0454 Make attach* functions return bool in multi-channel types
The attachAlarm and attachTimeStamps() return true if successful, false
otherwise in other classes. In NTMultiChannel and NTScalarMultiChannel
they returned void. Bring multi-channel behaviour in line.
2015-08-20 17:23:59 +01:00
Dave Hickin
5076057d8d Make isConnected optional field of multi-channel types
A boolean[] isConnected field was included in all constructed
NTMultiChannels and NTScalarMultiChannels. However this is neither a
required nor optional field of these types. Applications use this
though, (specifically pvaClient) so treat as if optional field. Add
addIsConnected() function to builders and retain isConnected() in
wrapper classes. Leave isConnected field in structures until clients
updated.
2015-08-20 17:19:18 +01:00
Dave Hickin
fd60732a8c Rename add() addColumn() in NTTable
Function for adding columns to table (i.e. to value subfield) was
add(ScalarType). However add(Field) adds extra field to top-level
structure. Rename former to avoid confusion and as more meaningful
name. Update unit tests.
2015-08-20 17:07:27 +01:00
Dave Hickin
002a465705 Clear up confusion between labels and column names
The labels are strings used in the displaying of the columns of a table
e.g. column titles or headers. The column names of an NTTable are the
names of the fields containing the column data. There was some confusion
in the implementation between these. Rename the labels variable
columnNames and correct the comments. Tables were created with labels
equal to the column names. Retain this behaviour for backwards
compatibility, as a sensible default and to always create a valid table,
but document this.
2015-08-20 17:03:27 +01:00
dhickin
28186f0e3d Merge pull request #6 from dhickin/add_missing_types
Add normative types
2015-08-20 16:35:53 +01:00
Dave Hickin
fc037cf6dc Add unit tests for NTAttribute 2015-08-20 16:16:58 +01:00
Dave Hickin
5ddcc70993 Add getName() and getTags() functions to NTAttribute 2015-08-20 16:16:34 +01:00
Dave Hickin
dc93316856 Merge branch 'add_missing_types' of github.com:dhickin/normativeTypesCPP into add_missing_types 2015-08-20 09:44:27 +01:00
Dave Hickin
b40eca79cf Add NTAttribute including builder 2015-08-20 08:43:27 +01:00
Dave Hickin
f6f5539f7b Add NTAggregate including builder and unit tests 2015-08-20 08:41:45 +01:00
Dave Hickin
0d66034092 Add NTUnion including builder and unit tests 2015-08-20 08:01:29 +01:00
Dave Hickin
1de2666993 Add NTEnum including builder and unit tests 2015-08-20 07:59:29 +01:00
Dave Hickin
7d0b6d86ea Add NTMatrix including builder and unit tests 2015-08-20 07:56:20 +01:00
Ralph Lange
bef1a86b8b jenkins: fix cut-n-paste issue in doc job 2015-08-18 16:54:42 +02:00
Ralph Lange
8f66d21cca Remove mercurial debris (.hg*) 2015-08-18 16:10:42 +02:00
Ralph Lange
f4b7bdbdf0 jenkins: remove hgweb job; split build and doc jobs; update EPICS Base version 2015-08-18 16:10:11 +02:00
Dave Hickin
5f8922e349 Incremented number of tests in NTTable test plan 2015-08-13 12:46:27 +01:00
Dave Hickin
5b7c6ea4d8 Fixed NTTable units tests for extra fields
After fix for NTTable extra fields not being created was merged, unit
tests failed. Tests were wrong. Test was checking number of fields of
constructed structure against number expected without the extra fields.
Corrected check and added checks for extra fields.
2015-08-13 10:59:15 +01:00
dhickin
08f8b56740 Merge pull request #5 from brunoseivam/patch-1
Fix extra fields not being created
2015-08-13 09:51:02 +01:00
Bruno Martins
b52fc4fce8 Fix extra fields not being created
FieldBuilder::createStructure() was being called too early inside NTTableBuilder::createStructure(), preventing extra fields from being properly created.
2015-08-12 22:46:46 -04:00
Andrew Johnson
b976d918d5 Resolves epics-base/normativeTypesCPP #1 2015-08-11 17:43:31 -05:00
Andrew Johnson
c7a58af787 Add COPYRIGHT file 2015-08-11 16:53:36 -05:00
Dave Hickin
b1143fea9e Make #endif comments match #ifdef in inclusion guards 2015-08-06 14:06:14 +01:00
Dave Hickin
efa9dff1d4 Change references to NTTableBuilder to NTScalarBuilder in NTScalar 2015-08-06 14:04:47 +01:00
Dave Hickin
3b9f8a26c0 Include ntscalarMultiChannel.h in nt.h 2015-08-06 13:57:11 +01:00
dhickin
f64329e661 Merge pull request #3 from dhickin/NTScalarMultiChannel
Add NTScalarMultiChannel
2015-08-05 22:13:19 +01:00
Dave Hickin
8b9a8e7050 Add tests for NTScalarMultiChannel 2015-08-04 21:32:34 +01:00
Dave Hickin
5381a0c294 Add NTScalarMultiChannel 2015-08-04 21:30:13 +01:00
Andrew Johnson
36b8e60152 Fix module name in sources LICENSE reference 2015-08-03 16:47:28 -05:00
Andrew Johnson
f226c7ac96 Add LICENSE file copied from pvDataCPP 2015-08-03 16:23:21 -05:00
Andrew Johnson
2f54b89227 Added .gitignore file 2015-06-16 18:06:08 -05:00
Andrew Johnson
ec02b9f7ee Cleanup: Remove extraneous / from SRC 2015-06-08 17:47:14 -05:00
dhickin
efff7f5041 Improve thread-safety of NTNDArray. 2015-06-08 10:34:10 +01:00
dhickin
8c292eeebc Reorder optional fields to consistent order to match new NT spec. 2015-05-11 14:02:18 +01:00
dhickin
25e8c65bb0 Reorder declarations/definitions. 2015-04-22 14:55:40 +01:00
dhickin
f47b059a5b Add definition of missing uniqueId() function. 2015-04-22 14:47:34 +01:00
dhickin
16d8284131 merge branch release/4.0 to default. 2015-04-22 14:42:00 +01:00
Ralph Lange
ef4a9d6b4b jenkins: fix cloudbees script (commands must return 0) 2014-12-19 14:16:57 +01:00
Ralph Lange
8ec19d25f1 jenkins: create and update documentation in only one build configuration 2014-12-19 13:18:23 +01:00
Matej Sekoranja
2d3b415c00 removed bin dbd from upload TAR 2014-12-16 10:43:47 +01:00
Matej Sekoranja
177a048220 added jenkins support 2014-12-15 23:26:01 +01:00
Marty Kraimer
acd986c19d work on doxygen 2014-12-15 08:31:41 -05:00
dhickin
3cb954aefa make local RELEASE.local files take precedence over those in TOP/.. 2014-12-09 13:48:15 +00:00
dhickin
bffeca57a8 Added tag 4.0.2 for changeset e4b8d66cee36 2014-12-05 12:07:35 +00:00
dhickin
e8a04138b0 Added dated version (20141009) for latest html documentation. 2014-12-04 16:05:51 +00:00
dhickin
9f5aec1609 Corrected some spelling and some minor formatting issues. 2014-12-04 15:49:43 +00:00
dhickin
8dadad8101 make "local" *.local files take precedence over those in TOP/.. 2014-12-03 16:55:25 +00:00
dhickin
9cc7c65df6 include CONFIG_SITE.local instead of CONFIG.local at top-level. 2014-12-03 16:10:23 +00:00
Matej Sekoranja
518718357c Added tag 4.0.1 for changeset 1c140dd0e199 2014-11-11 17:03:05 +01:00
Matej Sekoranja
1ae93ddaed merge 2014-11-11 17:02:58 +01:00
Matej Sekoranja
99bf23e8fa fixed Makefile for ntutils test 2014-11-11 17:02:33 +01:00
Matej Sekoranja
b5846433bf Added tag 4.0.1 for changeset 0daade17a744 2014-11-10 21:54:39 +01:00
Matej Sekoranja
8760d5e314 merge 2014-11-10 21:53:52 +01:00
Matej Sekoranja
a25a89fadc win32 build, all test pass 2014-11-10 21:52:10 +01:00
Matej Sekoranja
49312d62d5 added epicsShared export declarations 2014-11-10 10:24:10 +01:00
Matej Sekoranja
42fb15211a NTUtils added, is_a for new URI scheme 2014-11-10 10:04:32 +01:00
Matej Sekoranja
86ee0c5295 merge 2014-10-29 13:26:21 +01:00
Matej Sekoranja
1fca4d5757 Added tag 4.0.0 for changeset ec29bda853f5 2014-10-29 13:26:06 +01:00
Matej Sekoranja
95e9b394c4 fixed NTNDArray::isCompatible 2014-10-29 13:25:33 +01:00
Matej Sekoranja
3c5e4a1db5 URI: ev4 to epics 2014-10-28 20:18:08 +01:00
Marty Kraimer
70b30ade1a Added tag 4.0.0 for changeset df4c65e13c2c 2014-10-15 14:59:37 -04:00
Marty Kraimer
c9d4f6aa02 update ntCPP.html and TODO 2014-10-09 07:46:59 -04:00
dhickin
198a6a691f Spelling and typos 2014-10-04 01:48:33 +01:00
Marty Kraimer
acc87079d6 Added tag 4.0.0 for changeset aaa5f5840b7e 2014-10-02 06:47:53 -04:00
Marty Kraimer
2ede54033e flow: Created branch 'release/4.0'. 2014-10-01 08:38:48 -04:00
Marty Kraimer
6be30cd104 flow initialization: Added configuration file. 2014-10-01 08:38:20 -04:00
Marty Kraimer
4ee19f4dd1 URI of form ev4:nt/NTType:1.0 ; narrow, narrow_unsafe, is_compatible => wrap, wrapUnsafe, isCompatible 2014-10-01 08:34:34 -04:00
dhickin
08eb138d02 Added ntndarray tests for non-extended types and caching. 2014-09-24 16:51:36 +01:00
dhickin
3765a0567c Put back caching of ntndarray types when not extended and for sub-structure types. 2014-09-24 16:50:18 +01:00
dhickin
b06c13c5d8 Removed type caching for NTNDArray since incompatible with new adding extra fields feature. 2014-09-24 11:03:10 +01:00
Marty Kraimer
dbc5c434cb NTField::createAlarmLimit removed; NTNameValue names,values changed to name,value 2014-09-23 08:50:49 -04:00
dhickin
9c7cd05437 Correct a field name in NTNDArray (attribute.description->attribute.descriptor). 2014-09-23 11:02:13 +01:00
dhickin
6a187d274e Reordered fields in NTNDArray 2014-09-23 10:50:20 +01:00
Marty Kraimer
0d21cb267a mostly changes to ntCPP.html; in NTMultiChannel addValue changed to value 2014-09-19 09:52:53 -04:00
Marty Kraimer
eba5aa6c8b change implementation of createPVStructure in nttable.cpp 2014-09-12 16:28:55 -04:00
Marty Kraimer
7465da3217 implemented is_compatible 2014-09-12 15:41:36 -04:00
Marty Kraimer
ddee226a49 added "add(name,field)" to each bulder; added is_compatible to each NT(code is not complete) 2014-09-12 09:56:08 -04:00
Guobao Shen
76546d22b4 fix clang compiling 2014-09-05 14:27:08 -04:00
Matej Sekoranja
63eb1aa703 ntnameValue: extra fields can be added now 2014-09-04 12:30:02 +02:00
Matej Sekoranja
89396a7455 narrow and narrow_unsafe methods added 2014-08-31 23:29:45 +02:00
Marty Kraimer
f1aca7e20f fix bug for userTag 2014-08-26 06:30:30 -04:00
Marty Kraimer
f2bbec36ef added connectionState 2014-08-25 06:23:52 -04:00
Matej Sekoranja
887b453bac NTScalarArray added 2014-08-25 08:58:40 +02:00
Matej Sekoranja
131c2fc31a converted ntfieldTest to TAP test 2014-08-25 08:10:41 +02:00
dhickin
594aa52a20 Merge. 2014-08-22 23:27:06 +01:00
dhickin
eef8bd4fba NTNDArray. Added unit test. 2014-08-22 23:24:47 +01:00
dhickin
8058a389d7 NTNDArray. Reorder uniqueId and dataTimeStamp fields. 2014-08-22 23:21:42 +01:00
dhickin
52ab0ff37b NTNDArray. Created builder. Removed create and clone. 2014-08-22 22:32:31 +01:00
Matej Sekoranja
9df8d3cb2a merge 2014-08-22 22:56:51 +02:00
Matej Sekoranja
f27e741eca NTScalr value is cached 2014-08-22 22:56:05 +02:00
dhickin
53c89e5a73 updates to NTNDArray 2014-08-22 19:32:30 +01:00
dhickin
1fdcfb7ad1 Added first implementation of NTNDArray. 2014-08-22 16:56:43 +01:00
Matej Sekoranja
379a132cd7 NTScalar added 2014-08-22 09:12:24 +02:00
Matej Sekoranja
5b46b9ebed NTNameValue refactored 2014-08-21 21:49:46 +02:00
Marty Kraimer
c0cb48e97e added userTag 2014-08-21 12:57:36 -04:00
Marty Kraimer
072113ab4a change to implement builder 2014-08-21 10:27:09 -04:00
Marty Kraimer
7f521bdc3c added NTMultiChannel 2014-08-21 07:59:46 -04:00
Matej Sekoranja
fdeda9dc97 NTTable refactored 2014-08-21 13:28:52 +02:00
Marty Kraimer
327371151a make it work with latest pvDataCPP. 2014-08-20 10:12:10 -04:00
Ralph Lange
d7555b9c6c configure: add support for super-top RELEASE.local 2014-01-24 21:30:07 +01:00
Guobao Shen
479e3ab603 Added tag 1.0-BETA for changeset b9a943e68287 2013-01-09 15:15:20 -05:00
75 changed files with 19501 additions and 1738 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,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

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

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

View File

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

View File

@@ -0,0 +1,4 @@
<h1>Release 4.0 IN DEVELOPMENT</h1>
<p>This is the first release of normativeTypesCPP that is part of an official
EPICS V4 release.
It is a major rewrite of the previous versions of normativeTypesCPP.</p>

View File

@@ -0,0 +1,7 @@
Release 4.0 IN DEVELOPMENT
===========
This is the first release of normativeTypesCPP that is part of an official
EPICS V4 release.
It is a major rewrite of the previous versions of normativeTypesCPP.

22
documentation/TODO.html Normal file
View File

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

37
documentation/TODO.md Normal file
View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,289 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
<title>EPICS pvDataCPP</title>
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/base.css" />
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/epicsv4.css" />
<style type="text/css">
/*<![CDATA[*/
.about { margin-left: 3em; margin-right: 3em; font-size: .83em}
table { margin-left: auto; margin-right: auto }
.diagram { text-align: center; margin: 2.5em 0 }
span.opt { color: grey }
span.nterm { font-style:italic }
span.term { font-family:courier }
span.user { font-family:courier }
span.user:before { content:"<" }
span.user:after { content:">" }
.nonnorm { font-style:italic }
p.ed { color: #AA0000 }
span.ed { color: #AA0000 }
p.ed.priv { display: inline; }
span.ed.priv { display: inline; }
/*]]>*/</style>
<!-- Script that generates the Table of Contents -->
<script type="text/javascript"
src="http://epics-pvdata.sourceforge.net/script/tocgen.js">
</script>
</head>
<body>
<div class="head">
<h1>EPICS pvDataCPP</h1>
<!-- Maturity: Working Draft or Request for Comments, or Recommendation, and date. -->
<h2 class="nocount">EPICS v4 Working Group, Working Draft, 23-July-2014</h2>
<dl>
<dt>Latest version:</dt>
<dd><a
href="ntCPP.html">ntCPP.html</a>
</dd>
<dt>This version:</dt>
<dd><a
href="ntCPP_20140723.html">ntCPP_20140723.html</a>
</dd>
<dt>Previous version:</dt>
<dd>None</dd>
<dt>Editors:</dt>
<dd>Marty Kraimer, BNL</dd>
<dd>Michael Davidsaver, BNL</dd>
<dd>Matej Sekoranja, CosyLab</dd>
</dl>
<p class="copyright">This product is made available subject to acceptance of the <a
href="http://epics-pvdata.sourceforge.net/LICENSE.html">EPICS open source
license.</a></p>
<hr />
</div>
<h2 class="nocount">Abstract</h2>
<p>EPICS Version 4 provides efficient
storage, access, and communication, of memory resident structured data.
pvData is the storage compoment.
pvDataCPP is the C++ implementation of pvData.
It is one part of the set of related products in the EPICS
V4 control system programming environment:<br />
<a href="http://epics-pvdata.sourceforge.net/relatedDocumentsV4.html">relatedDocumentsV4.html</a>
</p>
<h2 class="nocount">Status of this Document</h2>
<p>For now this is a working copy so it is not the same as "This version" shown above.</p>
<p>This is the 23-July-2014 version of the C++ implementation of pvData.
</p>
<p>RELEASE_NOTES.md provides changes since the last release.
TODO.md describes things to do before the next release.
</p>
<div id="toc">
<h2 class="nocount" style="page-break-before: always">Table of Contents</h2>
</div>
<div id="contents" class="contents">
<body>
<h1 style="text-align: center">EPICS normative type C++ implementation
</h1>
<h2 class="nocount" id="L50">Draft, 4-Nov-2012</h2>
<dl>
<dt>This version:</dt>
<dd><a href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/normativeTypesCPP/raw-file/tip/documentation/ntCPP.html">ntCPP.html</a></dd>
<dt>Editors:</dt>
<dd>Matej Sekoranja, CosyLab<br>
Marty Kraimer, BNL
</dd>
</dl>
<hr />
</div>
<h2>Introduction</h2>
<p>This section describes the C++ implemmentation of normative types. Two (2) helper classes are implemented,
ntNameValue and NTTable respectively. </p>
<h3>Normative Type Fields.</h3>
<p>These are helper classes for creating standard fields for normative types.
There is a single instance of this class, which is obtained via NTField::get().
</p>
<pre>class NTField: NoDefaultMethods {
public:
static NTFieldPtr get();
~NTField() {}
PVStructurePtr createEnumerated(StringArray const &amp; choices);
PVStructurePtr createTimeStamp();
PVStructurePtr createAlarm();
PVStructurePtr createDisplay();
PVStructurePtr createAlarmLimit();
PVStructurePtr createControl();
PVStructureArrayPtr createEnumeratedArray();
PVStructureArrayPtr createTimeStampArray();
PVStructureArrayPtr createAlarmArray();
};</pre>
<p>where</p>
<dl>
<dt>createEnumerated</dt>
<dd>Create an introspection interface for an enumerated structure.</dd>
<dt>createTimeStamp</dt>
<dd>Create an interspection interface for a timeStamp structure.</dd>
<dt>createAlarm</dt>
<dd>Create an interspection interface for an alarm structure.</dd>
<dt>createDisplay</dt>
<dd>Create an introsepecion interface for a display structure.</dd>
<dt>createAlarmLimit</dt>
<dd>Create an introspection interface for an alarm limit structure.</dd>
<dt>createControl</dt>
<dd>Create an introspection interface for a control structure.</dd>
<dt>createEnumeratedArray</dt>
<dd>Create an introspection interface for an structureArray of enumerated
structures.</dd>
<dt>createTimeStampArray</dt>
<dd>Create an introspection interface for an structureArray of timeStamp
structures.</dd>
<dt>createAlarmArray</dt>
<dd>Create an introspection interface for an structureArray of alarm
structures.</dd>
</dl>
<h3>NTNameValue</h3>
<p>These are helper classes for NTNameValue</p>
<pre>class NTNameValue : private NoDefaultMethods
{
public:
static bool isNTNameValue(PVStructurePtr const & pvStructure);
static NTNameValuePtr create(
bool hasFunction,bool hasTimeStamp, bool hasAlarm);
static NTNameValuePtr create(
PVStructurePtr const & pvStructure);
~NTNameValue();
PVStringPtr getFunction();
void attachTimeStamp(PVTimeStamp &amp;pvTimeStamp);
void attachAlarm(PVAlarm &amp;pvAlarm);
PVStructurePtr getPVStructure();
PVStructurePtr getTimeStamp();
PVStructurePtr getAlarm();
PVStringArrayPtr getNames();
PVStringArrayPtr getValues();
};</pre>
<p>where</p>
<dl>
<dt>isNTNameValue</dt>
<dd>Is the structure a NTNameValue structure?</dd>
<dt>create</dt>
<dd>Create an NTNameValue that has the associated fields.</dd>
<dt>~NTNameValue</dt>
<dd>The destructor.</dd>
<dt>getFunction</dt>
<dd>Get the function field. This can be null.</dd>
<dt>attachTimeStamp</dt>
<dd>The timeStamp field of the NTNameValue is atttached to the
pvTimeStamp.</dd>
<dt>attachAlarm</dt>
<dd>The alarm field of the NTNameValue is atttached to the alarm.</dd>
<dt>getPVStructure</dt>
<dd>Get the pvStructure that this NTNameValue contains.</dd>
<dt>getTimeStamp</dt>
<dd>Get the timeStamp field.</dd>
<dt>getAlarm</dt>
<dd>Get the alarm field.</dd>
<dt>getNames</dt>
<dd>Get the names field.</dd>
<dt>getValues</dt>
<dd>Get the values field.</dd>
</dl>
<h3>NTTable</h3>
<p>These are helper classes for NTTable</p>
<pre>class NTTable: private NoDefaultMethods
{
public:
static bool isNTTable(PVStructurePtr const & pvStructure);
static PVStructure::shared_pointer create(
bool hasFunction,bool hasTimeStamp, bool hasAlarm,
int numberValues,
FieldConstPtrArray valueFields);
static NTTablePtr create(
bool hasFunction,bool hasTimeStamp, bool hasAlarm,
StringArray const & valueNames,
FieldConstPtrArray const &valueFields);
static NTTablePtr clone(PVStructurePtr const &);
~NTTable();
PVStringPtr getFunction();
void attachTimeStamp(PVTimeStamp &amp;pvTimeStamp);
void attachAlarm(PVAlarm &amp;pvAlarm);
PVStructurePtr getPVStructure();
PVStructurePtr getTimeStamp();
PVStructurePtr getAlarm();
PVStringArrayPtr getLabel();
size_t getNumberValues();
FieldConstPtr getField(int index);
PVFieldPtr getPVField(int index);
};</pre>
<p>where</p>
<dl>
<dt>isNTTable</dt>
<dd>y</dd>
<dt>create</dt>
<dd>Create an NTTable that has the associated fields.</dd>
<dt>~NTTable</dt>
<dd>The destructor.</dd>
<dt>getFunction</dt>
<dd>Get the function field. This can be null.</dd>
<dt>attachTimeStamp</dt>
<dd>The timeStamp field of the NTTable is atttached to the pvTimeStamp.</dd>
<dt>attachAlarm</dt>
<dd>The alarm field of the NTTable is atttached to the alarm.</dd>
<dt>getPVStructure</dt>
<dd>Get the pvStructure that this NTTable contains.</dd>
<dt>getTimeStamp</dt>
<dd>Get the timeStamp field.</dd>
<dt>getAlarm</dt>
<dd>Get the alarm field.</dd>
<dt>getLabel</dt>
<dd>Get the label field.</dd>
<dt>getNumberValues</dt>
<dd>Get the number of value fields.</dd>
<dt>getField</dt>
<dd>Get the introspection interface for the specified field.</dd>
<dt>getPVField</dt>
<dd>Get the data field for the specified field.</dd>
</dl>
<h2>MTMultiChannel</h2>
<pre>
structure NTMultiChannel
union_t[] value
string[] channelName
time_t timeStamp :opt // time when data collected
alarm_t alarm :opt // alarm associated with data collection
int[] severity :opt // alarm severity for each value
int[] status :opt // alarm status for each value
string[] message :opt // alarm message for each value
long[] secondsPastEpoch :opt // seconds for each value.
int[] nanoseconds :opt // nanoseconds for each value
string descriptor :opt // descriptor data
</pre>
</div>
</body>
</html>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

67
jenkins/cloudbees_build Normal file
View File

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

51
jenkins/cloudbees_doc Normal file
View File

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

View File

@@ -1,20 +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,15 +1,38 @@
/* nt.h */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* This software is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#ifndef NT_H
#define NT_H
/*
* Include all the normative types here.
*/
#include <pv/ntfield.h>
#include <pv/ntscalar.h>
#include <pv/ntscalarArray.h>
#include <pv/ntnameValue.h>
#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,16 +1,19 @@
/* ntfield.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* This software is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#include <pv/lock.h>
#define epicsExportSharedSymbols
#include <pv/ntfield.h>
using namespace epics::pvData;
using std::tr1::static_pointer_cast;
namespace epics { namespace pvData {
namespace epics { namespace nt {
NTFieldPtr NTField::get()
{
@@ -64,7 +67,7 @@ bool NTField::isTimeStamp(FieldConstPtr const & field)
ScalarConstPtr s = static_pointer_cast<const Scalar>(f);
if(s->getScalarType()!=pvLong) return false;
f = fields[1];
if(names[1].compare("nanoSeconds")!=0) return false;
if(names[1].compare("nanoseconds")!=0) return false;
if(f->getType()!=scalar) return false;
s = static_pointer_cast<const Scalar>(f);
if(s->getScalarType()!=pvInt) return false;
@@ -154,15 +157,23 @@ bool NTField::isAlarmLimit(FieldConstPtr const & field)
f = fields[1];
if(names[1].compare("lowAlarmLimit")!=0) return false;
if(f->getType()!=scalar) return false;
s = static_pointer_cast<const Scalar>(f);
if(s->getScalarType()!=pvDouble) return false;
f = fields[2];
if(names[2].compare("lowWarningLimit")!=0) return false;
if(f->getType()!=scalar) return false;
s = static_pointer_cast<const Scalar>(f);
if(s->getScalarType()!=pvDouble) return false;
f = fields[3];
if(names[3].compare("highWarningLimit")!=0) return false;
if(f->getType()!=scalar) return false;
s = static_pointer_cast<const Scalar>(f);
if(s->getScalarType()!=pvDouble) return false;
f = fields[4];
if(names[4].compare("highAlarmLimit")!=0) return false;
if(f->getType()!=scalar) return false;
s = static_pointer_cast<const Scalar>(f);
if(s->getScalarType()!=pvDouble) return false;
f = fields[5];
if(names[5].compare("lowAlarmSeverity")!=0) return false;
if(f->getType()!=scalar) return false;
@@ -184,7 +195,7 @@ bool NTField::isAlarmLimit(FieldConstPtr const & field)
s = static_pointer_cast<const Scalar>(f);
if(s->getScalarType()!=pvInt) return false;
f = fields[9];
if(names[9].compare("hystersis")!=0) return false;
if(names[9].compare("hysteresis")!=0) return false;
if(f->getType()!=scalar) return false;
return true;
}
@@ -235,11 +246,6 @@ StructureConstPtr NTField::createDisplay()
return standardField->display();
}
StructureConstPtr NTField::createAlarmLimit()
{
return standardField->doubleAlarm();
}
StructureConstPtr NTField::createControl()
{
return standardField->control();
@@ -306,12 +312,6 @@ PVStructurePtr PVNTField::createDisplay()
return pvDataCreate->createPVStructure(display);
}
PVStructurePtr PVNTField::createAlarmLimit()
{
StructureConstPtr structure = NTField::get()->createAlarmLimit();
return pvDataCreate->createPVStructure(structure);
}
PVStructurePtr PVNTField::createControl()
{

View File

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

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

@@ -0,0 +1,238 @@
/* ntcontinuum.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* This software is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#define epicsExportSharedSymbols
#include <pv/nthistogram.h>
#include <pv/ntutils.h>
using namespace std;
using namespace epics::pvData;
namespace epics { namespace nt {
static NTFieldPtr ntField = NTField::get();
namespace detail {
NTHistogramBuilder::shared_pointer NTHistogramBuilder::value(
epics::pvData::ScalarType scalarType
)
{
valueType = scalarType;
valueTypeSet = true;
return shared_from_this();
}
StructureConstPtr NTHistogramBuilder::createStructure()
{
if (!valueTypeSet)
throw std::runtime_error("value array element type not set");
FieldBuilderPtr builder =
getFieldCreate()->createFieldBuilder()->
setId(NTHistogram::URI)->
addArray("ranges", pvDouble)->
addArray("value", valueType);
if (descriptor)
builder->add("descriptor", pvString);
if (alarm)
builder->add("alarm", ntField->createAlarm());
if (timeStamp)
builder->add("timeStamp", ntField->createTimeStamp());
size_t extraCount = extraFieldNames.size();
for (size_t i = 0; i< extraCount; i++)
builder->add(extraFieldNames[i], extraFields[i]);
StructureConstPtr s = builder->createStructure();
reset();
return s;
}
NTHistogramBuilder::shared_pointer NTHistogramBuilder::addDescriptor()
{
descriptor = true;
return shared_from_this();
}
NTHistogramBuilder::shared_pointer NTHistogramBuilder::addAlarm()
{
alarm = true;
return shared_from_this();
}
NTHistogramBuilder::shared_pointer NTHistogramBuilder::addTimeStamp()
{
timeStamp = true;
return shared_from_this();
}
PVStructurePtr NTHistogramBuilder::createPVStructure()
{
return getPVDataCreate()->createPVStructure(createStructure());
}
NTHistogramPtr NTHistogramBuilder::create()
{
return NTHistogramPtr(new NTHistogram(createPVStructure()));
}
NTHistogramBuilder::NTHistogramBuilder()
{
reset();
}
void NTHistogramBuilder::reset()
{
valueTypeSet = false;
descriptor = false;
alarm = false;
timeStamp = false;
extraFieldNames.clear();
extraFields.clear();
}
NTHistogramBuilder::shared_pointer NTHistogramBuilder::add(string const & name, FieldConstPtr const & field)
{
extraFields.push_back(field); extraFieldNames.push_back(name);
return shared_from_this();
}
}
const std::string NTHistogram::URI("epics:nt/NTHistogram:1.0");
NTHistogram::shared_pointer NTHistogram::wrap(PVStructurePtr const & 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 */

381
src/nt/ntmultiChannel.cpp Normal file
View File

@@ -0,0 +1,381 @@
/* ntmultiChannel.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/ntmultiChannel.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 {
NTMultiChannelBuilder::shared_pointer NTMultiChannelBuilder::value(UnionConstPtr valuePtr)
{
valueType = valuePtr;
return shared_from_this();
}
NTMultiChannelBuilder::shared_pointer NTMultiChannelBuilder::addDescriptor()
{
descriptor = true;
return shared_from_this();
}
NTMultiChannelBuilder::shared_pointer NTMultiChannelBuilder::addAlarm()
{
alarm = true;
return shared_from_this();
}
NTMultiChannelBuilder::shared_pointer NTMultiChannelBuilder::addTimeStamp()
{
timeStamp = true;
return shared_from_this();
}
NTMultiChannelBuilder::shared_pointer NTMultiChannelBuilder::addSeverity()
{
severity = true;
return shared_from_this();
}
NTMultiChannelBuilder::shared_pointer NTMultiChannelBuilder::addStatus()
{
status = true;
return shared_from_this();
}
NTMultiChannelBuilder::shared_pointer NTMultiChannelBuilder::addMessage()
{
message = true;
return shared_from_this();
}
NTMultiChannelBuilder::shared_pointer NTMultiChannelBuilder::addSecondsPastEpoch()
{
secondsPastEpoch = true;
return shared_from_this();
}
NTMultiChannelBuilder::shared_pointer NTMultiChannelBuilder::addNanoseconds()
{
nanoseconds = true;
return shared_from_this();
}
NTMultiChannelBuilder::shared_pointer NTMultiChannelBuilder::addUserTag()
{
userTag = true;
return shared_from_this();
}
NTMultiChannelBuilder::shared_pointer NTMultiChannelBuilder::addIsConnected()
{
isConnected = true;
return shared_from_this();
}
StructureConstPtr NTMultiChannelBuilder::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";
if(valueType) {
fields[ind++] = fieldCreate->createUnionArray(valueType);
} else {
fields[ind++] = fieldCreate->createVariantUnionArray();
}
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(NTMultiChannel::URI,names,fields);
reset();
return st;
}
PVStructurePtr NTMultiChannelBuilder::createPVStructure()
{
return pvDataCreate->createPVStructure(createStructure());
}
NTMultiChannelPtr NTMultiChannelBuilder::create()
{
return NTMultiChannelPtr(new NTMultiChannel(createPVStructure()));
}
NTMultiChannelBuilder::NTMultiChannelBuilder()
{
reset();
}
void NTMultiChannelBuilder::reset()
{
valueType.reset();
extraFieldNames.clear();
extraFields.clear();
descriptor = false;
alarm = false;
timeStamp = false;
severity = false;
status = false;
message = false;
secondsPastEpoch = false;
nanoseconds = false;
userTag = false;
isConnected = false;
}
NTMultiChannelBuilder::shared_pointer NTMultiChannelBuilder::add(string const & name, FieldConstPtr const & field)
{
extraFields.push_back(field); extraFieldNames.push_back(name);
return shared_from_this();
}
}
const std::string NTMultiChannel::URI("epics:nt/NTMultiChannel:1.0");
NTMultiChannel::shared_pointer NTMultiChannel::wrap(PVStructurePtr const & structure)
{
if(!isCompatible(structure)) return shared_pointer();
return wrapUnsafe(structure);
}
NTMultiChannel::shared_pointer NTMultiChannel::wrapUnsafe(PVStructurePtr const & structure)
{
return shared_pointer(new NTMultiChannel(structure));
}
bool NTMultiChannel::is_a(StructureConstPtr const &structure)
{
return NTUtils::is_a(structure->getID(), URI);
}
bool NTMultiChannel::isCompatible(StructureConstPtr const & structure)
{
if (!structure.get()) return false;
UnionArrayConstPtr valueField = structure->getField<UnionArray>("value");
if (!valueField.get()) return false;
ScalarArrayConstPtr channelNameField = structure->getField<ScalarArray>(
"channelName");
if (!channelNameField.get()) return false;
if (channelNameField->getElementType() != pvString) return false;
FieldConstPtr field = structure->getField("severity");
if (field.get())
{
ScalarArrayConstPtr severityField = structure->getField<ScalarArray>("severity");
if (!severityField.get() || severityField->getElementType() != pvInt)
return false;
}
field = structure->getField("status");
if (field.get())
{
ScalarArrayConstPtr statusField = structure->getField<ScalarArray>("status");
if (!statusField.get() || statusField->getElementType() != pvInt)
return false;
}
field = structure->getField("message");
if (field.get())
{
ScalarArrayConstPtr messageField = structure->getField<ScalarArray>("message");
if (!messageField.get() || messageField->getElementType() != pvString)
return false;
}
field = structure->getField("secondsPastEpoch");
if (field.get())
{
ScalarArrayConstPtr secondsPastEpochField = structure->getField<ScalarArray>("secondsPastEpoch");
if (!secondsPastEpochField.get() || secondsPastEpochField->getElementType() != pvLong)
return false;
}
field = structure->getField("nanoseconds");
if (field.get())
{
ScalarArrayConstPtr nanosecondsField = structure->getField<ScalarArray>("nanoseconds");
if (!nanosecondsField.get() || nanosecondsField->getElementType() != pvInt)
return false;
}
field = structure->getField("userTag");
if (field.get())
{
ScalarArrayConstPtr userTagField = structure->getField<ScalarArray>("userTag");
if (!userTagField.get() || userTagField->getElementType() != pvInt)
return false;
}
field = structure->getField("descriptor");
if (field.get())
{
ScalarConstPtr descriptorField = structure->getField<Scalar>("descriptor");
if (!descriptorField.get() || descriptorField->getScalarType() != pvString)
return false;
}
NTFieldPtr ntField = NTField::get();
field = structure->getField("alarm");
if (field.get() && !ntField->isAlarm(field))
return false;
field = structure->getField("timeStamp");
if (field.get() && !ntField->isTimeStamp(field))
return false;
return true;
}
bool NTMultiChannel::isCompatible(PVStructurePtr const &pvStructure)
{
if(!pvStructure.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")),
pvAlarm(pvStructure->getSubField<PVStructure>("alarm")),
pvValue(pvStructure->getSubField<PVUnionArray>("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 NTMultiChannel::attachTimeStamp(PVTimeStamp &pv) const
{
if (pvTimeStamp)
return pv.attach(pvTimeStamp);
else
return false;
}
bool NTMultiChannel::attachAlarm(PVAlarm &pv) const
{
if (pvAlarm)
return pv.attach(pvAlarm);
else
return false;
}
}}

353
src/nt/ntmultiChannel.h Normal file
View File

@@ -0,0 +1,353 @@
/* ntmultiChannel.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 NTMULTICHANNEL_H
#define NTMULTICHANNEL_H
#include <vector>
#include <string>
#ifdef epicsExportSharedSymbols
# define ntmultiChannelEpicsExportSharedSymbols
# undef epicsExportSharedSymbols
#endif
#include <pv/pvDisplay.h>
#include <pv/pvControl.h>
#ifdef ntmultiChannelEpicsExportSharedSymbols
# define epicsExportSharedSymbols
# undef ntmultiChannelEpicsExportSharedSymbols
#endif
#include <pv/ntfield.h>
#include <shareLib.h>
namespace epics { namespace nt {
class NTMultiChannel;
typedef std::tr1::shared_ptr<NTMultiChannel> NTMultiChannelPtr;
namespace detail {
/**
* @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
*/
class epicsShareClass NTMultiChannelBuilder :
public std::tr1::enable_shared_from_this<NTMultiChannelBuilder>
{
public:
POINTER_DEFINITIONS(NTMultiChannelBuilder);
/**
* specify the union for the value field.
* If this is not called then a variantUnion is the default.
* @return this instance of <b>NTMultiChannelBuilder</b>.
*/
shared_pointer value(epics::pvData::UnionConstPtr valuePtr);
/**
* Add descriptor field to the NTMultiChannel.
* @return this instance of <b>NTMultiChannelBuilder</b>.
*/
shared_pointer addDescriptor();
/**
* Add alarm structure to the NTMultiChannel.
* @return this instance of <b>NTMultiChannelBuilder</b>.
*/
shared_pointer addAlarm();
/**
* Add timeStamp structure to the NTMultiChannel.
* @return this instance of <b>NTMultiChannelBuilder</b>.
*/
shared_pointer addTimeStamp();
/**
* Add severity array to the NTMultiChannel.
* @return this instance of <b>NTMultiChannelBuilder</b>.
*/
shared_pointer addSeverity();
/**
* Add status array to the NTMultiChannel.
* @return this instance of <b>NTMultiChannelBuilder</b>.
*/
shared_pointer addStatus();
/**
* Add message array to the NTMultiChannel.
* @return this instance of <b>NTMultiChannelBuilder</b>.
*/
shared_pointer addMessage();
/**
* Add secondsPastEpoch array to the NTMultiChannel.
* @return this instance of <b>NTMultiChannelBuilder</b>.
*/
shared_pointer addSecondsPastEpoch();
/**
* Add nanoseconds array to the NTMultiChannel.
* @return this instance of <b>NTMultiChannelBuilder</b>.
*/
shared_pointer addNanoseconds();
/**
* Add userTag array to the NTMultiChannel.
* @return this instance of <b>NTMultiChannelBuilder</b>.
*/
shared_pointer addUserTag();
/**
* 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 <b>Structure</b>.
*/
epics::pvData::StructureConstPtr createStructure();
/**
* 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 <b>PVStructure</b>
*/
epics::pvData::PVStructurePtr createPVStructure();
/**
* 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 <b>NTMultiChannel</b>
*/
NTMultiChannelPtr 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>NTMultiChannelBuilder</b>
*/
shared_pointer add(std::string const & name, epics::pvData::FieldConstPtr const & field);
private:
NTMultiChannelBuilder();
void reset();
epics::pvData::UnionConstPtr 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::NTMultiChannel;
};
}
typedef std::tr1::shared_ptr<detail::NTMultiChannelBuilder> NTMultiChannelBuilderPtr;
/**
* @brief Convenience Class for NTMultiChannel
*
* @author mrk
*
*/
class epicsShareClass NTMultiChannel
{
public:
POINTER_DEFINITIONS(NTMultiChannel);
static const std::string URI;
/**
* Wrap (aka dynamic cast, or wrap) the structure to NTMultiChannel.
* First isCompatible is called.
* This method will nullptr if the structure is is not compatible.
* @param structure The structure to wrap-ed (dynamic cast, wrapped) to NTMultiChannel.
* @return NTMultiChannel instance on success, nullptr otherwise.
*/
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 NTMultiChannel.
* @return NTMultiChannel instance.
*/
static shared_pointer wrapUnsafe(epics::pvData::PVStructurePtr const & structure);
/**
* 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);
/**
* 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 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.
*/
static NTMultiChannelBuilderPtr createBuilder();
/**
* Destructor
*/
~NTMultiChannel() {}
/**
* 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 pvNTMultiChannel;}
/**
* Get the timeStamp.
* @return PVStructurePtr which may be null.
*/
epics::pvData::PVStructurePtr getTimeStamp() const
{return pvTimeStamp;}
/**
* Get the alarm.
* @return PVStructurePtr which may be null.
*/
epics::pvData::PVStructurePtr getAlarm() const
{return pvAlarm;}
/**
* Get the value of each channel.
* @return PVUnionArrayPtr
*/
epics::pvData::PVUnionArrayPtr getValue() const
{return pvValue;}
/**
* Get the channelName of each channel.
* @return PVStringArrayPtr
*/
epics::pvData::PVStringArrayPtr getChannelName() const
{ return pvChannelName;};
/**
* Get the connection state of each channel.
* @return PVBooleanArrayPtr
*/
epics::pvData::PVBooleanArrayPtr getIsConnected() const
{ return pvIsConnected;};
/**
* Get the severity of each channel.
* @return PVIntArrayPtr which may be null.
*/
epics::pvData::PVIntArrayPtr getSeverity() const
{return pvSeverity;}
/**
* Get the status of each channel.
* @return PVIntArrayPtr which may be null.
*/
epics::pvData::PVIntArrayPtr getStatus() const
{return pvStatus;}
/**
* Get the message of each chnnel.
* @return PVStringArrayPtr which may be null.
*/
epics::pvData::PVStringArrayPtr getMessage() const
{return pvMessage;}
/**
* Get the secondsPastEpoch of each channel.
* @return PVLongArrayPtr which may be null.
*/
epics::pvData::PVLongArrayPtr getSecondsPastEpoch() const
{return pvSecondsPastEpoch;}
/**
* Get the nanoseconds of each channel.
* @return PVIntArrayPtr which may be null.
*/
epics::pvData::PVIntArrayPtr getNanoseconds() const
{return pvNanoseconds;}
/**
* Get the userTag of each channel.
* @return PVIntArrayPtr which may be null.
*/
epics::pvData::PVIntArrayPtr getUserTag() const
{return pvUserTag;}
/**
* Get the descriptor.
* @return PVStringPtr which may be null.
*/
epics::pvData::PVStringPtr getDescriptor() const
{return pvDescriptor;}
private:
NTMultiChannel(epics::pvData::PVStructurePtr const & pvStructure);
epics::pvData::PVStructurePtr pvNTMultiChannel;
epics::pvData::PVStructurePtr pvTimeStamp;
epics::pvData::PVStructurePtr pvAlarm;
epics::pvData::PVUnionArrayPtr 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::NTMultiChannelBuilder;
};
}}
#endif /* NTMULTICHANNEL_H */

View File

@@ -1,110 +1,234 @@
/* ntnameValue.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* This software is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#define epicsExportSharedSymbols
#include <pv/ntnameValue.h>
#include <pv/ntutils.h>
namespace epics { namespace pvData {
using namespace std;
using namespace epics::pvData;
using std::tr1::static_pointer_cast;
namespace epics { namespace nt {
static NTFieldPtr ntField = NTField::get();
bool NTNameValue::isNTNameValue(PVStructurePtr const & pvStructure)
namespace detail {
NTNameValueBuilder::shared_pointer NTNameValueBuilder::value(
epics::pvData::ScalarType scalarType
)
{
PVFieldPtr pvField = pvStructure->getSubField("names");
if(pvField.get()==NULL) return false;
FieldConstPtr field = pvField->getField();
if(field->getType()!=scalarArray) return false;
ScalarArrayConstPtr pscalarArray =
static_pointer_cast<const ScalarArray>(field);
if(pscalarArray->getElementType()!=pvString) return false;
pvField = pvStructure->getSubField("values");
if(pvField==0) return false;
field = pvField->getField();
if(field->getType()!=scalarArray) return false;
pscalarArray = static_pointer_cast<const ScalarArray>(field);
if(pscalarArray->getElementType()!=pvString) return false;
valueType = scalarType;
valueTypeSet = true;
return shared_from_this();
}
StructureConstPtr NTNameValueBuilder::createStructure()
{
if (!valueTypeSet)
throw std::runtime_error("value type not set");
FieldBuilderPtr builder =
getFieldCreate()->createFieldBuilder()->
setId(NTNameValue::URI)->
addArray("name", pvString)->
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;
}
NTNameValueBuilder::shared_pointer NTNameValueBuilder::addDescriptor()
{
descriptor = true;
return shared_from_this();
}
NTNameValueBuilder::shared_pointer NTNameValueBuilder::addAlarm()
{
alarm = true;
return shared_from_this();
}
NTNameValueBuilder::shared_pointer NTNameValueBuilder::addTimeStamp()
{
timeStamp = true;
return shared_from_this();
}
PVStructurePtr NTNameValueBuilder::createPVStructure()
{
return getPVDataCreate()->createPVStructure(createStructure());
}
NTNameValuePtr NTNameValueBuilder::create()
{
return NTNameValuePtr(new NTNameValue(createPVStructure()));
}
NTNameValueBuilder::NTNameValueBuilder()
{
reset();
}
void NTNameValueBuilder::reset()
{
valueTypeSet = false;
descriptor = false;
alarm = false;
timeStamp = false;
extraFieldNames.clear();
extraFields.clear();
}
NTNameValueBuilder::shared_pointer NTNameValueBuilder::add(string const & name, FieldConstPtr const & field)
{
extraFields.push_back(field); extraFieldNames.push_back(name);
return shared_from_this();
}
}
const std::string NTNameValue::URI("epics:nt/NTNameValue:1.0");
NTNameValue::shared_pointer NTNameValue::wrap(PVStructurePtr const & structure)
{
if(!isCompatible(structure)) return shared_pointer();
return wrapUnsafe(structure);
}
NTNameValue::shared_pointer NTNameValue::wrapUnsafe(PVStructurePtr const & structure)
{
return shared_pointer(new NTNameValue(structure));
}
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;
}
NTNameValuePtr NTNameValue::create(
bool hasFunction,bool hasTimeStamp, bool hasAlarm)
bool NTNameValue::isCompatible(PVStructurePtr const & pvStructure)
{
StandardFieldPtr standardField = getStandardField();
size_t nfields = 2;
if(hasFunction) nfields++;
if(hasTimeStamp) nfields++;
if(hasAlarm) nfields++;
FieldCreatePtr fieldCreate = getFieldCreate();
PVDataCreatePtr pvDataCreate = getPVDataCreate();
FieldConstPtrArray fields;
StringArray names;
fields.resize(nfields);
names.resize(nfields);
names[0] = "names";
fields[0] = fieldCreate->createScalarArray(pvString);
names[1] = "values";
fields[1] = fieldCreate->createScalarArray(pvString);
size_t ind = 2;
if(hasFunction) {
names[ind] = "function";
fields[ind++] = fieldCreate->createScalar(pvString);
}
if(hasTimeStamp) {
names[ind] = "timeStamp";
fields[ind++] = standardField->timeStamp();
}
if(hasAlarm) {
names[ind] = "alarm";
fields[ind++] = standardField->alarm();
}
StructureConstPtr st = fieldCreate->createStructure(names,fields);
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(st);
return NTNameValuePtr(new NTNameValue(pvStructure));
if(!pvStructure) return false;
return isCompatible(pvStructure->getStructure());
}
NTNameValuePtr NTNameValue::create(
PVStructurePtr const & pvStructure)
bool NTNameValue::isValid()
{
return NTNameValuePtr(new NTNameValue(pvStructure));
return (getValue<PVScalarArray>()->getLength() == getName()->getLength());
}
NTNameValue::NTNameValue(PVStructure::shared_pointer const & pvStructure)
: pvNTNameValue(pvStructure)
NTNameValueBuilderPtr NTNameValue::createBuilder()
{
NTFieldPtr ntfield = NTField::get();
PVScalarArrayPtr pvArray =
pvStructure->getScalarArrayField("names",pvString);
pvNames = static_pointer_cast<PVStringArray>(pvArray);
pvArray = pvStructure->getScalarArrayField("values",pvString);
pvValues = static_pointer_cast<PVStringArray>(pvArray);
PVFieldPtr pvField = pvStructure->getSubField("function");
if(pvField.get()!=NULL) {
pvFunction = pvStructure->getStringField("function");
}
pvField = pvStructure->getSubField("timeStamp");
if(pvField.get()!=NULL && ntfield->isTimeStamp(pvField->getField())) {
pvTimeStamp = static_pointer_cast<PVStructure>(pvField);
}
pvField = pvStructure->getSubField("alarm");
if(pvField.get()!=NULL && ntfield->isAlarm(pvField->getField())) {
pvAlarm = static_pointer_cast<PVStructure>(pvField);
}
return NTNameValueBuilderPtr(new detail::NTNameValueBuilder());
}
void NTNameValue::attachTimeStamp(PVTimeStamp &pv)
bool NTNameValue::attachTimeStamp(PVTimeStamp &pvTimeStamp) const
{
if(pvTimeStamp.get()==NULL) return;
pv.attach(pvTimeStamp);
PVStructurePtr ts = getTimeStamp();
if (ts)
return pvTimeStamp.attach(ts);
else
return false;
}
void NTNameValue::attachAlarm(PVAlarm &pv)
bool NTNameValue::attachAlarm(PVAlarm &pvAlarm) const
{
if(pvAlarm.get()==NULL) return;
pv.attach(pvAlarm);
PVStructurePtr al = getAlarm();
if (al)
return pvAlarm.attach(al);
else
return false;
}
PVStructurePtr NTNameValue::getPVStructure() const
{
return pvNTNameValue;
}
PVStringPtr NTNameValue::getDescriptor() const
{
return pvNTNameValue->getSubField<PVString>("descriptor");
}
PVStructurePtr NTNameValue::getTimeStamp() const
{
return pvNTNameValue->getSubField<PVStructure>("timeStamp");
}
PVStructurePtr NTNameValue::getAlarm() const
{
return pvNTNameValue->getSubField<PVStructure>("alarm");
}
PVStringArrayPtr NTNameValue::getName() const
{
return pvNTNameValue->getSubField<PVStringArray>("name");
}
PVFieldPtr NTNameValue::getValue() const
{
return pvNTNameValue->getSubField("value");
}
NTNameValue::NTNameValue(PVStructurePtr const & pvStructure) :
pvNTNameValue(pvStructure)
{}
}}

View File

@@ -1,100 +1,277 @@
/* ntnameValue.h */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* This software is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#ifndef NTNAMEVALUE_H
#define NTNAMEVALUE_H
#ifdef epicsExportSharedSymbols
# define ntnameValueEpicsExportSharedSymbols
# undef epicsExportSharedSymbols
#endif
#include <pv/pvDisplay.h>
#include <pv/pvControl.h>
#ifdef ntnameValueEpicsExportSharedSymbols
# define epicsExportSharedSymbols
# undef ntnameValueEpicsExportSharedSymbols
#endif
#include <pv/ntfield.h>
namespace epics { namespace pvData {
#include <shareLib.h>
/**
* Convenience Class for NTNameValue
* @author mrk
*
*/
namespace epics { namespace nt {
class NTNameValue;
typedef std::tr1::shared_ptr<NTNameValue> NTNameValuePtr;
class NTNameValue
namespace detail {
/**
* @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
*/
class epicsShareClass NTNameValueBuilder :
public std::tr1::enable_shared_from_this<NTNameValueBuilder>
{
public:
POINTER_DEFINITIONS(NTNameValueBuilder);
/**
* Set a value array <b>Scalar</b> type.
* @param scalarType value array scalar array.
* @return this instance of <b>NTTableBuilder</b>.
*/
shared_pointer value(epics::pvData::ScalarType scalarType);
/**
* Add descriptor field to the NTNameValue.
* @return this instance of <b>NTTableBuilder</b>.
*/
shared_pointer addDescriptor();
/**
* Add alarm structure to the NTNameValue.
* @return this instance of <b>NTTableBuilder</b>.
*/
shared_pointer addAlarm();
/**
* Add timeStamp structure to the NTNameValue.
* @return this instance of <b>NTTableBuilder</b>.
*/
shared_pointer addTimeStamp();
/**
* 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 <b>Structure</b>.
*/
epics::pvData::StructureConstPtr createStructure();
/**
* 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 <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 <b>Field</b> to the type.
* @param name name of the field.
* @param field a field to add.
* @return this instance of <b>NTTableBuilder</b>.
*/
shared_pointer add(std::string const & name, epics::pvData::FieldConstPtr const & field);
private:
NTNameValueBuilder();
void reset();
bool valueTypeSet;
epics::pvData::ScalarType valueType;
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::NTNameValue;
};
}
typedef std::tr1::shared_ptr<detail::NTNameValueBuilder> NTNameValueBuilderPtr;
/**
* @brief Convenience Class for NTNameValue
*
* @author mrk
*/
class epicsShareClass NTNameValue
{
public:
POINTER_DEFINITIONS(NTNameValue);
static const std::string URI;
/**
* Is the pvStructure an NTNameValue.
* @param pvStructure The pvStructure to test.
* Wrap (aka dynamic cast, or wrap) the structure to NTNameValue.
* First isCompatible is called.
* This method will nullptr if the structure is is not compatible.
* This method will nullptr if the structure is nullptr.
* @param structure The structure to wrap-ed (dynamic cast, wrapped) to NTNameValue.
* @return NTNameValue instance on success, nullptr otherwise.
*/
static shared_pointer wrap(epics::pvData::PVStructurePtr const & structure);
/**
* 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.
*/
static shared_pointer wrapUnsafe(epics::pvData::PVStructurePtr const & structure);
/**
* Is the structure an NTNameValue.
* @param structure The structure to test.
* @return (false,true) if (is not, is) an NTNameValue.
*/
static bool isNTNameValue(PVStructurePtr const & pvStructure);
static bool is_a(epics::pvData::StructureConstPtr const & structure);
/**
* Create an NTNameValue pvStructure.
* @param hasFunction Create a PVString field named function.
* @param hasTimeStamp Create a timeStamp structure field.
* @param hasAlarm Create an alarm structure field.
* @return NTNameValuePtr
* Is the structure an NTNameValue.
* @param pvStructure The PVStructure to test.
* @return (false,true) if (is not, is) an NTNameValue.
*/
static NTNameValuePtr create(
bool hasFunction,bool hasTimeStamp, bool hasAlarm);
static NTNameValuePtr create(
PVStructurePtr const & pvStructure);
static bool is_a(epics::pvData::PVStructurePtr const & pvStructure);
/**
* Destructor
* Is the Structure compatible with NTNameValue.
* 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 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.
*/
static NTNameValueBuilderPtr createBuilder();
/**
* Destructor.
*/
~NTNameValue() {}
/**
* Get the function field.
* @return The pvString or null if no function field.
*/
PVStringPtr getFunction() {return pvFunction;}
/**
* Attach a pvTimeStamp.
* @param pvTimeStamp The pvTimeStamp that will be attached.
* Does nothing if no timeStamp
*/
void attachTimeStamp(PVTimeStamp &pvTimeStamp);
/**
* 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
* Does nothing if no alarm.
* @return true if the operation was successfull (i.e. this instance has a timeStamp field), otherwise false.
*/
void attachAlarm(PVAlarm &pvAlarm);
bool attachAlarm(epics::pvData::PVAlarm &pvAlarm) const;
/**
* Get the pvStructure.
* @return PVStructurePtr.
*/
PVStructurePtr getPVStructure(){return pvNTNameValue;}
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.
*/
PVStructurePtr getTimeStamp(){return pvTimeStamp;}
epics::pvData::PVStructurePtr getTimeStamp() const;
/**
* Get the alarm.
* @return PVStructurePtr which may be null.
*/
PVStructurePtr getAlarm() {return pvAlarm;}
epics::pvData::PVStructurePtr getAlarm() const;
/**
* Get the string array on names.
* @return The array of names.
* Get the name array field.
* @return The PVStringArray for the name.
*/
PVStringArrayPtr getNames() {return pvNames;}
epics::pvData::PVStringArrayPtr getName() const;
/**
* Get the string array on values.
* @return The array of values.
* Get the value array field.
* @return The PVField for the value.
*/
PVStringArrayPtr getValues() {return pvValues;}
epics::pvData::PVFieldPtr getValue() const;
/**
* Get the value array field of a specified type (e.g. PVDoubleArray).
* @return The <PVT> array for the value.
*/
template<typename PVT>
std::tr1::shared_ptr<PVT> getValue() const
{
epics::pvData::PVFieldPtr pvField = getValue();
if (pvField.get())
return std::tr1::dynamic_pointer_cast<PVT>(pvField);
else
return std::tr1::shared_ptr<PVT>();
}
private:
NTNameValue(PVStructurePtr const & pvStructure);
PVStructurePtr pvNTNameValue;
PVStringPtr pvFunction;
PVStructurePtr pvTimeStamp;
PVStructurePtr pvAlarm;
PVStringArrayPtr pvNames;
PVStringArrayPtr pvValues;
NTNameValue(epics::pvData::PVStructurePtr const & pvStructure);
epics::pvData::PVStructurePtr pvNTNameValue;
friend class detail::NTNameValueBuilder;
};
}}

580
src/nt/ntndarray.cpp Normal file
View File

@@ -0,0 +1,580 @@
/* ntndarray.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/ntndarray.h>
#include <pv/ntndarrayAttribute.h>
#include <pv/ntutils.h>
using namespace std;
using namespace epics::pvData;
namespace epics { namespace nt {
static NTFieldPtr ntField = NTField::get();
namespace detail {
static FieldCreatePtr fieldCreate = getFieldCreate();
static PVDataCreatePtr pvDataCreate = getPVDataCreate();
static Mutex mutex;
StructureConstPtr NTNDArrayBuilder::createStructure()
{
enum
{
DISCRIPTOR_INDEX,
TIMESTAMP_INDEX,
ALARM_INDEX,
DISPLAY_INDEX
};
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;
StructureConstPtr returnedStruc;
size_t index = 0;
if (descriptor) index |= 1 << DISCRIPTOR_INDEX;
if (timeStamp) index |= 1 << TIMESTAMP_INDEX;
if (alarm) index |= 1 << ALARM_INDEX;
if (display) index |= 1 << DISPLAY_INDEX;
bool isExtended = !extraFieldNames.empty();
if (isExtended || !ntndarrayStruc[index])
{
StandardFieldPtr standardField = getStandardField();
FieldBuilderPtr fb = fieldCreate->createFieldBuilder();
if (!valueType)
{
for (int i = pvBoolean; i < pvString; ++i)
{
ScalarType st = static_cast<ScalarType>(i);
fb->addArray(std::string(ScalarTypeFunc::name(st)) + "Value", st);
}
valueType = fb->createUnion();
}
if (!codecStruc)
{
codecStruc = fb->setId("codec_t")->
add("name", pvString)->
add("parameters", fieldCreate->createVariantUnion())->
createStructure();
}
if (!dimensionStruc)
{
dimensionStruc = fb->setId("dimension_t")->
add("size", pvInt)->
add("offset", pvInt)->
add("fullSize", pvInt)->
add("binning", pvInt)->
add("reverse", pvBoolean)->
createStructure();
}
if (!attributeStruc)
{
attributeStruc = NTNDArrayAttribute::createBuilder()->createStructure();
}
fb->setId(NTNDArray::URI)->
add("value", valueType)->
add("codec", codecStruc)->
add("compressedSize", pvLong)->
add("uncompressedSize", pvLong)->
addArray("dimension", dimensionStruc)->
add("uniqueId", pvInt)->
add("dataTimeStamp", standardField->timeStamp())->
addArray("attribute", attributeStruc);
if (descriptor)
fb->add("descriptor", pvString);
if (alarm)
fb->add("alarm", standardField->alarm());
if (timeStamp)
fb->add("timeStamp", standardField->timeStamp());
if (display)
fb->add("display", standardField->display());
size_t extraCount = extraFieldNames.size();
for (size_t i = 0; i< extraCount; i++)
fb->add(extraFieldNames[i], extraFields[i]);
returnedStruc = fb->createStructure();
if (!isExtended)
ntndarrayStruc[index] = returnedStruc;
}
else
{
return ntndarrayStruc[index];
}
return returnedStruc;
}
NTNDArrayBuilder::shared_pointer NTNDArrayBuilder::addDescriptor()
{
descriptor = true;
return shared_from_this();
}
NTNDArrayBuilder::shared_pointer NTNDArrayBuilder::addAlarm()
{
alarm = true;
return shared_from_this();
}
NTNDArrayBuilder::shared_pointer NTNDArrayBuilder::addTimeStamp()
{
timeStamp = true;
return shared_from_this();
}
NTNDArrayBuilder::shared_pointer NTNDArrayBuilder::addDisplay()
{
display = true;
return shared_from_this();
}
PVStructurePtr NTNDArrayBuilder::createPVStructure()
{
return getPVDataCreate()->createPVStructure(createStructure());
}
NTNDArrayPtr NTNDArrayBuilder::create()
{
return NTNDArrayPtr(new NTNDArray(createPVStructure()));
}
NTNDArrayBuilder::NTNDArrayBuilder()
{
reset();
}
void NTNDArrayBuilder::reset()
{
descriptor = false;
timeStamp = false;
alarm = false;
display = false;
extraFieldNames.clear();
extraFields.clear();
}
NTNDArrayBuilder::shared_pointer NTNDArrayBuilder::add(string const & name, FieldConstPtr const & field)
{
extraFields.push_back(field); extraFieldNames.push_back(name);
return shared_from_this();
}
}
const std::string NTNDArray::URI("epics:nt/NTNDArray:1.0");
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();
return wrapUnsafe(structure);
}
NTNDArray::shared_pointer NTNDArray::wrapUnsafe(PVStructurePtr const & structure)
{
return shared_pointer(new NTNDArray(structure));
}
bool NTNDArray::is_a(StructureConstPtr const & structure)
{
return NTUtils::is_a(structure->getID(), URI);
}
bool NTNDArray::isCompatible(StructureConstPtr const &structure)
{
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());
}
bool NTNDArray::attachTimeStamp(PVTimeStamp &pvTimeStamp) const
{
PVStructurePtr ts = getTimeStamp();
if (ts)
return pvTimeStamp.attach(ts);
else
return false;
}
bool NTNDArray::attachDataTimeStamp(PVTimeStamp &pvTimeStamp) const
{
PVStructurePtr ts = getDataTimeStamp();
if (ts)
return pvTimeStamp.attach(ts);
else
return false;
}
bool NTNDArray::attachAlarm(PVAlarm &pvAlarm) const
{
PVStructurePtr al = getAlarm();
if (al)
return pvAlarm.attach(al);
else
return false;
}
PVStructurePtr NTNDArray::getPVStructure() const
{
return pvNTNDArray;
}
PVUnionPtr NTNDArray::getValue() const
{
return pvNTNDArray->getSubField<PVUnion>("value");
}
PVStructurePtr NTNDArray::getCodec() const
{
return pvNTNDArray->getSubField<PVStructure>("codec");
}
PVLongPtr NTNDArray::getCompressedDataSize() const
{
return pvNTNDArray->getSubField<PVLong>("compressedSize");
}
PVLongPtr NTNDArray::getUncompressedDataSize() const
{
return pvNTNDArray->getSubField<PVLong>("uncompressedSize");
}
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");
}
PVStructurePtr NTNDArray::getTimeStamp() const
{
return pvNTNDArray->getSubField<PVStructure>("timeStamp");
}
PVStructurePtr NTNDArray::getAlarm() const
{
return pvNTNDArray->getSubField<PVStructure>("alarm");
}
PVStructurePtr NTNDArray::getDisplay() const
{
return pvNTNDArray->getSubField<PVStructure>("display");
}
NTNDArray::NTNDArray(PVStructurePtr const & pvStructure) :
pvNTNDArray(pvStructure)
{}
}}

319
src/nt/ntndarray.h Normal file
View File

@@ -0,0 +1,319 @@
/* ntndarray.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 NTNDARRAY_H
#define NTNDARRAY_H
#include <vector>
#include <string>
#ifdef epicsExportSharedSymbols
# define ntscalarArrayEpicsExportSharedSymbols
# undef epicsExportSharedSymbols
#endif
#include <pv/pvDisplay.h>
#include <pv/pvControl.h>
#ifdef ntscalarArrayEpicsExportSharedSymbols
# define epicsExportSharedSymbols
# undef ntscalarArrayEpicsExportSharedSymbols
#endif
#include <pv/ntfield.h>
#include <shareLib.h>
namespace epics { namespace nt {
class NTNDArray;
typedef std::tr1::shared_ptr<NTNDArray> NTNDArrayPtr;
namespace detail {
/**
* @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
*/
class epicsShareClass NTNDArrayBuilder :
public std::tr1::enable_shared_from_this<NTNDArrayBuilder>
{
public:
POINTER_DEFINITIONS(NTNDArrayBuilder);
/**
* Add descriptor field to the NTNDArray.
* @return this instance of <b>NTNDArrayBuilder</b>.
*/
shared_pointer addDescriptor();
/**
* Add alarm structure to the NTNDArray.
* @return this instance of <b>NTNDArrayBuilder</b>.
*/
shared_pointer addAlarm();
/**
* Add timeStamp structure to the NTNDArray.
* @return this instance of <b>NTNDArrayBuilder</b>.
*/
shared_pointer addTimeStamp();
/**
* Add display structure to the NTNDArray.
* @return this instance of <b>NTNDArrayBuilder</b>.
*/
shared_pointer addDisplay();
/**
* 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 <b>Structure</b>.
*/
epics::pvData::StructureConstPtr createStructure();
/**
* 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 <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 <b>Field</b> to the type.
* @param name name of the field.
* @param field a field to add.
* @return this instance of a <b>NTArrayBuilder</b>.
*/
shared_pointer add(std::string const & name, epics::pvData::FieldConstPtr const & field);
private:
NTNDArrayBuilder();
void reset();
bool descriptor;
bool timeStamp;
bool alarm;
bool display;
// NOTE: this preserves order, however it does not handle duplicates
epics::pvData::StringArray extraFieldNames;
epics::pvData::FieldConstPtrArray extraFields;
friend class ::epics::nt::NTNDArray;
};
}
typedef std::tr1::shared_ptr<detail::NTNDArrayBuilder> NTNDArrayBuilderPtr;
/**
* @brief Convenience Class for NTNDArray
*
* @author dgh
*/
class epicsShareClass NTNDArray
{
public:
POINTER_DEFINITIONS(NTNDArray);
static const std::string URI;
/**
* Wrap (aka dynamic cast, or wrap) the structure to NTNDArray.
* First isCompatible is called.
* This method will nullptr if the structure is is not compatible.
* This method will nullptr if the structure is nullptr.
* @param structure The structure to wrap-ed (dynamic cast, wrapped) to NTNDArray.
* @return NTNDArray instance on success, nullptr otherwise.
*/
static shared_pointer wrap(epics::pvData::PVStructurePtr const & structure);
/**
* 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.
*/
static shared_pointer wrapUnsafe(epics::pvData::PVStructurePtr const & structure);
/**
* Is the structure an NTNDArray.
* @param structure The structure to test.
* @return (false,true) if (is not, is) an NTNDArray.
*/
static bool is_a(epics::pvData::StructureConstPtr const & structure);
/**
* 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 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.
*/
static NTNDArrayBuilderPtr createBuilder();
/**
* Destructor.
*/
~NTNDArray() {}
/**
* Attach a pvTimeStamp to timeStamp field.
* @param pvTimeStamp The pvTimeStamp that will be attached.
* Does nothing if no timeStamp.
* @return true if the operation was successfull (i.e. this instance has a timeStamp field), otherwise false.
*/
bool attachTimeStamp(epics::pvData::PVTimeStamp &pvTimeStamp) const;
/**
* Attach a pvTimeStamp to dataTimeStamp field.
* @param pvTimeStamp The pvTimeStamp that will be attached.
* Does nothing if no timeStamp.
* @return true if the operation was successfull (i.e. this instance has a timeStamp field), otherwise false.
*/
bool attachDataTimeStamp(epics::pvData::PVTimeStamp &pvTimeStamp) const;
/**
* Attach an pvAlarm.
* @param pvAlarm The pvAlarm that will be attached.
* Does nothing if no alarm.
* @return true if the operation was successfull (i.e. this instance has a timeStamp field), otherwise false.
*/
bool attachAlarm(epics::pvData::PVAlarm &pvAlarm) const;
/**
* Get the pvStructure.
* @return PVStructurePtr.
*/
epics::pvData::PVStructurePtr getPVStructure() const;
/**
* Get the value field.
* @return The PVField for the values.
*/
epics::pvData::PVUnionPtr getValue() const;
/**
* Get the codec field.
* @return the PVStructurePtr.
*/
epics::pvData::PVStructurePtr getCodec() const;
/**
* Get the compressedDataSize field.
* @return PVStructurePtr.
*/
epics::pvData::PVLongPtr getCompressedDataSize() const;
/**
* Get the uncompressedDataSize field.
* @return PVStructurePtr.
*/
epics::pvData::PVLongPtr getUncompressedDataSize() const;
/**
* Get the dimension field.
* @return the PVStructurePtr.
*/
epics::pvData::PVStructureArrayPtr getDimension() const;
/**
* Get the uniqueId field.
* @return PVStructurePtr.
*/
epics::pvData::PVIntPtr getUniqueId() const;
/**
* Get the data timeStamp field.
* @return PVStructurePtr.
*/
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.
*/
epics::pvData::PVStringPtr getDescriptor() const;
/**
* Get the timeStamp field.
* @return PVStructurePtr which may be null.
*/
epics::pvData::PVStructurePtr getTimeStamp() const;
/**
* Get the alarm field.
* @return PVStructurePtr which may be null.
*/
epics::pvData::PVStructurePtr getAlarm() const;
/**
* Get the display field.
* @return PVStructurePtr which may be null.
*/
epics::pvData::PVStructurePtr getDisplay() const;
private:
NTNDArray(epics::pvData::PVStructurePtr const & pvStructure);
epics::pvData::int64 getExpectedUncompressedSize();
epics::pvData::int64 getValueSize();
epics::pvData::int64 getValueTypeSize();
epics::pvData::PVStructurePtr pvNTNDArray;
friend class detail::NTNDArrayBuilder;
};
}}
#endif /* NTNDARRAY_H */

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

280
src/nt/ntscalar.cpp Normal file
View File

@@ -0,0 +1,280 @@
/* ntscalar.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/ntscalar.h>
#include <pv/ntutils.h>
using namespace std;
using namespace epics::pvData;
namespace epics { namespace nt {
static NTFieldPtr ntField = NTField::get();
namespace detail {
NTScalarBuilder::shared_pointer NTScalarBuilder::value(
epics::pvData::ScalarType scalarType
)
{
valueType = scalarType;
valueTypeSet = true;
return shared_from_this();
}
StructureConstPtr NTScalarBuilder::createStructure()
{
if (!valueTypeSet)
throw std::runtime_error("value type not set");
FieldBuilderPtr builder =
getFieldCreate()->createFieldBuilder()->
setId(NTScalar::URI)->
add("value", valueType);
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());
if (control)
builder->add("control", ntField->createControl());
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;
}
NTScalarBuilder::shared_pointer NTScalarBuilder::addDescriptor()
{
descriptor = true;
return shared_from_this();
}
NTScalarBuilder::shared_pointer NTScalarBuilder::addAlarm()
{
alarm = true;
return shared_from_this();
}
NTScalarBuilder::shared_pointer NTScalarBuilder::addTimeStamp()
{
timeStamp = true;
return shared_from_this();
}
NTScalarBuilder::shared_pointer NTScalarBuilder::addDisplay()
{
display = true;
return shared_from_this();
}
NTScalarBuilder::shared_pointer NTScalarBuilder::addControl()
{
control = true;
return shared_from_this();
}
PVStructurePtr NTScalarBuilder::createPVStructure()
{
return getPVDataCreate()->createPVStructure(createStructure());
}
NTScalarPtr NTScalarBuilder::create()
{
return NTScalarPtr(new NTScalar(createPVStructure()));
}
NTScalarBuilder::NTScalarBuilder()
{
reset();
}
void NTScalarBuilder::reset()
{
valueTypeSet = false;
descriptor = false;
alarm = false;
timeStamp = false;
display = false;
control = false;
}
NTScalarBuilder::shared_pointer NTScalarBuilder::add(string const & name, FieldConstPtr const & field)
{
extraFields.push_back(field); extraFieldNames.push_back(name);
return shared_from_this();
}
}
const std::string NTScalar::URI("epics:nt/NTScalar:1.0");
NTScalar::shared_pointer NTScalar::wrap(PVStructurePtr const & structure)
{
if(!isCompatible(structure)) return shared_pointer();
return wrapUnsafe(structure);
}
NTScalar::shared_pointer NTScalar::wrapUnsafe(PVStructurePtr const & structure)
{
return shared_pointer(new NTScalar(structure));
}
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;
return isCompatible(pvStructure->getStructure());
}
bool NTScalar::isValid()
{
return true;
}
NTScalarBuilderPtr NTScalar::createBuilder()
{
return NTScalarBuilderPtr(new detail::NTScalarBuilder());
}
bool NTScalar::attachTimeStamp(PVTimeStamp &pvTimeStamp) const
{
PVStructurePtr ts = getTimeStamp();
if (ts)
return pvTimeStamp.attach(ts);
else
return false;
}
bool NTScalar::attachAlarm(PVAlarm &pvAlarm) const
{
PVStructurePtr al = getAlarm();
if (al)
return pvAlarm.attach(al);
else
return false;
}
bool NTScalar::attachDisplay(PVDisplay &pvDisplay) const
{
PVStructurePtr dp = getDisplay();
if (dp)
return pvDisplay.attach(dp);
else
return false;
}
bool NTScalar::attachControl(PVControl &pvControl) const
{
PVStructurePtr ctrl = getControl();
if (ctrl)
return pvControl.attach(ctrl);
else
return false;
}
PVStructurePtr NTScalar::getPVStructure() const
{
return pvNTScalar;
}
PVStringPtr NTScalar::getDescriptor() const
{
return pvNTScalar->getSubField<PVString>("descriptor");
}
PVStructurePtr NTScalar::getTimeStamp() const
{
return pvNTScalar->getSubField<PVStructure>("timeStamp");
}
PVStructurePtr NTScalar::getAlarm() const
{
return pvNTScalar->getSubField<PVStructure>("alarm");
}
PVStructurePtr NTScalar::getDisplay() const
{
return pvNTScalar->getSubField<PVStructure>("display");
}
PVStructurePtr NTScalar::getControl() const
{
return pvNTScalar->getSubField<PVStructure>("control");
}
PVFieldPtr NTScalar::getValue() const
{
return pvValue;
}
NTScalar::NTScalar(PVStructurePtr const & pvStructure) :
pvNTScalar(pvStructure), pvValue(pvNTScalar->getSubField("value"))
{}
}}

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

@@ -0,0 +1,313 @@
/* ntscalar.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 NTSCALAR_H
#define NTSCALAR_H
#ifdef epicsExportSharedSymbols
# define ntscalarEpicsExportSharedSymbols
# undef epicsExportSharedSymbols
#endif
#include <pv/pvDisplay.h>
#include <pv/pvControl.h>
#ifdef ntscalarEpicsExportSharedSymbols
# define epicsExportSharedSymbols
# undef ntscalarEpicsExportSharedSymbols
#endif
#include <pv/ntfield.h>
#include <shareLib.h>
namespace epics { namespace nt {
class NTScalar;
typedef std::tr1::shared_ptr<NTScalar> NTScalarPtr;
namespace detail {
/**
* @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
*/
class epicsShareClass NTScalarBuilder :
public std::tr1::enable_shared_from_this<NTScalarBuilder>
{
public:
POINTER_DEFINITIONS(NTScalarBuilder);
/**
* Set a value type of a NTScalar.
* @param scalarType the value type.
* @return this instance of <b>NTScalarBuilder</b>.
*/
shared_pointer value(epics::pvData::ScalarType scalarType);
/**
* Add descriptor field to the NTScalar.
* @return this instance of <b>NTScalarBuilder</b>.
*/
shared_pointer addDescriptor();
/**
* Add alarm structure to the NTScalar.
* @return this instance of <b>NTScalarBuilder</b>.
*/
shared_pointer addAlarm();
/**
* Add timeStamp structure to the NTScalar.
* @return this instance of <b>NTScalarBuilder</b>.
*/
shared_pointer addTimeStamp();
/**
* Add display structure to the NTScalar.
* @return this instance of <b>NTScalarBuilder</b>.
*/
shared_pointer addDisplay();
/**
* Add control structure to the NTScalar.
* @return this instance of <b>NTScalarBuilder</b>.
*/
shared_pointer addControl();
/**
* 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 <b>Structure</b>.
*/
epics::pvData::StructureConstPtr createStructure();
/**
* 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 <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 <b>Field</b> to the type.
* @param name name of the field.
* @param field a field to add.
* @return this instance of <b>NTScalarBuilder</b>.
*/
shared_pointer add(std::string const & name, epics::pvData::FieldConstPtr const & field);
private:
NTScalarBuilder();
void reset();
bool valueTypeSet;
epics::pvData::ScalarType valueType;
bool descriptor;
bool alarm;
bool timeStamp;
bool display;
bool control;
// NOTE: this preserves order, however it does not handle duplicates
epics::pvData::StringArray extraFieldNames;
epics::pvData::FieldConstPtrArray extraFields;
friend class ::epics::nt::NTScalar;
};
}
typedef std::tr1::shared_ptr<detail::NTScalarBuilder> NTScalarBuilderPtr;
/**
* @brief Convenience Class for NTScalar
*
* @author mrk
*/
class epicsShareClass NTScalar
{
public:
POINTER_DEFINITIONS(NTScalar);
static const std::string URI;
/**
* Wrap (aka dynamic cast, or wrap) the structure to NTScalar.
* First isCompatible is called.
* This method will nullptr if the structure is is not compatible.
* This method will nullptr if the structure is nullptr.
* @param structure The structure to wrap-ed (dynamic cast, wrapped) to NTScalar.
* @return NTScalar instance on success, nullptr otherwise.
*/
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 NTScalar.
* @return NTScalar instance.
*/
static shared_pointer wrapUnsafe(epics::pvData::PVStructurePtr const & structure);
/**
* Is the structure an NTScalar.
* @param structure The structure to test.
* @return (false,true) if (is not, is) an NTScalar.
*/
static bool is_a(epics::pvData::StructureConstPtr const & structure);
/**
* 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 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.
*/
static NTScalarBuilderPtr createBuilder();
/**
* Destructor.
*/
~NTScalar() {}
/**
* 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;
/**
* Attach an pvControl.
* @param pvControl The pvControl that will be attached.
* Does nothing if no control.
* @return true if the operation was successfull (i.e. this instance has a control field), otherwise false.
*/
bool attachControl(epics::pvData::PVControl &pvControl) 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 control.
* @return PVStructurePtr which may be null.
*/
epics::pvData::PVStructurePtr getControl() const;
/**
* Get the value field.
* @return The PVField for the values.
*/
epics::pvData::PVFieldPtr getValue() const;
/**
* Get the value field of a specified type (e.g. PVDouble).
* @return The <PVT> field for the values.
*/
template<typename PVT>
std::tr1::shared_ptr<PVT> getValue() const
{
return std::tr1::dynamic_pointer_cast<PVT>(pvValue);
}
private:
NTScalar(epics::pvData::PVStructurePtr const & pvStructure);
epics::pvData::PVStructurePtr pvNTScalar;
epics::pvData::PVFieldPtr pvValue;
friend class detail::NTScalarBuilder;
};
}}
#endif /* NTSCALAR_H */

278
src/nt/ntscalarArray.cpp Normal file
View File

@@ -0,0 +1,278 @@
/* ntscalarArray.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/ntscalarArray.h>
#include <pv/ntutils.h>
using namespace std;
using namespace epics::pvData;
namespace epics { namespace nt {
static NTFieldPtr ntField = NTField::get();
namespace detail {
NTScalarArrayBuilder::shared_pointer NTScalarArrayBuilder::arrayValue(
epics::pvData::ScalarType elementType
)
{
valueType = elementType;
valueTypeSet = true;
return shared_from_this();
}
StructureConstPtr NTScalarArrayBuilder::createStructure()
{
if (!valueTypeSet)
throw std::runtime_error("value array element type not set");
FieldBuilderPtr builder =
getFieldCreate()->createFieldBuilder()->
setId(NTScalarArray::URI)->
addArray("value", valueType);
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());
if (control)
builder->add("control", ntField->createControl());
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;
}
NTScalarArrayBuilder::shared_pointer NTScalarArrayBuilder::addDescriptor()
{
descriptor = true;
return shared_from_this();
}
NTScalarArrayBuilder::shared_pointer NTScalarArrayBuilder::addAlarm()
{
alarm = true;
return shared_from_this();
}
NTScalarArrayBuilder::shared_pointer NTScalarArrayBuilder::addTimeStamp()
{
timeStamp = true;
return shared_from_this();
}
NTScalarArrayBuilder::shared_pointer NTScalarArrayBuilder::addDisplay()
{
display = true;
return shared_from_this();
}
NTScalarArrayBuilder::shared_pointer NTScalarArrayBuilder::addControl()
{
control = true;
return shared_from_this();
}
PVStructurePtr NTScalarArrayBuilder::createPVStructure()
{
return getPVDataCreate()->createPVStructure(createStructure());
}
NTScalarArrayPtr NTScalarArrayBuilder::create()
{
return NTScalarArrayPtr(new NTScalarArray(createPVStructure()));
}
NTScalarArrayBuilder::NTScalarArrayBuilder()
{
reset();
}
void NTScalarArrayBuilder::reset()
{
valueTypeSet = false;
descriptor = false;
alarm = false;
timeStamp = false;
display = false;
control = false;
}
NTScalarArrayBuilder::shared_pointer NTScalarArrayBuilder::add(string const & name, FieldConstPtr const & field)
{
extraFields.push_back(field); extraFieldNames.push_back(name);
return shared_from_this();
}
}
const std::string NTScalarArray::URI("epics:nt/NTScalarArray:1.0");
NTScalarArray::shared_pointer NTScalarArray::wrap(PVStructurePtr const & structure)
{
if(!isCompatible(structure)) return shared_pointer();
return wrapUnsafe(structure);
}
NTScalarArray::shared_pointer NTScalarArray::wrapUnsafe(PVStructurePtr const & structure)
{
return shared_pointer(new NTScalarArray(structure));
}
bool NTScalarArray::is_a(StructureConstPtr const & structure)
{
return NTUtils::is_a(structure->getID(), URI);
}
bool NTScalarArray::isCompatible(StructureConstPtr const & structure)
{
if (structure.get() == 0) return false;
ScalarArrayConstPtr valueField = structure->getField<ScalarArray>("value");
if (valueField.get() == 0)
return false;
FieldConstPtr field = structure->getField("descriptor");
if (field.get())
{
ScalarConstPtr descriptorField = structure->getField<Scalar>("descriptor");
if (!descriptorField.get() || descriptorField->getScalarType() != pvString)
return false;
}
NTFieldPtr ntField = NTField::get();
field = structure->getField("alarm");
if (field.get() && !ntField->isAlarm(field))
return false;
field = structure->getField("timeStamp");
if (field.get() && !ntField->isTimeStamp(field))
return false;
field = structure->getField("display");
if (field.get() && !ntField->isDisplay(field))
return false;
field = structure->getField("control");
if (field.get() && !ntField->isControl(field))
return false;
return true;
}
bool NTScalarArray::isCompatible(PVStructurePtr const & pvStructure)
{
if(!pvStructure) return false;
return isCompatible(pvStructure->getStructure());
}
bool NTScalarArray::isValid()
{
return true;
}
NTScalarArrayBuilderPtr NTScalarArray::createBuilder()
{
return NTScalarArrayBuilderPtr(new detail::NTScalarArrayBuilder());
}
bool NTScalarArray::attachTimeStamp(PVTimeStamp &pvTimeStamp) const
{
PVStructurePtr ts = getTimeStamp();
if (ts)
return pvTimeStamp.attach(ts);
else
return false;
}
bool NTScalarArray::attachAlarm(PVAlarm &pvAlarm) const
{
PVStructurePtr al = getAlarm();
if (al)
return pvAlarm.attach(al);
else
return false;
}
bool NTScalarArray::attachDisplay(PVDisplay &pvDisplay) const
{
PVStructurePtr dp = getDisplay();
if (dp)
return pvDisplay.attach(dp);
else
return false;
}
bool NTScalarArray::attachControl(PVControl &pvControl) const
{
PVStructurePtr ctrl = getControl();
if (ctrl)
return pvControl.attach(ctrl);
else
return false;
}
PVStructurePtr NTScalarArray::getPVStructure() const
{
return pvNTScalarArray;
}
PVStringPtr NTScalarArray::getDescriptor() const
{
return pvNTScalarArray->getSubField<PVString>("descriptor");
}
PVStructurePtr NTScalarArray::getTimeStamp() const
{
return pvNTScalarArray->getSubField<PVStructure>("timeStamp");
}
PVStructurePtr NTScalarArray::getAlarm() const
{
return pvNTScalarArray->getSubField<PVStructure>("alarm");
}
PVStructurePtr NTScalarArray::getDisplay() const
{
return pvNTScalarArray->getSubField<PVStructure>("display");
}
PVStructurePtr NTScalarArray::getControl() const
{
return pvNTScalarArray->getSubField<PVStructure>("control");
}
PVFieldPtr NTScalarArray::getValue() const
{
return pvValue;
}
NTScalarArray::NTScalarArray(PVStructurePtr const & pvStructure) :
pvNTScalarArray(pvStructure), pvValue(pvNTScalarArray->getSubField("value"))
{}
}}

314
src/nt/ntscalarArray.h Normal file
View File

@@ -0,0 +1,314 @@
/* ntscalarArray.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 NTSCALARARRAY_H
#define NTSCALARARRAY_H
#ifdef epicsExportSharedSymbols
# define ntscalarArrayEpicsExportSharedSymbols
# undef epicsExportSharedSymbols
#endif
#include <pv/pvDisplay.h>
#include <pv/pvControl.h>
#ifdef ntscalarArrayEpicsExportSharedSymbols
# define epicsExportSharedSymbols
# undef ntscalarArrayEpicsExportSharedSymbols
#endif
#include <pv/ntfield.h>
#include <shareLib.h>
namespace epics { namespace nt {
class NTScalarArray;
typedef std::tr1::shared_ptr<NTScalarArray> NTScalarArrayPtr;
namespace detail {
/**
* @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
*/
class epicsShareClass NTScalarArrayBuilder :
public std::tr1::enable_shared_from_this<NTScalarArrayBuilder>
{
public:
POINTER_DEFINITIONS(NTScalarArrayBuilder);
/**
* Set a value type of a NTScalarArray.
* @param elementType the value array element type.
* @return this instance of <b>NTScalarArrayBuilder</b>.
*/
shared_pointer arrayValue(epics::pvData::ScalarType elementType);
/**
* Add descriptor field to the NTScalarArray.
* @return this instance of <b>NTScalarArrayBuilder</b>.
*/
shared_pointer addDescriptor();
/**
* Add alarm structure to the NTScalarArray.
* @return this instance of <b>NTScalarArrayBuilder</b>.
*/
shared_pointer addAlarm();
/**
* Add timeStamp structure to the NTScalarArray.
* @return this instance of <b>NTScalarArrayBuilder</b>.
*/
shared_pointer addTimeStamp();
/**
* Add display structure to the NTScalarArray.
* @return this instance of <b>NTScalarArrayBuilder</b>.
*/
shared_pointer addDisplay();
/**
* Add control structure to the NTScalarArray.
* @return this instance of <b>NTScalarArrayBuilder</b>.
*/
shared_pointer addControl();
/**
* 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 <b>Structure</b>.
*/
epics::pvData::StructureConstPtr createStructure();
/**
* 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 <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 <b>Field</b> to the type.
* @param name name of the field.
* @param field a field to add.
* @return this instance of <b>NTScalarArrayBuilder</b>.
*/
shared_pointer add(std::string const & name, epics::pvData::FieldConstPtr const & field);
private:
NTScalarArrayBuilder();
void reset();
bool valueTypeSet;
epics::pvData::ScalarType valueType;
bool descriptor;
bool alarm;
bool timeStamp;
bool display;
bool control;
// NOTE: this preserves order, however it does not handle duplicates
epics::pvData::StringArray extraFieldNames;
epics::pvData::FieldConstPtrArray extraFields;
friend class ::epics::nt::NTScalarArray;
};
}
typedef std::tr1::shared_ptr<detail::NTScalarArrayBuilder> NTScalarArrayBuilderPtr;
/**
* @brief Convenience Class for NTScalarArray
*
* @author mrk
*/
class epicsShareClass NTScalarArray
{
public:
POINTER_DEFINITIONS(NTScalarArray);
static const std::string URI;
/**
* Wrap (aka dynamic cast, or wrap) the structure to NTScalarArray.
* First isCompatible is called.
* This method will nullptr if the structure is is not compatible.
* This method will nullptr if the structure is nullptr.
* @param structure The structure to wrap-ed (dynamic cast, wrapped) to NTScalarArray.
* @return NTScalarArray instance on success, nullptr otherwise.
*/
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 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 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 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.
*/
static NTScalarArrayBuilderPtr createBuilder();
/**
* Destructor.
*/
~NTScalarArray() {}
/**
* 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;
/**
* Attach an pvControl.
* @param pvControl The pvControl that will be attached.
* Does nothing if no control.
* @return true if the operation was successfull (i.e. this instance has a control field), otherwise false.
*/
bool attachControl(epics::pvData::PVControl &pvControl) 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 control.
* @return PVStructurePtr which may be null.
*/
epics::pvData::PVStructurePtr getControl() const;
/**
* Get the value field.
* @return The PVField for the values.
*/
epics::pvData::PVFieldPtr getValue() const;
/**
* Get the value field of a specified type (e.g. PVDoubleArray).
* @return The <PVT> field for the values.
*/
template<typename PVT>
std::tr1::shared_ptr<PVT> getValue() const
{
return std::tr1::dynamic_pointer_cast<PVT>(pvValue);
}
private:
NTScalarArray(epics::pvData::PVStructurePtr const & pvStructure);
epics::pvData::PVStructurePtr pvNTScalarArray;
epics::pvData::PVFieldPtr pvValue;
friend class detail::NTScalarArrayBuilder;
};
}}
#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,151 +1,282 @@
/* nttable.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* This software is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#include <algorithm>
#define epicsExportSharedSymbols
#include <pv/nttable.h>
#include <pv/ntutils.h>
namespace epics { namespace pvData {
using namespace std;
using namespace epics::pvData;
using std::tr1::static_pointer_cast;
namespace epics { namespace nt {
bool NTTable::isNTTable(PVStructurePtr const & pvStructure)
static NTFieldPtr ntField = NTField::get();
namespace detail {
NTTableBuilder::shared_pointer NTTableBuilder::addColumn(
std::string const & name, epics::pvData::ScalarType scalarType
)
{
NTFieldPtr ntfield = NTField::get();
PVStringArrayPtr pvLabel = static_pointer_cast<PVStringArray>
(pvStructure->getScalarArrayField("label",pvString));
if(pvLabel.get()==NULL) return false;
size_t nfields = pvLabel->getLength();
size_t nextra = 1; // label is 1 field
PVFieldPtr pvField = pvStructure->getSubField("function");
if(pvField.get()!=NULL
&& pvStructure->getStringField("function").get()!=NULL) nextra++;
pvField = pvStructure->getSubField("timeStamp");
if(pvField!=0 && ntfield->isTimeStamp(pvField->getField())) {
nextra++;
}
pvField = pvStructure->getSubField("alarm");
if(pvField.get()!=NULL && ntfield->isAlarm(pvField->getField())) {
nextra++;
}
if(nfields!=(pvStructure->getStructure()->getNumberFields()-nextra)) {
if (std::find(columnNames.begin(), columnNames.end(), name) != columnNames.end())
throw std::runtime_error("duplicate column name");
columnNames.push_back(name);
types.push_back(scalarType);
return shared_from_this();
}
StructureConstPtr NTTableBuilder::createStructure()
{
FieldBuilderPtr builder = getFieldCreate()->createFieldBuilder();
FieldBuilderPtr nestedBuilder =
builder->
setId(NTTable::URI)->
addArray("labels", pvString)->
addNestedStructure("value");
vector<string>::size_type len = columnNames.size();
for (vector<string>::size_type i = 0; i < len; i++)
nestedBuilder->addArray(columnNames[i], types[i]);
builder = nestedBuilder->endNested();
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;
}
NTTableBuilder::shared_pointer NTTableBuilder::addDescriptor()
{
descriptor = true;
return shared_from_this();
}
NTTableBuilder::shared_pointer NTTableBuilder::addAlarm()
{
alarm = true;
return shared_from_this();
}
NTTableBuilder::shared_pointer NTTableBuilder::addTimeStamp()
{
timeStamp = true;
return shared_from_this();
}
PVStructurePtr NTTableBuilder::createPVStructure()
{
// 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] = columnNames[i];
PVStructurePtr s = getPVDataCreate()->createPVStructure(createStructure());
s->getSubField<PVStringArray>("labels")->replace(freeze(l));
return s;
}
NTTablePtr NTTableBuilder::create()
{
return NTTablePtr(new NTTable(createPVStructure()));
}
NTTableBuilder::NTTableBuilder()
{
reset();
}
void NTTableBuilder::reset()
{
columnNames.clear();
types.clear();
descriptor = false;
alarm = false;
timeStamp = false;
}
NTTableBuilder::shared_pointer NTTableBuilder::add(string const & name, FieldConstPtr const & field)
{
extraFields.push_back(field); extraFieldNames.push_back(name);
return shared_from_this();
}
}
const std::string NTTable::URI("epics:nt/NTTable:1.0");
NTTable::shared_pointer NTTable::wrap(PVStructurePtr const & structure)
{
if(!isCompatible(structure)) return shared_pointer();
return wrapUnsafe(structure);
}
NTTable::shared_pointer NTTable::wrapUnsafe(PVStructurePtr const & structure)
{
return shared_pointer(new NTTable(structure));
}
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;
}
FieldConstPtrArray fields = pvStructure->getStructure()->getFields();
for(size_t i=0; i<nfields; i++) {
FieldConstPtr field = fields[i+nextra];
Type type = field->getType();
if(type!=scalarArray && type!=structureArray) 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;
}
NTTablePtr NTTable::create(
bool hasFunction,bool hasTimeStamp, bool hasAlarm,
StringArray const & valueNames,
FieldConstPtrArray const &valueFields)
bool NTTable::isCompatible(PVStructurePtr const & pvStructure)
{
StandardFieldPtr standardField = getStandardField();
size_t nfields = 1;
if(hasFunction) nfields++;
if(hasTimeStamp) nfields++;
if(hasAlarm) nfields++;
nfields += valueFields.size();
FieldCreatePtr fieldCreate = getFieldCreate();
PVDataCreatePtr pvDataCreate = getPVDataCreate();
FieldConstPtrArray fields;
StringArray names;
fields.resize(nfields);
names.resize(nfields);
size_t ind = 0;
if(hasFunction) {
names[ind] = "function";
fields[ind++] = fieldCreate->createScalar(pvString);
if(!pvStructure) 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;
}
if(hasTimeStamp) {
names[ind] = "timeStamp";
fields[ind++] = standardField->timeStamp();
}
if(hasAlarm) {
names[ind] = "alarm";
fields[ind++] = standardField->alarm();
}
names[ind] = "label";
fields[ind++] = fieldCreate->createScalarArray(pvString);
size_t numberValues = valueNames.size();
for(size_t i=0; i<numberValues ; i++) {
names[ind] = valueNames[i];
fields[ind++] = valueFields[i];
}
StructureConstPtr st = fieldCreate->createStructure(names,fields);
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(st);
PVStringArrayPtr pvLabel = static_pointer_cast<PVStringArray>
(pvStructure->getScalarArrayField("label",pvString));
pvLabel->put(0,numberValues,valueNames,0);
return NTTablePtr(new NTTable(pvStructure));
return true;
}
NTTablePtr NTTable::clone(PVStructurePtr const & pv)
NTTableBuilderPtr NTTable::createBuilder()
{
PVStructurePtr pvStructure = getPVDataCreate()->createPVStructure(pv);
return NTTablePtr(new NTTable(pvStructure));
return NTTableBuilderPtr(new detail::NTTableBuilder());
}
NTTable::NTTable(PVStructurePtr const & pvStructure)
: pvNTTable(pvStructure),
offsetFields(1)
bool NTTable::attachTimeStamp(PVTimeStamp &pvTimeStamp) const
{
NTFieldPtr ntfield = NTField::get();
PVScalarArrayPtr pvScalarArray
= pvStructure->getScalarArrayField("label",pvString);
pvLabel = static_pointer_cast<PVStringArray>(pvScalarArray);
PVFieldPtr pvField = pvStructure->getSubField("function");
if(pvField.get()!=NULL) {
offsetFields++;
pvFunction = pvStructure->getStringField("function");
}
pvField = pvStructure->getSubField("timeStamp");
if(pvField.get()!=NULL && ntfield->isTimeStamp(pvField->getField())) {
offsetFields++;
pvTimeStamp = static_pointer_cast<PVStructure>(pvField);
}
pvField = pvStructure->getSubField("alarm");
if(pvField.get()!=NULL && ntfield->isAlarm(pvField->getField())) {
offsetFields++;
pvAlarm = static_pointer_cast<PVStructure>(pvField);
}
PVStructurePtr ts = getTimeStamp();
if (ts)
return pvTimeStamp.attach(ts);
else
return false;
}
void NTTable::attachTimeStamp(PVTimeStamp &pv)
bool NTTable::attachAlarm(PVAlarm &pvAlarm) const
{
if(pvTimeStamp.get()==NULL) return;
pv.attach(pvTimeStamp);
PVStructurePtr al = getAlarm();
if (al)
return pvAlarm.attach(al);
else
return false;
}
void NTTable::attachAlarm(PVAlarm &pv)
PVStructurePtr NTTable::getPVStructure() const
{
if(pvAlarm.get()==NULL) return;
pv.attach(pvAlarm);
return pvNTTable;
}
size_t NTTable::getNumberValues()
PVStringPtr NTTable::getDescriptor() const
{
return pvLabel->getLength();
return pvNTTable->getSubField<PVString>("descriptor");
}
FieldConstPtr NTTable::getField(size_t index)
PVStructurePtr NTTable::getTimeStamp() const
{
FieldConstPtrArray fields = pvNTTable->getStructure()->getFields();
return fields[index + offsetFields];
return pvNTTable->getSubField<PVStructure>("timeStamp");
}
PVFieldPtr NTTable::getPVField(size_t index)
PVStructurePtr NTTable::getAlarm() const
{
PVFieldPtrArray pvFields = pvNTTable->getPVFields();
return pvFields[index+offsetFields];
return pvNTTable->getSubField<PVStructure>("alarm");
}
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 pvValue->getSubField(columnName);
}
NTTable::NTTable(PVStructurePtr const & pvStructure) :
pvNTTable(pvStructure), pvValue(pvNTTable->getSubField<PVStructure>("value"))
{}
}}

View File

@@ -1,115 +1,295 @@
/* nttable.h */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* This software is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#ifndef NTTABLE_H
#define NTTABLE_H
#include <vector>
#include <string>
#ifdef epicsExportSharedSymbols
# define nttableEpicsExportSharedSymbols
# undef epicsExportSharedSymbols
#endif
#include <pv/pvDisplay.h>
#include <pv/pvControl.h>
#ifdef nttableEpicsExportSharedSymbols
# define epicsExportSharedSymbols
# undef nttableEpicsExportSharedSymbols
#endif
#include <pv/ntfield.h>
namespace epics { namespace pvData {
#include <shareLib.h>
/**
* Convenience Class for NTTable
* @author mrk
*
*/
namespace epics { namespace nt {
class NTTable;
typedef std::tr1::shared_ptr<NTTable> NTTablePtr;
class NTTable
namespace detail {
/**
* @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
*/
class epicsShareClass NTTableBuilder :
public std::tr1::enable_shared_from_this<NTTableBuilder>
{
public:
POINTER_DEFINITIONS(NTTableBuilder);
/**
* 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>NTTableBuilder</b>.
*/
shared_pointer addColumn(std::string const & name, epics::pvData::ScalarType elementType);
/**
* Add descriptor field to the NTTable.
* @return this instance of <b>NTTableBuilder</b>.
*/
shared_pointer addDescriptor();
/**
* Add alarm structure to the NTTable.
* @return this instance of <b>NTTableBuilder</b>.
*/
shared_pointer addAlarm();
/**
* Add timeStamp structure to the NTTable.
* @return this instance of <b>NTTableBuilder</b>.
*/
shared_pointer addTimeStamp();
/**
* 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 <b>Structure</b>.
*/
epics::pvData::StructureConstPtr createStructure();
/**
* 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 <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 <b>Field</b> to the type.
* @param name name of the field.
* @param field a field to add.
* @return this instance of <b>NTTableBuilder</b>.
*/
shared_pointer add(std::string const & name, epics::pvData::FieldConstPtr const & field);
private:
NTTableBuilder();
void reset();
std::vector<std::string> columnNames;
std::vector<epics::pvData::ScalarType> types;
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::NTTable;
};
}
typedef std::tr1::shared_ptr<detail::NTTableBuilder> NTTableBuilderPtr;
/**
* @brief Convenience Class for NTTable
*
* @author mrk
*/
class epicsShareClass NTTable
{
public:
POINTER_DEFINITIONS(NTTable);
static const std::string URI;
/**
* Is the pvStructure an NTTable.
* @param pvStructure The pvStructure to test.
* @return (false,true) if (is not, is) an NTNameValuePair.
* Wrap (aka dynamic cast, or wrap) the structure to NTTable.
* First isCompatible is called.
* This method will nullptr if the structure is is not compatible.
* This method will nullptr if the structure is nullptr.
* @param structure The structure to wrap-ed (dynamic cast, wrapped) to NTTable.
* @return NTTable instance on success, nullptr otherwise.
*/
static bool isNTTable(PVStructurePtr const &pvStructure);
static shared_pointer wrap(epics::pvData::PVStructurePtr const & structure);
/**
* Create an NTTable pvStructure.
* @param hasFunction Create a PVString field named function.
* @param hasTimeStamp Create a timeStamp structure field.
* @param hasAlarm Create an alarm structure field.
* @param numberValues The number of fields that follow the label field.
* @param valueFields The fields that follow the label field.
* @return an NTTablePtr
* Wrap (aka dynamic cast, or wrap) the structure to NTMultiChannel without checking for isCompatible
* @param structure The structure to wrap-ed (dynamic cast, wrapped) to NTTable.
* @return NTTable instance.
*/
static NTTablePtr create(
bool hasFunction,bool hasTimeStamp, bool hasAlarm,
StringArray const & valueNames,
FieldConstPtrArray const &valueFields);
static NTTablePtr clone(PVStructurePtr const &);
static shared_pointer wrapUnsafe(epics::pvData::PVStructurePtr const & structure);
/**
* Destructor
* Is the structure an NTTable.
* @param structure The structure to test.
* @return (false,true) if (is not, is) an NTTable.
*/
static bool is_a(epics::pvData::StructureConstPtr const & structure);
/**
* 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 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.
*/
static NTTableBuilderPtr createBuilder();
/**
* Destructor.
*/
~NTTable() {}
/**
* Get the function field.
* @return The pvString or null if no function field.
*/
PVStringPtr getFunction() {return pvFunction;}
/**
* Attach a pvTimeStamp.
* @param pvTimeStamp The pvTimeStamp that will be attached.
* Does nothing if no timeStamp
* Does nothing if no timeStamp.
* @return true if the operation was successfull (i.e. this instance has a timeStamp field), otherwise false.
*/
void attachTimeStamp(PVTimeStamp &pvTimeStamp);
bool attachTimeStamp(epics::pvData::PVTimeStamp &pvTimeStamp) const;
/**
* Attach an 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(PVAlarm &pvAlarm);
bool attachAlarm(epics::pvData::PVAlarm &pvAlarm) const;
/**
* Get the pvStructure.
* @return PVStructurePtr.
*/
PVStructurePtr getPVStructure(){return pvNTTable;}
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.
*/
PVStructurePtr getTimeStamp(){return pvTimeStamp;}
epics::pvData::PVStructurePtr getTimeStamp() const;
/**
* Get the alarm.
* @return PVStructurePtr which may be null.
*/
PVStructurePtr getAlarm() {return pvAlarm;}
epics::pvData::PVStructurePtr getAlarm() const;
/**
* Get the label field.
* @return The pvStringArray for the label.
* Get the labels field.
* @return The pvStringArray for the labels.
*/
PVStringArrayPtr getLabel() {return pvLabel;}
epics::pvData::PVStringArrayPtr getLabels() const;
/**
* Get the the number of fields that follow the label field.
* @return The number of fields.
* 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.
*/
size_t getNumberValues();
epics::pvData::StringArray const & getColumnNames() const;
/**
* Get the Field for a field that follows the label field.
* @param index The index of the field desired.
* @return The FieldConstPtr for the field.
*/
FieldConstPtr getField(size_t index);
/**
* Get the PVField for a field that follows the label field.
* @param index The index of the field desired.
* 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.
*/
PVFieldPtr getPVField(size_t index);
epics::pvData::PVFieldPtr getColumn(std::string const & columnName) const;
/**
* Get the PVField (column) for a field that follows the label field of a specified type (e.g. PVDoubleArray).
* @param columnName The name of the column.
* @return The <PVT> field.
*/
template<typename PVT>
std::tr1::shared_ptr<PVT> getColumn(std::string const & columnName) const
{
epics::pvData::PVFieldPtr pvField = getColumn(columnName);
if (pvField.get())
return std::tr1::dynamic_pointer_cast<PVT>(pvField);
else
return std::tr1::shared_ptr<PVT>();
}
private:
NTTable(PVStructurePtr const & pvStructure);
PVStructurePtr pvNTTable;
PVStringPtr pvFunction;
PVStructurePtr pvTimeStamp;
PVStructurePtr pvAlarm;
PVStringArrayPtr pvLabel;
size_t offsetFields;
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)
{}
}}

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

@@ -0,0 +1,279 @@
/* 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);
/**
* 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 */

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

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

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

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

View File

@@ -2,17 +2,77 @@ TOP=../..
include $(TOP)/configure/CONFIG
PROD_HOST += ntfieldTest
PROD_LIBS += nt pvData Com
TESTPROD_HOST += ntfieldTest
ntfieldTest_SRCS += ntfieldTest.cpp
ntfieldTest_LIBS += nt pvData Com
TESTS += ntfieldTest
PROD_HOST += ntnameValueTest
TESTPROD_HOST += ntscalarTest
ntscalarTest_SRCS += ntscalarTest.cpp
TESTS += ntscalarTest
TESTPROD_HOST += ntscalarArrayTest
ntscalarArrayTest_SRCS += ntscalarArrayTest.cpp
TESTS += ntscalarArrayTest
TESTPROD_HOST += ntnameValueTest
ntnameValueTest_SRCS += ntnameValueTest.cpp
ntnameValueTest_LIBS += nt pvData Com
TESTS += ntnameValueTest
PROD_HOST += nttableTest
nttableTest_SRCS += nttableTest.cpp
nttableTest_LIBS += nt pvData Com
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
TESTPROD_HOST += ntndarrayTest
ntndarrayTest_SRCS = ntndarrayTest.cpp
TESTS += ntndarrayTest
TESTPROD_HOST += ntmatrixTest
ntmatrixTest_SRCS = ntmatrixTest.cpp
TESTS += ntmatrixTest
TESTPROD_HOST += ntenumTest
ntenumTest_SRCS = ntenumTest.cpp
TESTS += ntenumTest
TESTPROD_HOST += ntunionTest
ntunionTest_SRCS = ntunionTest.cpp
TESTS += ntunionTest
TESTPROD_HOST += ntaggregateTest
ntaggregateTest_SRCS = ntaggregateTest.cpp
TESTS += ntaggregateTest
TESTPROD_HOST += ntattributeTest
ntattributeTest_SRCS = ntattributeTest.cpp
TESTS += ntattributeTest
TESTPROD_HOST += ntndarrayAttributeTest
ntndarrayAttributeTest_SRCS = ntndarrayAttributeTest.cpp
TESTS += ntndarrayAttributeTest
TESTPROD_HOST += ntcontinuumTest
ntattributeTest_SRCS = ntcontinuumTest.cpp
TESTS += ntcontinuumTest
TESTPROD_HOST += nthistogramTest
ntattributeTest_SRCS = nthistogramTest.cpp
TESTS += nthistogramTest
TESTPROD_HOST += ntutilsTest
ntutilsTest_SRCS = ntutilsTest.cpp
TESTS += ntutilsTest
TESTSCRIPTS_HOST += $(TESTS:%=%.t)
include $(TOP)/configure/RULES
#----------------------------------------

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

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

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

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

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

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

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

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

View File

@@ -1,6 +1,6 @@
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* This software is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
/*
@@ -10,20 +10,16 @@
* Author: Marty Kraimer
*/
#include <cstddef>
#include <cstdlib>
#include <cstddef>
#include <string>
#include <cstring>
#include <cstdio>
#include <ctime>
#include <list>
#include <epicsAssert.h>
#include <epicsUnitTest.h>
#include <testMain.h>
#include <pv/nt.h>
using namespace epics::nt;
using namespace epics::pvData;
using std::string;
using std::cout;
using std::endl;
static FieldCreatePtr fieldCreate = getFieldCreate();
static PVDataCreatePtr pvDataCreate = getPVDataCreate();
@@ -31,65 +27,50 @@ static StandardFieldPtr standardField = getStandardField();
static StandardPVFieldPtr standardPVField = getStandardPVField();
static NTFieldPtr ntField = NTField::get();
static PVNTFieldPtr pvntField = PVNTField::get();
static String builder;
static void testNTField(FILE * fd)
void testNTField()
{
testDiag("testNTField");
StructureConstPtr structureConstPtr = ntField->createEnumerated();
builder.clear();
structureConstPtr->toString(&builder);
fprintf(fd,"%s\n",builder.c_str());
assert(ntField->isEnumerated(structureConstPtr));
cout << *structureConstPtr << endl;
testOk1(ntField->isEnumerated(structureConstPtr));
structureConstPtr = ntField->createTimeStamp();
builder.clear();
structureConstPtr->toString(&builder);
fprintf(fd,"%s\n",builder.c_str());
assert(ntField->isTimeStamp(structureConstPtr));
cout << *structureConstPtr << endl;
testOk1(ntField->isTimeStamp(structureConstPtr));
structureConstPtr = ntField->createAlarm();
builder.clear();
structureConstPtr->toString(&builder);
fprintf(fd,"%s\n",builder.c_str());
assert(ntField->isAlarm(structureConstPtr));
cout << *structureConstPtr << endl;
testOk1(ntField->isAlarm(structureConstPtr));
structureConstPtr = ntField->createDisplay();
builder.clear();
structureConstPtr->toString(&builder);
fprintf(fd,"%s\n",builder.c_str());
assert(ntField->isDisplay(structureConstPtr));
cout << *structureConstPtr << endl;
testOk1(ntField->isDisplay(structureConstPtr));
structureConstPtr = ntField->createAlarmLimit();
builder.clear();
structureConstPtr->toString(&builder);
fprintf(fd,"%s\n",builder.c_str());
assert(ntField->isAlarmLimit(structureConstPtr));
structureConstPtr = standardField->doubleAlarm();
cout << *structureConstPtr << endl;
testOk1(ntField->isAlarmLimit(structureConstPtr));
structureConstPtr = ntField->createControl();
builder.clear();
structureConstPtr->toString(&builder);
fprintf(fd,"%s\n",builder.c_str());
assert(ntField->isControl(structureConstPtr));
cout << *structureConstPtr << endl;
testOk1(ntField->isControl(structureConstPtr));
StructureArrayConstPtr structureArrayConstPtr
= ntField->createEnumeratedArray();
builder.clear();
structureArrayConstPtr->toString(&builder);
fprintf(fd,"%s\n",builder.c_str());
cout << *structureConstPtr << endl;
structureArrayConstPtr = ntField->createTimeStampArray();
builder.clear();
structureArrayConstPtr->toString(&builder);
fprintf(fd,"%s\n",builder.c_str());
cout << *structureConstPtr << endl;
structureArrayConstPtr = ntField->createAlarmArray();
builder.clear();
structureArrayConstPtr->toString(&builder);
fprintf(fd,"%s\n",builder.c_str());
cout << *structureConstPtr << endl;
}
static void testPVNTField(FILE * fd)
void testPVNTField()
{
testDiag("testPVNTField");
StringArray choices;
choices.resize(3);
choices[0] = "one";
@@ -97,73 +78,44 @@ static void testPVNTField(FILE * fd)
choices[2] = "three";
PVStructurePtr pvStructure = PVStructurePtr(
pvntField->createEnumerated(choices));
builder.clear();
pvStructure->toString(&builder);
fprintf(fd,"%s\n",builder.c_str());
assert(ntField->isEnumerated(pvStructure->getStructure()));
cout << *pvStructure << endl;
testOk1(ntField->isEnumerated(pvStructure->getStructure()));
pvStructure = PVStructurePtr(pvntField->createTimeStamp());
builder.clear();
pvStructure->toString(&builder);
fprintf(fd,"%s\n",builder.c_str());
assert(ntField->isTimeStamp(pvStructure->getStructure()));
cout << *pvStructure << endl;
testOk1(ntField->isTimeStamp(pvStructure->getStructure()));
pvStructure = PVStructurePtr(pvntField->createAlarm());
builder.clear();
pvStructure->toString(&builder);
fprintf(fd,"%s\n",builder.c_str());
assert(ntField->isAlarm(pvStructure->getStructure()));
cout << *pvStructure << endl;
testOk1(ntField->isAlarm(pvStructure->getStructure()));
pvStructure = PVStructurePtr(pvntField->createDisplay());
builder.clear();
pvStructure->toString(&builder);
fprintf(fd,"%s\n",builder.c_str());
assert(ntField->isDisplay(pvStructure->getStructure()));
cout << *pvStructure << endl;
testOk1(ntField->isDisplay(pvStructure->getStructure()));
pvStructure = PVStructurePtr(pvntField->createAlarmLimit());
builder.clear();
pvStructure->toString(&builder);
fprintf(fd,"%s\n",builder.c_str());
assert(ntField->isAlarmLimit(pvStructure->getStructure()));
pvStructure = PVStructurePtr(pvDataCreate->createPVStructure(standardField->doubleAlarm()));
cout << *pvStructure << endl;
testOk1(ntField->isAlarmLimit(pvStructure->getStructure()));
PVStructureArrayPtr pvStructureArray = PVStructureArrayPtr(
pvntField->createEnumeratedArray());
builder.clear();
pvStructureArray->toString(&builder);
fprintf(fd,"\n%s\n",builder.c_str());
builder.clear();
pvStructureArray->getStructureArray()->getStructure()->toString(&builder);
fprintf(fd,"%s\n",builder.c_str());
cout << *pvStructure << endl;
cout << *pvStructureArray->getStructureArray()->getStructure();
pvStructureArray = PVStructureArrayPtr(
pvntField->createTimeStampArray());
builder.clear();
pvStructureArray->toString(&builder);
fprintf(fd,"\n%s\n",builder.c_str());
builder.clear();
pvStructureArray->getStructureArray()->getStructure()->toString(&builder);
fprintf(fd,"%s\n",builder.c_str());
cout << *pvStructure << endl;
cout << *pvStructureArray->getStructureArray()->getStructure();
pvStructureArray = PVStructureArrayPtr(
pvntField->createAlarmArray());
builder.clear();
pvStructureArray->toString(&builder);
fprintf(fd,"\n%s\n",builder.c_str());
builder.clear();
pvStructureArray->getStructureArray()->getStructure()->toString(&builder);
fprintf(fd,"%s\n",builder.c_str());
cout << *pvStructure << endl;
cout << *pvStructureArray->getStructureArray()->getStructure();
}
int main(int argc,char *argv[])
{
char *fileName = 0;
if(argc>1) fileName = argv[1];
FILE * fd = stdout;
if(fileName!=0 && fileName[0]!=0) {
fd = fopen(fileName,"w+");
}
testNTField(fd);
testPVNTField(fd);
return(0);
MAIN(testNTField) {
testPlan(11);
testNTField();
testPVNTField();
return testDone();
}

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

@@ -0,0 +1,194 @@
/**
* 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.
*/
/*
* ntmutiChannelTest.cpp
*
* Created on: 2014.08
* Author: Marty Kraimer
*/
#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/ntmultiChannel.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()
{
NTMultiChannelBuilderPtr builder = NTMultiChannel::createBuilder();
testOk(builder.get() != 0, "Got builder");
NTMultiChannelPtr 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(NTMultiChannel::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;}
UnionConstPtr unionPtr =
fieldCreate->createFieldBuilder()->
add("doubleValue", pvDouble)->
add("intValue", pvInt)->
createUnion();
multiChannel = builder->
value(unionPtr) ->
addDescriptor()->
addAlarm()->
addTimeStamp()->
addSeverity() ->
addIsConnected() ->
create();
testOk1(multiChannel.get() != 0);
pvStructure = multiChannel->getPVStructure();
if(debug) {cout << *pvStructure << endl;}
pvChannelName = multiChannel->getChannelName();
pvChannelName->replace(channelNames);
PVUnionArrayPtr pvValue = multiChannel->getValue();
shared_vector<PVUnionPtr> unions(nchan);
unions[0] = pvDataCreate->createPVUnion(unionPtr);
unions[1] = pvDataCreate->createPVUnion(unionPtr);
unions[2] = pvDataCreate->createPVUnion(unionPtr);
unions[0]->select("doubleValue");
unions[1]->select("intValue");
unions[2]->select("intValue");
PVDoublePtr pvDouble = unions[0]->get<PVDouble>();
pvDouble->put(1.235);
PVIntPtr pvInt = unions[1]->get<PVInt>();
pvInt->put(5);
pvInt = unions[2]->get<PVInt>();
pvInt->put(7);
pvValue->replace(freeze(unions));
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(unionPtr) ->
addDescriptor()->
addAlarm()->
addTimeStamp()->
addSeverity() ->
addStatus() ->
addMessage() ->
addSecondsPastEpoch() ->
addNanoseconds() ->
addUserTag() ->
addIsConnected() ->
create();
testOk1(multiChannel.get() != 0);
pvStructure = multiChannel->getPVStructure();
if(debug) {cout << *pvStructure << endl;}
testOk1(NTMultiChannel::isCompatible(pvStructure)==true);
PVStructurePtr pvTimeStamp = multiChannel->getTimeStamp();
testOk1(pvTimeStamp.get() !=0);
PVStructurePtr pvAlarm = multiChannel->getAlarm();
testOk1(pvAlarm.get() !=0);
pvValue = multiChannel->getValue();
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");
NTMultiChannelPtr nullPtr = NTMultiChannel::wrap(PVStructurePtr());
testOk(nullPtr.get() == 0, "nullptr wrap");
nullPtr = NTMultiChannel::wrap(
getPVDataCreate()->createPVStructure(
NTField::get()->createTimeStamp()
)
);
testOk(nullPtr.get() == 0, "wrong type wrap");
NTMultiChannelBuilderPtr builder = NTMultiChannel::createBuilder();
testOk(builder.get() != 0, "Got builder");
PVStructurePtr pvStructure = builder->
createPVStructure();
testOk1(pvStructure.get() != 0);
if (!pvStructure)
return;
NTMultiChannelPtr ptr = NTMultiChannel::wrap(pvStructure);
testOk(ptr.get() != 0, "wrap OK");
builder = NTMultiChannel::createBuilder();
ptr = NTMultiChannel::wrapUnsafe(pvStructure);
testOk(ptr.get() != 0, "wrapUnsafe OK");
}
MAIN(testCreateRequest)
{
testPlan(25);
test();
test_wrap();
return testDone();
}

View File

@@ -1,87 +1,256 @@
/**
* 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.
*/
/*
* ntnameValueTest.cpp
*
* Created on: 2011.11
* Author: Marty Kraimer
*/
#include <cstddef>
#include <cstdlib>
#include <cstddef>
#include <string>
#include <cstring>
#include <cstdio>
#include <ctime>
#include <list>
#include <epicsAssert.h>
#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 PVDataCreatePtr pvDataCreate = getPVDataCreate();
static NTFieldPtr ntField = NTField::get();
static PVNTFieldPtr pvntField = PVNTField::get();
static String builder;
static FieldCreatePtr fieldCreate = getFieldCreate();
static void test(FILE * fd)
void test_builder()
{
NTNameValuePtr ntNameValue = NTNameValue::create(true,true,true);
PVStructurePtr pvStructure = ntNameValue->getPVStructure();
builder.clear();
pvStructure->toString(&builder);
fprintf(fd,"%s\n",builder.c_str());
builder.clear();
pvStructure->getStructure()->toString(&builder);
fprintf(fd,"%s\n",builder.c_str());
PVStringArrayPtr names = ntNameValue->getNames();
PVStringArrayPtr values = ntNameValue->getValues();
size_t n = 2;
StringArray name;
StringArray value;
name.resize(n);
value.resize(n);
name[0] = "name 0";
name[1] = "name 1";
value[0] = "value 0";
value[1] = "value 1";
names->put(0,n,name,0);
values->put(0,n,value,0);
PVStringPtr function = ntNameValue->getFunction();
function->put("test");
PVAlarm pvAlarm;
ntNameValue->attachAlarm(pvAlarm);
Alarm alarm;
alarm.setMessage("test alarm");
alarm.setSeverity(majorAlarm);
alarm.setStatus(clientStatus);
pvAlarm.set(alarm);
PVTimeStamp pvTimeStamp;
ntNameValue->attachTimeStamp(pvTimeStamp);
TimeStamp timeStamp(1000,1000,10);
pvTimeStamp.set(timeStamp);
builder.clear();
pvStructure->toString(&builder);
fprintf(fd,"%s\n",builder.c_str());
assert(NTNameValue::isNTNameValue(pvStructure));
}
testDiag("test_builder");
NTNameValueBuilderPtr builder = NTNameValue::createBuilder();
testOk(builder.get() != 0, "Got builder");
int main(int argc,char *argv[])
{
char *fileName = 0;
if(argc>1) fileName = argv[1];
FILE * fd = stdout;
if(fileName!=0 && fileName[0]!=0) {
fd = fopen(fileName,"w+");
StructureConstPtr structure = builder->
value(pvDouble)->
addDescriptor()->
addAlarm()->
addTimeStamp()->
add("extra1",fieldCreate->createScalar(pvString)) ->
add("extra2",fieldCreate->createScalarArray(pvString)) ->
createStructure();
testOk1(structure.get() != 0);
if (!structure)
return;
testOk1(NTNameValue::is_a(structure));
testOk1(structure->getID() == NTNameValue::URI);
testOk1(structure->getNumberFields() == 7);
testOk1(structure->getField("name").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("value")).get() != 0 &&
dynamic_pointer_cast<const ScalarArray>(structure->getField("value"))->getElementType() == pvDouble, "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");
}
test(fd);
return(0);
}
void test_ntnameValue()
{
testDiag("test_ntnameValue");
NTNameValueBuilderPtr builder = NTNameValue::createBuilder();
testOk(builder.get() != 0, "Got builder");
NTNameValuePtr ntNameValue = builder->
value(pvInt)->
addDescriptor()->
addAlarm()->
addTimeStamp()->
add("extra1",fieldCreate->createScalar(pvString)) ->
add("extra2",fieldCreate->createScalarArray(pvString)) ->
create();
testOk1(ntNameValue.get() != 0);
testOk1(ntNameValue->getPVStructure().get() != 0);
testOk1(ntNameValue->getDescriptor().get() != 0);
testOk1(ntNameValue->getAlarm().get() != 0);
testOk1(ntNameValue->getTimeStamp().get() != 0);
testOk1(ntNameValue->getName().get() != 0);
testOk1(ntNameValue->getValue().get() != 0);
//
// example how to set name
//
PVStringArray::svector newName;
newName.push_back("name1");
newName.push_back("name2");
newName.push_back("name3");
PVStringArrayPtr pvNameField = ntNameValue->getName();
pvNameField->replace(freeze(newName));
//
// example how to get name
//
PVStringArray::const_svector name(pvNameField->view());
testOk1(name.size() == 3);
testOk1(name[0] == "name1");
testOk1(name[1] == "name2");
testOk1(name[2] == "name3");
//
// example how to set value
//
PVIntArray::svector newValue;
newValue.push_back(1);
newValue.push_back(2);
newValue.push_back(8);
PVIntArrayPtr pvValueField = ntNameValue->getValue<PVIntArray>();
pvValueField->replace(freeze(newValue));
//
// example how to get column value
//
PVIntArray::const_svector value(pvValueField->view());
testOk1(value.size() == 3);
testOk1(value[0] == 1);
testOk1(value[1] == 2);
testOk1(value[2] == 8);
//
// timeStamp ops
//
PVTimeStamp pvTimeStamp;
if (ntNameValue->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 (ntNameValue->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
//
ntNameValue->getDescriptor()->put("This is a test NTNameValue");
// dump NTNameValue
std::cout << *ntNameValue->getPVStructure() << std::endl;
}
void test_wrap()
{
testDiag("test_wrap");
NTNameValuePtr nullPtr = NTNameValue::wrap(PVStructurePtr());
testOk(nullPtr.get() == 0, "nullptr wrap");
nullPtr = NTNameValue::wrap(
getPVDataCreate()->createPVStructure(
NTField::get()->createTimeStamp()
)
);
testOk(nullPtr.get() == 0, "wrong type wrap");
NTNameValueBuilderPtr builder = NTNameValue::createBuilder();
testOk(builder.get() != 0, "Got builder");
PVStructurePtr pvStructure = builder->
value(pvString)->
createPVStructure();
testOk1(pvStructure.get() != 0);
if (!pvStructure)
return;
testOk1(NTNameValue::isCompatible(pvStructure)==true);
NTNameValuePtr ptr = NTNameValue::wrap(pvStructure);
testOk(ptr.get() != 0, "wrap OK");
ptr = NTNameValue::wrapUnsafe(pvStructure);
testOk(ptr.get() != 0, "wrapUnsafe OK");
}
void test_extra()
{
testDiag("test_extra");
NTNameValueBuilderPtr builder = NTNameValue::createBuilder();
testOk(builder.get() != 0, "Got builder");
StructureConstPtr structure = builder->
value(pvDouble)->
addTimeStamp()->
add("function", getFieldCreate()->createScalar(pvString))->
createStructure();
testOk1(structure.get() != 0);
if (!structure)
return;
testOk1(NTNameValue::is_a(structure));
testOk1(structure->getID() == NTNameValue::URI);
testOk1(structure->getNumberFields() == 4);
testOk1(structure->getField("name").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(testNTNameValue) {
testPlan(48);
test_builder();
test_ntnameValue();
test_wrap();
test_extra();
return testDone();
}

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

125
test/nt/ntndarrayTest.cpp Normal file
View File

@@ -0,0 +1,125 @@
/**
* 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(bool extraFields)
{
testDiag("test_builder");
NTNDArrayBuilderPtr builder = NTNDArray::createBuilder();
testOk(builder.get() != 0, "Got builder");
builder->addDescriptor()->
addTimeStamp()->
addAlarm()->
addDisplay();
if (extraFields)
{
builder->add("extra1",fieldCreate->createScalar(pvString))->
add("extra2",fieldCreate->createScalarArray(pvString));
}
StructureConstPtr structure = builder->createStructure();
testOk1(structure.get() != 0);
if (!structure)
return;
testOk1(NTNDArray::is_a(structure));
testOk1(structure->getID() == NTNDArray::URI);
testOk1(structure->getField("value").get() != 0);
testOk1(structure->getField("compressedSize").get() != 0);
testOk1(structure->getField("uncompressedSize").get() != 0);
testOk1(structure->getField("codec").get() != 0);
testOk1(structure->getField("dimension").get() != 0);
testOk1(structure->getField("uniqueId").get() != 0);
testOk1(structure->getField("dataTimeStamp").get() != 0);
testOk1(structure->getField("attribute").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);
if (extraFields)
{
testOk1(structure->getField("extra1").get() != 0);
testOk1(structure->getField("extra2").get() != 0);
}
std::cout << *structure << std::endl;
}
void test_all()
{
testDiag("test_builder");
NTNDArrayBuilderPtr builder = NTNDArray::createBuilder();
testOk(builder.get() != 0, "Got builder");
PVStructurePtr pvStructure = builder->
addDescriptor()->
addTimeStamp()->
addAlarm()->
addDisplay()->
add("extra1",fieldCreate->createScalar(pvString)) ->
add("extra2",fieldCreate->createScalarArray(pvString)) ->
createPVStructure();
std::cout << *pvStructure << std::endl;
testOk1(NTNDArray::isCompatible(pvStructure)==true);
}
void test_wrap()
{
testDiag("test_wrap");
NTNDArrayPtr nullPtr = NTNDArray::wrap(PVStructurePtr());
testOk(nullPtr.get() == 0, "nullptr wrap");
nullPtr = NTNDArray::wrap(
getPVDataCreate()->createPVStructure(
NTField::get()->createTimeStamp()
)
);
testOk(nullPtr.get() == 0, "wrong type wrap");
NTNDArrayBuilderPtr builder = NTNDArray::createBuilder();
testOk(builder.get() != 0, "Got builder");
PVStructurePtr pvStructure = builder->
createPVStructure();
testOk1(pvStructure.get() != 0);
if (!pvStructure)
return;
testOk1(NTNDArray::isCompatible(pvStructure)==true);
NTNDArrayPtr ptr = NTNDArray::wrap(pvStructure);
testOk(ptr.get() != 0, "wrap OK");
ptr = NTNDArray::wrapUnsafe(pvStructure);
testOk(ptr.get() != 0, "wrapUnsafe OK");
}
MAIN(testNTNDArray) {
testPlan(59);
test_builder(true);
test_builder(false);
test_builder(false); // called twice to test caching
test_all();
test_wrap();
return testDone();
}

View File

@@ -0,0 +1,245 @@
/**
* 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");
NTScalarArrayBuilderPtr builder = NTScalarArray::createBuilder();
testOk(builder.get() != 0, "Got builder");
StructureConstPtr structure = builder->
arrayValue(pvDouble)->
addDescriptor()->
addAlarm()->
addTimeStamp()->
addDisplay()->
addControl()->
add("extra1",fieldCreate->createScalar(pvString)) ->
add("extra2",fieldCreate->createScalarArray(pvString)) ->
createStructure();
testOk1(structure.get() != 0);
if (!structure)
return;
testOk1(NTScalarArray::is_a(structure));
testOk1(structure->getID() == NTScalarArray::URI);
testOk1(structure->getNumberFields() == 8);
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("display").get() != 0);
testOk1(structure->getField("control").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;
// no value set
try
{
structure = builder->
addDescriptor()->
addAlarm()->
addTimeStamp()->
addDisplay()->
addControl()->
createStructure();
testFail("no value type set");
} catch (std::runtime_error &) {
testPass("no value type set");
}
}
void test_ntscalarArray()
{
testDiag("test_ntscalarArray");
NTScalarArrayBuilderPtr builder = NTScalarArray::createBuilder();
testOk(builder.get() != 0, "Got builder");
NTScalarArrayPtr ntScalarArray = builder->
arrayValue(pvInt)->
addDescriptor()->
addAlarm()->
addTimeStamp()->
addDisplay()->
addControl()->
create();
testOk1(ntScalarArray.get() != 0);
testOk1(ntScalarArray->getPVStructure().get() != 0);
testOk1(ntScalarArray->getValue().get() != 0);
testOk1(ntScalarArray->getDescriptor().get() != 0);
testOk1(ntScalarArray->getAlarm().get() != 0);
testOk1(ntScalarArray->getTimeStamp().get() != 0);
testOk1(ntScalarArray->getDisplay().get() != 0);
testOk1(ntScalarArray->getControl().get() != 0);
//
// example how to set values
//
PVIntArray::svector newValues;
newValues.push_back(1);
newValues.push_back(2);
newValues.push_back(8);
PVIntArrayPtr pvValueField = ntScalarArray->getValue<PVIntArray>();
pvValueField->replace(freeze(newValues));
//
// example how to get values
//
PVIntArray::const_svector values(pvValueField->view());
testOk1(values.size() == 3);
testOk1(values[0] == 1);
testOk1(values[1] == 2);
testOk1(values[2] == 8);
//
// 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");
//
// control ops
//
PVControl pvControl;
if (ntScalarArray->attachControl(pvControl))
{
testPass("control attach");
// example how to set an control
Control control;
control.setLow(-10);
control.setHigh(10);
control.setMinStep(1);
pvControl.set(control);
}
else
testFail("control attach fail");
//
// set descriptor
//
ntScalarArray->getDescriptor()->put("This is a test NTScalarArray");
// dump ntScalarArray
std::cout << *ntScalarArray->getPVStructure() << std::endl;
}
void test_wrap()
{
testDiag("test_wrap");
NTScalarArrayPtr nullPtr = NTScalarArray::wrap(PVStructurePtr());
testOk(nullPtr.get() == 0, "nullptr wrap");
nullPtr = NTScalarArray::wrap(
getPVDataCreate()->createPVStructure(
NTField::get()->createTimeStamp()
)
);
testOk(nullPtr.get() == 0, "wrong type wrap");
NTScalarArrayBuilderPtr builder = NTScalarArray::createBuilder();
testOk(builder.get() != 0, "Got builder");
PVStructurePtr pvStructure = builder->
arrayValue(pvDouble)->
createPVStructure();
testOk1(pvStructure.get() != 0);
if (!pvStructure)
return;
testOk1(NTScalarArray::isCompatible(pvStructure)==true);
NTScalarArrayPtr ptr = NTScalarArray::wrap(pvStructure);
testOk(ptr.get() != 0, "wrap OK");
ptr = NTScalarArray::wrapUnsafe(pvStructure);
testOk(ptr.get() != 0, "wrapUnsafe OK");
}
MAIN(testNTScalarArray) {
testPlan(38);
test_builder();
test_ntscalarArray();
test_wrap();
return testDone();
}

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

236
test/nt/ntscalarTest.cpp Normal file
View File

@@ -0,0 +1,236 @@
/**
* 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();
void test_builder()
{
testDiag("test_builder");
NTScalarBuilderPtr builder = NTScalar::createBuilder();
testOk(builder.get() != 0, "Got builder");
StructureConstPtr structure = builder->
value(pvDouble)->
addDescriptor()->
addAlarm()->
addTimeStamp()->
addDisplay()->
addControl()->
add("valueAlarm",standardField->doubleAlarm()) ->
add("extra",fieldCreate->createScalarArray(pvString)) ->
createStructure();
testOk1(structure.get() != 0);
if (!structure)
return;
testOk1(NTScalar::is_a(structure));
testOk1(structure->getID() == NTScalar::URI);
testOk1(structure->getNumberFields() == 8);
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("display").get() != 0);
testOk1(structure->getField("control").get() != 0);
testOk(dynamic_pointer_cast<const Scalar>(structure->getField("value")).get() != 0 &&
dynamic_pointer_cast<const Scalar>(structure->getField("value"))->getScalarType() == pvDouble, "value type");
std::cout << *structure << std::endl;
// no value set
try
{
structure = builder->
addDescriptor()->
addAlarm()->
addTimeStamp()->
addDisplay()->
addControl()->
createStructure();
testFail("no value type set");
} catch (std::runtime_error &) {
testPass("no value type set");
}
}
void test_ntscalar()
{
testDiag("test_ntscalar");
NTScalarBuilderPtr builder = NTScalar::createBuilder();
testOk(builder.get() != 0, "Got builder");
NTScalarPtr ntScalar = builder->
value(pvInt)->
addDescriptor()->
addAlarm()->
addTimeStamp()->
addDisplay()->
addControl()->
add("valueAlarm",standardField->intAlarm()) ->
create();
testOk1(ntScalar.get() != 0);
testOk1(ntScalar->getPVStructure().get() != 0);
testOk1(ntScalar->getValue().get() != 0);
testOk1(ntScalar->getDescriptor().get() != 0);
testOk1(ntScalar->getAlarm().get() != 0);
testOk1(ntScalar->getTimeStamp().get() != 0);
testOk1(ntScalar->getDisplay().get() != 0);
testOk1(ntScalar->getControl().get() != 0);
//
// example how to set a value
//
ntScalar->getValue<PVInt>()->put(12);
//
// example how to get a value
//
int32 value = ntScalar->getValue<PVInt>()->get();
testOk1(value == 12);
//
// timeStamp ops
//
PVTimeStamp pvTimeStamp;
if (ntScalar->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 (ntScalar->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 (ntScalar->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");
display.setFormat("%d");
display.setUnits("A");
pvDisplay.set(display);
}
else
testFail("display attach fail");
//
// control ops
//
PVControl pvControl;
if (ntScalar->attachControl(pvControl))
{
testPass("control attach");
// example how to set an control
Control control;
control.setLow(-10);
control.setHigh(10);
control.setMinStep(1);
pvControl.set(control);
}
else
testFail("control attach fail");
//
// set descriptor
//
ntScalar->getDescriptor()->put("This is a test NTScalar");
// dump ntScalar
std::cout << *ntScalar->getPVStructure() << std::endl;
}
void test_wrap()
{
testDiag("test_wrap");
NTScalarPtr nullPtr = NTScalar::wrap(PVStructurePtr());
testOk(nullPtr.get() == 0, "nullptr wrap");
nullPtr = NTScalar::wrap(
getPVDataCreate()->createPVStructure(
NTField::get()->createTimeStamp()
)
);
testOk(nullPtr.get() == 0, "wrong type wrap");
NTScalarBuilderPtr builder = NTScalar::createBuilder();
testOk(builder.get() != 0, "Got builder");
PVStructurePtr pvStructure = builder->
value(pvDouble)->
createPVStructure();
testOk1(pvStructure.get() != 0);
if (!pvStructure)
return;
testOk1(NTScalar::isCompatible(pvStructure)==true);
NTScalarPtr ptr = NTScalar::wrap(pvStructure);
testOk(ptr.get() != 0, "wrap OK");
ptr = NTScalar::wrapUnsafe(pvStructure);
testOk(ptr.get() != 0, "wrapUnsafe OK");
}
MAIN(testNTScalar) {
testPlan(35);
test_builder();
test_ntscalar();
test_wrap();
return testDone();
}

View File

@@ -1,107 +1,247 @@
/**
* 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.
*/
/*
* nttableTest.cpp
*
* Created on: 2011.11
* Author: Marty Kraimer
*/
#include <cstddef>
#include <cstdlib>
#include <cstddef>
#include <string>
#include <cstring>
#include <cstdio>
#include <ctime>
#include <list>
#include <epicsAssert.h>
#include <epicsUnitTest.h>
#include <testMain.h>
#include <pv/nt.h>
using namespace epics::nt;
using namespace epics::pvData;
using std::tr1::static_pointer_cast;
using std::tr1::dynamic_pointer_cast;
static FieldCreatePtr fieldCreate = getFieldCreate();
static PVDataCreatePtr pvDataCreate = getPVDataCreate();
static NTFieldPtr ntField = NTField::get();
static PVNTFieldPtr pvntField = PVNTField::get();
static String builder;
static void test(FILE * fd)
void test_builder()
{
size_t n = 2;
FieldConstPtrArray fields(n);
StringArray names(n);
names[0] = "position";
names[1] = "alarms";
fields[0] = fieldCreate->createScalarArray(pvDouble);
fields[1] = ntField->createAlarmArray();
NTTablePtr ntTable = NTTable::create(
true,true,true,names,fields);
PVStructurePtr pvStructure = ntTable->getPVStructure();
builder.clear();
pvStructure->toString(&builder);
fprintf(fd,"%s\n",builder.c_str());
builder.clear();
pvStructure->getStructure()->toString(&builder);
fprintf(fd,"%s\n",builder.c_str());
PVDoubleArrayPtr pvPositions
= static_pointer_cast<PVDoubleArray>(ntTable->getPVField(0));
DoubleArray positions(2);
positions[0] = 1.0;
positions[1] = 2.0;
pvPositions->put(0,2,positions,0);
PVStructureArrayPtr pvAlarms
= static_pointer_cast<PVStructureArray>(ntTable->getPVField(1));
testDiag("test_builder");
NTTableBuilderPtr builder = NTTable::createBuilder();
testOk(builder.get() != 0, "Got builder");
StructureConstPtr structure = builder->
addColumn("column0", pvDouble)->
addColumn("column1", pvString)->
addColumn("column2", pvInt)->
addDescriptor()->
addAlarm()->
addTimeStamp()->
add("extra1",fieldCreate->createScalar(pvString)) ->
add("extra2",fieldCreate->createScalarArray(pvString)) ->
createStructure();
testOk1(structure.get() != 0);
if (!structure)
return;
testOk1(NTTable::is_a(structure));
testOk1(structure->getID() == NTTable::URI);
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) \
testOk(s.get() != 0 && \
s->getField(name).get() != 0 && \
dynamic_pointer_cast<const ScalarArray>(s->getField(name)).get() != 0 && \
dynamic_pointer_cast<const ScalarArray>(s->getField(name))->getElementType() == type, \
name " check");
TEST_COLUMN("column0", pvDouble);
TEST_COLUMN("column1", pvString);
TEST_COLUMN("column2", pvInt);
#undef TEST_COLUMN
std::cout << *structure << std::endl;
// duplicate test
try
{
structure = builder->
addColumn("column0", pvDouble)->
addColumn("column0", pvString)->
createStructure();
testFail("duplicate column name");
} catch (std::runtime_error &) {
testPass("duplicate column name");
}
}
void test_labels()
{
testDiag("test_labels");
NTTableBuilderPtr builder = NTTable::createBuilder();
testOk(builder.get() != 0, "Got builder");
PVStructurePtr pvStructure = builder->
addColumn("column0", pvDouble)->
addColumn("column1", pvString)->
addColumn("column2", pvInt)->
createPVStructure();
testOk1(pvStructure.get() != 0);
if (!pvStructure)
return;
testOk1(NTTable::isCompatible(pvStructure)==true);
std::cout << *pvStructure << std::endl;
PVStringArrayPtr labels = pvStructure->getSubField<PVStringArray>("labels");
testOk1(labels.get() != 0);
testOk1(labels->getLength() == 3);
PVStringArray::const_svector l(labels->view());
testOk1(l[0] == "column0");
testOk1(l[1] == "column1");
testOk1(l[2] == "column2");
}
void test_nttable()
{
testDiag("test_nttable");
NTTableBuilderPtr builder = NTTable::createBuilder();
testOk(builder.get() != 0, "Got builder");
NTTablePtr ntTable = builder->
addColumn("column0", pvDouble)->
addColumn("column1", pvString)->
addColumn("column2", pvInt)->
addDescriptor()->
addAlarm()->
addTimeStamp()->
create();
testOk1(ntTable.get() != 0);
testOk1(ntTable->getPVStructure().get() != 0);
testOk1(ntTable->getDescriptor().get() != 0);
testOk1(ntTable->getAlarm().get() != 0);
testOk1(ntTable->getTimeStamp().get() != 0);
testOk1(ntTable->getLabels().get() != 0);
testOk1(ntTable->getColumn<PVDoubleArray>("column0").get() != 0);
testOk1(ntTable->getColumn<PVStringArray>("column1").get() != 0);
testOk1(ntTable->getColumn<PVIntArray>("column2").get() != 0);
testOk1(ntTable->getColumn("invalid").get() == 0);
//
// example how to set column values
//
PVIntArray::svector newValues;
newValues.push_back(1);
newValues.push_back(2);
newValues.push_back(8);
PVIntArrayPtr intColumn = ntTable->getColumn<PVIntArray>("column2");
intColumn->replace(freeze(newValues));
//
// example how to get column values
//
PVIntArray::const_svector values(intColumn->view());
testOk1(values.size() == 3);
testOk1(values[0] == 1);
testOk1(values[1] == 2);
testOk1(values[2] == 8);
//
// timeStamp ops
//
PVTimeStamp pvTimeStamp;
if (ntTable->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;
Alarm alarm;
PVStructurePtrArray palarms(n);
for(size_t i=0; i<n; i++) {
palarms[i] = pvntField->createAlarm();
pvAlarm.attach(palarms[i]);
alarm.setMessage("test");
alarm.setSeverity(majorAlarm);
alarm.setStatus(clientStatus);
if (ntTable->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);
}
pvAlarms->put(0,n,palarms,0);
StringArray labels(n);
labels[0] = pvPositions->getFieldName();
labels[1] = pvAlarms->getFieldName();
PVStringArrayPtr label = ntTable->getLabel();
label->put(0,n,labels,0);
PVStringPtr function = ntTable->getFunction();
function->put("test");
ntTable->attachAlarm(pvAlarm);
alarm.setMessage("test alarm");
alarm.setSeverity(majorAlarm);
alarm.setStatus(clientStatus);
pvAlarm.set(alarm);
PVTimeStamp pvTimeStamp;
ntTable->attachTimeStamp(pvTimeStamp);
TimeStamp timeStamp(1000,1000,10);
pvTimeStamp.set(timeStamp);
builder.clear();
pvStructure->toString(&builder);
fprintf(fd,"%s\n",builder.c_str());
assert(NTTable::isNTTable(pvStructure));
else
testFail("alarm attach fail");
//
// set descriptor
//
ntTable->getDescriptor()->put("This is a test NTTable");
// dump NTTable
std::cout << *ntTable->getPVStructure() << std::endl;
}
int main(int argc,char *argv[])
void test_wrap()
{
char *fileName = 0;
if(argc>1) fileName = argv[1];
FILE * fd = stdout;
if(fileName!=0 && fileName[0]!=0) {
fd = fopen(fileName,"w+");
}
test(fd);
return(0);
testDiag("test_wrap");
NTTablePtr nullPtr = NTTable::wrap(PVStructurePtr());
testOk(nullPtr.get() == 0, "nullptr wrap");
nullPtr = NTTable::wrap(
getPVDataCreate()->createPVStructure(
NTField::get()->createTimeStamp()
)
);
testOk(nullPtr.get() == 0, "wrong type wrap");
NTTableBuilderPtr builder = NTTable::createBuilder();
testOk(builder.get() != 0, "Got builder");
PVStructurePtr pvStructure = builder->
addColumn("column0", pvDouble)->
addColumn("column1", pvString)->
addColumn("column2", pvInt)->
createPVStructure();
testOk1(pvStructure.get() != 0);
if (!pvStructure)
return;
NTTablePtr ptr = NTTable::wrap(pvStructure);
testOk(ptr.get() != 0, "wrap OK");
ptr = NTTable::wrapUnsafe(pvStructure);
testOk(ptr.get() != 0, "wrapUnsafe OK");
}
MAIN(testNTTable) {
testPlan(48);
test_builder();
test_labels();
test_nttable();
test_wrap();
return testDone();
}

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

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

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

@@ -0,0 +1,38 @@
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* This software is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#include <epicsUnitTest.h>
#include <testMain.h>
#include <pv/ntutils.h>
using namespace epics::nt;
void test_is_a()
{
testDiag("test_is_a");
testOk1(NTUtils::is_a("epics:nt/NTTable:1.0", "epics:nt/NTTable:1.0"));
testOk1(NTUtils::is_a("epics:nt/NTTable:2.0", "epics:nt/NTTable:2.0"));
testOk1(NTUtils::is_a("epics:nt/NTTable:1.0", "epics:nt/NTTable:1.1"));
testOk1(NTUtils::is_a("epics:nt/NTTable:1.1", "epics:nt/NTTable:1.0"));
testOk1(!NTUtils::is_a("epics:nt/NTTable:1.0", "epics:nt/NTTable:2.0"));
testOk1(!NTUtils::is_a("epics:nt/NTTable:2.0", "epics:nt/NTTable:1.0"));
testOk1(!NTUtils::is_a("epics:nt/NTTable:1.3", "epics:nt/NTTable:2.3"));
testOk1(!NTUtils::is_a("epics:nt/NTTable:1.0", "epics:nt/NTTable:11.0"));
testOk1(!NTUtils::is_a("epics:nt/NTTable:11.0", "epics:nt/NTTable:1.0"));
testOk1(!NTUtils::is_a("epics:nt/NTTable:1.0", "epics:nt/NTMatrix:1.0"));
}
MAIN(testNTUtils) {
testPlan(10);
test_is_a();
return testDone();
}