57 Commits

Author SHA1 Message Date
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
39 changed files with 9328 additions and 813 deletions

8
.hgflow Normal file
View File

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

9
.hgtags Normal file
View File

@@ -0,0 +1,9 @@
b9a943e6828731a8a89e811818b2d91faff69d86 1.0-BETA
aaa5f5840b7eea8afaafb4d13a49bf78975aac0f 4.0.0
aaa5f5840b7eea8afaafb4d13a49bf78975aac0f 4.0.0
df4c65e13c2cfaa92e42f84a7afc97c81b5f3888 4.0.0
df4c65e13c2cfaa92e42f84a7afc97c81b5f3888 4.0.0
ec29bda853f50fa501cbcf3ffd836a1ef2adcdd4 4.0.0
0daade17a7440f970750db4a8388e0cee2d04f17 4.0.1
0daade17a7440f970750db4a8388e0cee2d04f17 4.0.1
1c140dd0e1993ac0a2798e8148b90ccce44ad407 4.0.1

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

@@ -29,3 +29,4 @@ TEMPLATE_TOP=$(EPICS_BASE)/templates/makeBaseApp/top
#SCH2EDIF_PATH=
-include $(TOP)/configure/RELEASE.local
-include $(TOP)/../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

View File

@@ -6,13 +6,23 @@ SRC = $(TOP)/src/
SRC_DIRS += $(SRC)/nt
INC += nt.h
INC += ntutils.h
INC += ntfield.h
INC += ntscalar.h
INC += ntscalarArray.h
INC += ntnameValue.h
INC += nttable.h
INC += ntmultiChannel.h
INC += ntndarray.h
LIBSRCS += ntutils.cpp
LIBSRCS += ntfield.cpp
LIBSRCS += ntscalar.cpp
LIBSRCS += ntscalarArray.cpp
LIBSRCS += ntnameValue.cpp
LIBSRCS += nttable.cpp
LIBSRCS += ntmultiChannel.cpp
LIBSRCS += ntndarray.cpp
LIBRARY=nt

View File

@@ -7,9 +7,16 @@
#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>
#endif /* NT_H */

View File

@@ -6,11 +6,14 @@
*/
#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

@@ -9,29 +9,40 @@
#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 {
#ifdef ntfieldEpicsExportSharedSymbols
# define epicsExportSharedSymbols
# undef ntfieldEpicsExportSharedSymbols
#endif
#include <shareLib.h>
namespace epics { namespace nt {
/**
* Convenience Class for introspection fields of a Normative Type
* @author mrk
*
*/
typedef std::tr1::shared_ptr<epics::pvData::StringArray> StringArrayPtr;
class NTField;
typedef std::tr1::shared_ptr<NTField> NTFieldPtr;
class PVNTField;
typedef std::tr1::shared_ptr<PVNTField> PVNTFieldPtr;
class NTField {
class epicsShareClass NTField {
public:
POINTER_DEFINITIONS(NTField);
/**
@@ -48,88 +59,83 @@ 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;
};
/**
@@ -137,7 +143,7 @@ private:
* @author mrk
*
*/
class PVNTField {
class epicsShareClass PVNTField {
public:
POINTER_DEFINITIONS(PVNTField);
/**
@@ -154,54 +160,54 @@ 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;
};

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

@@ -0,0 +1,281 @@
/* ntmultiChannel.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP 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();
}
StructureConstPtr NTMultiChannelBuilder::createStructure()
{
StandardFieldPtr standardField = getStandardField();
size_t nfields = 3;
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;
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);
names[ind] = "isConnected";
fields[ind++] = fieldCreate->createScalarArray(pvBoolean);
if(timeStamp) {
names[ind] = "timeStamp";
fields[ind++] = standardField->timeStamp();
}
if(alarm) {
names[ind] = "alarm";
fields[ind++] = standardField->alarm();
}
if(descriptor) {
names[ind] = "descriptor";
fields[ind++] = fieldCreate->createScalar(pvString);
}
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);
}
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;
}
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(PVStructurePtr const &pvStructure)
{
if(!pvStructure) return false;
PVUnionArrayPtr pvValue = pvStructure->getSubField<PVUnionArray>("value");
if(!pvValue) return false;
PVFieldPtr pvField = pvStructure->getSubField("descriptor");
if(pvField && !pvStructure->getSubField<PVString>("descriptor")) return false;
pvField = pvStructure->getSubField("alarm");
if(pvField && !ntField->isAlarm(pvField->getField())) return false;
pvField = pvStructure->getSubField("timeStamp");
if(pvField && !ntField->isTimeStamp(pvField->getField())) return false;
pvField = pvStructure->getSubField("severity");
if(pvField && !pvStructure->getSubField<PVIntArray>("severity")) return false;
pvField = pvStructure->getSubField("status");
if(pvField && !pvStructure->getSubField<PVIntArray>("status")) return false;
pvField = pvStructure->getSubField("message");
if(pvField && !pvStructure->getSubField<PVStringArray>("message")) return false;
pvField = pvStructure->getSubField("secondsPastEpoch");
if(pvField && !pvStructure->getSubField<PVLongArray>("secondsPastEpoch")) return false;
pvField = pvStructure->getSubField("nanoseconds");
if(pvField && !pvStructure->getSubField<PVIntArray>("nanoseconds")) return false;
pvField = pvStructure->getSubField("userTag");
if(pvField && !pvStructure->getSubField<PVIntArray>("userTag")) return false;
return true;
}
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"))
{
}
void NTMultiChannel::attachTimeStamp(PVTimeStamp &pv) const
{
if(!pvTimeStamp) return;
pv.attach(pvTimeStamp);
}
void NTMultiChannel::attachAlarm(PVAlarm &pv) const
{
if(!pvAlarm) return;
pv.attach(pvAlarm);
}
}}

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

@@ -0,0 +1,316 @@
/* ntmultiChannel.h */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP 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 {
/**
* Convenience Class for NTMultiChannel
* @author mrk
*
*/
class NTMultiChannel;
typedef std::tr1::shared_ptr<NTMultiChannel> NTMultiChannelPtr;
namespace detail {
/**
* 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 a {@code NTMultiChannelBuilder}.
*/
shared_pointer value(epics::pvData::UnionConstPtr valuePtr);
/**
* Add descriptor field to the NTMultiChannel.
* @return this instance of a {@code NTMultiChannelBuilder}.
*/
shared_pointer addDescriptor();
/**
* Add alarm structure to the NTMultiChannel.
* @return this instance of a {@code NTMultiChannelBuilder}.
*/
shared_pointer addAlarm();
/**
* Add timeStamp structure to the NTMultiChannel.
* @return this instance of a {@code NTMultiChannelBuilder}.
*/
shared_pointer addTimeStamp();
/**
* Add severity array to the NTMultiChannel.
* @return this instance of a {@code NTMultiChannelBuilder}.
*/
shared_pointer addSeverity();
/**
* Add status array to the NTMultiChannel.
* @return this instance of a {@code NTMultiChannelBuilder}.
*/
shared_pointer addStatus();
/**
* Add message array to the NTMultiChannel.
* @return this instance of a {@code NTMultiChannelBuilder}.
*/
shared_pointer addMessage();
/**
* Add secondsPastEpoch array to the NTMultiChannel.
* @return this instance of a {@code NTMultiChannelBuilder}.
*/
shared_pointer addSecondsPastEpoch();
/**
* Add nanoseconds array to the NTMultiChannel.
* @return this instance of a {@code NTMultiChannelBuilder}.
*/
shared_pointer addNanoseconds();
/**
* Add userTag array to the NTMultiChannel.
* @return this instance of a {@code NTMultiChannelBuilder}.
*/
shared_pointer addUserTag();
/**
* Create a {@code Structure} that represents NTMultiChannel.
* This resets this instance state and allows new instance to be created.
* @return a new instance of a {@code Structure}.
*/
epics::pvData::StructureConstPtr createStructure();
/**
* Create a {@code PVStructure} that represents NTMultiChannel.
* This resets this instance state and allows new {@code instance to be created.}
* @return a new instance of a {@code PVStructure}
*/
epics::pvData::PVStructurePtr createPVStructure();
/**
* Create a {@code NTMultiChannel} instance.
* This resets this instance state and allows new {@code instance to be created.}
* @return a new instance of a {@code NTMultiChannel}
*/
NTMultiChannelPtr create();
/**
* Add extra {@code Field} to the type.
* @param name name of the field.
* @param field a field to add.
* @return this instance of a {@code NTMultiChannelBuilder}.
*/
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;
// 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;
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.
* This method structure->getID() and checks if it is the same as the URI.
* @param structure The structure to test.
* @return (false,true) if (is not, is) an NTMultiChannel.
*/
static bool is_a(
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);
/**
* 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
*/
void attachTimeStamp(epics::pvData::PVTimeStamp &pvTimeStamp) const;
/**
* Attach a pvAlarm.
* @param pvAlarm The pvAlarm that will be attached.
* Does nothing if no alarm
*/
void 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

@@ -5,106 +5,201 @@
* 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(PVStructurePtr const & pvStructure)
{
if(!pvStructure) return false;
PVStringArrayPtr pvName = pvStructure->getSubField<PVStringArray>("name");
if(!pvName) return false;
PVFieldPtr pvValue = pvStructure->getSubField("value");
if(!pvValue) return false;
PVFieldPtr pvField = pvStructure->getSubField("descriptor");
if(pvField && !pvStructure->getSubField<PVString>("descriptor")) return false;
pvField = pvStructure->getSubField("alarm");
if(pvField && !ntField->isAlarm(pvField->getField())) return false;
pvField = pvStructure->getSubField("timeStamp");
if(pvField && !ntField->isTimeStamp(pvField->getField())) return false;
return true;
}
NTNameValuePtr NTNameValue::create(
bool hasFunction,bool hasTimeStamp, bool hasAlarm)
NTNameValueBuilderPtr NTNameValue::createBuilder()
{
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));
return NTNameValueBuilderPtr(new detail::NTNameValueBuilder());
}
NTNameValuePtr NTNameValue::create(
PVStructurePtr const & pvStructure)
bool NTNameValue::attachTimeStamp(PVTimeStamp &pvTimeStamp) const
{
return NTNameValuePtr(new NTNameValue(pvStructure));
PVStructurePtr ts = getTimeStamp();
if (ts)
return pvTimeStamp.attach(ts);
else
return false;
}
NTNameValue::NTNameValue(PVStructure::shared_pointer const & pvStructure)
: pvNTNameValue(pvStructure)
bool NTNameValue::attachAlarm(PVAlarm &pvAlarm) const
{
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);
}
PVStructurePtr al = getAlarm();
if (al)
return pvAlarm.attach(al);
else
return false;
}
void NTNameValue::attachTimeStamp(PVTimeStamp &pv)
PVStructurePtr NTNameValue::getPVStructure() const
{
if(pvTimeStamp.get()==NULL) return;
pv.attach(pvTimeStamp);
return pvNTNameValue;
}
void NTNameValue::attachAlarm(PVAlarm &pv)
PVStringPtr NTNameValue::getDescriptor() const
{
if(pvAlarm.get()==NULL) return;
pv.attach(pvAlarm);
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

@@ -7,94 +7,244 @@
#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 {
/**
* 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 {@code Scalar} type.
* @param scalarType value array scalar array.
* @return this instance of a {@code NTTableBuilder}.
*/
shared_pointer value(epics::pvData::ScalarType scalarType);
/**
* Add descriptor field to the NTNameValue.
* @return this instance of a {@code NTNameValueBuilder}.
*/
shared_pointer addDescriptor();
/**
* Add alarm structure to the NTNameValue.
* @return this instance of a {@code NTNameValueBuilder}.
*/
shared_pointer addAlarm();
/**
* Add timeStamp structure to the NTNameValue.
* @return this instance of a {@code NTNameValueBuilder}.
*/
shared_pointer addTimeStamp();
/**
* Create a {@code Structure} that represents NTNameValue.
* This resets this instance state and allows new instance to be created.
* @return a new instance of a {@code Structure}.
*/
epics::pvData::StructureConstPtr createStructure();
/**
* Create a {@code PVStructure} that represents NTNameValue.
* This resets this instance state and allows new {@code instance to be created.
* @return a new instance of a {@code PVStructure}
*/
epics::pvData::PVStructurePtr createPVStructure();
/**
* Create a {@code NTNameValue} instance.
* This resets this instance state and allows new {@code instance to be created.
* @return a new instance of a {@code NTNameValue}
*/
NTNameValuePtr create();
/**
* Add extra {@code Field} to the type.
* @param name name of the field.
* @param field a field to add.
* @return this instance of a {@code NTNameValueBuilder}.
*/
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;
/**
* 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 NTMultiChannel 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 pvStructure compatible with NTNameValue..
* This method introspects the fields to see if they are compatible.
* @param pvStructure The pvStructure to test.
* @return (false,true) if (is not, is) an NTMultiChannel.
*/
static NTNameValuePtr create(
bool hasFunction,bool hasTimeStamp, bool hasAlarm);
static NTNameValuePtr create(
PVStructurePtr const & pvStructure);
static bool isCompatible(
epics::pvData::PVStructurePtr const &pvStructure);
/**
* Destructor
* 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;
};
}}

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

@@ -0,0 +1,354 @@
/* ntndarray.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP 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/ntutils.h>
using namespace std;
using namespace epics::pvData;
namespace epics { namespace nt {
static NTFieldPtr ntField = NTField::get();
namespace detail {
const std::string ntAttrStr("epics:nt/NTAttribute:1.0");
static FieldCreatePtr fieldCreate = getFieldCreate();
static PVDataCreatePtr pvDataCreate = getPVDataCreate();
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;
static StructureConstPtr ntndarrayStruc[NUMBER_OF_STRUCTURES];
static UnionConstPtr valueType;
static StructureConstPtr codecStruc;
static StructureConstPtr dimensionStruc;
static StructureConstPtr attributeStruc;
static Mutex mutex;
Lock xx(mutex);
StructureConstPtr returnedStruc;
size_t index = 0;
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 = fb->setId(ntAttrStr)->
add("name", pvString)->
add("value", fieldCreate->createVariantUnion())->
add("descriptor", pvString)->
add("sourceType", pvInt)->
add("source", pvString)->
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 (timeStamp)
fb->add("timeStamp", standardField->timeStamp());
if (alarm)
fb->add("alarm", standardField->alarm());
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();
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(PVStructurePtr const & pvStructure)
{
if(!pvStructure) return false;
PVUnionPtr pvValue = pvStructure->getSubField<PVUnion>("value");
if(!pvValue) return false;
PVFieldPtr pvField = pvStructure->getSubField("descriptor");
if(pvField && !pvStructure->getSubField<PVString>("descriptor")) return false;
pvField = pvStructure->getSubField("alarm");
if(pvField && !ntField->isAlarm(pvField->getField())) return false;
pvField = pvStructure->getSubField("timeStamp");
if(pvField && !ntField->isTimeStamp(pvField->getField())) return false;
pvField = pvStructure->getSubField("display");
if(pvField && !ntField->isDisplay(pvField->getField())) return false;
if(!pvStructure->getSubField<PVLong>("compressedSize")) return false;
if(!pvStructure->getSubField<PVLong>("uncompressedSize")) return false;
PVStructurePtr pvCodec = pvStructure->getSubField<PVStructure>("codec");
if(!pvCodec) return false;
if(!pvCodec->getSubField<PVString>("name")) return false;
if(!pvCodec->getSubField<PVUnion>("parameters")) return false;
PVStructureArrayPtr pvDimension = pvStructure->getSubField<PVStructureArray>("dimension");
if(pvDimension->getStructureArray()->getStructure()->getID().compare("dimension_t")!=0) return false;
if(!pvStructure->getSubField<PVInt>("uniqueId")) return false;
pvField = pvStructure->getSubField("dataTimeStamp");
if(pvField && !ntField->isTimeStamp(pvField->getField())) return false;
PVStructureArrayPtr pvAttribute = pvStructure->getSubField<PVStructureArray>("attribute");
if(pvAttribute->getStructureArray()->getStructure()->getID().compare(ntAttrStr)!=0) return false;
return true;
}
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::getAttribute() const
{
return pvNTNDArray->getSubField<PVStructureArray>("attribute");
}
PVStructureArrayPtr NTNDArray::getDimension() const
{
return pvNTNDArray->getSubField<PVStructureArray>("dimension");
}
PVStructurePtr NTNDArray::getDataTimeStamp() const
{
return pvNTNDArray->getSubField<PVStructure>("dataTimeStamp");
}
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)
{}
}}

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

@@ -0,0 +1,286 @@
/* ntndarray.h */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP 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 {
/**
* 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 a {@code NTNDArrayBuilder}.
*/
shared_pointer addDescriptor();
/**
* Add alarm structure to the NTNDArray.
* @return this instance of a {@code NTNDArrayBuilder}.
*/
shared_pointer addAlarm();
/**
* Add timeStamp structure to the NTNDArray.
* @return this instance of a {@code NTNDArrayBuilder}.
*/
shared_pointer addTimeStamp();
/**
* Add display structure to the NTNDArray.
* @return this instance of a {@code NTNDArrayBuilder}.
*/
shared_pointer addDisplay();
/**
* Create a {@code Structure} that represents NTNDArray.
* This resets this instance state and allows new instance to be created.
* @return a new instance of a {@code Structure}.
*/
epics::pvData::StructureConstPtr createStructure();
/**
* Create a {@code PVStructure} that represents NTNDArray.
* This resets this instance state and allows new {@code instance to be created.
* @return a new instance of a {@code PVStructure}
*/
epics::pvData::PVStructurePtr createPVStructure();
/**
* Create a {@code NTNDArray} instance.
* This resets this instance state and allows new {@code instance to be created.
* @return a new instance of a {@code NTNDArray}
*/
NTNDArrayPtr create();
/**
* Add extra {@code Field} to the type.
* @param name name of the field.
* @param field a field to add.
* @return this instance of a {@code NTArrayBuilder}.
*/
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;
/**
* 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 NTMultiChannel 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 pvStructure compatible with NTNDArray..
* This method introspects the fields to see if they are compatible.
* @param pvStructure The pvStructure to test.
* @return (false,true) if (is not, is) an NTMultiChannel.
*/
static bool isCompatible(
epics::pvData::PVStructurePtr const &pvStructure);
/**
* 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 attribute field.
* @return the PVStructurePtr.
*/
epics::pvData::PVStructureArrayPtr getAttribute() 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 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::PVStructurePtr pvNTNDArray;
friend class detail::NTNDArrayBuilder;
};
}}
#endif /* NTNDARRAY_H */

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

@@ -0,0 +1,250 @@
/* ntscalar.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP 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 {
static NTFieldPtr ntField = NTField::get();
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(PVStructurePtr const & pvStructure)
{
if(!pvStructure) return false;
PVScalarPtr pvValue = pvStructure->getSubField<PVScalar>("value");
if(!pvValue) return false;
PVFieldPtr pvField = pvStructure->getSubField("descriptor");
if(pvField && !pvStructure->getSubField<PVString>("descriptor")) return false;
pvField = pvStructure->getSubField("alarm");
if(pvField && !ntField->isAlarm(pvField->getField())) return false;
pvField = pvStructure->getSubField("timeStamp");
if(pvField && !ntField->isTimeStamp(pvField->getField())) return false;
pvField = pvStructure->getSubField("display");
if(pvField && !ntField->isDisplay(pvField->getField())) return false;
pvField = pvStructure->getSubField("control");
if(pvField && !ntField->isControl(pvField->getField())) return false;
return 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"))
{}
}}

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

@@ -0,0 +1,284 @@
/* ntscalar.h */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP 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 {
/**
* 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 a {@code NTTableBuilder}.
*/
shared_pointer value(epics::pvData::ScalarType scalarType);
/**
* Add descriptor field to the NTScalar.
* @return this instance of a {@code NTScalarBuilder}.
*/
shared_pointer addDescriptor();
/**
* Add alarm structure to the NTScalar.
* @return this instance of a {@code NTScalarBuilder}.
*/
shared_pointer addAlarm();
/**
* Add timeStamp structure to the NTScalar.
* @return this instance of a {@code NTScalarBuilder}.
*/
shared_pointer addTimeStamp();
/**
* Add display structure to the NTScalar.
* @return this instance of a {@code NTScalarBuilder}.
*/
shared_pointer addDisplay();
/**
* Add control structure to the NTScalar.
* @return this instance of a {@code NTScalarBuilder}.
*/
shared_pointer addControl();
/**
* Create a {@code Structure} that represents NTScalar.
* This resets this instance state and allows new instance to be created.
* @return a new instance of a {@code Structure}.
*/
epics::pvData::StructureConstPtr createStructure();
/**
* Create a {@code PVStructure} that represents NTScalar.
* This resets this instance state and allows new {@code instance to be created.
* @return a new instance of a {@code PVStructure}
*/
epics::pvData::PVStructurePtr createPVStructure();
/**
* Create a {@code NTScalar} instance.
* This resets this instance state and allows new {@code instance to be created.
* @return a new instance of a {@code NTScalar}
*/
NTScalarPtr create();
/**
* Add extra {@code Field} to the type.
* @param name name of the field.
* @param field a field to add.
* @return this instance of a {@code NTScalarBuilder}.
*/
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;
/**
* 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 pvStructure compatible with NTScalar.
* This method introspects the fields to see if they are compatible.
* @param pvStructure The pvStructure to test.
* @return (false,true) if (is not, is) an NTMultiChannel.
*/
static bool isCompatible(
epics::pvData::PVStructurePtr const &pvStructure);
/**
* 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 */

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

@@ -0,0 +1,248 @@
/* ntscalarArray.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP 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(PVStructurePtr const & pvStructure)
{
if(!pvStructure) return false;
PVScalarArrayPtr pvValue = pvStructure->getSubField<PVScalarArray>("value");
if(!pvValue) return false;
PVFieldPtr pvField = pvStructure->getSubField("descriptor");
if(pvField && !pvStructure->getSubField<PVString>("descriptor")) return false;
pvField = pvStructure->getSubField("alarm");
if(pvField && !ntField->isAlarm(pvField->getField())) return false;
pvField = pvStructure->getSubField("timeStamp");
if(pvField && !ntField->isTimeStamp(pvField->getField())) return false;
pvField = pvStructure->getSubField("display");
if(pvField && !ntField->isDisplay(pvField->getField())) return false;
pvField = pvStructure->getSubField("control");
if(pvField && !ntField->isControl(pvField->getField())) return false;
return true;
}
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"))
{}
}}

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

@@ -0,0 +1,287 @@
/* ntscalarArray.h */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP 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 {
/**
* 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 a {@code NTTableBuilder}.
*/
shared_pointer arrayValue(epics::pvData::ScalarType elementType);
/**
* Add descriptor field to the NTScalarArray.
* @return this instance of a {@code NTScalarArrayBuilder}.
*/
shared_pointer addDescriptor();
/**
* Add alarm structure to the NTScalarArray.
* @return this instance of a {@code NTScalarArrayBuilder}.
*/
shared_pointer addAlarm();
/**
* Add timeStamp structure to the NTScalarArray.
* @return this instance of a {@code NTScalarArrayBuilder}.
*/
shared_pointer addTimeStamp();
/**
* Add display structure to the NTScalarArray.
* @return this instance of a {@code NTScalarArrayBuilder}.
*/
shared_pointer addDisplay();
/**
* Add control structure to the NTScalarArray.
* @return this instance of a {@code NTScalarArrayBuilder}.
*/
shared_pointer addControl();
/**
* Create a {@code Structure} that represents NTScalarArray.
* This resets this instance state and allows new instance to be created.
* @return a new instance of a {@code Structure}.
*/
epics::pvData::StructureConstPtr createStructure();
/**
* Create a {@code PVStructure} that represents NTScalarArray.
* This resets this instance state and allows new {@code instance to be created.
* @return a new instance of a {@code PVStructure}
*/
epics::pvData::PVStructurePtr createPVStructure();
/**
* Create a {@code NTScalarArray} instance.
* This resets this instance state and allows new {@code instance to be created.
* @return a new instance of a {@code NTScalarArray}
*/
NTScalarArrayPtr create();
/**
* Add extra {@code Field} to the type.
* @param name name of the field.
* @param field a field to add.
* @return this instance of a {@code NTScalarArrayBuilder}.
*/
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;
/**
* 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 NTMultiChannel without checking for isCompatible
* @param structure The structure to wrap-ed (dynamic cast, wrapped) to NTScalarArray.
* @return NTScalarArray instance.
*/
static shared_pointer wrapUnsafe(epics::pvData::PVStructurePtr const & structure);
/**
* Is the structure an NTScalarArray.
* @param structure The structure to test.
* @return (false,true) if (is not, is) an NTScalarArray.
*/
static bool is_a(epics::pvData::StructureConstPtr const & structure);
/**
* Is the pvStructure compatible with NTScalarArray..
* 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);
/**
* 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

@@ -5,147 +5,212 @@
* 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::add(
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++;
if (std::find(labels.begin(), labels.end(), name) != labels.end())
throw std::runtime_error("duplicate column name");
labels.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 = labels.size();
for (vector<string>::size_type i = 0; i < len; i++)
nestedBuilder->addArray(labels[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());
StructureConstPtr s = builder->createStructure();
size_t extraCount = extraFieldNames.size();
for (size_t i = 0; i< extraCount; i++)
builder->add(extraFieldNames[i], extraFields[i]);
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()
{
size_t len = labels.size();
shared_vector<string> l(len);
for(size_t i=0; i<len; ++i) l[i] = labels[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()
{
labels.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(PVStructurePtr const & pvStructure)
{
if(!pvStructure) return false;
PVFieldPtr pvField = pvStructure->getSubField("alarm");
if(pvField && !ntField->isAlarm(pvField->getField())) return false;
pvField = pvStructure->getSubField("timeStamp");
if(pvField!=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)) {
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;
}
if(pvField && !ntField->isTimeStamp(pvField->getField())) return false;
PVStringArrayPtr pvLabel = pvStructure->getSubField<PVStringArray>("labels");
if(!pvLabel) return false;
return true;
}
NTTablePtr NTTable::create(
bool hasFunction,bool hasTimeStamp, bool hasAlarm,
StringArray const & valueNames,
FieldConstPtrArray const &valueFields)
NTTableBuilderPtr NTTable::createBuilder()
{
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(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 NTTableBuilderPtr(new detail::NTTableBuilder());
}
NTTablePtr NTTable::clone(PVStructurePtr const & pv)
bool NTTable::attachTimeStamp(PVTimeStamp &pvTimeStamp) const
{
PVStructurePtr pvStructure = getPVDataCreate()->createPVStructure(pv);
return NTTablePtr(new NTTable(pvStructure));
PVStructurePtr ts = getTimeStamp();
if (ts)
return pvTimeStamp.attach(ts);
else
return false;
}
NTTable::NTTable(PVStructurePtr const & pvStructure)
: pvNTTable(pvStructure),
offsetFields(1)
bool NTTable::attachAlarm(PVAlarm &pvAlarm) 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 al = getAlarm();
if (al)
return pvAlarm.attach(al);
else
return false;
}
void NTTable::attachTimeStamp(PVTimeStamp &pv)
PVStructurePtr NTTable::getPVStructure() const
{
if(pvTimeStamp.get()==NULL) return;
pv.attach(pvTimeStamp);
return pvNTTable;
}
void NTTable::attachAlarm(PVAlarm &pv)
PVStringPtr NTTable::getDescriptor() const
{
if(pvAlarm.get()==NULL) return;
pv.attach(pvAlarm);
return pvNTTable->getSubField<PVString>("descriptor");
}
size_t NTTable::getNumberValues()
PVStructurePtr NTTable::getTimeStamp() const
{
return pvLabel->getLength();
return pvNTTable->getSubField<PVStructure>("timeStamp");
}
FieldConstPtr NTTable::getField(size_t index)
PVStructurePtr NTTable::getAlarm() const
{
FieldConstPtrArray fields = pvNTTable->getStructure()->getFields();
return fields[index + offsetFields];
return pvNTTable->getSubField<PVStructure>("alarm");
}
PVFieldPtr NTTable::getPVField(size_t index)
PVStringArrayPtr NTTable::getLabels() const
{
PVFieldPtrArray pvFields = pvNTTable->getPVFields();
return pvFields[index+offsetFields];
return pvNTTable->getSubField<PVStringArray>("labels");
}
PVFieldPtr NTTable::getColumn(std::string const & columnName) const
{
return pvNTTable->getSubField("value." + columnName);
}
NTTable::NTTable(PVStructurePtr const & pvStructure) :
pvNTTable(pvStructure)
{}
}}

View File

@@ -7,109 +7,249 @@
#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 {
/**
* 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 {@code Scalar} type.
* @param name name of the column.
* @param elementType column type, a scalar array.
* @return this instance of a {@code NTTableBuilder}.
*/
shared_pointer add(std::string const & name, epics::pvData::ScalarType elememtType);
/**
* Add descriptor field to the NTTable.
* @return this instance of a {@code NTTableBuilder}.
*/
shared_pointer addDescriptor();
/**
* Add alarm structure to the NTTable.
* @return this instance of a {@code NTTableBuilder}.
*/
shared_pointer addAlarm();
/**
* Add timeStamp structure to the NTTable.
* @return this instance of a {@code NTTableBuilder}.
*/
shared_pointer addTimeStamp();
/**
* Create a {@code Structure} that represents NTTable.
* This resets this instance state and allows new instance to be created.
* @return a new instance of a {@code Structure}.
*/
epics::pvData::StructureConstPtr createStructure();
/**
* Create a {@code PVStructure} that represents NTTable.
* This resets this instance state and allows new {@code instance to be created.
* @return a new instance of a {@code PVStructure}
*/
epics::pvData::PVStructurePtr createPVStructure();
/**
* Create a {@code NTTable} instance.
* This resets this instance state and allows new {@code instance to be created.
* @return a new instance of a {@code NTTable}
*/
NTTablePtr create();
/**
* Add extra {@code Field} to the type.
* @param name name of the field.
* @param field a field to add.
* @return this instance of a {@code NTTableBuilder}.
*/
shared_pointer add(std::string const & name, epics::pvData::FieldConstPtr const & field);
private:
NTTableBuilder();
void reset();
std::vector<std::string> labels;
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;
/**
* Convenience Class for NTTable
* @author mrk
*/
class epicsShareClass NTTable
{
public:
POINTER_DEFINITIONS(NTTable);
static const std::string URI;
/**
* Is the pvStructure an NTTable.
* 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 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 NTTable.
* @return NTTable instance.
*/
static shared_pointer wrapUnsafe(epics::pvData::PVStructurePtr const & structure);
/**
* 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 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 NTNameValuePair.
* @return (false,true) if (is not, is) an NTMultiChannel.
*/
static bool isNTTable(PVStructurePtr const &pvStructure);
static bool isCompatible(
epics::pvData::PVStructurePtr const &pvStructure);
/**
* 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
* Create a NTTable builder instance.
* @return builder instance.
*/
static NTTablePtr create(
bool hasFunction,bool hasTimeStamp, bool hasAlarm,
StringArray const & valueNames,
FieldConstPtrArray const &valueFields);
static NTTablePtr clone(PVStructurePtr const &);
static NTTableBuilderPtr createBuilder();
/**
* Destructor
* 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.
*/
size_t getNumberValues();
/**
* 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;
friend class detail::NTTableBuilder;
};
}}

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

@@ -0,0 +1,25 @@
/* ntutils.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP 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 u2
size_t pos = u2.find_last_of('.');
std::string su2 = (pos == string::npos) ? u2 : u2.substr(0, pos);
// "starts with comparison"
return su2.size() <= u1.size() && u1.compare(0, su2.size(), su2) == 0;
}
}}

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

@@ -0,0 +1,39 @@
/* ntutils.h */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP 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 {
/**
* 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,41 @@ 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 += nttableTest
nttableTest_SRCS = nttableTest.cpp
TESTS += nttableTest
TESTPROD_HOST += ntndarrayTest
ntndarrayTest_SRCS = ntndarrayTest.cpp
TESTS += ntndarrayTest
TESTPROD_HOST += ntutilsTest
ntutilsTest_SRCS = ntutilsTest.cpp
TESTS += ntutilsTest
TESTSCRIPTS_HOST += $(TESTS:%=%.t)
include $(TOP)/configure/RULES
#----------------------------------------

View File

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

View File

@@ -0,0 +1,192 @@
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP 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() ->
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() ->
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

@@ -3,85 +3,254 @@
* EPICS pvDataCPP 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();
}

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

@@ -0,0 +1,125 @@
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP 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.
* EPICS pvDataCPP 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();
}

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

@@ -0,0 +1,236 @@
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP 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

@@ -3,105 +3,243 @@
* EPICS pvDataCPP 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->
add("column0", pvDouble)->
add("column1", pvString)->
add("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() == 5);
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);
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->
add("column0", pvDouble)->
add("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->
add("column0", pvDouble)->
add("column1", pvString)->
add("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->
add("column0", pvDouble)->
add("column1", pvString)->
add("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->
add("column0", pvDouble)->
add("column1", pvString)->
add("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(46);
test_builder();
test_labels();
test_nttable();
test_wrap();
return testDone();
}

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

@@ -0,0 +1,36 @@
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP 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/NTMatrix:1.0"));
}
MAIN(testNTUtils) {
testPlan(8);
test_is_a();
return testDone();
}