completed merge
This commit is contained in:
17
.hgignore
17
.hgignore
@@ -1,11 +1,12 @@
|
||||
^QtC-
|
||||
^bin/
|
||||
^lib/
|
||||
^doc/
|
||||
^include/
|
||||
^db/
|
||||
^dbd/
|
||||
^documentation/html
|
||||
QtC-
|
||||
bin/
|
||||
lib/
|
||||
doc/
|
||||
include/
|
||||
db/
|
||||
dbd/
|
||||
documentation/html
|
||||
documentation/*.tag
|
||||
envPaths
|
||||
configure/.*\.local
|
||||
/O\..*
|
||||
|
||||
47
documentation/RELEASE_NOTES.md
Normal file
47
documentation/RELEASE_NOTES.md
Normal file
@@ -0,0 +1,47 @@
|
||||
Release release/3.1 IN DEVELOPMENT
|
||||
===========
|
||||
|
||||
The main changes since release 3.0.2 are:
|
||||
|
||||
* array semantics now enforce Copy On Write.
|
||||
* union is new type.
|
||||
* copy is new.
|
||||
* monitorPlugin is new.
|
||||
|
||||
New Semantics for Arrays
|
||||
--------
|
||||
|
||||
PVScalarArray, PVStructureArray, and PVUnionArray all enforce COW (Copy On Write) Semantics.
|
||||
In order to limit memory usage the storage for raw data is managed via a new shared_vector facility.
|
||||
This allows multiple instances of array data to use the shared raw data.
|
||||
COW is implemented via shared_vectors of const data, i. e. data that can not be modified.
|
||||
|
||||
union is a new basic type.
|
||||
------------
|
||||
|
||||
There are two new basic types: union_t and unionArray.
|
||||
|
||||
A union is like a structure that has a single subfield.
|
||||
There are two flavors:
|
||||
|
||||
* <b>varient union</b> The field can have any type.
|
||||
* <b>union</b> The field can any of specified set of types.
|
||||
|
||||
The field type can be dynamically changed.
|
||||
|
||||
copy
|
||||
----
|
||||
|
||||
This consists of createRequest and pvCopy.
|
||||
createRequest was moved from pvAccess to here.
|
||||
pvCopy is moved from pvDatabaseCPP and now depends
|
||||
only on pvData, i. e. it no longer has any knowledge of PVRecord.
|
||||
|
||||
monitorPlugin
|
||||
-------------
|
||||
|
||||
This is for is for use by code that implements pvAccess monitors.
|
||||
|
||||
Release 3.0.2
|
||||
==========
|
||||
This was the starting point for RELEASE_NOTES
|
||||
54
documentation/TODO.md
Normal file
54
documentation/TODO.md
Normal file
@@ -0,0 +1,54 @@
|
||||
TODO
|
||||
===========
|
||||
|
||||
toString, dumpValue, printer, and streams
|
||||
------------
|
||||
|
||||
The way to print introspection and data instances is not consistent.
|
||||
This needs work.
|
||||
Some items that need work are:
|
||||
|
||||
* Introspection has no support for streams. Only for toString.
|
||||
* data has problems. toString is implemented by calling Convert::getString.
|
||||
It look like this was intended to use printer but that did nor properly indent fields of structures.
|
||||
|
||||
The current implementation is:
|
||||
|
||||
void Convert::getString(StringBuilder buf,PVField const *pvField,int /*indentLevel*/)
|
||||
{
|
||||
// TODO indextLevel ignored
|
||||
std::ostringstream strm;
|
||||
strm << pvField->dumpValue(strm) << std::endl;
|
||||
// PrinterPlain p;
|
||||
// p.setStream(strm);
|
||||
// p.print(*pvField);
|
||||
strm.str().swap(*buf);
|
||||
}
|
||||
|
||||
Thus it just uses dumpValue.
|
||||
What should it do?
|
||||
If printer is used it must do proper indentation.
|
||||
|
||||
doxygen
|
||||
-------
|
||||
|
||||
There is a lot of public code that does not have doxygen tags.
|
||||
|
||||
|
||||
monitorPlugin
|
||||
-------------
|
||||
|
||||
A debate is on-going about what semantics should be.
|
||||
|
||||
PVFieldConstPtr etc
|
||||
-------------------
|
||||
|
||||
In pvDataCPP.html look at the monoitorPlugin example.
|
||||
It has a discussion of a possible need for shared pointers that can not be used to modify data.
|
||||
This in addition to PVFieldPtr should PVFieldConstPtr exist.
|
||||
But this means that all methods defined in pvDataCPP must be checked.
|
||||
This is a BIG job.
|
||||
|
||||
Release 3.0.2
|
||||
==========
|
||||
This was the starting point for RELEASE_NOTES
|
||||
679
documentation/copyandmonitor.html
Normal file
679
documentation/copyandmonitor.html
Normal file
@@ -0,0 +1,679 @@
|
||||
<?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: copy and monitor</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 id="toc">
|
||||
<h2 class="nocount" style="page-break-before: always">Table of Contents</h2>
|
||||
</div>
|
||||
<div id="contents" class="contents">
|
||||
|
||||
<h2>support for copy and monitor</h2>
|
||||
<p><b>copy</b> and <b>monitor</b> are not used in this project.
|
||||
They are intended for use by pvAccess and by pvAccess servers.
|
||||
They are provided with this project because the code depends only on
|
||||
pvData itself.
|
||||
</p>
|
||||
<p>This document describes C++ specific code.
|
||||
<a href="http://epics-pvdata.sourceforge.net/informative/pvRequest.html">
|
||||
pvRequest.html</a>
|
||||
provides a language independent overview of <b>copy</b> and <b>monitor</b>.
|
||||
</p>
|
||||
<p>
|
||||
<b>NOTE:pvRequest.html</b> must be updated since it is based on an earlier version of pvCopy that
|
||||
had knowlege of PVRecord. The C++ version was implemented in pvDatabaseCPP
|
||||
and the Java version on pvIOCJava.
|
||||
At present only the C++ version of the new API for pvCopy is implemented.
|
||||
</p>
|
||||
<p>Copy provides:
|
||||
<dl>
|
||||
<dt>createRequest</dt>
|
||||
<dd>
|
||||
The Channel create methods in pvAccess all have an argument
|
||||
<b>PVStructure pvRequest</b>.<br />
|
||||
Given an ascii string createRequest creates a PVStructure that provides
|
||||
a pvData representation of the information from the ascii string.
|
||||
It is this structure that can be passed to the channel create methods.<br />
|
||||
The information in a pvRequest selects an arbitrarary subset of the
|
||||
fields in a top level structure that resides in the server.
|
||||
In addition options can be specified. Both global and field specific
|
||||
options can be specified.
|
||||
</dd>
|
||||
<dt>pvCopy</dt>
|
||||
<dd>This is a faculity used by channel providers.
|
||||
It provides client specific code that manages a copy of an arbitrary
|
||||
subset of the fields in a top level structure that resides in the
|
||||
provider. It also allows provider access to options specified
|
||||
by the client.
|
||||
</dd>
|
||||
</dl>
|
||||
Monitor provides:
|
||||
<dl>
|
||||
<dt>monitor</dt>
|
||||
<dd>This is support code for channel providers that implement channel
|
||||
monitor. It, together with the queue facility, provides support for
|
||||
monitor queues.
|
||||
</dd>
|
||||
<dt>monitorPlugin</dt>
|
||||
<dd>This is support for implementing monitor plugins.
|
||||
A monitor plugin can be developed that has no knowledge
|
||||
of pvAccess but only pvData.
|
||||
</dd>
|
||||
</dl>
|
||||
</p>
|
||||
|
||||
<h2>support for copy</h2>
|
||||
<p><b>copy</b> provides the ability to create a structure that has
|
||||
a copy of an arbitrary subset of the fields in an existing top level
|
||||
structure. In addition it allows global options and field specific options.
|
||||
It has two main components: <b>createRequest</b> and <b>pvCopy</b>.
|
||||
Given a string createRequest creates a pvRequest, which is a PVStructure
|
||||
that has the format expected by <b>pvCopy</b>.
|
||||
</p>
|
||||
|
||||
<h3>createRequest</h3>
|
||||
<p>This is mainly used by pvAccess clients. Given a request string it creates
|
||||
a pvRequest structure that can be passed to the pvAccess create methods.
|
||||
In turn pvAccess passes the pvRequest to a local channel provider which
|
||||
then passes it to pvCopy.
|
||||
</p>
|
||||
<p>The definition of the public members is:</p>
|
||||
<pre>
|
||||
class CreateRequest {
|
||||
...
|
||||
static CreateRequestPtr create();
|
||||
virtual PVStructurePtr createRequest(String const &request);
|
||||
String getMessage();
|
||||
};
|
||||
</pre>
|
||||
<p>An example of how it is used is:</p>
|
||||
<pre>
|
||||
CreateRequestPtr createRequest = CreateRequest::create();
|
||||
PVStructurePtr pvRequest = createRequest->createRequest(request);
|
||||
if(pvRequest==NULL) {
|
||||
String error = createRequest->getMessage();
|
||||
// take some action
|
||||
} else {
|
||||
//success do something
|
||||
}
|
||||
</pre>
|
||||
<h3>pvCopy</h3>
|
||||
<p>The definition of the public members is:</p>
|
||||
<pre>
|
||||
class epicsShareClass PVCopyTraverseMasterCallback
|
||||
{
|
||||
...
|
||||
virtual void nextMasterPVField(PVFieldPtr const &pvField);
|
||||
};
|
||||
|
||||
class class epicsShareClass PVCopy
|
||||
{
|
||||
...
|
||||
static PVCopyPtr create(
|
||||
PVStructurePtr const &pvMaster,
|
||||
PVStructurePtr const &pvRequest,
|
||||
String const & structureName);
|
||||
PVStructurePtr getPVMaster();
|
||||
void traverseMaster(PVCopyTraverseMasterCallbackPtr const & callback);
|
||||
StructureConstPtr getStructure();
|
||||
PVStructurePtr createPVStructure();
|
||||
size_t getCopyOffset(PVFieldPtr const &masterPVField);
|
||||
size_t getCopyOffset(
|
||||
PVStructurePtr const &masterPVStructure,
|
||||
PVFieldPtr const &masterPVField);
|
||||
PVFieldPtr getMasterPVField(std::size_t structureOffset);
|
||||
void initCopy(
|
||||
PVStructurePtr const &copyPVStructure,
|
||||
BitSetPtr const &bitSet);
|
||||
void updateCopySetBitSet(
|
||||
PVStructurePtr const &copyPVStructure,
|
||||
BitSetPtr const &bitSet);
|
||||
void updateCopyFromBitSet(
|
||||
PVStructurePtr const &copyPVStructure,
|
||||
BitSetPtr const &bitSet);
|
||||
void updateMaster(
|
||||
PVStructurePtr const &copyPVStructure,
|
||||
BitSetPtr const &bitSet);
|
||||
PVStructurePtr getOptions(std::size_t fieldOffset);
|
||||
...
|
||||
};
|
||||
</pre>
|
||||
where
|
||||
<dl>
|
||||
<dt>PVCopyTraverseMasterCallback::nextMasterPVField</dt>
|
||||
<dd>
|
||||
<b>PVCopyTraverseMasterCallback</b> is a callback which must
|
||||
be implemented by the code that uses pvCopy, normally
|
||||
the channel provider. It has the single method <b>nextMasterPVField</b>
|
||||
<br />
|
||||
<b>nextMasterPVField</b> is called for each field in the master
|
||||
as a result of a call to <b>traverseMaster</b>.
|
||||
</dd>
|
||||
<dt>create</dt>
|
||||
<dd>
|
||||
This is the method for creating a PVCopy instance.<br/>
|
||||
<dl>
|
||||
<dt>pvMaster</dt>
|
||||
<dd>the top level sructure managed by the server.</dd>
|
||||
<dt>pvRequest</dt>
|
||||
<dd>selects the set of subfields desired
|
||||
and options for each field.</dd>
|
||||
<dt>structureName</dt>
|
||||
<dd>the name for the top level of any PVStructure created.
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt>getPVMaster</dt>
|
||||
<dd>
|
||||
Gets the top level structure from pvMaster.
|
||||
</dd>
|
||||
<dt>traverseMaster</dt>
|
||||
<dd>
|
||||
Traverse all fields of the top level structure of pvMaster.
|
||||
For each field the callback is called.
|
||||
</dd>
|
||||
<dt>getStructure</dt>
|
||||
<dd>
|
||||
Get the introspection interface for a PVStructure for e copy.
|
||||
</dd>
|
||||
<dt>createPVStructure</dt>
|
||||
<dd>Create a copy instance.
|
||||
Monitors keep a queue of monitor elements.
|
||||
Since each element needs a PVStructure, multiple top level structures
|
||||
will be created.
|
||||
</dd>
|
||||
<dt>getCopyOffset</dt>
|
||||
<dd>Given a field in pvMaster.
|
||||
return the offset in copy for the same field.
|
||||
A value of String::npos means that the copy does not have this field.
|
||||
Two overloaded methods are provided. The first is called if
|
||||
the field of master is not a structure. The second is for
|
||||
subfields of a structure.
|
||||
</dd>
|
||||
<dt>getMasterPVField</dt>
|
||||
<dd>
|
||||
Given a offset in the copy get the corresponding field in pvMaster.
|
||||
</dd>
|
||||
<dt>initCopy</dt>
|
||||
<dd>
|
||||
Initialize the fields in copyPVStructure
|
||||
by giving each field the value from the corresponding field in pvMaster.
|
||||
bitSet will be set to show that all fields are changed.
|
||||
This means that bit set will have the value <b>{0}</b>.
|
||||
</dd>
|
||||
<dt>updateCopySetBitSet</dt>
|
||||
<dd>
|
||||
Set all fields in copyPVStructure to the value of the corresponding field
|
||||
in pvMaster. Each field that is changed has it's corresponding
|
||||
bit set in bitSet.
|
||||
</dd>
|
||||
<dt>updateCopyFromBitSet</dt>
|
||||
<dd>
|
||||
For each set bit in bitSet set the field in copyPVStructure to the value
|
||||
of the corrseponding field in pvMaster.
|
||||
</dd>
|
||||
<dt>updateMaster</dt>
|
||||
<dd>
|
||||
For each set bit in bitSet set the field in pvMaster to the value
|
||||
of the corrseponding field in copyPVStructure.
|
||||
|
||||
</dd>
|
||||
<dt>getOptions</dt>
|
||||
<dd>
|
||||
Get the options for the field at the specified offset.
|
||||
A NULL is returned if no options were specified for the field.
|
||||
If options were specified,PVStructurePtr is
|
||||
a structure with a set of PVString subfields that specify name,value
|
||||
pairs. name is the subField name and value is the subField value.
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
<h2>support for monitor</h2>
|
||||
<p>This consists of two components:
|
||||
<dl>
|
||||
<dt>monitor</dt>
|
||||
<dd>Used by code that implements pvAccess montors.</dd>
|
||||
<dt>monitorPlugin</dt>
|
||||
<dd>Code that provides special semantics for monitors.</dd>
|
||||
</dl>
|
||||
</p>
|
||||
<h3>monitor</h3>
|
||||
<pre>
|
||||
class MonitorElement {
|
||||
MonitorElement(PVStructurePtr const & pvStructurePtr);
|
||||
PVStructurePtr pvStructurePtr;
|
||||
BitSetPtr changedBitSet;
|
||||
BitSetPtr overrunBitSet;
|
||||
};
|
||||
|
||||
class Monitor {
|
||||
virtual Status start() = 0;
|
||||
virtual Status stop() = 0;
|
||||
virtual MonitorElementPtr poll() = 0;
|
||||
virtual void release(MonitorElementPtr const & monitorElement) = 0;
|
||||
};
|
||||
|
||||
class MonitorRequester : public virtual Requester {
|
||||
virtual void monitorConnect(Status const & status,
|
||||
MonitorPtr const & monitor, StructureConstPtr const & structure) = 0;
|
||||
virtual void monitorEvent(MonitorPtr const & monitor) = 0;
|
||||
virtual void unlisten(MonitorPtr const & monitor) = 0;
|
||||
};
|
||||
</pre>
|
||||
<h4>monitorElement</h4>
|
||||
<p><b>MonitorElement</b> holds the data for one element of a monitor queue.
|
||||
It has the fields:
|
||||
<dl>
|
||||
<dt>pvStructurePtr</dt>
|
||||
<dd>A top level structure with data values at the time the monitors occurs.</dd>
|
||||
<dt>changedBitSet</dt>
|
||||
<dd>Shows which fields have changed since the previous monitor.</dd>
|
||||
<dt>overrunBitSet</dt>
|
||||
<dd>Shows which fields have changed more han once since the previous monitor.</dd>
|
||||
</dl>
|
||||
</p>
|
||||
<h4>monitorElement queue</h4>
|
||||
<p>
|
||||
A queue of monitor elements must be implemented by any channel provider that implements
|
||||
<b>Channel::createMonitor</b>.
|
||||
For an example implementation look at pvDatabaseCPP.
|
||||
It has the following:
|
||||
<pre>
|
||||
typedef Queue<MonitorElement> MonitorElementQueue;
|
||||
typedef std::tr1::shared_ptr<MonitorElementQueue> MonitorElementQueuePtr;
|
||||
|
||||
class MultipleElementQueue :
|
||||
public ElementQueue
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(MultipleElementQueue);
|
||||
virtual ~MultipleElementQueue(){}
|
||||
MultipleElementQueue(
|
||||
MonitorLocalPtr const &monitorLocal,
|
||||
MonitorElementQueuePtr const &queue,
|
||||
size_t nfields);
|
||||
virtual void destroy(){}
|
||||
virtual Status start();
|
||||
virtual Status stop();
|
||||
virtual bool dataChanged();
|
||||
virtual MonitorElementPtr poll();
|
||||
virtual void release(MonitorElementPtr const &monitorElement);
|
||||
...
|
||||
};
|
||||
</pre>
|
||||
<h4>Monitor</h4>
|
||||
<p><b>Monitor</b> must be implemented by any channel provider that implements
|
||||
<b>Channel::createMonitor</b>.
|
||||
Remote PVAccess also implements Monitor on the client side.
|
||||
Note that each client has it's own queue that is not shared with other client.
|
||||
</p>
|
||||
<p>Monitor has the following methods:</p>
|
||||
<dl>
|
||||
<dt>start</dt>
|
||||
<dd>
|
||||
Start monitoring.
|
||||
This will result in a an inital monitor that has the current value
|
||||
of all fields.
|
||||
</dd>
|
||||
<dt>stop</dt>
|
||||
<dd>
|
||||
Stop monitoring.
|
||||
</dd>
|
||||
<dt>poll</dt>
|
||||
<dd>
|
||||
Called to get a monitor element.
|
||||
If no new elemants are available then a null pointer is returned.
|
||||
</dd>
|
||||
<dt>release</dt>
|
||||
<dd>
|
||||
Release the monotor element.
|
||||
The caller owns the monitor element between the calls to poll and release.
|
||||
</dd>
|
||||
<dl>
|
||||
</dl>
|
||||
<h4>MonitorRequester</h4>
|
||||
<p>This must be implemented by a pvAccess client.
|
||||
It has the methods:</p>
|
||||
<dl>
|
||||
<dt>monitorConnect</dt>
|
||||
<dd>
|
||||
A monitor has either connected of disconnected.
|
||||
</dd>
|
||||
<dt>monitorEvent</dt>
|
||||
<dd>
|
||||
A new monitor element is available.
|
||||
</dd>
|
||||
<dt>unlisten</dt>
|
||||
<dd>
|
||||
The channel is going away. The client cam no longer access the monitor.
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<h3>monitorPlugin</h3>
|
||||
<pre>
|
||||
class MonitorPlugin
|
||||
{
|
||||
virtual String const & getName() = 0;
|
||||
virtual bool causeMonitor(
|
||||
PVFieldPtr const &pvField,
|
||||
PVStructurePtr const &pvTop,
|
||||
MonitorElementPtr const &monitorElement) = 0;
|
||||
virtual void monitorDone(
|
||||
MonitorElementPtr const &monitorElement);
|
||||
virtual void startMonitoring();
|
||||
virtual void stopMonitoring();
|
||||
virtual void beginGroupPut();
|
||||
virtual void endGroupPut();
|
||||
};
|
||||
|
||||
class MonitorPluginCreator
|
||||
{
|
||||
virtual MonitorPluginPtr create(
|
||||
FieldConstPtr const &field,
|
||||
StructureConstPtr const &top,
|
||||
PVStructurePtr const &pvFieldOptions) = 0;
|
||||
virtual String const & getName() = 0;
|
||||
}
|
||||
|
||||
class MonitorPluginManager
|
||||
{
|
||||
static MonitorPluginManagerPtr get();
|
||||
bool addPlugin(
|
||||
String const &pluginName,
|
||||
MonitorPluginCreatorPtr const &creator);
|
||||
MonitorPluginCreatorPtr findPlugin(String const &pluginName);
|
||||
void showNames();
|
||||
};
|
||||
|
||||
</pre>
|
||||
<h4>MonitorPlugin</h4>
|
||||
<p><b>MonitorPlugin</b> must be implemented by the plugin implementation.
|
||||
It has methods:</p>
|
||||
<dl>
|
||||
<dt>getName</dt>
|
||||
<dd>Get the name of the plugin.</dd>
|
||||
<dt>causeMonitor</dt>
|
||||
<dd>
|
||||
Should the value of pvField cause a monitor to be raised.
|
||||
pvField and pvTop are fields in the top level structure
|
||||
being monitored. monitorElement has the top level structure
|
||||
for the copy</b>.
|
||||
The implementation should <b>not</b> modify the fields in the structure
|
||||
being monitored.
|
||||
Called with pvTop locked.
|
||||
</dd>
|
||||
<dt>monitorDone</dt>
|
||||
<dd>
|
||||
Called just before monitorElement will be given to client.
|
||||
The plugin can change the data values and bitSets in monitorElement.
|
||||
Called with pvTop unlocked.
|
||||
</dd>
|
||||
<dt>startMonitoring</dt>
|
||||
<dd>
|
||||
Monitoring is starting.
|
||||
</dd>
|
||||
<dt>stopMonitoring</dt>
|
||||
<dd>
|
||||
Monitoring is being stopped.
|
||||
</dd>
|
||||
<dt>beginGroupPut</dt>
|
||||
<dd>
|
||||
A set of puts is starting.
|
||||
Called with pvTop locked.
|
||||
</dd>
|
||||
<dt>endGroupPut</dt>
|
||||
<dd>
|
||||
The set of puts is complete.
|
||||
Called with pvTop locked.
|
||||
</dd>
|
||||
</dl>
|
||||
<h4>MonitorPluginCreator</h4>
|
||||
<p><b>MonitorPluginCreator</b> must also be implemented by the plugin implementation.
|
||||
It is called for each field instance that has options of the from
|
||||
<b>[plugin=name...]</b> where <b>name</b> is the name of the plugin.
|
||||
Note that a plugin instance will belong to a single client.
|
||||
It has methods:</p>
|
||||
<dl>
|
||||
<dt>getName</dt>
|
||||
<dd>Get the name of the plugin.</dd>
|
||||
<dt>create</dt>
|
||||
<dd>
|
||||
Create a new plugin instance.
|
||||
If the arguments are not compatible with the plugin a NULL shared pointer is
|
||||
returned.<br/>
|
||||
pvFieldOptions is
|
||||
a structure with a set of PVString subfields that specify <b>name,value</b>
|
||||
pairs. name is the subField name and value is the subField value.<br/>
|
||||
Note that a plugin will below to a single client.
|
||||
</dd>
|
||||
<dl>
|
||||
<h4>MonitorPluginManager</h4>
|
||||
<p><b>MonitorPluginManager</b> has the methods:</p>
|
||||
<dl>
|
||||
<dt>get</dt>
|
||||
<dd>
|
||||
MonitorPluginManager is a singleton.
|
||||
The first call to get will create the single instance.
|
||||
Further calls will rerurn the single instance.
|
||||
</dd>
|
||||
<dt>addPlugin</dt>
|
||||
<dd>
|
||||
Add a new plugin.
|
||||
</dd>
|
||||
<dt>findPlugin</dt>
|
||||
<dd>
|
||||
Find a plugin. A NULL shared pointer is reurned if it has not been added.
|
||||
</dd>
|
||||
<dt>showNames</dt>
|
||||
<dd>
|
||||
Show the names of all puugins that have been added.
|
||||
</dd>
|
||||
</dl>
|
||||
<p><b>NOTE:</b>
|
||||
Should the method <b>causeMonitor</b>
|
||||
have arguments <b>pvField</b> and <b>pvTop</b>
|
||||
be defined so that they can not be modfied.
|
||||
This would be posssible if the following was defined:
|
||||
<pre>
|
||||
typedef std::tr1::shared_ptr<const PVField> PVFieldConstPtr;
|
||||
typedef std::tr1::shared_ptr<const PVStructure> PVStructureConstPtr;
|
||||
</pre>
|
||||
then the definition for causeMonitor could be:
|
||||
<pre>
|
||||
virtual bool causeMonitor(
|
||||
PVFieldConstPtr const &pvField,
|
||||
PVStructureConstPtr const &pvTop,
|
||||
MonitorElementPtr const &monitorElement) = 0;
|
||||
</pre>
|
||||
But just adding these definitions is not sufficent.
|
||||
In addition all methods defined in pvDataCPP must be checked.
|
||||
In particular many of the methods in <b>Convert</b> must have
|
||||
their arguments modified.
|
||||
Big job.
|
||||
</p>
|
||||
<h2>monitorPlugin example</h2>
|
||||
<h3>Example Plugin Overview</h3>
|
||||
<p>This section describes an example plugin that:</p>
|
||||
<ul>
|
||||
<li>Only raises monitors when a field changes value.<br />
|
||||
If no plugin is provided
|
||||
the default is to raise a monitor when a put is issued to a field.</li>
|
||||
<li>Optionally a change will not raise a monitor.<br />
|
||||
The change will, however,
|
||||
appear if a put to another field raise a monitor.</li>
|
||||
</ul>
|
||||
<p>As an example assume that a channel provided by pvAccess has a top level structure
|
||||
that represents a power supply.</p>
|
||||
<pre>
|
||||
structure powerSupply
|
||||
structure alarm
|
||||
structure timeStamp
|
||||
structure power
|
||||
double value
|
||||
structure alarm
|
||||
struvture display
|
||||
structure voltage
|
||||
double value
|
||||
structure alarm
|
||||
struvture display
|
||||
structure current
|
||||
double value
|
||||
structure alarm
|
||||
struvture display
|
||||
</pre>
|
||||
<p>A pvAccess client wants to create a monitor on the powerSupply as follows:
|
||||
The client wants a top level structure that looks like:
|
||||
<pre>
|
||||
structure powerSupply
|
||||
structure alarm
|
||||
structure timeStamp
|
||||
structure power
|
||||
double value
|
||||
structure voltage
|
||||
double value
|
||||
structure current
|
||||
double value
|
||||
</pre>
|
||||
In addition the client wants monitors to occur only when one of the monitored
|
||||
fields changes value but not just because a put occured.
|
||||
Also if only the timeStamp changes value then that should not cause a monitor.
|
||||
</p>
|
||||
<p>The example monitor plugin implements the semantics the
|
||||
client wants. It can be attached to any field via the following options:
|
||||
<pre>
|
||||
[plugin=onChange,raiseMonitor=value]
|
||||
</pre>
|
||||
This plugin will trigger a monitor for the field only if the field changes
|
||||
value. In addition <b>value</b> equals <b>false</b> means do not raise a monotor
|
||||
for changes to this field.
|
||||
But if a change to another field does cause a monitor the change to this field
|
||||
will be passed to the client.
|
||||
</p>
|
||||
<p>
|
||||
Assume that the client has already connected to the channel.
|
||||
The client can then issue the commands:</p>
|
||||
<pre>
|
||||
String request("field(alarm[plugin=onChange]");
|
||||
request += ",timeStamp[plugin=onChange,raiseMonitor=false]";
|
||||
request += ",power.value[plugin=onChange";
|
||||
request += ",voltage.value[plugin=onChange";
|
||||
request += ",current.value[plugin=onChange";
|
||||
|
||||
PVStructurePtr pvRequest = createRequest->createRequest(request);
|
||||
|
||||
MonitorPtr monitor = channel->createMonitor(monitorRequester,pvRequest);
|
||||
</pre>
|
||||
<h3>Example Plugin Code</h3>
|
||||
<p>The header file to create the example has the definition:</p>
|
||||
<pre>
|
||||
class ExampleMonitorPlugin{
|
||||
public:
|
||||
static void create();
|
||||
};
|
||||
</pre>
|
||||
<p>The implementation is:</p>
|
||||
<pre>
|
||||
class OnChangePlugin : public MonitorPlugin
|
||||
{
|
||||
public:
|
||||
virtual ~OnChangePlugin(){}
|
||||
OnChangePlugin() {}
|
||||
bool init(
|
||||
FieldConstPtr const &field,
|
||||
StructureConstPtr const &top,
|
||||
PVStructurePtr const &pvFieldOptions)
|
||||
{
|
||||
pvField = getPVDataCreate()->createPVField(field);
|
||||
raiseMonitor = true;
|
||||
if(pvFieldOptions!=NULL) {
|
||||
PVStringPtr pvString =
|
||||
pvFieldOptions->getSubField<PVString>("raiseMonitor");
|
||||
if(pvString!=NULL) {
|
||||
String value = pvString->get();
|
||||
if(value.compare("false")==0) raiseMonitor = false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
virtual String &getName(){return pluginName;}
|
||||
virtual bool causeMonitor(
|
||||
PVFieldPtr const &pvNew,
|
||||
PVStructurePtr const &pvTop,
|
||||
MonitorElementPtr const &monitorElement)
|
||||
{
|
||||
bool isSame = convert->equals(pvNew,pvField);
|
||||
if(isSame) return false;
|
||||
convert->copy(pvNew,pvField);
|
||||
return raiseMonitor;
|
||||
}
|
||||
private:
|
||||
PVFieldPtr pvField;
|
||||
bool raiseMonitor;
|
||||
};
|
||||
class OnChangePluginCreator : public MonitorPluginCreator
|
||||
{
|
||||
public:
|
||||
virtual String &getName(){return pluginName;}
|
||||
virtual MonitorPluginPtr create(
|
||||
FieldConstPtr const &field,
|
||||
StructureConstPtr const &top,
|
||||
PVStructurePtr const &pvFieldOptions)
|
||||
{
|
||||
OnChangePluginPtr plugin(new OnChangePlugin());
|
||||
bool result = plugin->init(field,top,pvFieldOptions);
|
||||
if(!result) return MonitorPluginPtr();
|
||||
return plugin;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
void ExampleMonitorPlugin::create()
|
||||
{
|
||||
static OnChangePluginCreatorPtr plugin;
|
||||
static Mutex mutex;
|
||||
Lock xx(mutex);
|
||||
if(plugin==NULL) {
|
||||
plugin = OnChangePluginCreatorPtr(new OnChangePluginCreator());
|
||||
MonitorPluginManager::get()->addPlugin(pluginName,plugin);
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
BIN
documentation/examples.zip
Normal file
BIN
documentation/examples.zip
Normal file
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -18,7 +18,7 @@ getFieldCreate()->createFieldBuilder()->
|
||||
createStructure();
|
||||
|
||||
// create a structure (cntd.)
|
||||
PVStructure::const_shared_pointer enum_t =
|
||||
StructureConstPtr enum_t =
|
||||
getFieldCreate()->createFieldBuilder()->
|
||||
setId("enum_t")->
|
||||
add("index", pvInt)->
|
||||
@@ -26,7 +26,7 @@ PVStructure::const_shared_pointer enum_t =
|
||||
createStructure();
|
||||
|
||||
// create a structure (cntd.)
|
||||
PVStructure::const_shared_pointer ntEnum =
|
||||
StructureConstPtr ntEnum =
|
||||
getFieldCreate()->createFieldBuilder()->
|
||||
setId("uri:ev4:nt/2012/pwd/NTEnum")->
|
||||
add("value", enum_t)->
|
||||
|
||||
5537
documentation/pvDataCPP_20140501.html
Normal file
5537
documentation/pvDataCPP_20140501.html
Normal file
File diff suppressed because it is too large
Load Diff
@@ -12,6 +12,7 @@ include $(PVDATA_SRC)/misc/Makefile
|
||||
include $(PVDATA_SRC)/pv/Makefile
|
||||
include $(PVDATA_SRC)/factory/Makefile
|
||||
include $(PVDATA_SRC)/property/Makefile
|
||||
include $(PVDATA_SRC)/copy/Makefile
|
||||
include $(PVDATA_SRC)/pvMisc/Makefile
|
||||
include $(PVDATA_SRC)/monitor/Makefile
|
||||
|
||||
|
||||
532
src/copy/createRequest.cpp
Normal file
532
src/copy/createRequest.cpp
Normal file
@@ -0,0 +1,532 @@
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* pvAccessCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/lock.h>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/createRequest.h>
|
||||
|
||||
using namespace epics::pvData;
|
||||
using std::tr1::static_pointer_cast;
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
static PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
||||
static FieldCreatePtr fieldCreate = getFieldCreate();
|
||||
|
||||
class CreateRequestImpl : public CreateRequest {
|
||||
private:
|
||||
|
||||
void removeBlanks(String& str)
|
||||
{
|
||||
while(true) {
|
||||
String::size_type pos = str.find_first_of(' ');
|
||||
if(pos==String::npos) return;
|
||||
str.erase(pos,1);
|
||||
}
|
||||
}
|
||||
|
||||
size_t findMatchingBrace(String& request, size_t index, int numOpen) {
|
||||
size_t openBrace = request.find('{', index+1);
|
||||
size_t closeBrace = request.find('}', index+1);
|
||||
if(openBrace == String::npos && closeBrace == std::string::npos){
|
||||
message = request + " missing }";
|
||||
return std::string::npos;
|
||||
}
|
||||
if (openBrace != String::npos && openBrace!=0) {
|
||||
if(openBrace<closeBrace) return findMatchingBrace(request,openBrace,numOpen+1);
|
||||
if(numOpen==1) return closeBrace;
|
||||
return findMatchingBrace(request,closeBrace,numOpen-1);
|
||||
}
|
||||
if(numOpen==1) return closeBrace;
|
||||
return findMatchingBrace(request,closeBrace,numOpen-1);
|
||||
}
|
||||
|
||||
size_t findMatchingBracket(String& request, size_t index) {
|
||||
for(size_t i=index+1; i< request.size(); ++i) {
|
||||
if(request[i] == ']') {
|
||||
if(i==index+1) {
|
||||
message = request + " illegal []";
|
||||
return String::npos;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
}
|
||||
message = request + " missing ]";
|
||||
return std::string::npos;
|
||||
}
|
||||
|
||||
size_t findEndField(String& request) {
|
||||
size_t ind = 0;
|
||||
size_t maxind = request.size() -1;
|
||||
while(true) {
|
||||
if(request[ind]==',') return ind;
|
||||
if(request[ind]=='[') {
|
||||
size_t closeBracket = findMatchingBracket(request,ind);
|
||||
if(closeBracket==String::npos) return closeBracket;
|
||||
ind = closeBracket;
|
||||
continue;
|
||||
}
|
||||
if(request[ind]=='{') {
|
||||
size_t closeBrace = findMatchingBrace(request,ind,1);
|
||||
if(closeBrace==String::npos) return closeBrace;
|
||||
if(ind>=request.size()) return request.size();
|
||||
ind = closeBrace;
|
||||
continue;
|
||||
}
|
||||
if(ind>=maxind) break;
|
||||
++ind;
|
||||
}
|
||||
return request.size();
|
||||
}
|
||||
|
||||
std::vector<String> split(String const & commaSeparatedList) {
|
||||
String::size_type numValues = 1;
|
||||
String::size_type index=0;
|
||||
while(true) {
|
||||
String::size_type pos = commaSeparatedList.find(',',index);
|
||||
if(pos==String::npos) break;
|
||||
numValues++;
|
||||
index = pos +1;
|
||||
}
|
||||
std::vector<String> valueList(numValues,"");
|
||||
index=0;
|
||||
for(size_t i=0; i<numValues; i++) {
|
||||
size_t pos = commaSeparatedList.find(',',index);
|
||||
String value = commaSeparatedList.substr(index,pos-index);
|
||||
valueList[i] = value;
|
||||
index = pos +1;
|
||||
}
|
||||
return valueList;
|
||||
}
|
||||
|
||||
StructureConstPtr createRequestOptions(
|
||||
String request)
|
||||
{
|
||||
if(request.length()<=1) return StructureConstPtr();
|
||||
std::vector<String> items = split(request);
|
||||
size_t nitems = items.size();
|
||||
StringArray fieldNames(nitems);
|
||||
FieldConstPtrArray fields(nitems);
|
||||
for(size_t j=0; j<nitems; j++) {
|
||||
String item = items[j];
|
||||
size_t equals = item.find('=');
|
||||
if(equals==String::npos || equals==0) {
|
||||
message = item + " illegal option";
|
||||
StructureConstPtr xxx;
|
||||
return xxx;
|
||||
}
|
||||
fieldNames[j] = item.substr(0,equals);
|
||||
fields[j] = fieldCreate->createScalar(pvString);
|
||||
}
|
||||
return fieldCreate->createStructure(fieldNames,fields);
|
||||
}
|
||||
|
||||
void initRequestOptions(
|
||||
PVStructurePtr const & pvParent,
|
||||
String request)
|
||||
{
|
||||
if(request.length()<=1) return;
|
||||
std::vector<String> items = split(request);
|
||||
size_t nitems = items.size();
|
||||
for(size_t j=0; j<nitems; j++) {
|
||||
String item = items[j];
|
||||
size_t equals = item.find('=');
|
||||
String name = item.substr(0,equals);
|
||||
String value = item.substr(equals+1);
|
||||
PVStringPtr pvValue = pvParent->getSubField<PVString>(name);
|
||||
pvValue->put(value);
|
||||
}
|
||||
}
|
||||
|
||||
StructureConstPtr createSubFieldRequest(
|
||||
StructureConstPtr parent,
|
||||
String request)
|
||||
{
|
||||
if(request.length()<=0) return parent;
|
||||
size_t period = request.find('.');
|
||||
size_t openBracket = request.find('[');
|
||||
size_t openBrace = request.find('{');
|
||||
|
||||
// name only
|
||||
if(period==String::npos
|
||||
&& openBracket==String::npos
|
||||
&& openBrace==String::npos)
|
||||
{
|
||||
StructureConstPtr subField = fieldCreate->createStructure();
|
||||
parent = fieldCreate->appendField(parent,request,subField);
|
||||
return parent;
|
||||
}
|
||||
|
||||
// period is first
|
||||
if(period!=String::npos
|
||||
&& (openBracket==String::npos || period<openBracket)
|
||||
&& (openBrace==String::npos || period<openBrace) )
|
||||
{
|
||||
String fieldName = request.substr(0,period);
|
||||
StructureConstPtr subField = fieldCreate->createStructure();
|
||||
subField = createSubFieldRequest(subField,request.substr(period+1));
|
||||
if(subField==NULL) return subField;
|
||||
parent = fieldCreate->appendField(parent,fieldName,subField);
|
||||
return parent;
|
||||
}
|
||||
|
||||
// brace before [ or .
|
||||
if(openBrace!=String::npos
|
||||
&& (openBracket==String::npos || openBrace<openBracket) )
|
||||
{
|
||||
String fieldName = request.substr(0,openBrace);
|
||||
size_t closeBrace = findMatchingBrace(request,openBrace,1);
|
||||
if(closeBrace==String::npos) return StructureConstPtr();
|
||||
size_t nextChar = closeBrace+1;
|
||||
if(nextChar>= request.size()) nextChar = String::npos;
|
||||
if(nextChar!=String::npos) {
|
||||
message = request + " syntax error " + request[nextChar] + " after } illegal";
|
||||
return StructureConstPtr();
|
||||
}
|
||||
StructureConstPtr subField = fieldCreate->createStructure();
|
||||
String subRequest = request.substr(openBrace+1,closeBrace-openBrace-1);
|
||||
subField = createFieldRequest(subField,subRequest);
|
||||
if(subField==NULL) return subField;
|
||||
parent = fieldCreate->appendField(parent,fieldName,subField);
|
||||
return parent;
|
||||
}
|
||||
|
||||
// [ is before brace or .
|
||||
if(openBracket!=String::npos
|
||||
&& (openBrace==String::npos || openBracket<openBrace) )
|
||||
{
|
||||
String fieldName = request.substr(0,openBracket);
|
||||
size_t closeBracket = findMatchingBracket(request,openBracket);
|
||||
if(closeBracket==String::npos) return StructureConstPtr();
|
||||
size_t nextChar = closeBracket+1;
|
||||
if(nextChar>= request.size()) nextChar = String::npos;
|
||||
if(nextChar==String::npos) {
|
||||
StringArray fieldNames(1);
|
||||
FieldConstPtrArray fields(1);
|
||||
fieldNames[0] = "_options";
|
||||
fields[0] = createRequestOptions(
|
||||
request.substr(openBracket+1,closeBracket-openBracket-1));
|
||||
StructureConstPtr subField = fieldCreate->createStructure(fieldNames,fields);
|
||||
parent = fieldCreate->appendField(parent,fieldName,subField);
|
||||
return parent;
|
||||
}
|
||||
if(request[nextChar]=='.') {
|
||||
StructureConstPtr subField = fieldCreate->createStructure();
|
||||
subField = createSubFieldRequest(subField,request.substr(nextChar+1));
|
||||
if(subField==NULL) return StructureConstPtr();
|
||||
if(subField->getNumberFields()!=1) {
|
||||
message = request + " logic error createSubFieldRequest openBracket subField";
|
||||
return StructureConstPtr();
|
||||
}
|
||||
StringArray fieldNames(2);
|
||||
FieldConstPtrArray fields(2);
|
||||
fieldNames[0] = "_options";
|
||||
fields[0] = createRequestOptions(
|
||||
request.substr(openBracket+1,closeBracket-openBracket-1));
|
||||
fieldNames[1] = subField->getFieldNames()[0];
|
||||
fields[1] = subField;
|
||||
subField = fieldCreate->createStructure(fieldNames,fields);
|
||||
parent = fieldCreate->appendField(parent,fieldName,subField);
|
||||
return parent;
|
||||
}
|
||||
if(request[nextChar]=='{') {
|
||||
size_t closeBrace = findMatchingBrace(request,openBrace,1);
|
||||
if(closeBrace==String::npos) return StructureConstPtr();
|
||||
StructureConstPtr subField = fieldCreate->createStructure();
|
||||
String subRequest = request.substr(openBrace+1,closeBrace-openBrace-1);
|
||||
subField = createFieldRequest(subField,subRequest);
|
||||
if(subField==NULL) return subField;
|
||||
size_t numSub = subField->getNumberFields();
|
||||
StringArray fieldNames(numSub + 1);
|
||||
FieldConstPtrArray fields(numSub+1);
|
||||
fieldNames[0] = "_options";
|
||||
fields[0] = createRequestOptions(
|
||||
request.substr(openBracket+1,closeBracket-openBracket-1));
|
||||
StringArray subNames = subField->getFieldNames();
|
||||
FieldConstPtrArray subFields = subField->getFields();
|
||||
for(size_t i=0; i<numSub; ++i) {
|
||||
fieldNames[i+1] = subNames[i];
|
||||
fields[i+1] = subFields[i];
|
||||
}
|
||||
subField = fieldCreate->appendFields(parent,fieldNames,fields);
|
||||
parent = fieldCreate->appendField(parent,fieldName,subField);
|
||||
return parent;
|
||||
}
|
||||
}
|
||||
message = request + " logic error createSubFieldRequest";
|
||||
return StructureConstPtr();
|
||||
}
|
||||
|
||||
|
||||
StructureConstPtr createFieldRequest(
|
||||
StructureConstPtr parent,
|
||||
String request)
|
||||
{
|
||||
size_t length = request.length();
|
||||
if(length<=0) return parent;
|
||||
size_t end = findEndField(request);
|
||||
if(end==String::npos) return StructureConstPtr();
|
||||
StringArray fieldNames;
|
||||
FieldConstPtrArray fields;
|
||||
StructureConstPtr subField = fieldCreate->createStructure();
|
||||
subField = createSubFieldRequest(subField,request.substr(0,end));
|
||||
if(subField==NULL) return subField;
|
||||
fieldNames.push_back(subField->getFieldNames()[0]);
|
||||
fields.push_back(subField->getFields()[0]);
|
||||
if(end!=length) {
|
||||
if(request[end]!=',') {
|
||||
message = request;
|
||||
message += " expected char ";
|
||||
message += length;
|
||||
message += " to be ,";
|
||||
return StructureConstPtr();
|
||||
}
|
||||
StructureConstPtr nextSubField = fieldCreate->createStructure();
|
||||
nextSubField = createFieldRequest(nextSubField,request.substr(end+1));
|
||||
if(nextSubField==NULL) return nextSubField;
|
||||
size_t numFields = nextSubField->getNumberFields();
|
||||
StringArray subNames = nextSubField->getFieldNames();
|
||||
FieldConstPtrArray subFields = nextSubField->getFields();
|
||||
for(size_t i=0; i<numFields; ++i) {
|
||||
fieldNames.push_back(subNames[i]);
|
||||
fields.push_back(subFields[i]);
|
||||
}
|
||||
}
|
||||
parent = fieldCreate->appendFields(parent,fieldNames,fields);
|
||||
return parent;
|
||||
}
|
||||
|
||||
void initSubFieldOptions(
|
||||
PVStructurePtr const & pvParent,
|
||||
String request)
|
||||
{
|
||||
if(request.length()<=0) return;
|
||||
size_t period = request.find('.');
|
||||
size_t openBracket = request.find('[');
|
||||
size_t openBrace = request.find('{');
|
||||
// name only
|
||||
if(period==String::npos
|
||||
&& openBracket==String::npos
|
||||
&& openBrace==String::npos)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// period is first
|
||||
if(period!=String::npos
|
||||
&& (openBracket==String::npos || period<openBracket)
|
||||
&& (openBrace==String::npos || period<openBrace) )
|
||||
{
|
||||
PVStructurePtr pvSubField = static_pointer_cast<PVStructure>(pvParent->getPVFields()[0]);
|
||||
initSubFieldOptions(pvSubField,request.substr(period+1));
|
||||
return;
|
||||
}
|
||||
|
||||
// brace before [ or .
|
||||
if(openBrace!=String::npos
|
||||
&& (openBracket==String::npos || openBrace<openBracket) )
|
||||
{
|
||||
PVStructurePtr pvSubField = static_pointer_cast<PVStructure>(pvParent->getPVFields()[0]);
|
||||
size_t closeBrace = findMatchingBrace(request,openBrace,1);
|
||||
String subRequest = request.substr(openBrace+1,closeBrace-openBrace-1);
|
||||
initFieldOptions(pvSubField,subRequest);
|
||||
return;
|
||||
}
|
||||
PVStructurePtr pvOptions = pvParent->getSubField<PVStructure>("_options");
|
||||
if(pvOptions==NULL) throw std::logic_error("initSubFieldOptions pvOptions NULL");
|
||||
size_t closeBracket = findMatchingBracket(request,openBracket);
|
||||
initRequestOptions(pvOptions,request.substr(openBracket+1,closeBracket-openBracket-1));
|
||||
size_t nextChar = closeBracket+1;
|
||||
if(nextChar>= request.size()) nextChar = String::npos;
|
||||
if(nextChar==String::npos) return;
|
||||
if(request[nextChar]=='.') {
|
||||
PVStructurePtr pvSubField = static_pointer_cast<PVStructure>(pvParent->getPVFields()[1]);
|
||||
initSubFieldOptions(pvSubField,request.substr(nextChar+1));
|
||||
return;
|
||||
}
|
||||
if(request[nextChar]!='{') throw std::logic_error("initSubFieldOptions request[nextChar]!='{'");
|
||||
size_t closeBrace = findMatchingBrace(request,openBrace,1);
|
||||
const PVFieldPtrArray &pvFields = pvParent->getPVFields();
|
||||
String subRequest = request.substr(openBrace+1,closeBrace-openBrace-1);
|
||||
for(size_t i=1; i<pvFields.size(); ++i) {
|
||||
PVStructurePtr pvSubField = static_pointer_cast<PVStructure>(pvFields[i]);
|
||||
size_t comma = subRequest.find(',');
|
||||
initSubFieldOptions(pvSubField, subRequest.substr(0,comma-1));
|
||||
subRequest = subRequest.substr(comma+1);
|
||||
}
|
||||
}
|
||||
|
||||
void initFieldOptions(
|
||||
PVStructurePtr const & pvParent,
|
||||
String request)
|
||||
{
|
||||
if(request.find('[')==String::npos) return;
|
||||
size_t num = pvParent->getStructure()->getNumberFields();
|
||||
if(num==0) return;
|
||||
if(num==1) {
|
||||
initSubFieldOptions(pvParent,request);
|
||||
return;
|
||||
}
|
||||
size_t end = findEndField(request);
|
||||
size_t start = 0;
|
||||
for(size_t i=0; i<num; ++i) {
|
||||
PVStructurePtr pvSub = static_pointer_cast<PVStructure>(pvParent->getPVFields()[i]);
|
||||
String subRequest = request.substr(start, end - start);
|
||||
initSubFieldOptions(pvSub,subRequest);
|
||||
if(i==num-1) break;
|
||||
start = end +1;
|
||||
String xxx = request.substr(start);
|
||||
end += findEndField(xxx) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
|
||||
virtual PVStructure::shared_pointer createRequest(
|
||||
String const & crequest)
|
||||
{
|
||||
String request = crequest;
|
||||
StructureConstPtr topStructure = fieldCreate->createStructure();
|
||||
|
||||
if (!request.empty()) removeBlanks(request);
|
||||
if (request.empty())
|
||||
{
|
||||
PVFieldPtrArray pvFields;
|
||||
StringArray fieldNames;
|
||||
return pvDataCreate->createPVStructure(fieldNames,pvFields);
|
||||
}
|
||||
size_t offsetRecord = request.find("record[");
|
||||
size_t offsetField = request.find("field(");
|
||||
size_t offsetPutField = request.find("putField(");
|
||||
size_t offsetGetField = request.find("getField(");
|
||||
if(offsetRecord==String::npos
|
||||
&& offsetField==String::npos
|
||||
&& offsetPutField==String::npos
|
||||
&& offsetGetField==String::npos)
|
||||
{
|
||||
request = "field(" + crequest + ")";
|
||||
offsetField = request.find("field(");
|
||||
}
|
||||
if (offsetRecord != String::npos) {
|
||||
size_t openBracket = request.find('[', offsetRecord);
|
||||
size_t closeBracket = request.find(']', openBracket);
|
||||
if(closeBracket == String::npos) {
|
||||
message = request.substr(offsetRecord)
|
||||
+ " record[ does not have matching ]";
|
||||
return PVStructurePtr();
|
||||
}
|
||||
StructureConstPtr structure = createRequestOptions(
|
||||
request.substr(openBracket+1,closeBracket-openBracket-1));
|
||||
if(structure==NULL)
|
||||
{
|
||||
return PVStructurePtr();
|
||||
}
|
||||
topStructure = fieldCreate->appendField(topStructure,"record",structure);
|
||||
}
|
||||
if (offsetField != String::npos) {
|
||||
size_t openBrace = request.find('(', offsetField);
|
||||
size_t closeBrace = request.find(')', openBrace);
|
||||
if(closeBrace == String::npos) {
|
||||
message = request.substr(offsetField)
|
||||
+ " field( does not have matching )";
|
||||
return PVStructurePtr();
|
||||
}
|
||||
StructureConstPtr structure = fieldCreate->createStructure();
|
||||
structure = createFieldRequest(structure,request.substr(openBrace+1,closeBrace-openBrace-1));
|
||||
if(structure==NULL)
|
||||
{
|
||||
return PVStructurePtr();
|
||||
}
|
||||
topStructure = fieldCreate->appendField(topStructure,"field",structure);
|
||||
}
|
||||
if (offsetPutField != String::npos) {
|
||||
size_t openBrace = request.find('(', offsetPutField);
|
||||
size_t closeBrace = request.find(')', openBrace);
|
||||
if(closeBrace == String::npos) {
|
||||
message = request.substr(offsetField)
|
||||
+ " putField( does not have matching )";
|
||||
return PVStructurePtr();
|
||||
}
|
||||
StructureConstPtr structure = fieldCreate->createStructure();
|
||||
structure = createFieldRequest(structure,request.substr(openBrace+1,closeBrace-openBrace-1));
|
||||
if(structure==NULL)
|
||||
{
|
||||
return PVStructurePtr();
|
||||
}
|
||||
topStructure = fieldCreate->appendField(topStructure,"putField",structure);
|
||||
}
|
||||
if (offsetGetField != String::npos) {
|
||||
size_t openBrace = request.find('(', offsetGetField);
|
||||
size_t closeBrace = request.find(')', openBrace);
|
||||
if(closeBrace == String::npos) {
|
||||
message = request.substr(offsetField)
|
||||
+ " getField( does not have matching )";
|
||||
return PVStructurePtr();
|
||||
}
|
||||
StructureConstPtr structure = fieldCreate->createStructure();
|
||||
structure = createFieldRequest(structure,request.substr(openBrace+1,closeBrace-openBrace-1));
|
||||
if(structure==NULL)
|
||||
{
|
||||
return PVStructurePtr();
|
||||
}
|
||||
topStructure = fieldCreate->appendField(topStructure,"getField",structure);
|
||||
}
|
||||
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(topStructure);
|
||||
if (offsetRecord != String::npos) {
|
||||
size_t openBracket = request.find('[', offsetRecord);
|
||||
size_t closeBracket = request.find(']', openBracket);
|
||||
initRequestOptions(
|
||||
pvStructure->getSubField<PVStructure>("record"),
|
||||
request.substr(openBracket+1,closeBracket-openBracket-1));
|
||||
}
|
||||
if (offsetField != String::npos) {
|
||||
size_t openParam = request.find('(', offsetField);
|
||||
size_t closeParam = request.find(')', openParam);
|
||||
PVStructurePtr pvSub = pvStructure->getSubField<PVStructure>("field");
|
||||
if(pvSub->getStructure()->getNumberFields()==1) {
|
||||
pvSub = static_pointer_cast<PVStructure>(pvSub->getPVFields()[0]);
|
||||
}
|
||||
if(pvSub!=NULL) initFieldOptions(pvSub,request.substr(openParam+1,closeParam-openParam-1));
|
||||
}
|
||||
if (offsetPutField != String::npos) {
|
||||
size_t openParam = request.find('(', offsetPutField);
|
||||
size_t closeParam = request.find(')', openParam);
|
||||
PVStructurePtr pvSub = pvStructure->getSubField<PVStructure>("putField");
|
||||
if(pvSub->getStructure()->getNumberFields()==1) {
|
||||
pvSub = static_pointer_cast<PVStructure>(pvSub->getPVFields()[0]);
|
||||
}
|
||||
if(pvSub!=NULL) initFieldOptions(pvSub,request.substr(openParam+1,closeParam-openParam-1));
|
||||
}
|
||||
if (offsetGetField != String::npos) {
|
||||
size_t openParam = request.find('(', offsetGetField);
|
||||
size_t closeParam = request.find(')', openParam);
|
||||
PVStructurePtr pvSub = pvStructure->getSubField<PVStructure>("getField");
|
||||
if(pvSub->getStructure()->getNumberFields()==1) {
|
||||
pvSub = static_pointer_cast<PVStructure>(pvSub->getPVFields()[0]);
|
||||
}
|
||||
if(pvSub!=NULL) initFieldOptions(pvSub,request.substr(openParam+1,closeParam-openParam-1));
|
||||
}
|
||||
return pvStructure;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
CreateRequest::shared_pointer CreateRequest::create()
|
||||
{
|
||||
CreateRequest::shared_pointer createRequest(new CreateRequestImpl());
|
||||
return createRequest;
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
67
src/copy/createRequest.h
Normal file
67
src/copy/createRequest.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/*createRequest.h*/
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* pvDataCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
|
||||
#ifndef CREATEREQUEST_H
|
||||
#define CREATEREQUEST_H
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
#ifdef epicsExportSharedSymbols
|
||||
# define pvDataEpicsExportSharedSymbols
|
||||
# undef epicsExportSharedSymbols
|
||||
#endif
|
||||
|
||||
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/lock.h>
|
||||
|
||||
#ifdef pvDataEpicsExportSharedSymbols
|
||||
# define epicsExportSharedSymbols
|
||||
# undef pvDataEpicsExportSharedSymbols
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
/**
|
||||
* Class to create pvRequest structures to pass to pvAccess Channel methods.
|
||||
*/
|
||||
class epicsShareClass CreateRequest {
|
||||
public:
|
||||
POINTER_DEFINITIONS(CreateRequest);
|
||||
/**
|
||||
* Create s new instance of CreateRequest
|
||||
* @returns A shared pointer to the new instance.
|
||||
*/
|
||||
static CreateRequest::shared_pointer create();
|
||||
virtual ~CreateRequest() {};
|
||||
/**
|
||||
* Create a request structure for the create calls in Channel.
|
||||
* See the package overview documentation for details.
|
||||
* @param request The field request. See the package overview documentation for details.
|
||||
* @param requester The requester;
|
||||
* @return The request PVStructure if a valid request was given.
|
||||
* If a NULL PVStructure is returned then getMessage will return
|
||||
* the reason.
|
||||
*/
|
||||
virtual PVStructure::shared_pointer createRequest(String const & request) = 0;
|
||||
/**
|
||||
* Get the error message of createRequest returns NULL
|
||||
* return the error message
|
||||
*/
|
||||
String getMessage() {return message;}
|
||||
protected:
|
||||
CreateRequest() {}
|
||||
String message;
|
||||
};
|
||||
|
||||
|
||||
}}
|
||||
|
||||
#endif /* CREATEREQUEST_H */
|
||||
|
||||
644
src/copy/pvCopy.cpp
Normal file
644
src/copy/pvCopy.cpp
Normal file
@@ -0,0 +1,644 @@
|
||||
/* pvCopy.cpp */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author Marty Kraimer
|
||||
* @date 2013.04
|
||||
*/
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
|
||||
#include <pv/thread.h>
|
||||
|
||||
#include <pv/pvCopy.h>
|
||||
#include <pv/convert.h>
|
||||
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
using namespace epics::pvData;
|
||||
using std::tr1::static_pointer_cast;
|
||||
using std::tr1::dynamic_pointer_cast;
|
||||
using std::size_t;
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
static PVCopyPtr NULLPVCopy;
|
||||
static FieldConstPtr NULLField;
|
||||
static StructureConstPtr NULLStructure;
|
||||
static PVStructurePtr NULLPVStructure;
|
||||
static CopyNodePtr NULLCopyNode;
|
||||
static CopyMasterNodePtr NULLCopyMasterNode;
|
||||
|
||||
struct CopyNode {
|
||||
CopyNode()
|
||||
: isStructure(false),
|
||||
structureOffset(0),
|
||||
nfields(0)
|
||||
{}
|
||||
bool isStructure;
|
||||
size_t structureOffset; // In the copy
|
||||
size_t nfields;
|
||||
PVStructurePtr options;
|
||||
};
|
||||
|
||||
struct CopyMasterNode : public CopyNode{
|
||||
PVFieldPtr masterPVField;
|
||||
};
|
||||
|
||||
typedef std::vector<CopyNodePtr> CopyNodePtrArray;
|
||||
typedef std::tr1::shared_ptr<CopyNodePtrArray> CopyNodePtrArrayPtr;
|
||||
|
||||
struct CopyStructureNode : public CopyNode {
|
||||
CopyNodePtrArrayPtr nodes;
|
||||
};
|
||||
|
||||
PVCopyPtr PVCopy::create(
|
||||
PVStructurePtr const &pvMaster,
|
||||
PVStructurePtr const &pvRequest,
|
||||
String const & structureName)
|
||||
{
|
||||
PVStructurePtr pvStructure(pvRequest);
|
||||
if(structureName.size()>0) {
|
||||
if(pvRequest->getStructure()->getNumberFields()>0) {
|
||||
pvStructure = pvRequest->getStructureField(structureName);
|
||||
if(pvStructure.get()==NULL) return NULLPVCopy;
|
||||
}
|
||||
} else if(pvStructure->getSubField("field")!=NULL) {
|
||||
pvStructure = pvRequest->getStructureField("field");
|
||||
}
|
||||
PVCopyPtr pvCopy = PVCopyPtr(new PVCopy(pvMaster));
|
||||
bool result = pvCopy->init(pvStructure);
|
||||
if(!result) pvCopy.reset();
|
||||
return pvCopy;
|
||||
}
|
||||
|
||||
PVCopy::PVCopy(
|
||||
PVStructurePtr const &pvMaster)
|
||||
: pvMaster(pvMaster)
|
||||
{
|
||||
}
|
||||
|
||||
void PVCopy::destroy()
|
||||
{
|
||||
headNode.reset();
|
||||
}
|
||||
|
||||
PVStructurePtr PVCopy::getPVMaster()
|
||||
{
|
||||
return pvMaster;
|
||||
}
|
||||
|
||||
void PVCopy::traverseMaster(CopyNodePtr const &innode, PVCopyTraverseMasterCallbackPtr const & callback)
|
||||
{
|
||||
CopyNodePtr node = innode;
|
||||
if(!node->isStructure) {
|
||||
CopyMasterNodePtr masterNode = static_pointer_cast<CopyMasterNode>(node);
|
||||
callback->nextMasterPVField(masterNode->masterPVField);
|
||||
return;
|
||||
}
|
||||
CopyStructureNodePtr structNode = static_pointer_cast<CopyStructureNode>(node);
|
||||
CopyNodePtrArrayPtr nodes = structNode->nodes;
|
||||
for(size_t i=0; i< nodes->size(); i++) {
|
||||
node = (*nodes)[i];
|
||||
traverseMaster(node,callback);
|
||||
}
|
||||
}
|
||||
|
||||
StructureConstPtr PVCopy::getStructure()
|
||||
{
|
||||
return structure;
|
||||
}
|
||||
|
||||
PVStructurePtr PVCopy::createPVStructure()
|
||||
{
|
||||
if(cacheInitStructure.get()!=NULL) {
|
||||
PVStructurePtr save = cacheInitStructure;
|
||||
cacheInitStructure.reset();
|
||||
return save;
|
||||
}
|
||||
PVStructurePtr pvStructure =
|
||||
getPVDataCreate()->createPVStructure(structure);
|
||||
return pvStructure;
|
||||
}
|
||||
|
||||
PVStructurePtr PVCopy::getOptions(std::size_t fieldOffset)
|
||||
{
|
||||
if(fieldOffset==0) return headNode->options;
|
||||
CopyNodePtr node = headNode;
|
||||
while(true) {
|
||||
if(!node->isStructure) {
|
||||
if(node->structureOffset==fieldOffset) return node->options;
|
||||
return NULLPVStructure;
|
||||
}
|
||||
CopyStructureNodePtr structNode = static_pointer_cast<CopyStructureNode>(node);
|
||||
CopyNodePtrArrayPtr nodes = structNode->nodes;
|
||||
boolean okToContinue = false;
|
||||
for(size_t i=0; i< nodes->size(); i++) {
|
||||
node = (*nodes)[i];
|
||||
size_t soff = node->structureOffset;
|
||||
if(fieldOffset>=soff && fieldOffset<soff+node->nfields) {
|
||||
if(fieldOffset==soff) return node->options;
|
||||
if(!node->isStructure) {
|
||||
return NULLPVStructure;
|
||||
}
|
||||
okToContinue = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(okToContinue) continue;
|
||||
throw std::invalid_argument("fieldOffset not valid");
|
||||
}
|
||||
}
|
||||
|
||||
size_t PVCopy::getCopyOffset(PVFieldPtr const &masterPVField)
|
||||
{
|
||||
if(masterPVField->getFieldOffset()==0) return 0;
|
||||
if(!headNode->isStructure) {
|
||||
CopyMasterNodePtr masterNode = static_pointer_cast<CopyMasterNode>(headNode);
|
||||
if((masterNode->masterPVField.get())==masterPVField.get()) {
|
||||
return headNode->structureOffset;
|
||||
}
|
||||
PVStructure * parent = masterPVField->getParent();
|
||||
size_t offsetParent = parent->getFieldOffset();
|
||||
size_t off = masterPVField->getFieldOffset();
|
||||
size_t offdiff = off -offsetParent;
|
||||
if(offdiff<masterNode->nfields) return headNode->structureOffset + offdiff;
|
||||
return String::npos;
|
||||
}
|
||||
CopyStructureNodePtr node = static_pointer_cast<CopyStructureNode>(headNode);
|
||||
CopyMasterNodePtr masterNode = getCopyOffset(node,masterPVField);
|
||||
if(masterNode.get()!=NULL) return masterNode->structureOffset;
|
||||
return String::npos;
|
||||
}
|
||||
|
||||
size_t PVCopy::getCopyOffset(
|
||||
PVStructurePtr const &masterPVStructure,
|
||||
PVFieldPtr const &masterPVField)
|
||||
{
|
||||
CopyMasterNodePtr masterNode;
|
||||
if(!headNode->isStructure) {
|
||||
masterNode = static_pointer_cast<CopyMasterNode>(headNode);
|
||||
if(masterNode->masterPVField.get()!=masterPVStructure.get()) return String::npos;
|
||||
} else {
|
||||
CopyStructureNodePtr node = static_pointer_cast<CopyStructureNode>(headNode);
|
||||
masterNode = getCopyOffset(node,masterPVField);
|
||||
}
|
||||
if(masterNode.get()==NULL) return String::npos;
|
||||
size_t diff = masterPVField->getFieldOffset()
|
||||
- masterPVStructure->getFieldOffset();
|
||||
return masterNode->structureOffset + diff;
|
||||
}
|
||||
|
||||
PVFieldPtr PVCopy::getMasterPVField(size_t structureOffset)
|
||||
{
|
||||
CopyMasterNodePtr masterNode;
|
||||
if(!headNode->isStructure) {
|
||||
masterNode = static_pointer_cast<CopyMasterNode>(headNode);
|
||||
} else {
|
||||
CopyStructureNodePtr node = static_pointer_cast<CopyStructureNode>(headNode);
|
||||
masterNode = getMasterNode(node,structureOffset);
|
||||
}
|
||||
if(masterNode.get()==NULL) {
|
||||
throw std::invalid_argument(
|
||||
"PVCopy::getMasterPVField: setstructureOffset not valid");
|
||||
}
|
||||
size_t diff = structureOffset - masterNode->structureOffset;
|
||||
PVFieldPtr pvMasterField = masterNode->masterPVField;
|
||||
if(diff==0) return pvMasterField;
|
||||
PVStructurePtr pvStructure
|
||||
= static_pointer_cast<PVStructure>(pvMasterField);
|
||||
return pvStructure->getSubField(
|
||||
pvMasterField->getFieldOffset() + diff);
|
||||
}
|
||||
|
||||
void PVCopy::initCopy(
|
||||
PVStructurePtr const ©PVStructure,
|
||||
BitSetPtr const &bitSet)
|
||||
{
|
||||
bitSet->clear();
|
||||
bitSet->set(0);
|
||||
updateCopyFromBitSet(copyPVStructure,bitSet);
|
||||
}
|
||||
|
||||
void PVCopy::updateCopySetBitSet(
|
||||
PVStructurePtr const ©PVStructure,
|
||||
BitSetPtr const &bitSet)
|
||||
{
|
||||
if(headNode->isStructure) {
|
||||
CopyStructureNodePtr node = static_pointer_cast<CopyStructureNode>(headNode);
|
||||
updateStructureNodeSetBitSet(copyPVStructure,node,bitSet);
|
||||
} else {
|
||||
CopyMasterNodePtr masterNode = static_pointer_cast<CopyMasterNode>(headNode);
|
||||
PVFieldPtr pvMasterField= masterNode->masterPVField;
|
||||
PVFieldPtr copyPVField = copyPVStructure;
|
||||
PVFieldPtr pvField = pvMasterField;
|
||||
if(pvField->getField()->getType()==epics::pvData::structure) {
|
||||
updateSubFieldSetBitSet(copyPVField,pvMasterField,bitSet);
|
||||
return;
|
||||
}
|
||||
ConvertPtr convert = getConvert();
|
||||
bool isEqual = convert->equals(copyPVField,pvField);
|
||||
if(!isEqual) {
|
||||
convert->copy(pvField, copyPVField);
|
||||
bitSet->set(copyPVField->getFieldOffset());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PVCopy::updateCopyFromBitSet(
|
||||
PVStructurePtr const ©PVStructure,
|
||||
BitSetPtr const &bitSet)
|
||||
{
|
||||
bool doAll = bitSet->get(0);
|
||||
if(headNode->isStructure) {
|
||||
CopyStructureNodePtr node = static_pointer_cast<CopyStructureNode>(headNode);
|
||||
updateStructureNodeFromBitSet(copyPVStructure,node,bitSet,true,doAll);
|
||||
} else {
|
||||
CopyMasterNodePtr masterNode = static_pointer_cast<CopyMasterNode>(headNode);
|
||||
updateSubFieldFromBitSet(copyPVStructure, masterNode->masterPVField,bitSet, true,doAll);
|
||||
}
|
||||
}
|
||||
|
||||
void PVCopy::updateMaster(
|
||||
PVStructurePtr const ©PVStructure,
|
||||
BitSetPtr const &bitSet)
|
||||
{
|
||||
bool doAll = bitSet->get(0);
|
||||
if(headNode->isStructure) {
|
||||
CopyStructureNodePtr node =
|
||||
static_pointer_cast<CopyStructureNode>(headNode);
|
||||
updateStructureNodeFromBitSet(
|
||||
copyPVStructure,node,bitSet,false,doAll);
|
||||
} else {
|
||||
CopyMasterNodePtr masterNode =
|
||||
static_pointer_cast<CopyMasterNode>(headNode);
|
||||
updateSubFieldFromBitSet( copyPVStructure,masterNode->masterPVField,bitSet,false,doAll);
|
||||
}
|
||||
}
|
||||
|
||||
epics::pvData::String PVCopy::dump()
|
||||
{
|
||||
String builder;
|
||||
dump(&builder,headNode,0);
|
||||
return builder;
|
||||
}
|
||||
|
||||
void PVCopy::dump(String *builder,CopyNodePtr const &node,int indentLevel)
|
||||
{
|
||||
getConvert()->newLine(builder,indentLevel);
|
||||
std::stringstream ss;
|
||||
ss << (node->isStructure ? "structureNode" : "masterNode");
|
||||
ss << " structureOffset " << node->structureOffset;
|
||||
ss << " nfields " << node->nfields;
|
||||
*builder += ss.str();
|
||||
PVStructurePtr options = node->options;
|
||||
if(options.get()!=NULL) {
|
||||
getConvert()->newLine(builder,indentLevel +1);
|
||||
options->toString(builder);
|
||||
getConvert()->newLine(builder,indentLevel);
|
||||
}
|
||||
if(!node->isStructure) {
|
||||
CopyMasterNodePtr masterNode = static_pointer_cast<CopyMasterNode>(node);
|
||||
String name = masterNode->masterPVField->getFullName();
|
||||
*builder += " masterField " + name;
|
||||
return;
|
||||
}
|
||||
CopyStructureNodePtr structureNode =
|
||||
static_pointer_cast<CopyStructureNode>(node);
|
||||
CopyNodePtrArrayPtr nodes = structureNode->nodes;
|
||||
for(size_t i=0; i<nodes->size(); ++i) {
|
||||
if((*nodes)[i].get()==NULL) {
|
||||
getConvert()->newLine(builder,indentLevel +1);
|
||||
ss.str("");
|
||||
ss << "node[" << i << "] is null";
|
||||
*builder += ss.str();
|
||||
continue;
|
||||
}
|
||||
dump(builder,(*nodes)[i],indentLevel+1);
|
||||
}
|
||||
}
|
||||
|
||||
bool PVCopy::init(epics::pvData::PVStructurePtr const &pvRequest)
|
||||
{
|
||||
PVStructurePtr pvMasterStructure = pvMaster;
|
||||
size_t len = pvRequest->getPVFields().size();
|
||||
bool entireMaster = false;
|
||||
if(len==String::npos) entireMaster = true;
|
||||
if(len==0) entireMaster = true;
|
||||
PVStructurePtr pvOptions;
|
||||
if(len==1 && pvRequest->getSubField("_options")!=NULL) {
|
||||
pvOptions = pvRequest->getStructureField("_options");
|
||||
}
|
||||
if(entireMaster) {
|
||||
structure = pvMasterStructure->getStructure();
|
||||
CopyMasterNodePtr masterNode(new CopyMasterNode());
|
||||
headNode = masterNode;
|
||||
masterNode->options = pvOptions;
|
||||
masterNode->isStructure = false;
|
||||
masterNode->structureOffset = 0;
|
||||
masterNode->masterPVField = pvMasterStructure;
|
||||
masterNode->nfields = pvMasterStructure->getNumberFields();
|
||||
return true;
|
||||
}
|
||||
structure = createStructure(pvMasterStructure,pvRequest);
|
||||
if(structure==NULL) return false;
|
||||
cacheInitStructure = createPVStructure();
|
||||
headNode = createStructureNodes(
|
||||
pvMaster,
|
||||
pvRequest,
|
||||
cacheInitStructure);
|
||||
return true;
|
||||
}
|
||||
|
||||
epics::pvData::String PVCopy::dump(
|
||||
String const &value,
|
||||
CopyNodePtr const &node,
|
||||
int indentLevel)
|
||||
{
|
||||
throw std::logic_error(String("Not Implemented"));
|
||||
}
|
||||
|
||||
|
||||
StructureConstPtr PVCopy::createStructure(
|
||||
PVStructurePtr const &pvMaster,
|
||||
PVStructurePtr const &pvFromRequest)
|
||||
{
|
||||
if(pvFromRequest->getStructure()->getNumberFields()==0) {
|
||||
return pvMaster->getStructure();
|
||||
}
|
||||
PVFieldPtrArray const &pvFromRequestFields = pvFromRequest->getPVFields();
|
||||
StringArray const &fromRequestFieldNames = pvFromRequest->getStructure()->getFieldNames();
|
||||
size_t length = pvFromRequestFields.size();
|
||||
if(length==0) return NULLStructure;
|
||||
FieldConstPtrArray fields; fields.reserve(length);
|
||||
StringArray fieldNames; fields.reserve(length);
|
||||
for(size_t i=0; i<length; ++i) {
|
||||
String const &fieldName = fromRequestFieldNames[i];
|
||||
PVFieldPtr pvMasterField = pvMaster->getSubField(fieldName);
|
||||
if(pvMasterField==NULL) continue;
|
||||
FieldConstPtr field = pvMasterField->getField();
|
||||
if(field->getType()==epics::pvData::structure) {
|
||||
PVStructurePtr pvRequestStructure = static_pointer_cast<PVStructure>(
|
||||
pvFromRequestFields[i]);
|
||||
if(pvRequestStructure->getNumberFields()>0) {
|
||||
StringArray const &names = pvRequestStructure->getStructure()->
|
||||
getFieldNames();
|
||||
size_t num = names.size();
|
||||
if(num>0 && names[0].compare("_options")==0) --num;
|
||||
if(num>0) {
|
||||
if(pvMasterField->getField()->getType()!=epics::pvData::structure) continue;
|
||||
fieldNames.push_back(fieldName);
|
||||
fields.push_back(createStructure(
|
||||
static_pointer_cast<PVStructure>(pvMasterField),
|
||||
pvRequestStructure));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
fieldNames.push_back(fieldName);
|
||||
fields.push_back(field);
|
||||
}
|
||||
size_t numsubfields = fields.size();
|
||||
if(numsubfields==0) return NULLStructure;
|
||||
return getFieldCreate()->createStructure(fieldNames, fields);
|
||||
}
|
||||
|
||||
CopyNodePtr PVCopy::createStructureNodes(
|
||||
PVStructurePtr const &pvMasterStructure,
|
||||
PVStructurePtr const &pvFromRequest,
|
||||
PVStructurePtr const &pvFromCopy)
|
||||
{
|
||||
PVFieldPtrArray const & copyPVFields = pvFromCopy->getPVFields();
|
||||
PVStructurePtr pvOptions;
|
||||
PVFieldPtr pvField = pvFromRequest->getSubField("_options");
|
||||
if(pvField!=NULL) pvOptions = static_pointer_cast<PVStructure>(pvField);
|
||||
size_t number = copyPVFields.size();
|
||||
CopyNodePtrArrayPtr nodes(new CopyNodePtrArray());
|
||||
nodes->reserve(number);
|
||||
for(size_t i=0; i<number; i++) {
|
||||
PVFieldPtr copyPVField = copyPVFields[i];
|
||||
String fieldName = copyPVField->getFieldName();
|
||||
|
||||
PVStructurePtr requestPVStructure = static_pointer_cast<PVStructure>(
|
||||
pvFromRequest->getSubField(fieldName));
|
||||
PVStructurePtr pvSubFieldOptions;
|
||||
PVFieldPtr pvField = requestPVStructure->getSubField("_options");
|
||||
if(pvField!=NULL) pvSubFieldOptions = static_pointer_cast<PVStructure>(pvField);
|
||||
PVFieldPtr pvMasterField;
|
||||
PVFieldPtrArray const & pvMasterFields = pvMasterStructure->getPVFields();
|
||||
for(size_t j=0; i<pvMasterFields.size(); j++ ) {
|
||||
if(pvMasterFields[j]->getFieldName().compare(fieldName)==0) {
|
||||
pvMasterField = pvMasterFields[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
size_t numberRequest = requestPVStructure->getPVFields().size();
|
||||
if(pvSubFieldOptions!=NULL) numberRequest--;
|
||||
if(numberRequest>0) {
|
||||
nodes->push_back(createStructureNodes(
|
||||
static_pointer_cast<PVStructure>(pvMasterField),
|
||||
requestPVStructure,
|
||||
static_pointer_cast<PVStructure>(copyPVField)));
|
||||
continue;
|
||||
}
|
||||
CopyMasterNodePtr masterNode(new CopyMasterNode());
|
||||
masterNode->options = pvSubFieldOptions;
|
||||
masterNode->isStructure = false;
|
||||
masterNode->masterPVField = pvMasterField;
|
||||
masterNode->nfields = copyPVField->getNumberFields();
|
||||
masterNode->structureOffset = copyPVField->getFieldOffset();
|
||||
nodes->push_back(masterNode);
|
||||
}
|
||||
CopyStructureNodePtr structureNode(new CopyStructureNode());
|
||||
structureNode->isStructure = true;
|
||||
structureNode->nodes = nodes;
|
||||
structureNode->structureOffset = pvFromCopy->getFieldOffset();
|
||||
structureNode->nfields = pvFromCopy->getNumberFields();
|
||||
structureNode->options = pvOptions;
|
||||
return structureNode;
|
||||
}
|
||||
|
||||
void PVCopy::updateStructureNodeSetBitSet(
|
||||
PVStructurePtr const &pvCopy,
|
||||
CopyStructureNodePtr const &structureNode,
|
||||
epics::pvData::BitSetPtr const &bitSet)
|
||||
{
|
||||
for(size_t i=0; i<structureNode->nodes->size(); i++) {
|
||||
CopyNodePtr node = (*structureNode->nodes)[i];
|
||||
PVFieldPtr pvField = pvCopy->getSubField(node->structureOffset);
|
||||
if(node->isStructure) {
|
||||
PVStructurePtr xxx = static_pointer_cast<PVStructure>(pvField);
|
||||
CopyStructureNodePtr yyy =
|
||||
static_pointer_cast<CopyStructureNode>(node);
|
||||
updateStructureNodeSetBitSet(xxx,yyy,bitSet);
|
||||
} else {
|
||||
CopyMasterNodePtr masterNode =
|
||||
static_pointer_cast<CopyMasterNode>(node);
|
||||
updateSubFieldSetBitSet(pvField,masterNode->masterPVField,bitSet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PVCopy::updateSubFieldSetBitSet(
|
||||
PVFieldPtr const &pvCopy,
|
||||
PVFieldPtr const &pvMaster,
|
||||
BitSetPtr const &bitSet)
|
||||
{
|
||||
FieldConstPtr field = pvCopy->getField();
|
||||
Type type = field->getType();
|
||||
if(type!=epics::pvData::structure) {
|
||||
ConvertPtr convert = getConvert();
|
||||
bool isEqual = convert->equals(pvCopy,pvMaster);
|
||||
if(isEqual) {
|
||||
if(type==structureArray) {
|
||||
// always act as though a change occurred.
|
||||
// Note that array elements are shared.
|
||||
bitSet->set(pvCopy->getFieldOffset());
|
||||
}
|
||||
}
|
||||
if(isEqual) return;
|
||||
convert->copy(pvMaster, pvCopy);
|
||||
bitSet->set(pvCopy->getFieldOffset());
|
||||
return;
|
||||
}
|
||||
PVStructurePtr pvCopyStructure = static_pointer_cast<PVStructure>(pvCopy);
|
||||
PVFieldPtrArray const & pvCopyFields = pvCopyStructure->getPVFields();
|
||||
PVStructurePtr pvMasterStructure =
|
||||
static_pointer_cast<PVStructure>(pvMaster);
|
||||
PVFieldPtrArray const & pvMasterFields =
|
||||
pvMasterStructure->getPVFields();
|
||||
size_t length = pvCopyFields.size();
|
||||
for(size_t i=0; i<length; i++) {
|
||||
updateSubFieldSetBitSet(pvCopyFields[i],pvMasterFields[i],bitSet);
|
||||
}
|
||||
}
|
||||
|
||||
void PVCopy::updateStructureNodeFromBitSet(
|
||||
PVStructurePtr const &pvCopy,
|
||||
CopyStructureNodePtr const &structureNode,
|
||||
BitSetPtr const &bitSet,
|
||||
bool toCopy,
|
||||
bool doAll)
|
||||
{
|
||||
size_t offset = structureNode->structureOffset;
|
||||
if(!doAll) {
|
||||
size_t nextSet = bitSet->nextSetBit(offset);
|
||||
if(nextSet==String::npos) return;
|
||||
}
|
||||
if(offset>=pvCopy->getNextFieldOffset()) return;
|
||||
if(!doAll) doAll = bitSet->get(offset);
|
||||
CopyNodePtrArrayPtr nodes = structureNode->nodes;
|
||||
for(size_t i=0; i<nodes->size(); i++) {
|
||||
CopyNodePtr node = (*nodes)[i];
|
||||
PVFieldPtr pvField = pvCopy->getSubField(node->structureOffset);
|
||||
if(node->isStructure) {
|
||||
PVStructurePtr xxx = static_pointer_cast<PVStructure>(pvField);
|
||||
CopyStructureNodePtr subStructureNode =
|
||||
static_pointer_cast<CopyStructureNode>(node);
|
||||
updateStructureNodeFromBitSet(
|
||||
xxx,subStructureNode,bitSet,toCopy,doAll);
|
||||
} else {
|
||||
CopyMasterNodePtr masterNode =
|
||||
static_pointer_cast<CopyMasterNode>(node);
|
||||
updateSubFieldFromBitSet(
|
||||
pvField,masterNode->masterPVField,bitSet,toCopy,doAll);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PVCopy::updateSubFieldFromBitSet(
|
||||
PVFieldPtr const &pvCopy,
|
||||
PVFieldPtr const &pvMasterField,
|
||||
BitSetPtr const &bitSet,
|
||||
bool toCopy,
|
||||
bool doAll)
|
||||
{
|
||||
if(!doAll) {
|
||||
doAll = bitSet->get(pvCopy->getFieldOffset());
|
||||
}
|
||||
if(!doAll) {
|
||||
size_t offset = pvCopy->getFieldOffset();
|
||||
size_t nextSet = bitSet->nextSetBit(offset);
|
||||
if(nextSet==String::npos) return;
|
||||
if(nextSet>=pvCopy->getNextFieldOffset()) return;
|
||||
}
|
||||
ConvertPtr convert = getConvert();
|
||||
if(pvCopy->getField()->getType()==epics::pvData::structure) {
|
||||
PVStructurePtr pvCopyStructure =
|
||||
static_pointer_cast<PVStructure>(pvCopy);
|
||||
PVFieldPtrArray const & pvCopyFields = pvCopyStructure->getPVFields();
|
||||
if(pvMasterField->getField()->getType() !=epics::pvData::structure)
|
||||
{
|
||||
throw std::logic_error(String("Logic error"));
|
||||
}
|
||||
PVStructurePtr pvMasterStructure =
|
||||
static_pointer_cast<PVStructure>(pvMasterField);
|
||||
PVFieldPtrArray const & pvMasterFields =
|
||||
pvMasterStructure->getPVFields();
|
||||
for(size_t i=0; i<pvCopyFields.size(); i++) {
|
||||
updateSubFieldFromBitSet(
|
||||
pvCopyFields[i],
|
||||
pvMasterFields[i],
|
||||
bitSet,toCopy,doAll);
|
||||
}
|
||||
} else {
|
||||
if(toCopy) {
|
||||
convert->copy(pvMasterField, pvCopy);
|
||||
} else {
|
||||
convert->copy(pvCopy, pvMasterField);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CopyMasterNodePtr PVCopy::getCopyOffset(
|
||||
CopyStructureNodePtr const &structureNode,
|
||||
PVFieldPtr const &masterPVField)
|
||||
{
|
||||
size_t offset = masterPVField->getFieldOffset();
|
||||
CopyNodePtrArrayPtr nodes = structureNode->nodes;
|
||||
for(size_t i=0; i< nodes->size(); i++) {
|
||||
CopyNodePtr node = (*nodes)[i];
|
||||
if(!node->isStructure) {
|
||||
CopyMasterNodePtr masterNode =
|
||||
static_pointer_cast<CopyMasterNode>(node);
|
||||
size_t off = masterNode->masterPVField->getFieldOffset();
|
||||
size_t nextOffset = masterNode->masterPVField->getNextFieldOffset();
|
||||
if(offset>= off && offset<nextOffset) return masterNode;
|
||||
} else {
|
||||
CopyStructureNodePtr subNode =
|
||||
static_pointer_cast<CopyStructureNode>(node);
|
||||
CopyMasterNodePtr masterNode =
|
||||
getCopyOffset(subNode,masterPVField);
|
||||
if(masterNode.get()!=NULL) return masterNode;
|
||||
}
|
||||
}
|
||||
return NULLCopyMasterNode;
|
||||
}
|
||||
|
||||
CopyMasterNodePtr PVCopy::getMasterNode(
|
||||
CopyStructureNodePtr const &structureNode,
|
||||
std::size_t structureOffset)
|
||||
{
|
||||
CopyNodePtrArrayPtr nodes = structureNode->nodes;
|
||||
for(size_t i=0; i< nodes->size(); i++) {
|
||||
CopyNodePtr node = (*nodes)[i];
|
||||
if(structureOffset>=(node->structureOffset + node->nfields)) continue;
|
||||
if(!node->isStructure) {
|
||||
CopyMasterNodePtr masterNode =
|
||||
static_pointer_cast<CopyMasterNode>(node);
|
||||
return masterNode;
|
||||
}
|
||||
CopyStructureNodePtr subNode =
|
||||
static_pointer_cast<CopyStructureNode>(node);
|
||||
return getMasterNode(subNode,structureOffset);
|
||||
}
|
||||
return NULLCopyMasterNode;
|
||||
}
|
||||
|
||||
}}
|
||||
230
src/copy/pvCopy.h
Normal file
230
src/copy/pvCopy.h
Normal file
@@ -0,0 +1,230 @@
|
||||
/* pvCopy.h */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author Marty Kraimer
|
||||
* @date 2013.04
|
||||
*/
|
||||
#ifndef PVCOPY_H
|
||||
#define PVCOPY_H
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <memory>
|
||||
|
||||
#include <shareLib.h>
|
||||
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/bitSet.h>
|
||||
|
||||
namespace epics { namespace pvData{
|
||||
|
||||
class PVCopyTraverseMasterCallback;
|
||||
typedef std::tr1::shared_ptr<PVCopyTraverseMasterCallback> PVCopyTraverseMasterCallbackPtr;
|
||||
|
||||
/**
|
||||
* Callback for traversing master structure
|
||||
* Must be implemented by code that creates pvCopy.
|
||||
*/
|
||||
class epicsShareClass PVCopyTraverseMasterCallback
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(PVCopyTraverseMasterCallback);
|
||||
virtual ~PVCopyTraverseMasterCallback() {}
|
||||
/**
|
||||
* Called once for each field in master.
|
||||
* @param pvField The field in master.
|
||||
*/
|
||||
virtual void nextMasterPVField(epics::pvData::PVFieldPtr const &pvField) = 0;
|
||||
};
|
||||
|
||||
|
||||
class PVCopy;
|
||||
typedef std::tr1::shared_ptr<PVCopy> PVCopyPtr;
|
||||
|
||||
struct CopyNode;
|
||||
typedef std::tr1::shared_ptr<CopyNode> CopyNodePtr;
|
||||
struct CopyMasterNode;
|
||||
typedef std::tr1::shared_ptr<CopyMasterNode> CopyMasterNodePtr;
|
||||
struct CopyStructureNode;
|
||||
typedef std::tr1::shared_ptr<CopyStructureNode> CopyStructureNodePtr;
|
||||
|
||||
|
||||
/**
|
||||
* Class that manages one or more PVStructures that holds an arbitrary subset of the fields
|
||||
* in another PVStructure called master.
|
||||
*/
|
||||
class epicsShareClass PVCopy :
|
||||
public std::tr1::enable_shared_from_this<PVCopy>
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(PVCopy);
|
||||
/**
|
||||
* Create a new pvCopy
|
||||
* @param pvMaster The top level sructure for which a copy of
|
||||
* an arbritary subset of the fields in master will be created and managed.
|
||||
* @param pvRequest Selects the set of subfields desired and options for each field.
|
||||
* @param structureName The name for the top level of any PVStructure created.
|
||||
*/
|
||||
static PVCopyPtr create(
|
||||
PVStructurePtr const &pvMaster,
|
||||
PVStructurePtr const &pvRequest,
|
||||
String const & structureName);
|
||||
virtual ~PVCopy(){}
|
||||
virtual void destroy();
|
||||
/**
|
||||
* Get the top level structure of master
|
||||
* @returns The master top level structure.
|
||||
* This should not be modified.
|
||||
*/
|
||||
PVStructurePtr getPVMaster();
|
||||
/**
|
||||
* Traverse all the fields in master.
|
||||
* @param callback This is called for each field on master.
|
||||
*/
|
||||
void traverseMaster(PVCopyTraverseMasterCallbackPtr const & callback)
|
||||
{
|
||||
traverseMaster(headNode,callback);
|
||||
}
|
||||
/**
|
||||
* Get the introspection interface for a PVStructure for e copy.
|
||||
*/
|
||||
StructureConstPtr getStructure();
|
||||
/**
|
||||
* Create a copy instance. Monitors keep a queue of monitor elements.
|
||||
* Since each element needs a PVStructure, multiple top level structures will be created.
|
||||
*/
|
||||
PVStructurePtr createPVStructure();
|
||||
/**
|
||||
* Given a field in pvMaster. return the offset in copy for the same field.
|
||||
* A value of String::npos means that the copy does not have this field.
|
||||
* @param masterPVField The field in master.
|
||||
*/
|
||||
std::size_t getCopyOffset(PVFieldPtr const &masterPVField);
|
||||
/**
|
||||
* Given a field in pvMaster. return the offset in copy for the same field.
|
||||
* A value of String::npos means that the copy does not have this field.
|
||||
* @param masterPVStructure A structure in master that has masterPVField.
|
||||
* @param masterPVField The field in master.
|
||||
*/
|
||||
std::size_t getCopyOffset(
|
||||
PVStructurePtr const &masterPVStructure,
|
||||
PVFieldPtr const &masterPVField);
|
||||
/**
|
||||
* Given a offset in the copy get the corresponding field in pvMaster.
|
||||
* @param offset The offset in the copy.
|
||||
*/
|
||||
PVFieldPtr getMasterPVField(std::size_t structureOffset);
|
||||
/**
|
||||
* Initialize the fields in copyPVStructure by giving each field
|
||||
* the value from the corresponding field in pvMaster.
|
||||
* bitSet will be set to show that all fields are changed.
|
||||
* @param copyPVStructure A copy top level structure.
|
||||
* @param bitSet A bitSet for copyPVStructure.
|
||||
*/
|
||||
void initCopy(
|
||||
PVStructurePtr const ©PVStructure,
|
||||
BitSetPtr const &bitSet);
|
||||
/**
|
||||
* Set all fields in copyPVStructure to the value of the corresponding field in pvMaster.
|
||||
* Each field that is changed has it's corresponding bit set in bitSet.
|
||||
* @param copyPVStructure A copy top level structure.
|
||||
* @param bitSet A bitSet for copyPVStructure.
|
||||
*/
|
||||
void updateCopySetBitSet(
|
||||
PVStructurePtr const ©PVStructure,
|
||||
BitSetPtr const &bitSet);
|
||||
/**
|
||||
* For each set bit in bitSet
|
||||
* set the field in copyPVStructure to the value of the corrseponding field in pvMaster.
|
||||
* @param copyPVStructure A copy top level structure.
|
||||
* @param bitSet A bitSet for copyPVStructure.
|
||||
*/
|
||||
void updateCopyFromBitSet(
|
||||
PVStructurePtr const ©PVStructure,
|
||||
BitSetPtr const &bitSet);
|
||||
/**
|
||||
* For each set bit in bitSet
|
||||
* set the field in pvMaster to the value of the corrseponding field in copyPVStructure
|
||||
* @param copyPVStructure A copy top level structure.
|
||||
* @param bitSet A bitSet for copyPVStructure.
|
||||
*/
|
||||
void updateMaster(
|
||||
PVStructurePtr const ©PVStructure,
|
||||
BitSetPtr const &bitSet);
|
||||
/**
|
||||
* Get the options for the field at the specified offset.
|
||||
* @param offset the offset in copy.
|
||||
* @returns A NULL is returned if no options were specified for the field.
|
||||
* If options were specified,PVStructurePtr is a structures
|
||||
* with a set of PVString subfields that specify name,value pairs.s
|
||||
* name is the subField name and value is the subField value.
|
||||
*/
|
||||
PVStructurePtr getOptions(std::size_t fieldOffset);
|
||||
/**
|
||||
* For debugging.
|
||||
*/
|
||||
String dump();
|
||||
private:
|
||||
void dump(
|
||||
String *builder,
|
||||
CopyNodePtr const &node,
|
||||
int indentLevel);
|
||||
PVCopyPtr getPtrSelf()
|
||||
{
|
||||
return shared_from_this();
|
||||
}
|
||||
void traverseMaster(CopyNodePtr const &node, PVCopyTraverseMasterCallbackPtr const & callback);
|
||||
|
||||
PVStructurePtr pvMaster;
|
||||
StructureConstPtr structure;
|
||||
CopyNodePtr headNode;
|
||||
PVStructurePtr cacheInitStructure;
|
||||
PVCopy(PVStructurePtr const &pvMaster);
|
||||
friend class PVCopyMonitor;
|
||||
bool init(PVStructurePtr const &pvRequest);
|
||||
String dump(
|
||||
String const &value,
|
||||
CopyNodePtr const &node,
|
||||
int indentLevel);
|
||||
StructureConstPtr createStructure(
|
||||
PVStructurePtr const &pvMaster,
|
||||
PVStructurePtr const &pvFromRequest);
|
||||
CopyNodePtr createStructureNodes(
|
||||
PVStructurePtr const &pvMasterStructure,
|
||||
PVStructurePtr const &pvFromRequest,
|
||||
PVStructurePtr const &pvFromField);
|
||||
void updateStructureNodeSetBitSet(
|
||||
PVStructurePtr const &pvCopy,
|
||||
CopyStructureNodePtr const &structureNode,
|
||||
BitSetPtr const &bitSet);
|
||||
void updateSubFieldSetBitSet(
|
||||
PVFieldPtr const &pvCopy,
|
||||
PVFieldPtr const &pvMaster,
|
||||
BitSetPtr const &bitSet);
|
||||
void updateStructureNodeFromBitSet(
|
||||
PVStructurePtr const &pvCopy,
|
||||
CopyStructureNodePtr const &structureNode,
|
||||
BitSetPtr const &bitSet,
|
||||
bool toCopy,
|
||||
bool doAll);
|
||||
void updateSubFieldFromBitSet(
|
||||
PVFieldPtr const &pvCopy,
|
||||
PVFieldPtr const &pvMasterField,
|
||||
BitSetPtr const &bitSet,
|
||||
bool toCopy,
|
||||
bool doAll);
|
||||
CopyMasterNodePtr getCopyOffset(
|
||||
CopyStructureNodePtr const &structureNode,
|
||||
PVFieldPtr const &masterPVField);
|
||||
CopyMasterNodePtr getMasterNode(
|
||||
CopyStructureNodePtr const &structureNode,
|
||||
std::size_t structureOffset);
|
||||
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif /* PVCOPY_H */
|
||||
@@ -50,9 +50,10 @@ void Convert::getString(StringBuilder buf,PVField const *pvField,int /*indentLev
|
||||
{
|
||||
// TODO indextLevel ignored
|
||||
std::ostringstream strm;
|
||||
PrinterPlain p;
|
||||
p.setStream(strm);
|
||||
p.print(*pvField);
|
||||
strm << pvField->dumpValue(strm) << std::endl;
|
||||
// PrinterPlain p;
|
||||
// p.setStream(strm);
|
||||
// p.print(*pvField);
|
||||
strm.str().swap(*buf);
|
||||
}
|
||||
|
||||
@@ -470,7 +471,7 @@ void Convert::copyUnion(PVUnionPtr const & from, PVUnionPtr const & to)
|
||||
if (fromValue.get() == 0)
|
||||
to->select(PVUnion::UNDEFINED_INDEX);
|
||||
else
|
||||
copy(fromValue, to->select(from->getSelectedIndex()));
|
||||
to->set(from->getSelectedFieldName(),from->get());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -216,8 +216,15 @@ static UnionConstPtr deserializeUnionField(const FieldCreate* fieldCreate, ByteB
|
||||
return fieldCreate->createUnion(id, fieldNames, fields);
|
||||
}
|
||||
|
||||
Array::Array(Type type)
|
||||
: Field(type)
|
||||
{
|
||||
}
|
||||
|
||||
Array::~Array() {}
|
||||
|
||||
ScalarArray::ScalarArray(ScalarType elementType)
|
||||
: Field(scalarArray),elementType(elementType)
|
||||
: Array(scalarArray),elementType(elementType)
|
||||
{
|
||||
if(elementType<0 || elementType>MAX_SCALAR_TYPE)
|
||||
throw std::invalid_argument("Can't construct ScalarArray from invalid ScalarType");
|
||||
@@ -282,7 +289,7 @@ void ScalarArray::deserialize(ByteBuffer* /*buffer*/, DeserializableControl* /*c
|
||||
}
|
||||
|
||||
StructureArray::StructureArray(StructureConstPtr const & structure)
|
||||
: Field(structureArray),pstructure(structure)
|
||||
: Array(structureArray),pstructure(structure)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -312,7 +319,7 @@ void StructureArray::deserialize(ByteBuffer* /*buffer*/, DeserializableControl*
|
||||
}
|
||||
|
||||
UnionArray::UnionArray(UnionConstPtr const & _punion)
|
||||
: Field(unionArray),punion(_punion)
|
||||
: Array(unionArray),punion(_punion)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -781,6 +788,13 @@ ScalarArrayConstPtr FieldCreate::createScalarArray(ScalarType elementType) const
|
||||
return scalarArrays[elementType];
|
||||
}
|
||||
|
||||
StructureConstPtr FieldCreate::createStructure () const
|
||||
{
|
||||
StringArray fieldNames;
|
||||
FieldConstPtrArray fields;
|
||||
return createStructure(fieldNames,fields);
|
||||
}
|
||||
|
||||
StructureConstPtr FieldCreate::createStructure (
|
||||
StringArray const & fieldNames,FieldConstPtrArray const & fields) const
|
||||
{
|
||||
|
||||
@@ -5,7 +5,6 @@ SRC_DIRS += $(PVDATA_SRC)/factory
|
||||
INC += factory.h
|
||||
LIBSRCS += TypeFunc.cpp
|
||||
LIBSRCS += FieldCreateFactory.cpp
|
||||
LIBSRCS += PVAuxInfoImpl.cpp
|
||||
LIBSRCS += PVField.cpp
|
||||
LIBSRCS += PVScalar.cpp
|
||||
LIBSRCS += PVArray.cpp
|
||||
|
||||
@@ -1,86 +0,0 @@
|
||||
/*PVAuxInfo.cpp*/
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
*/
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/noDefaultMethods.h>
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/convert.h>
|
||||
#include <pv/factory.h>
|
||||
#include <pv/lock.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
|
||||
PVAuxInfo::PVAuxInfo(PVField * pvField)
|
||||
: pvField(pvField),
|
||||
pvInfos(std::map<String,std::tr1::shared_ptr<PVScalar> > ())
|
||||
{
|
||||
}
|
||||
|
||||
PVAuxInfo::~PVAuxInfo()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
PVField * PVAuxInfo::getPVField() {
|
||||
return pvField;
|
||||
}
|
||||
|
||||
|
||||
PVScalarPtr PVAuxInfo::createInfo(String const & key,ScalarType scalarType)
|
||||
{
|
||||
PVInfoIter iter = pvInfos.find(key);
|
||||
if(iter!=pvInfos.end()) {
|
||||
String message = key.c_str();
|
||||
message += " already exists ";
|
||||
pvField->message(message,errorMessage);
|
||||
return nullPVScalar;
|
||||
}
|
||||
PVScalarPtr pvScalar = getPVDataCreate()->createPVScalar(scalarType);
|
||||
pvInfos.insert(PVInfoPair(key,pvScalar));
|
||||
return pvScalar;
|
||||
}
|
||||
|
||||
PVScalarPtr PVAuxInfo::getInfo(String const & key)
|
||||
{
|
||||
PVInfoIter iter;
|
||||
iter = pvInfos.find(key);
|
||||
if(iter==pvInfos.end()) return nullPVScalar;
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
PVAuxInfo::PVInfoMap & PVAuxInfo::getInfoMap()
|
||||
{
|
||||
return pvInfos;
|
||||
}
|
||||
|
||||
|
||||
void PVAuxInfo::toString(StringBuilder buf)
|
||||
{
|
||||
PVAuxInfo::toString(buf,0);
|
||||
}
|
||||
|
||||
void PVAuxInfo::toString(StringBuilder buf,int indentLevel)
|
||||
{
|
||||
if(pvInfos.size()<=0) return;
|
||||
ConvertPtr convert = getConvert();
|
||||
convert->newLine(buf,indentLevel);
|
||||
*buf += "auxInfo";
|
||||
for(PVInfoIter iter = pvInfos.begin(); iter!= pvInfos.end(); ++iter) {
|
||||
convert->newLine(buf,indentLevel+1);
|
||||
PVFieldPtr value = iter->second;
|
||||
value->toString(buf,indentLevel + 1);
|
||||
}
|
||||
}
|
||||
}}
|
||||
@@ -548,16 +548,6 @@ PVScalarPtr PVDataCreate::createPVScalar(PVScalarPtr const & scalarToClone)
|
||||
ScalarType scalarType = scalarToClone->getScalar()->getScalarType();
|
||||
PVScalarPtr pvScalar = createPVScalar(scalarType);
|
||||
getConvert()->copyScalar(scalarToClone, pvScalar);
|
||||
PVAuxInfoPtr from = scalarToClone->getPVAuxInfo();
|
||||
PVAuxInfoPtr to = pvScalar->getPVAuxInfo();
|
||||
PVAuxInfo::PVInfoMap & map = from->getInfoMap();
|
||||
for(PVAuxInfo::PVInfoIter iter = map.begin(); iter!= map.end(); ++iter) {
|
||||
String key = iter->first;
|
||||
PVScalarPtr pvFrom = iter->second;
|
||||
ScalarConstPtr scalar = pvFrom->getScalar();
|
||||
PVScalarPtr pvTo = to->createInfo(key,scalar->getScalarType());
|
||||
getConvert()->copyScalar(pvFrom,pvTo);
|
||||
}
|
||||
return pvScalar;
|
||||
}
|
||||
|
||||
@@ -607,16 +597,6 @@ PVScalarArrayPtr PVDataCreate::createPVScalarArray(
|
||||
PVScalarArrayPtr pvArray = createPVScalarArray(
|
||||
arrayToClone->getScalarArray()->getElementType());
|
||||
pvArray->assign(*arrayToClone.get());
|
||||
PVAuxInfoPtr from = arrayToClone->getPVAuxInfo();
|
||||
PVAuxInfoPtr to = pvArray->getPVAuxInfo();
|
||||
PVAuxInfo::PVInfoMap & map = from->getInfoMap();
|
||||
for(PVAuxInfo::PVInfoIter iter = map.begin(); iter!= map.end(); ++iter) {
|
||||
String key = iter->first;
|
||||
PVScalarPtr pvFrom = iter->second;
|
||||
ScalarConstPtr scalar = pvFrom->getScalar();
|
||||
PVScalarPtr pvTo = to->createInfo(key,scalar->getScalarType());
|
||||
getConvert()->copyScalar(pvFrom,pvTo);
|
||||
}
|
||||
return pvArray;
|
||||
}
|
||||
|
||||
|
||||
@@ -35,49 +35,6 @@ PVField::PVField(FieldConstPtr field)
|
||||
PVField::~PVField()
|
||||
{ }
|
||||
|
||||
void PVField::message(
|
||||
String message,
|
||||
MessageType messageType,
|
||||
String fullFieldName)
|
||||
{
|
||||
if(parent!=NULL) {
|
||||
if(fullFieldName.length()>0) {
|
||||
fullFieldName = fieldName + '.' + fullFieldName;
|
||||
} else {
|
||||
fullFieldName = fieldName;
|
||||
}
|
||||
parent->message(message,messageType,fullFieldName);
|
||||
return;
|
||||
}
|
||||
message = fullFieldName + " " + message;
|
||||
if(requester) {
|
||||
requester->message(message,messageType);
|
||||
} else {
|
||||
printf("%s %s %s\n",
|
||||
getMessageTypeName(messageType).c_str(),
|
||||
fieldName.c_str(),
|
||||
message.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void PVField::message(String message,MessageType messageType)
|
||||
{
|
||||
PVField::message(message,messageType,"");
|
||||
}
|
||||
|
||||
void PVField::setRequester(RequesterPtr const &req)
|
||||
{
|
||||
if(parent!=NULL) {
|
||||
throw std::logic_error(
|
||||
"PVField::setRequester only legal for top level structure");
|
||||
}
|
||||
if(requester.get()!=NULL) {
|
||||
if(requester.get()==req.get()) return;
|
||||
throw std::logic_error(
|
||||
"PVField::setRequester requester is already present");
|
||||
}
|
||||
requester = req;
|
||||
}
|
||||
|
||||
size_t PVField::getFieldOffset() const
|
||||
{
|
||||
@@ -97,12 +54,6 @@ size_t PVField::getNumberFields() const
|
||||
return (nextFieldOffset - fieldOffset);
|
||||
}
|
||||
|
||||
PVAuxInfoPtr & PVField::getPVAuxInfo(){
|
||||
if(pvAuxInfo.get()==NULL) {
|
||||
pvAuxInfo = PVAuxInfoPtr(new PVAuxInfo(this));
|
||||
}
|
||||
return pvAuxInfo;
|
||||
}
|
||||
|
||||
bool PVField::isImmutable() const {return immutable;}
|
||||
|
||||
@@ -112,46 +63,6 @@ const FieldConstPtr & PVField::getField() const {return field;}
|
||||
|
||||
PVStructure *PVField::getParent() const {return parent;}
|
||||
|
||||
void PVField::replacePVField(const PVFieldPtr & newPVField)
|
||||
{
|
||||
if(parent==NULL) {
|
||||
throw std::logic_error("no parent");
|
||||
}
|
||||
PVFieldPtrArray pvFields = parent->getPVFields();
|
||||
StructureConstPtr structure = parent->getStructure();
|
||||
StringArray fieldNames = structure->getFieldNames();
|
||||
for(size_t i=0; i<fieldNames.size(); i++) {
|
||||
if(newPVField->getFieldName().compare(fieldNames[i]) == 0) {
|
||||
pvFields[i] = newPVField;
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw std::logic_error("Did not find field in parent");
|
||||
}
|
||||
|
||||
void PVField::replaceField(FieldConstPtr &xxx)
|
||||
{
|
||||
field = xxx;
|
||||
}
|
||||
|
||||
void PVField::renameField(String const & newName)
|
||||
{
|
||||
if(parent==NULL) {
|
||||
throw std::logic_error("no parent");
|
||||
}
|
||||
std::tr1::shared_ptr<Structure> parentStructure = const_pointer_cast<Structure>(
|
||||
parent->getStructure());
|
||||
PVFieldPtrArray pvFields = parent->getPVFields();
|
||||
for(size_t i=0; i<pvFields.size(); i++) {
|
||||
if(pvFields[i].get()==this) {
|
||||
parentStructure->renameField(i,newName);
|
||||
fieldName = newName;
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw std::logic_error("Did not find field in parent");
|
||||
}
|
||||
|
||||
void PVField::postPut()
|
||||
{
|
||||
if(postHandler.get()!=NULL) postHandler->postPut();
|
||||
@@ -187,14 +98,11 @@ void PVField::toString(StringBuilder buf)
|
||||
void PVField::toString(StringBuilder buf,int indentLevel)
|
||||
{
|
||||
Convert().getString(buf,this,indentLevel);
|
||||
if(pvAuxInfo.get()!=NULL) pvAuxInfo->toString(buf,indentLevel);
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& o, const PVField& f)
|
||||
{
|
||||
std::ostream& ro = f.dumpValue(o);
|
||||
// TODO I do not want to call getPVAuxInfo() since it lazily creates a new instance of it
|
||||
//if (f.pvAuxInfo.get()!=NULL) ro << *(f.pvAuxInfo.get());
|
||||
return ro;
|
||||
};
|
||||
|
||||
@@ -221,26 +129,12 @@ namespace format
|
||||
|
||||
String PVField::getFullName() const
|
||||
{
|
||||
size_t size=fieldName.size();
|
||||
|
||||
String ret(fieldName);
|
||||
for(PVField *fld=getParent(); fld; fld=fld->getParent())
|
||||
{
|
||||
size+=fld->fieldName.size()+1;
|
||||
if(fld->getFieldName().size()==0) break;
|
||||
ret = fld->getFieldName() + '.' + ret;
|
||||
}
|
||||
|
||||
String ret(size, '.');
|
||||
size_t pos=size - fieldName.size();
|
||||
|
||||
ret.replace(pos, String::npos, fieldName);
|
||||
|
||||
for(PVField *fld=getParent(); fld; fld=fld->getParent())
|
||||
{
|
||||
const String& nref = fld->fieldName;
|
||||
assert(pos >= nref.size()+1);
|
||||
pos -= nref.size()+1;
|
||||
ret.replace(pos, String::npos, nref);
|
||||
}
|
||||
assert(pos==0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ PVStructure::PVStructure(StructureConstPtr const & structurePtr)
|
||||
pvFields.reserve(numberFields);
|
||||
PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
||||
for(size_t i=0; i<numberFields; i++) {
|
||||
pvFields.push_back(pvDataCreate->createPVField(fields[i]));
|
||||
pvFields.push_back(pvDataCreate->createPVField(fields[i]));
|
||||
}
|
||||
for(size_t i=0; i<numberFields; i++) {
|
||||
pvFields[i]->setParentAndName(this,fieldNames[i]);
|
||||
@@ -134,110 +134,6 @@ PVFieldPtr PVStructure::getSubField(size_t fieldOffset) const
|
||||
throw std::logic_error("PVStructure.getSubField: Logic error");
|
||||
}
|
||||
|
||||
void PVStructure::fixParentStructure()
|
||||
{
|
||||
PVStructure *parent = getParent();
|
||||
if(parent==NULL) return;
|
||||
StructureConstPtr parentStructure = parent->structurePtr;
|
||||
String fieldName = getFieldName();
|
||||
size_t index = parentStructure->getFieldIndex(fieldName);
|
||||
StringArray const &fieldNames = parentStructure->getFieldNames();
|
||||
size_t num = fieldNames.size();
|
||||
FieldConstPtrArray fields(num);
|
||||
FieldConstPtrArray const & oldFields = parentStructure->getFields();
|
||||
for(size_t i=0; i< num; i++) {
|
||||
if(i==index) {
|
||||
fields[i] = structurePtr;
|
||||
} else {
|
||||
fields[i] = oldFields[i];
|
||||
}
|
||||
}
|
||||
FieldConstPtr field = getFieldCreate()->createStructure(
|
||||
parentStructure->getID(),fieldNames,fields);
|
||||
parent->replaceField(field);
|
||||
parent->fixParentStructure();
|
||||
}
|
||||
|
||||
void PVStructure::appendPVField(
|
||||
String const &fieldName,
|
||||
PVFieldPtr const & pvField)
|
||||
{
|
||||
size_t origLength = pvFields.size();
|
||||
size_t newLength = origLength+1;
|
||||
PVFieldPtrArray * xxx = const_cast<PVFieldPtrArray *>(&pvFields);
|
||||
xxx->push_back(pvField);
|
||||
FieldConstPtr field = getFieldCreate()->appendField(
|
||||
structurePtr,fieldName,pvField->getField());
|
||||
replaceField(field);
|
||||
structurePtr = static_pointer_cast<const Structure>(field);
|
||||
StringArray fieldNames = structurePtr->getFieldNames();
|
||||
for(size_t i=0; i<newLength; i++) {
|
||||
pvFields[i]->setParentAndName(this,fieldNames[i]);
|
||||
}
|
||||
fixParentStructure();
|
||||
}
|
||||
|
||||
void PVStructure::appendPVFields(
|
||||
StringArray const & fieldNames,
|
||||
PVFieldPtrArray const & pvFields)
|
||||
{
|
||||
size_t origLength = this->pvFields.size();
|
||||
size_t extra = fieldNames.size();
|
||||
if(extra==0) return;
|
||||
size_t newLength = origLength + extra;
|
||||
PVFieldPtrArray * xxx = const_cast<PVFieldPtrArray *>(&this->pvFields);
|
||||
xxx->reserve(newLength);
|
||||
for(size_t i=0; i<extra; i++) {
|
||||
xxx->push_back(pvFields[i]);
|
||||
}
|
||||
FieldConstPtrArray fields;
|
||||
fields.reserve(extra);
|
||||
for(size_t i=0; i<extra; i++) fields.push_back(pvFields[i]->getField());
|
||||
FieldConstPtr field = getFieldCreate()->appendFields(
|
||||
structurePtr,fieldNames,fields);
|
||||
replaceField(field);
|
||||
structurePtr = static_pointer_cast<const Structure>(field);
|
||||
StringArray names = structurePtr->getFieldNames();
|
||||
for(size_t i=0; i<newLength; i++) {
|
||||
(*xxx)[i]->setParentAndName(this,names[i]);
|
||||
}
|
||||
fixParentStructure();
|
||||
}
|
||||
|
||||
void PVStructure::removePVField(String const &fieldName)
|
||||
{
|
||||
PVFieldPtr pvField = getSubField(fieldName);
|
||||
if(pvField.get()==NULL) {
|
||||
return;
|
||||
}
|
||||
size_t origLength = pvFields.size();
|
||||
size_t newLength = origLength - 1;
|
||||
PVFieldPtrArray const & origPVFields = pvFields;
|
||||
FieldConstPtrArray origFields = structurePtr->getFields();
|
||||
PVFieldPtrArray newPVFields;
|
||||
newPVFields.reserve(newLength);
|
||||
StringArray newFieldNames;
|
||||
newFieldNames.reserve(newLength);
|
||||
FieldConstPtrArray fields;
|
||||
fields.reserve(newLength);
|
||||
for(size_t i=0; i<origLength; i++) {
|
||||
if(origPVFields[i]!=pvField) {
|
||||
newFieldNames.push_back(origPVFields[i]->getFieldName());
|
||||
newPVFields.push_back(origPVFields[i]);
|
||||
fields.push_back(origFields[i]);
|
||||
}
|
||||
}
|
||||
PVFieldPtrArray * xxx = const_cast<PVFieldPtrArray *>(&pvFields);
|
||||
xxx->swap(newPVFields);
|
||||
FieldConstPtr field = getFieldCreate()->createStructure(
|
||||
structurePtr->getID(),newFieldNames,fields);
|
||||
replaceField(field);
|
||||
structurePtr = static_pointer_cast<const Structure>(field);
|
||||
StringArray fieldNames = structurePtr->getFieldNames();
|
||||
for(size_t i=0; i<newLength; i++) {
|
||||
pvFields[i]->setParentAndName(this,fieldNames[i]);
|
||||
}
|
||||
}
|
||||
|
||||
PVBooleanPtr PVStructure::getBooleanField(String const &fieldName)
|
||||
{
|
||||
@@ -341,18 +237,6 @@ PVUnionArrayPtr PVStructure::getUnionArrayField(
|
||||
return getSubField<PVUnionArray>(fieldName);
|
||||
}
|
||||
|
||||
String PVStructure::getExtendsStructureName() const
|
||||
{
|
||||
return extendsStructureName;
|
||||
}
|
||||
|
||||
bool PVStructure::putExtendsStructureName(
|
||||
String const &xxx)
|
||||
{
|
||||
if(extendsStructureName.length()!=0) return false;
|
||||
extendsStructureName = xxx;
|
||||
return true;
|
||||
}
|
||||
|
||||
void PVStructure::serialize(ByteBuffer *pbuffer,
|
||||
SerializableControl *pflusher) const {
|
||||
@@ -477,10 +361,6 @@ static PVFieldPtr findSubField(
|
||||
std::ostream& PVStructure::dumpValue(std::ostream& o) const
|
||||
{
|
||||
o << format::indent() << getStructure()->getID() << ' ' << getFieldName();
|
||||
String extendsName = getExtendsStructureName();
|
||||
if(extendsName.length()>0) {
|
||||
o << " extends " << extendsName;
|
||||
}
|
||||
o << std::endl;
|
||||
{
|
||||
format::indent_scope s(o);
|
||||
|
||||
@@ -126,6 +126,7 @@ void PVUnion::set(int32 index, PVFieldPtr const & value)
|
||||
|
||||
selector = index;
|
||||
this->value = value;
|
||||
postPut();
|
||||
}
|
||||
|
||||
void PVUnion::set(String const & fieldName, PVFieldPtr const & value)
|
||||
|
||||
@@ -505,6 +505,20 @@ StructureConstPtr StandardField::scalar(
|
||||
return createProperties("uri:ev4:nt/2012/pwd:NTScalar",field,properties);
|
||||
}
|
||||
|
||||
StructureConstPtr StandardField::regUnion(
|
||||
UnionConstPtr const &field,
|
||||
String const & properties)
|
||||
{
|
||||
return createProperties("uri:ev4:nt/2012/pwd:NTUnion",field,properties);
|
||||
}
|
||||
|
||||
StructureConstPtr StandardField::variantUnion(
|
||||
String const & properties)
|
||||
{
|
||||
UnionConstPtr field = fieldCreate->createVariantUnion();
|
||||
return createProperties("uri:ev4:nt/2012/pwd:NTUnion",field,properties);
|
||||
}
|
||||
|
||||
StructureConstPtr StandardField::scalarArray(
|
||||
ScalarType elementType, String const &properties)
|
||||
{
|
||||
@@ -518,7 +532,15 @@ StructureConstPtr StandardField::structureArray(
|
||||
{
|
||||
StructureArrayConstPtr field = fieldCreate->createStructureArray(
|
||||
structure);
|
||||
return createProperties("uri:ev4:nt/2012/pwd:NTAny",field,properties);
|
||||
return createProperties("uri:ev4:nt/2012/pwd:NTStructureArray",field,properties);
|
||||
}
|
||||
|
||||
StructureConstPtr StandardField::unionArray(
|
||||
UnionConstPtr const & punion,String const &properties)
|
||||
{
|
||||
UnionArrayConstPtr field = fieldCreate->createUnionArray(
|
||||
punion);
|
||||
return createProperties("uri:ev4:nt/2012/pwd:NTUnionArray",field,properties);
|
||||
}
|
||||
|
||||
StructureConstPtr StandardField::enumerated()
|
||||
|
||||
@@ -53,6 +53,14 @@ PVStructurePtr StandardPVField::structureArray(
|
||||
return pvStructure;
|
||||
}
|
||||
|
||||
PVStructurePtr StandardPVField::unionArray(
|
||||
UnionConstPtr const & punion,String const & properties)
|
||||
{
|
||||
StructureConstPtr field = standardField->unionArray(punion,properties);
|
||||
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(field);
|
||||
return pvStructure;
|
||||
}
|
||||
|
||||
PVStructurePtr StandardPVField::enumerated(StringArray const &choices)
|
||||
{
|
||||
StructureConstPtr field = standardField->enumerated();
|
||||
|
||||
@@ -199,9 +199,6 @@ void PrinterPlain::beginStructure(const PVStructure& pv)
|
||||
{
|
||||
indentN(S(), ilvl);
|
||||
S() << pv.getStructure()->getID() << " " << pv.getFieldName();
|
||||
String ename(pv.getExtendsStructureName());
|
||||
if(!ename.empty())
|
||||
S() << " extends " << ename;
|
||||
S() << std::endl;
|
||||
ilvl++;
|
||||
}
|
||||
|
||||
@@ -15,30 +15,33 @@
|
||||
#include <pv/pvSubArrayCopy.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
template<typename T>
|
||||
void copy(
|
||||
PVValueArray<T> & pvFrom,
|
||||
size_t fromOffset,
|
||||
size_t fromStride,
|
||||
PVValueArray<T> & pvTo,
|
||||
size_t toOffset,
|
||||
size_t len)
|
||||
size_t toStride,
|
||||
size_t count)
|
||||
{
|
||||
if(pvTo.isImmutable()) {
|
||||
throw std::logic_error("pvSubArrayCopy to is immutable");
|
||||
}
|
||||
if(pvTo.isImmutable()) throw std::invalid_argument("pvSubArrayCopy: pvTo is immutable");
|
||||
if(fromStride<1 || toStride<1) throw std::invalid_argument("stride must be >=1");
|
||||
size_t fromLength = pvFrom.getLength();
|
||||
if(fromOffset+len>fromLength) {
|
||||
throw std::length_error("pvSubArrayCopy from length error");
|
||||
}
|
||||
size_t num = fromOffset + count*fromStride;
|
||||
if(num>fromLength) throw std::invalid_argument("pvSubArrayCopy pvFrom length error");
|
||||
size_t newLength = toOffset + count*toStride;
|
||||
size_t capacity = pvTo.getCapacity();
|
||||
if(toOffset+len>capacity) capacity = toOffset + len;
|
||||
if(newLength>capacity) capacity = newLength;
|
||||
shared_vector<T> temp(capacity);
|
||||
typename PVValueArray<T>::const_svector vecFrom = pvFrom.view();
|
||||
typename PVValueArray<T>::const_svector vecTo = pvTo.view();
|
||||
for(size_t i=0; i<toOffset; ++i) temp[i] = vecTo[i];
|
||||
for(size_t i=0; i<len; ++i) temp[i + toOffset] = vecFrom[i + fromOffset];
|
||||
for(size_t i=len + toOffset; i<capacity; ++i) temp[i] = vecTo[i];
|
||||
for(size_t i=0; i<pvTo.getLength(); ++i) temp[i] = vecTo[i];
|
||||
for(size_t i=pvTo.getLength(); i< capacity; ++i) temp[i] = T();
|
||||
for(size_t i=0; i<count; ++i) temp[i*toStride + toOffset] = vecFrom[i*fromStride+fromOffset];
|
||||
shared_vector<const T> temp2(freeze(temp));
|
||||
pvTo.replace(temp2);
|
||||
}
|
||||
@@ -46,9 +49,11 @@ void copy(
|
||||
void copy(
|
||||
PVScalarArray & from,
|
||||
size_t fromOffset,
|
||||
size_t fromStride,
|
||||
PVScalarArray & to,
|
||||
size_t toOffset,
|
||||
size_t len)
|
||||
size_t toStride,
|
||||
size_t count)
|
||||
{
|
||||
ScalarType scalarType = from.getScalarArray()->getElementType();
|
||||
ScalarType otherType = to.getScalarArray()->getElementType();
|
||||
@@ -59,146 +64,170 @@ void copy(
|
||||
{
|
||||
case pvBoolean:
|
||||
{
|
||||
copy(dynamic_cast<PVValueArray<boolean> &>(from),fromOffset,
|
||||
copy(dynamic_cast<PVValueArray<boolean> &>(from),fromOffset,fromStride,
|
||||
dynamic_cast<PVValueArray<boolean>& >(to),
|
||||
toOffset,len);
|
||||
toOffset,toStride,count);
|
||||
}
|
||||
break;
|
||||
case pvByte:
|
||||
{
|
||||
copy(dynamic_cast<PVValueArray<int8> &>(from),fromOffset,
|
||||
copy(dynamic_cast<PVValueArray<int8> &>(from),fromOffset,fromStride,
|
||||
dynamic_cast<PVValueArray<int8>& >(to),
|
||||
toOffset,len);
|
||||
toOffset,toStride,count);
|
||||
}
|
||||
break;
|
||||
case pvShort:
|
||||
{
|
||||
copy(dynamic_cast<PVValueArray<int16> &>(from),fromOffset,
|
||||
copy(dynamic_cast<PVValueArray<int16> &>(from),fromOffset,fromStride,
|
||||
dynamic_cast<PVValueArray<int16>& >(to),
|
||||
toOffset,len);
|
||||
toOffset,toStride,count);
|
||||
}
|
||||
break;
|
||||
case pvInt:
|
||||
{
|
||||
copy(dynamic_cast<PVValueArray<int32> &>(from),fromOffset,
|
||||
copy(dynamic_cast<PVValueArray<int32> &>(from),fromOffset,fromStride,
|
||||
dynamic_cast<PVValueArray<int32>& >(to),
|
||||
toOffset,len);
|
||||
toOffset,toStride,count);
|
||||
}
|
||||
break;
|
||||
case pvLong:
|
||||
{
|
||||
copy(dynamic_cast<PVValueArray<int64> &>(from),fromOffset,
|
||||
copy(dynamic_cast<PVValueArray<int64> &>(from),fromOffset,fromStride,
|
||||
dynamic_cast<PVValueArray<int64>& >(to),
|
||||
toOffset,len);
|
||||
toOffset,toStride,count);
|
||||
}
|
||||
break;
|
||||
case pvUByte:
|
||||
{
|
||||
copy(dynamic_cast<PVValueArray<uint8> &>(from),fromOffset,
|
||||
copy(dynamic_cast<PVValueArray<uint8> &>(from),fromOffset,fromStride,
|
||||
dynamic_cast<PVValueArray<uint8>& >(to),
|
||||
toOffset,len);
|
||||
toOffset,toStride,count);
|
||||
}
|
||||
break;
|
||||
case pvUShort:
|
||||
{
|
||||
copy(dynamic_cast<PVValueArray<uint16> &>(from),fromOffset,
|
||||
copy(dynamic_cast<PVValueArray<uint16> &>(from),fromOffset,fromStride,
|
||||
dynamic_cast<PVValueArray<uint16>& >(to),
|
||||
toOffset,len);
|
||||
toOffset,toStride,count);
|
||||
}
|
||||
break;
|
||||
case pvUInt:
|
||||
{
|
||||
copy(dynamic_cast<PVValueArray<uint32> &>(from),fromOffset,
|
||||
copy(dynamic_cast<PVValueArray<uint32> &>(from),fromOffset,fromStride,
|
||||
dynamic_cast<PVValueArray<uint32>& >(to),
|
||||
toOffset,len);
|
||||
toOffset,toStride,count);
|
||||
}
|
||||
break;
|
||||
case pvULong:
|
||||
{
|
||||
copy(dynamic_cast<PVValueArray<uint64> &>(from),fromOffset,
|
||||
copy(dynamic_cast<PVValueArray<uint64> &>(from),fromOffset,fromStride,
|
||||
dynamic_cast<PVValueArray<uint64>& >(to),
|
||||
toOffset,len);
|
||||
toOffset,toStride,count);
|
||||
}
|
||||
break;
|
||||
case pvFloat:
|
||||
{
|
||||
copy(dynamic_cast<PVValueArray<float> &>(from),fromOffset,
|
||||
copy(dynamic_cast<PVValueArray<float> &>(from),fromOffset,fromStride,
|
||||
dynamic_cast<PVValueArray<float>& >(to),
|
||||
toOffset,len);
|
||||
toOffset,toStride,count);
|
||||
}
|
||||
break;
|
||||
case pvDouble:
|
||||
{
|
||||
copy(dynamic_cast<PVValueArray<double> &>(from),fromOffset,
|
||||
copy(dynamic_cast<PVValueArray<double> &>(from),fromOffset,fromStride,
|
||||
dynamic_cast<PVValueArray<double>& >(to),
|
||||
toOffset,len);
|
||||
toOffset,toStride,count);
|
||||
}
|
||||
break;
|
||||
case pvString:
|
||||
{
|
||||
copy(dynamic_cast<PVValueArray<String> &>(from),fromOffset,
|
||||
copy(dynamic_cast<PVValueArray<String> &>(from),fromOffset,fromStride,
|
||||
dynamic_cast<PVValueArray<String>& >(to),
|
||||
toOffset,len);
|
||||
toOffset,toStride,count);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void copy(
|
||||
PVStructureArray & from,
|
||||
size_t fromOffset,
|
||||
PVStructureArray & to,
|
||||
PVStructureArray & pvFrom,
|
||||
size_t pvFromOffset,
|
||||
size_t pvFromStride,
|
||||
PVStructureArray & pvTo,
|
||||
size_t toOffset,
|
||||
size_t len)
|
||||
size_t toStride,
|
||||
size_t count)
|
||||
{
|
||||
if(to.isImmutable()) {
|
||||
throw std::logic_error("pvSubArrayCopy to is immutable");
|
||||
if(pvTo.isImmutable()) {
|
||||
throw std::logic_error("pvSubArrayCopy pvTo is immutable");
|
||||
}
|
||||
StructureArrayConstPtr fromStructure = from.getStructureArray();
|
||||
StructureArrayConstPtr toStructure = to.getStructureArray();
|
||||
if(fromStructure!=toStructure) {
|
||||
if(pvFromStride<1 || toStride<1) throw std::invalid_argument("stride must be >=1");
|
||||
StructureArrayConstPtr pvFromStructure = pvFrom.getStructureArray();
|
||||
StructureArrayConstPtr toStructure = pvTo.getStructureArray();
|
||||
if(pvFromStructure!=toStructure) {
|
||||
throw std::invalid_argument(
|
||||
"pvSubArrayCopy structureArray to and from have different structures");
|
||||
"pvSubArrayCopy structureArray pvTo and pvFrom have different structures");
|
||||
}
|
||||
size_t fromLength = from.getLength();
|
||||
if(fromOffset+len>fromLength) {
|
||||
throw std::length_error("pvSubArrayCopy from length error");
|
||||
}
|
||||
size_t capacity = to.getCapacity();
|
||||
if(toOffset+len>capacity) capacity = toOffset+len;
|
||||
size_t pvFromLength = pvFrom.getLength();
|
||||
size_t num = pvFromOffset + count*pvFromStride;
|
||||
if(num>pvFromLength) throw std::invalid_argument("pvSubArrayCopy pvFrom length error");
|
||||
size_t newLength = toOffset + count*toStride;
|
||||
size_t capacity = pvTo.getCapacity();
|
||||
if(newLength>capacity) capacity = newLength;
|
||||
shared_vector<PVStructurePtr> temp(capacity);
|
||||
PVValueArray<PVStructurePtr>::const_svector vecFrom = from.view();
|
||||
PVValueArray<PVStructurePtr>::const_svector vecTo = to.view();
|
||||
for(size_t i=0; i<toOffset; ++i) temp[i] = vecTo[i];
|
||||
for(size_t i=0; i<len; ++i) temp[i + toOffset] = vecFrom[i + fromOffset];
|
||||
for(size_t i=len + toOffset; i<capacity; ++i) temp[i] = vecTo[i];
|
||||
PVValueArray<PVStructurePtr>::const_svector vecFrom = pvFrom.view();
|
||||
PVValueArray<PVStructurePtr>::const_svector vecTo = pvTo.view();
|
||||
for(size_t i=0; i<pvTo.getLength(); ++i) temp[i] = vecTo[i];
|
||||
for(size_t i=pvTo.getLength(); i< capacity; ++i)
|
||||
temp[i] = getPVDataCreate()->createPVStructure(toStructure->getStructure());
|
||||
for(size_t i=0; i<count; ++i) temp[i*toStride + toOffset] = vecFrom[i*pvFromStride+pvFromOffset];
|
||||
shared_vector<const PVStructurePtr> temp2(freeze(temp));
|
||||
to.replace(temp2);
|
||||
pvTo.replace(temp2);
|
||||
}
|
||||
|
||||
void copy(
|
||||
PVArray & from,
|
||||
size_t fromOffset,
|
||||
PVArray & to,
|
||||
size_t toOffset,
|
||||
size_t len)
|
||||
PVArray & pvFrom,
|
||||
size_t pvFromOffset,
|
||||
size_t pvFromStride,
|
||||
PVArray & pvTo,
|
||||
size_t pvToOffset,
|
||||
size_t pvToStride,
|
||||
size_t count)
|
||||
{
|
||||
Type type = from.getField()->getType();
|
||||
Type otherType = to.getField()->getType();
|
||||
if(type!=otherType) {
|
||||
throw std::invalid_argument("pvSubArrayCopy types do not match");
|
||||
Type pvFromType = pvFrom.getField()->getType();
|
||||
Type pvToType = pvTo.getField()->getType();
|
||||
if(pvFromType!=pvToType) throw std::invalid_argument("pvSubArrayCopy: pvFrom and pvTo different types");
|
||||
if(pvFromType==scalarArray) {
|
||||
ScalarType pvFromScalarType= static_cast<ScalarType>(pvFromType);
|
||||
ScalarType pvToScalarType = static_cast<ScalarType>(pvToType);
|
||||
if(pvFromScalarType!=pvToScalarType){
|
||||
throw std::invalid_argument("pvSubArrayCopy: pvFrom and pvTo different types");
|
||||
}
|
||||
}
|
||||
if(type==scalarArray) {
|
||||
copy(dynamic_cast<PVScalarArray &>(from) ,fromOffset,
|
||||
dynamic_cast<PVScalarArray&>(to),
|
||||
toOffset,len);
|
||||
if(pvTo.isImmutable()) throw std::invalid_argument("pvSubArrayCopy: pvTo is immutable");
|
||||
if(pvFromType==scalarArray) {
|
||||
copy(dynamic_cast<PVScalarArray &>(pvFrom) ,pvFromOffset,pvFromStride,
|
||||
dynamic_cast<PVScalarArray&>(pvTo),
|
||||
pvToOffset,pvToStride,count);
|
||||
}
|
||||
if(type==structureArray) {
|
||||
copy(dynamic_cast<PVStructureArray &>(from) ,fromOffset,
|
||||
dynamic_cast<PVStructureArray&>(to),
|
||||
toOffset,len);
|
||||
if(pvFromType==structureArray) {
|
||||
copy(dynamic_cast<PVStructureArray &>(pvFrom) ,pvFromOffset,pvFromStride,
|
||||
dynamic_cast<PVStructureArray&>(pvTo),
|
||||
pvToOffset,pvToStride,count);
|
||||
}
|
||||
}
|
||||
|
||||
void copy(
|
||||
PVArray::shared_pointer const & pvFrom,
|
||||
size_t pvFromOffset,
|
||||
size_t pvFromStride,
|
||||
PVArray::shared_pointer & pvTo,
|
||||
size_t pvToOffset,
|
||||
size_t pvToStride,
|
||||
size_t count)
|
||||
{
|
||||
copy(*pvFrom,pvFromOffset,pvFromStride,*pvTo,pvToOffset,pvToStride,count);
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
|
||||
@@ -374,5 +374,20 @@ namespace epics { namespace pvData {
|
||||
words[i] |= (buffer->getByte() & 0xffL) << (8 * j);
|
||||
|
||||
}
|
||||
|
||||
epicsShareExtern std::ostream& operator<<(std::ostream& o, const BitSet& b)
|
||||
{
|
||||
o << '{';
|
||||
int32 i = b.nextSetBit(0);
|
||||
if (i != -1) {
|
||||
o << i;
|
||||
for (i = b.nextSetBit(i+1); i >= 0; i = b.nextSetBit(i+1)) {
|
||||
int32 endOfRun = b.nextClearBit(i);
|
||||
do { o << ", " << i; } while (++i < endOfRun);
|
||||
}
|
||||
}
|
||||
o << '}';
|
||||
return o;
|
||||
}
|
||||
|
||||
}};
|
||||
|
||||
@@ -317,6 +317,8 @@ namespace epics { namespace pvData {
|
||||
static uint32 bitCount(uint64 i);
|
||||
|
||||
};
|
||||
|
||||
epicsShareExtern std::ostream& operator<<(std::ostream& o, const BitSet& b);
|
||||
|
||||
}}
|
||||
#endif /* BITSET_H */
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
SRC_DIRS += $(PVDATA_SRC)/monitor
|
||||
|
||||
INC += monitor.h
|
||||
INC += monitorPlugin.h
|
||||
|
||||
LIBSRCS += monitor.cpp
|
||||
|
||||
LIBSRCS += monitorPlugin.cpp
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/sharedPtr.h>
|
||||
#include <pv/bitSet.h>
|
||||
#include <pv/requester.h>
|
||||
|
||||
#include <shareLib.h>
|
||||
|
||||
|
||||
82
src/monitor/monitorPlugin.cpp
Normal file
82
src/monitor/monitorPlugin.cpp
Normal file
@@ -0,0 +1,82 @@
|
||||
/* monitorPlugin.cpp */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
*/
|
||||
|
||||
#include <pv/monitorPlugin.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
MonitorPluginManagerPtr MonitorPluginManager::get()
|
||||
{
|
||||
static MonitorPluginManagerPtr pluginManager;
|
||||
static Mutex mutex;
|
||||
Lock xx(mutex);
|
||||
if(pluginManager==NULL) {
|
||||
pluginManager = MonitorPluginManagerPtr(new MonitorPluginManager());
|
||||
}
|
||||
return pluginManager;
|
||||
}
|
||||
|
||||
bool MonitorPluginManager::addPlugin(
|
||||
String const &pluginName,
|
||||
MonitorPluginCreatorPtr const &creator)
|
||||
{
|
||||
mutex.lock();
|
||||
std::list<MonitorPluginCreatorPtr>::iterator iter;
|
||||
for (iter = monitorPluginList.begin();iter!=monitorPluginList.end();iter++)
|
||||
{
|
||||
if(*iter==creator)
|
||||
{
|
||||
mutex.unlock();
|
||||
return false;
|
||||
}
|
||||
if(((*iter)->getName().compare(pluginName))==0)
|
||||
{
|
||||
mutex.unlock();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
monitorPluginList.push_back(creator);
|
||||
mutex.unlock();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
MonitorPluginCreatorPtr MonitorPluginManager::findPlugin(
|
||||
String const &pluginName)
|
||||
{
|
||||
mutex.lock();
|
||||
std::list<MonitorPluginCreatorPtr>::iterator iter;
|
||||
for (iter = monitorPluginList.begin();iter!=monitorPluginList.end();++iter)
|
||||
{
|
||||
if(((*iter)->getName().compare(pluginName))==0)
|
||||
{
|
||||
mutex.unlock();
|
||||
return *iter;
|
||||
}
|
||||
}
|
||||
mutex.unlock();
|
||||
return MonitorPluginCreatorPtr();
|
||||
}
|
||||
|
||||
void MonitorPluginManager::showNames()
|
||||
{
|
||||
mutex.lock();
|
||||
std::list<MonitorPluginCreatorPtr>::iterator iter;
|
||||
for (iter = monitorPluginList.begin();iter!=monitorPluginList.end();++iter)
|
||||
{
|
||||
std::cout << (*iter)->getName() << std::endl;
|
||||
}
|
||||
mutex.unlock();
|
||||
}
|
||||
|
||||
|
||||
}}
|
||||
177
src/monitor/monitorPlugin.h
Normal file
177
src/monitor/monitorPlugin.h
Normal file
@@ -0,0 +1,177 @@
|
||||
/* monitorPlugin.h */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
*/
|
||||
#ifndef MONITORPLUGIN_H
|
||||
#define MONITORPLUGIN_H
|
||||
|
||||
#include <list>
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/sharedPtr.h>
|
||||
#include <pv/bitSet.h>
|
||||
#include <pv/monitor.h>
|
||||
|
||||
#include <shareLib.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
/**
|
||||
* typedef for a pointer to a MonitorPlugin
|
||||
*/
|
||||
class MonitorPlugin;
|
||||
typedef std::tr1::shared_ptr<MonitorPlugin> MonitorPluginPtr;
|
||||
|
||||
|
||||
/**
|
||||
* typedef for a pointer to a MonitorPluginCreator
|
||||
*/
|
||||
class MonitorPluginCreator;
|
||||
typedef std::tr1::shared_ptr<MonitorPluginCreator> MonitorPluginCreatorPtr;
|
||||
|
||||
|
||||
/**
|
||||
* typedef for a pointer to a MonitorPluginManager
|
||||
*/
|
||||
class MonitorPluginManager;
|
||||
typedef std::tr1::shared_ptr<MonitorPluginManager> MonitorPluginManagerPtr;
|
||||
|
||||
|
||||
/** A plugin for raising monitors;
|
||||
* This is for use by pvAccess servers that support monitors.
|
||||
* Since the interface has only a dependence on pvData it
|
||||
* can be used for other purposes.
|
||||
* A monitor is assumed to be associated with a field of a top level
|
||||
* structure.
|
||||
*/
|
||||
class MonitorPlugin
|
||||
{
|
||||
public:
|
||||
virtual ~MonitorPlugin(){}
|
||||
/**
|
||||
* getName
|
||||
* @returns The name of the plugin
|
||||
*/
|
||||
virtual String const & getName() = 0;
|
||||
/**
|
||||
* Should a monitor be raised?
|
||||
* @param pvField The field being monitored.
|
||||
* @param pvTop The top level sructure in which the field resides.
|
||||
* @param monitorElement The client data and bitSets.
|
||||
* @returns true or false.
|
||||
* True is returned if the change to this field should cause a monitor.
|
||||
* False is returned in a change only to this field should not cause a
|
||||
* monitor.
|
||||
*/
|
||||
virtual bool causeMonitor(
|
||||
PVFieldPtr const &pvField,
|
||||
PVStructurePtr const &pvTop,
|
||||
MonitorElementPtr const &monitorElement) = 0;
|
||||
/**
|
||||
* A monitor will be sent to the client.
|
||||
* @param pvField The copy of the field being monitored.
|
||||
* The plugin can modify the data.
|
||||
* @param pvTop The top level sructure in which the field resides.
|
||||
* @param monitorElement The data for the client.
|
||||
* The plugin is allowed to change the data values.
|
||||
*/
|
||||
virtual void monitorDone(
|
||||
MonitorElementPtr const &monitorElement)
|
||||
{}
|
||||
/**
|
||||
* Begin monitoring
|
||||
*/
|
||||
virtual void startMonitoring(){}
|
||||
/**
|
||||
* Stop monitoring
|
||||
*/
|
||||
virtual void stopMonitoring(){}
|
||||
/**
|
||||
* Begin a set of puts.
|
||||
*/
|
||||
virtual void beginGroupPut() {};
|
||||
/**
|
||||
* End a set of puts.
|
||||
*/
|
||||
virtual void endGroupPut() {};
|
||||
};
|
||||
|
||||
/** A class that creates a plugin.
|
||||
* Normlly a plugin is created for a single client.
|
||||
*/
|
||||
class MonitorPluginCreator
|
||||
{
|
||||
public:
|
||||
virtual ~MonitorPluginCreator() {}
|
||||
/**
|
||||
* Create a monitor plugin.
|
||||
* @param field The introspection interface for the field monitored.
|
||||
* @param top The introspsction interface for the client structure.
|
||||
* @param pvFieldOptions The options the client requested.
|
||||
* The structure has a set of PVString subfields.
|
||||
* The options are a set of name,value pairs.
|
||||
* The subfield name is the name and the subfield value is the value.
|
||||
* @returns shared pointer to a MonitorPluginCreator.
|
||||
*/
|
||||
virtual MonitorPluginPtr create(
|
||||
FieldConstPtr const &field,
|
||||
StructureConstPtr const &top,
|
||||
PVStructurePtr const &pvFieldOptions) = 0;
|
||||
/**
|
||||
* getName
|
||||
* @returns The name of the plugin
|
||||
*/
|
||||
virtual String const & getName() = 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* This manages a set of monitor plugins.
|
||||
* @author mrk
|
||||
*/
|
||||
class epicsShareClass MonitorPluginManager
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(MonitorPluginManager);
|
||||
/**
|
||||
* Factory to get the manager.
|
||||
* @return shared pointer to manager.
|
||||
*/
|
||||
static MonitorPluginManagerPtr get();
|
||||
/** destructor
|
||||
*/
|
||||
~MonitorPluginManager(){}
|
||||
/* add plugin
|
||||
* @param pluginName The name of the plugin.
|
||||
* @param creator The creator.
|
||||
* @returns true or false
|
||||
* false is returned if a plugin with that name is already present
|
||||
*/
|
||||
bool addPlugin(
|
||||
String const &pluginName,
|
||||
MonitorPluginCreatorPtr const &creator);
|
||||
/* find plugin
|
||||
*
|
||||
* @param plugin name
|
||||
* @returns share pointer to plugin creator.
|
||||
* If a plugin with that name is not found NULL is returned.
|
||||
*/
|
||||
MonitorPluginCreatorPtr findPlugin(String const &pluginName);
|
||||
/* showNames
|
||||
*
|
||||
*/
|
||||
void showNames();
|
||||
private:
|
||||
MonitorPluginManager(){}
|
||||
std::list<MonitorPluginCreatorPtr> monitorPluginList;
|
||||
epics::pvData::Mutex mutex;
|
||||
};
|
||||
|
||||
|
||||
|
||||
}}
|
||||
#endif /* MONITORPLUGIN_H */
|
||||
@@ -25,25 +25,17 @@ String PVAlarm::notAttached("Not attached to an alarm structure");
|
||||
|
||||
bool PVAlarm::attach(PVFieldPtr const & pvField)
|
||||
{
|
||||
if(pvField->getField()->getType()!=structure) {
|
||||
pvField->message(noAlarmFound,errorMessage);
|
||||
return false;
|
||||
}
|
||||
if(pvField->getField()->getType()!=structure) return false;
|
||||
PVStructurePtr pvStructure = static_pointer_cast<PVStructure>(pvField);
|
||||
pvSeverity = pvStructure->getIntField("severity");
|
||||
if(pvSeverity.get()==NULL) {
|
||||
pvField->message(noAlarmFound,errorMessage);
|
||||
return false;
|
||||
}
|
||||
if(pvSeverity.get()==NULL) return false;
|
||||
pvStatus = pvStructure->getIntField("status");
|
||||
if(pvStatus.get()==NULL) {
|
||||
pvField->message(noAlarmFound,errorMessage);
|
||||
pvSeverity.reset();
|
||||
return false;
|
||||
}
|
||||
pvMessage = pvStructure->getStringField("message");
|
||||
if(pvMessage.get()==NULL) {
|
||||
pvField->message(noAlarmFound,errorMessage);
|
||||
pvSeverity.reset();
|
||||
pvStatus.reset();
|
||||
return false;
|
||||
|
||||
@@ -25,20 +25,13 @@ String PVControl::notAttached("Not attached to an control structure");
|
||||
|
||||
bool PVControl::attach(PVFieldPtr const & pvField)
|
||||
{
|
||||
if(pvField->getField()->getType()!=structure) {
|
||||
pvField->message(noControlFound,errorMessage);
|
||||
return false;
|
||||
}
|
||||
if(pvField->getField()->getType()!=structure) return false;
|
||||
PVStructurePtr pvStructure = static_pointer_cast<PVStructure>(pvField);
|
||||
pvLow = pvStructure->getDoubleField("limitLow");
|
||||
if(pvLow.get()==NULL) {
|
||||
pvField->message(noControlFound,errorMessage);
|
||||
return false;
|
||||
}
|
||||
if(pvLow.get()==NULL) return false;
|
||||
pvHigh = pvStructure->getDoubleField(String("limitHigh"));
|
||||
if(pvHigh.get()==NULL) {
|
||||
pvLow.reset();
|
||||
pvField->message(noControlFound,errorMessage);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -25,37 +25,27 @@ String PVDisplay::notAttached("Not attached to an display structure");
|
||||
|
||||
bool PVDisplay::attach(PVFieldPtr const & pvField)
|
||||
{
|
||||
if(pvField->getField()->getType()!=structure) {
|
||||
pvField->message(noDisplayFound,errorMessage);
|
||||
return false;
|
||||
}
|
||||
if(pvField->getField()->getType()!=structure) return false;
|
||||
PVStructurePtr pvStructure = static_pointer_cast<PVStructure>(pvField);
|
||||
pvDescription = pvStructure->getStringField("description");
|
||||
if(pvDescription.get()==NULL) {
|
||||
pvField->message(noDisplayFound,errorMessage);
|
||||
return false;
|
||||
}
|
||||
if(pvDescription.get()==NULL) return false;
|
||||
pvFormat = pvStructure->getStringField("format");
|
||||
if(pvFormat.get()==NULL) {
|
||||
pvField->message(noDisplayFound,errorMessage);
|
||||
detach();
|
||||
return false;
|
||||
}
|
||||
pvUnits = pvStructure->getStringField("units");
|
||||
if(pvUnits.get()==NULL) {
|
||||
pvField->message(noDisplayFound,errorMessage);
|
||||
detach();
|
||||
return false;
|
||||
}
|
||||
pvLow = pvStructure->getDoubleField(String("limitLow"));
|
||||
if(pvLow.get()==NULL) {
|
||||
pvField->message(noDisplayFound,errorMessage);
|
||||
detach();
|
||||
return false;
|
||||
}
|
||||
pvHigh = pvStructure->getDoubleField(String("limitHigh"));
|
||||
if(pvHigh.get()==NULL) {
|
||||
pvField->message(noDisplayFound,errorMessage);
|
||||
detach();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -25,21 +25,14 @@ String PVEnumerated::notAttached("Not attached to an enumerated structure");
|
||||
|
||||
bool PVEnumerated::attach(PVFieldPtr const & pvField)
|
||||
{
|
||||
if(pvField->getField()->getType()!=structure) {
|
||||
pvField->message(notFound,errorMessage);
|
||||
return false;
|
||||
}
|
||||
if(pvField->getField()->getType()!=structure) return false;
|
||||
PVStructurePtr pvStructure = static_pointer_cast<PVStructure>(pvField);
|
||||
pvIndex = pvStructure->getIntField("index");
|
||||
if(pvIndex.get()==NULL) {
|
||||
pvField->message(notFound,errorMessage);
|
||||
return false;
|
||||
}
|
||||
if(pvIndex.get()==NULL) return false;
|
||||
PVScalarArrayPtr pvScalarArray = pvStructure->getScalarArrayField(
|
||||
"choices",pvString);
|
||||
if(pvScalarArray.get()==NULL) {
|
||||
pvIndex.reset();
|
||||
pvField->message(notFound,errorMessage);
|
||||
return false;
|
||||
}
|
||||
pvChoices = static_pointer_cast<PVStringArray>(pvScalarArray);
|
||||
|
||||
@@ -25,10 +25,7 @@ String PVTimeStamp::notAttached("Not attached to a timeStamp structure");
|
||||
|
||||
bool PVTimeStamp::attach(PVFieldPtr const & pvField)
|
||||
{
|
||||
if(pvField->getField()->getType()!=structure) {
|
||||
pvField->message(noTimeStamp,errorMessage);
|
||||
return false;
|
||||
}
|
||||
if(pvField->getField()->getType()!=structure) return false;
|
||||
PVStructurePtr xxx = static_pointer_cast<PVStructure>(pvField);
|
||||
PVStructure* pvStructure = xxx.get();
|
||||
while(true) {
|
||||
|
||||
457
src/pv/pvData.h
457
src/pv/pvData.h
@@ -14,13 +14,6 @@
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 3
|
||||
/* error attribute was introduced in gcc 4.3.x */
|
||||
#define USAGE_ERROR(MSG) __attribute__((error(MSG)))
|
||||
#else
|
||||
#define USAGE_ERROR(MSG) { throw std::runtime_error(MSG); }
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <stdexcept>
|
||||
@@ -30,7 +23,6 @@
|
||||
#include <iomanip>
|
||||
|
||||
#include <pv/pvIntrospect.h>
|
||||
#include <pv/requester.h>
|
||||
#include <pv/typeCast.h>
|
||||
#include <pv/sharedVector.h>
|
||||
|
||||
@@ -106,7 +98,6 @@ epicsShareExtern array_at_internal operator<<(std::ostream& str, array_at const&
|
||||
};
|
||||
|
||||
|
||||
class PVAuxInfo;
|
||||
class PostHandler;
|
||||
|
||||
class PVField;
|
||||
@@ -124,11 +115,6 @@ template<typename T> class PVScalarValue;
|
||||
template<typename T> class PVValueArray;
|
||||
|
||||
|
||||
/**
|
||||
* typedef for a pointer to a PVAuxInfo.
|
||||
*/
|
||||
typedef std::tr1::shared_ptr<PVAuxInfo> PVAuxInfoPtr;
|
||||
|
||||
/**
|
||||
* typedef for a pointer to a PostHandler.
|
||||
*/
|
||||
@@ -198,67 +184,6 @@ typedef std::tr1::shared_ptr<PVUnionArrayPtrArray> PVUnionArrayPtrArrayPtr;
|
||||
class PVDataCreate;
|
||||
typedef std::tr1::shared_ptr<PVDataCreate> PVDataCreatePtr;
|
||||
|
||||
/**
|
||||
* This class provides auxillary information about a PVField.
|
||||
* Each item is stored as a PVScalar.
|
||||
* A (key,value) is provided for accessing the items where the key is a String.
|
||||
*/
|
||||
class epicsShareClass PVAuxInfo : private NoDefaultMethods {
|
||||
public:
|
||||
typedef std::map<String,PVScalarPtr> PVInfoMap;
|
||||
typedef std::map<String,PVScalarPtr>::iterator PVInfoIter;
|
||||
typedef std::pair<String,PVScalarPtr> PVInfoPair;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param The fields to which the Auxinfo is attached.
|
||||
*/
|
||||
PVAuxInfo(PVField *pvField);
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~PVAuxInfo();
|
||||
/**
|
||||
* Get the PVField to which the Auxinfo is attached.
|
||||
* @return The fields to which the Auxinfo is attached.
|
||||
*/
|
||||
PVField * getPVField();
|
||||
/**
|
||||
* Add a new auxiliary item or retrieve the interface to an existing item.
|
||||
*
|
||||
* @param key The key.
|
||||
* @param scalarType The scalarType for the new item being added/
|
||||
* @return The new PVScalar that has been added to the Auxinfo.
|
||||
*/
|
||||
PVScalarPtr createInfo(String const & key,ScalarType scalarType);
|
||||
/**
|
||||
* Get the Auxinfo with the specified key.
|
||||
* @return The PVScalar or null if it does not exist.
|
||||
*/
|
||||
PVScalarPtr getInfo(String const & key);
|
||||
/**
|
||||
* Get the map for the info.
|
||||
* @return The map;
|
||||
*/
|
||||
PVInfoMap & getInfoMap();
|
||||
/**
|
||||
* Convert the Auxinfo to a string and add it to builder.
|
||||
* @param builder The string builder.
|
||||
*/
|
||||
void toString(StringBuilder buf);
|
||||
/**
|
||||
* Convert the Auxinfo to a string and add it to builder.
|
||||
* @param builder The string builder.
|
||||
* @param indentLevel The number of blanks at the beginning of new lines.
|
||||
*/
|
||||
void toString(StringBuilder buf,int indentLevel);
|
||||
private:
|
||||
PVScalarPtr nullPVScalar;
|
||||
PVField * pvField;
|
||||
PVInfoMap pvInfos;
|
||||
friend class PVDataCreate;
|
||||
};
|
||||
|
||||
/**
|
||||
* This class is implemented by code that calls setPostHander
|
||||
*/
|
||||
@@ -294,12 +219,6 @@ public:
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~PVField();
|
||||
/**
|
||||
* Called to report errors associated with the field.
|
||||
* @param message The message.
|
||||
* @param messageType The message type.
|
||||
*/
|
||||
virtual void message(String message,MessageType messageType) ;
|
||||
/**
|
||||
* Get the fieldName for this field.
|
||||
* @return The name or empty string if top level field.
|
||||
@@ -311,12 +230,6 @@ public:
|
||||
* each name.
|
||||
*/
|
||||
String getFullName() const;
|
||||
/**
|
||||
* Register the message requester.
|
||||
* At most one requester can be registered.
|
||||
* @param prequester The requester.
|
||||
*/
|
||||
virtual void setRequester(RequesterPtr const &prequester);
|
||||
/**
|
||||
* Get offset of the PVField field within top level structure.
|
||||
* Every field within the PVStructure has a unique offset.
|
||||
@@ -338,11 +251,6 @@ public:
|
||||
* This is equal to nextFieldOffset - fieldOffset.
|
||||
*/
|
||||
std::size_t getNumberFields() const;
|
||||
/**
|
||||
* Get the PVAuxInfo interface for the PVField.
|
||||
* @return The PVAuxInfo interface.
|
||||
*/
|
||||
PVAuxInfoPtr & getPVAuxInfo();
|
||||
/**
|
||||
* Is the field immutable, i.e. does it not allow changes.
|
||||
* @return (false,true) if it (is not, is) immutable.
|
||||
@@ -363,16 +271,6 @@ public:
|
||||
* @return The parent interface or null if this is PVRecord
|
||||
*/
|
||||
PVStructure * getParent() const ;
|
||||
/**
|
||||
* Replace the data implementation for the field.
|
||||
* @param newPVField The new implementation
|
||||
*/
|
||||
void replacePVField(const PVFieldPtr& newPVField);
|
||||
/**
|
||||
* Rename the field name.
|
||||
* @param newName The new name.
|
||||
*/
|
||||
void renameField(String const & newName);
|
||||
/**
|
||||
* postPut. Called when the field is updated by the implementation.
|
||||
*/
|
||||
@@ -417,20 +315,16 @@ protected:
|
||||
}
|
||||
PVField(FieldConstPtr field);
|
||||
void setParentAndName(PVStructure *parent, String const & fieldName);
|
||||
void replaceField(FieldConstPtr &field);
|
||||
private:
|
||||
void message(String message,MessageType messageType,String fullFieldName);
|
||||
static void computeOffset(const PVField *pvField);
|
||||
static void computeOffset(const PVField *pvField,std::size_t offset);
|
||||
String notImplemented;
|
||||
PVAuxInfoPtr pvAuxInfo;
|
||||
String fieldName;
|
||||
PVStructure *parent;
|
||||
FieldConstPtr field;
|
||||
size_t fieldOffset;
|
||||
size_t nextFieldOffset;
|
||||
bool immutable;
|
||||
RequesterPtr requester;
|
||||
PostHandlerPtr postHandler;
|
||||
friend class PVDataCreate;
|
||||
friend class PVStructure;
|
||||
@@ -649,6 +543,11 @@ public:
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~PVArray(){};
|
||||
/**
|
||||
* Get the introspection interface
|
||||
* @return The interface.
|
||||
*/
|
||||
virtual ArrayConstPtr getArray() const = 0;
|
||||
/**
|
||||
* Set the field to be immutable, i. e. it can no longer be modified.
|
||||
* This is permanent, i.e. once done the field can onot be made mutable.
|
||||
@@ -696,31 +595,6 @@ private:
|
||||
|
||||
epicsShareExtern std::ostream& operator<<(format::array_at_internal const& manip, const PVArray& array);
|
||||
|
||||
/**
|
||||
* Class provided by caller of get
|
||||
*/
|
||||
template<typename T>
|
||||
class PVArrayData {
|
||||
private:
|
||||
std::vector<T> init;
|
||||
public:
|
||||
POINTER_DEFINITIONS(PVArrayData);
|
||||
typedef T value_type;
|
||||
typedef T* pointer;
|
||||
typedef const T* const_pointer;
|
||||
/**
|
||||
* The data array.
|
||||
*/
|
||||
std::vector<T> & data;
|
||||
/**
|
||||
* The offset. This is the offset into the actual array of the first element in data,
|
||||
*/
|
||||
std::size_t offset;
|
||||
PVArrayData()
|
||||
: data(init)
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Base class for a scalarArray.
|
||||
@@ -864,92 +738,86 @@ public:
|
||||
return std::tr1::shared_ptr<PVT>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a field to the structure.
|
||||
* @param fieldName The name of the field to append.
|
||||
* @param pvField The field to append.
|
||||
*/
|
||||
void appendPVField(String const &fieldName,PVFieldPtr const & pvField);
|
||||
/**
|
||||
* Append fields to the structure.
|
||||
* @param fieldNames The names of the fields to add.
|
||||
* @param pvFields The fields to append.
|
||||
* @return Pointer to the field or null if field does not exist.
|
||||
*/
|
||||
void appendPVFields(StringArray const & fieldNames,PVFieldPtrArray const & pvFields);
|
||||
/**
|
||||
* Remove a field from the structure.
|
||||
* @param fieldName The name of the field to remove.
|
||||
*/
|
||||
void removePVField(String const &fieldName);
|
||||
/**
|
||||
* Get a boolean field with the specified name.
|
||||
* No longer needed. Use templete version of getSubField
|
||||
* @param fieldName The name of the field to get.
|
||||
* @return Pointer to the field of null if a field with that name and type does not exist.
|
||||
*/
|
||||
PVBooleanPtr getBooleanField(String const &fieldName) ;
|
||||
/**
|
||||
* Get a byte field with the specified name.
|
||||
* No longer needed. Use templete version of getSubField
|
||||
* @param fieldName The name of the field to get.
|
||||
* @return Pointer to the field of null if a field with that name and type does not exist.
|
||||
*/
|
||||
PVBytePtr getByteField(String const &fieldName) ;
|
||||
/**
|
||||
* Get a short field with the specified name.
|
||||
* No longer needed. Use templete version of getSubField
|
||||
* @param fieldName The name of the field to get.
|
||||
* @return Pointer to the field of null if a field with that name and type does not exist.
|
||||
*/
|
||||
PVShortPtr getShortField(String const &fieldName) ;
|
||||
/**
|
||||
* Get a int field with the specified name.
|
||||
* No longer needed. Use templete version of getSubField
|
||||
* @param fieldName The name of the field to get.
|
||||
* @return Pointer to the field of null if a field with that name and type does not exist.
|
||||
*/
|
||||
PVIntPtr getIntField(String const &fieldName) ;
|
||||
/**
|
||||
* Get a long field with the specified name.
|
||||
* No longer needed. Use templete version of getSubField
|
||||
* @param fieldName The name of the field to get.
|
||||
* @return Pointer to the field of null if a field with that name and type does not exist.
|
||||
*/
|
||||
PVLongPtr getLongField(String const &fieldName) ;
|
||||
/**
|
||||
* Get an unsigned byte field with the specified name.
|
||||
* No longer needed. Use templete version of getSubField
|
||||
* @param fieldName The name of the field to get.
|
||||
* @return Pointer to the field of null if a field with that name and type does not exist.
|
||||
*/
|
||||
PVUBytePtr getUByteField(String const &fieldName) ;
|
||||
/**
|
||||
* Get an unsigned short field with the specified name.
|
||||
* No longer needed. Use templete version of getSubField
|
||||
* @param fieldName The name of the field to get.
|
||||
* @return Pointer to the field of null if a field with that name and type does not exist.
|
||||
*/
|
||||
PVUShortPtr getUShortField(String const &fieldName) ;
|
||||
/**
|
||||
* Get an unsigned int field with the specified name.
|
||||
* No longer needed. Use templete version of getSubField
|
||||
* @param fieldName The name of the field to get.
|
||||
* @return Pointer to the field of null if a field with that name and type does not exist.
|
||||
*/
|
||||
PVUIntPtr getUIntField(String const &fieldName) ;
|
||||
/**
|
||||
* Get an unsigned long field with the specified name.
|
||||
* No longer needed. Use templete version of getSubField
|
||||
* @param fieldName The name of the field to get.
|
||||
* @return Pointer to the field of null if a field with that name and type does not exist.
|
||||
*/
|
||||
PVULongPtr getULongField(String const &fieldName) ;
|
||||
/**
|
||||
* Get a float field with the specified name.
|
||||
* No longer needed. Use templete version of getSubField
|
||||
* @param fieldName The name of the field to get.
|
||||
* @return Pointer to the field of null if a field with that name and type does not exist.
|
||||
*/
|
||||
PVFloatPtr getFloatField(String const &fieldName) ;
|
||||
/**
|
||||
* Get a double field with the specified name.
|
||||
* No longer needed. Use templete version of getSubField
|
||||
* @param fieldName The name of the field to get.
|
||||
* @return Pointer to the field of null if a field with that name and type does not exist.
|
||||
*/
|
||||
PVDoublePtr getDoubleField(String const &fieldName) ;
|
||||
/**
|
||||
* Get a string field with the specified name.
|
||||
* No longer needed. Use templete version of getSubField
|
||||
* @param fieldName The name of the field to get.
|
||||
* @return Pointer to the field of null if a field with that name and type does not exist.
|
||||
*/
|
||||
@@ -957,18 +825,21 @@ public:
|
||||
|
||||
/**
|
||||
* Get a structure field with the specified name.
|
||||
* No longer needed. Use templete version of getSubField
|
||||
* @param fieldName The name of the field to get.
|
||||
* @return Pointer to the field of null if a field with that name and type does not exist.
|
||||
*/
|
||||
PVStructurePtr getStructureField(String const &fieldName) ;
|
||||
/**
|
||||
* Get a union field with the specified name.
|
||||
* No longer needed. Use templete version of getSubField
|
||||
* @param fieldName The name of the field to get.
|
||||
* @return Pointer to the field of null if a field with that name and type does not exist.
|
||||
*/
|
||||
PVUnionPtr getUnionField(String const &fieldName) ;
|
||||
/**
|
||||
* Get a scalarArray field with the specified name.
|
||||
* No longer needed. Use templete version of getSubField
|
||||
* @param fieldName The name of the field to get.
|
||||
* @param elementType The element type.
|
||||
* @return Pointer to the field of null if a field with that name and type does not exist.
|
||||
@@ -977,27 +848,18 @@ public:
|
||||
String const &fieldName,ScalarType elementType) ;
|
||||
/**
|
||||
* Get a structureArray field with the specified name.
|
||||
* No longer needed. Use templete version of getSubField
|
||||
* @param fieldName The name of the field to get.
|
||||
* @return Pointer to the field of null if a field with that name and type does not exist.
|
||||
*/
|
||||
PVStructureArrayPtr getStructureArrayField(String const &fieldName) ;
|
||||
/**
|
||||
* Get a unionArray field with the specified name.
|
||||
* No longer needed. Use templete version of getSubField
|
||||
* @param fieldName The name of the field to get.
|
||||
* @return Pointer to the field of null if a field with that name and type does not exist.
|
||||
*/
|
||||
PVUnionArrayPtr getUnionArrayField(String const &fieldName) ;
|
||||
/**
|
||||
* Get the name if this structure extends another structure.
|
||||
* @return The string which may be null.
|
||||
*/
|
||||
String getExtendsStructureName() const;
|
||||
/**
|
||||
* Put the extends name.
|
||||
* @param extendsStructureName The name.
|
||||
*/
|
||||
bool putExtendsStructureName(
|
||||
String const &extendsStructureName);
|
||||
/**
|
||||
* Serialize.
|
||||
* @param pbuffer The byte buffer.
|
||||
@@ -1043,7 +905,6 @@ public:
|
||||
virtual std::ostream& dumpValue(std::ostream& o) const;
|
||||
|
||||
private:
|
||||
void fixParentStructure();
|
||||
static PVFieldPtr nullPVField;
|
||||
static PVBooleanPtr nullPVBoolean;
|
||||
static PVBytePtr nullPVByte;
|
||||
@@ -1070,6 +931,9 @@ private:
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* PVUnion has a single subfield which has a type specified by a union introspection interface.
|
||||
*/
|
||||
class epicsShareClass PVUnion : public PVField
|
||||
{
|
||||
public:
|
||||
@@ -1225,12 +1089,6 @@ namespace detail {
|
||||
typedef ::epics::pvData::shared_vector<T> svector;
|
||||
typedef ::epics::pvData::shared_vector<const T> const_svector;
|
||||
|
||||
// begin deprecated
|
||||
typedef PVArrayData<T> ArrayDataType;
|
||||
typedef std::vector<T> vector;
|
||||
typedef const std::vector<T> const_vector;
|
||||
typedef std::tr1::shared_ptr<vector> shared_vector;
|
||||
// end deprecated
|
||||
|
||||
protected:
|
||||
PVVectorStorage() : Base() {}
|
||||
@@ -1279,79 +1137,6 @@ namespace detail {
|
||||
return thaw(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get array elements
|
||||
* @param offset The offset of the first element,
|
||||
* @param length The number of elements to get.
|
||||
* @param data The place where the data is placed.
|
||||
*/
|
||||
std::size_t get(
|
||||
std::size_t offset, std::size_t length, ArrayDataType &data) EPICS_DEPRECATED
|
||||
{
|
||||
const_svector ref = this->view();
|
||||
ref.slice(offset, length);
|
||||
data.data.resize(ref.size());
|
||||
data.offset = 0;
|
||||
std::copy(ref.begin(), ref.end(), data.data.begin());
|
||||
return ref.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy data into the array growing the length as needed.
|
||||
* @param offset The offset of the first element,
|
||||
* @param length The number of elements to get.
|
||||
* @param from The new values to put into the array.
|
||||
* @param fromOffset The offset in from.
|
||||
* @return The number of elements put into the array.
|
||||
* calls postPut()
|
||||
*/
|
||||
std::size_t put(std::size_t offset,
|
||||
std::size_t length, const_pointer from, std::size_t fromOffset) EPICS_DEPRECATED
|
||||
{
|
||||
from += fromOffset;
|
||||
|
||||
svector temp(this->reuse());
|
||||
if(temp.size() < length+offset)
|
||||
temp.resize(length+offset);
|
||||
else
|
||||
temp.make_unique();
|
||||
|
||||
std::copy(from, from + length, temp.begin() + offset);
|
||||
this->replace(freeze(temp));
|
||||
return length;
|
||||
}
|
||||
|
||||
std::size_t put(std::size_t offset,
|
||||
std::size_t length, const_vector &from, std::size_t fromOffset) EPICS_DEPRECATED
|
||||
{ return this->put(offset,length, &from[0], fromOffset); }
|
||||
|
||||
/**
|
||||
* Share data from another source.
|
||||
* @param value The data to share.
|
||||
* @param capacity The capacity of the array.
|
||||
* @param length The length of the array.
|
||||
* Does @b not call postPut()
|
||||
*/
|
||||
void shareData(
|
||||
shared_vector const & value,
|
||||
std::size_t capacity,
|
||||
std::size_t length) EPICS_DEPRECATED
|
||||
{
|
||||
vector& vref = *value.get();
|
||||
typename svector::shared_pointer_type p(&vref[0],
|
||||
detail::shared_ptr_vector_deletor<T>(value));
|
||||
const_svector temp(p, 0, std::min(length, vref.size()));
|
||||
this->swap(temp);
|
||||
}
|
||||
|
||||
pointer get() const EPICS_DEPRECATED {
|
||||
// evil unsafe cast!
|
||||
return (pointer)this->view().data();
|
||||
}
|
||||
|
||||
vector const & getVector() USAGE_ERROR("No longer implemented. Replace with view()");
|
||||
shared_vector const & getSharedVector() USAGE_ERROR("No longer implemented. Replace with view()");
|
||||
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
@@ -1368,14 +1153,6 @@ public:
|
||||
typedef ::epics::pvData::shared_vector<T> svector;
|
||||
typedef ::epics::pvData::shared_vector<const T> const_svector;
|
||||
|
||||
// begin deprecated
|
||||
typedef PVArrayData<T> ArrayDataType;
|
||||
typedef std::vector<T> vector;
|
||||
typedef const std::vector<T> const_vector;
|
||||
typedef std::tr1::shared_ptr<vector> shared_vector;
|
||||
typedef PVValueArray & reference;
|
||||
typedef const PVValueArray & const_reference;
|
||||
// end deprecated
|
||||
|
||||
static const ScalarType typeCode;
|
||||
|
||||
@@ -1384,6 +1161,11 @@ public:
|
||||
*/
|
||||
virtual ~PVValueArray() {}
|
||||
|
||||
virtual ArrayConstPtr getArray() const
|
||||
{
|
||||
return std::tr1::static_pointer_cast<const Array>(this->getField());
|
||||
}
|
||||
|
||||
std::ostream& dumpValue(std::ostream& o) const
|
||||
{
|
||||
const_svector v(this->view());
|
||||
@@ -1421,10 +1203,6 @@ protected:
|
||||
friend class PVDataCreate;
|
||||
};
|
||||
|
||||
/**
|
||||
* This is provided by code that calls get.
|
||||
*/
|
||||
typedef PVArrayData<PVStructurePtr> StructureArrayData;
|
||||
|
||||
/**
|
||||
* Data class for a structureArray
|
||||
@@ -1438,10 +1216,6 @@ public:
|
||||
typedef PVStructurePtr value_type;
|
||||
typedef PVStructurePtr* pointer;
|
||||
typedef const PVStructurePtr* const_pointer;
|
||||
typedef PVArrayData<PVStructurePtr> ArrayDataType;
|
||||
typedef std::vector<PVStructurePtr> vector;
|
||||
typedef const std::vector<PVStructurePtr> const_vector;
|
||||
typedef std::tr1::shared_ptr<vector> shared_vector;
|
||||
typedef PVStructureArray &reference;
|
||||
typedef const PVStructureArray& const_reference;
|
||||
|
||||
@@ -1453,6 +1227,11 @@ public:
|
||||
*/
|
||||
virtual ~PVValueArray() {}
|
||||
|
||||
virtual ArrayConstPtr getArray() const
|
||||
{
|
||||
return std::tr1::static_pointer_cast<const Array>(structureArray);
|
||||
}
|
||||
|
||||
virtual size_t getLength() const {return value.size();}
|
||||
virtual size_t getCapacity() const {return value.capacity();}
|
||||
|
||||
@@ -1519,10 +1298,6 @@ private:
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* This is provided by code that calls get.
|
||||
*/
|
||||
typedef PVArrayData<PVUnionPtr> UnionArrayData;
|
||||
|
||||
/**
|
||||
* Data class for a unionArray
|
||||
@@ -1536,10 +1311,6 @@ public:
|
||||
typedef PVUnionPtr value_type;
|
||||
typedef PVUnionPtr* pointer;
|
||||
typedef const PVUnionPtr* const_pointer;
|
||||
typedef PVArrayData<PVUnionPtr> ArrayDataType;
|
||||
typedef std::vector<PVUnionPtr> vector;
|
||||
typedef const std::vector<PVUnionPtr> const_vector;
|
||||
typedef std::tr1::shared_ptr<vector> shared_vector;
|
||||
typedef PVUnionArray &reference;
|
||||
typedef const PVUnionArray& const_reference;
|
||||
|
||||
@@ -1551,6 +1322,11 @@ public:
|
||||
*/
|
||||
virtual ~PVValueArray() {}
|
||||
|
||||
virtual ArrayConstPtr getArray() const
|
||||
{
|
||||
return std::tr1::static_pointer_cast<const Array>(unionArray);
|
||||
}
|
||||
|
||||
virtual size_t getLength() const {return value.size();}
|
||||
virtual size_t getCapacity() const {return value.capacity();}
|
||||
|
||||
@@ -1620,51 +1396,39 @@ private:
|
||||
/**
|
||||
* Definitions for the various scalarArray types.
|
||||
*/
|
||||
typedef PVArrayData<boolean> BooleanArrayData;
|
||||
typedef PVValueArray<boolean> PVBooleanArray;
|
||||
typedef std::tr1::shared_ptr<PVBooleanArray> PVBooleanArrayPtr;
|
||||
|
||||
typedef PVArrayData<int8> ByteArrayData;
|
||||
typedef PVValueArray<int8> PVByteArray;
|
||||
typedef std::tr1::shared_ptr<PVByteArray> PVByteArrayPtr;
|
||||
|
||||
typedef PVArrayData<int16> ShortArrayData;
|
||||
typedef PVValueArray<int16> PVShortArray;
|
||||
typedef std::tr1::shared_ptr<PVShortArray> PVShortArrayPtr;
|
||||
|
||||
typedef PVArrayData<int32> IntArrayData;
|
||||
typedef PVValueArray<int32> PVIntArray;
|
||||
typedef std::tr1::shared_ptr<PVIntArray> PVIntArrayPtr;
|
||||
|
||||
typedef PVArrayData<int64> LongArrayData;
|
||||
typedef PVValueArray<int64> PVLongArray;
|
||||
typedef std::tr1::shared_ptr<PVLongArray> PVLongArrayPtr;
|
||||
|
||||
typedef PVArrayData<uint8> UByteArrayData;
|
||||
typedef PVValueArray<uint8> PVUByteArray;
|
||||
typedef std::tr1::shared_ptr<PVUByteArray> PVUByteArrayPtr;
|
||||
|
||||
typedef PVArrayData<uint16> UShortArrayData;
|
||||
typedef PVValueArray<uint16> PVUShortArray;
|
||||
typedef std::tr1::shared_ptr<PVUShortArray> PVUShortArrayPtr;
|
||||
|
||||
typedef PVArrayData<uint32> UIntArrayData;
|
||||
typedef PVValueArray<uint32> PVUIntArray;
|
||||
typedef std::tr1::shared_ptr<PVUIntArray> PVUIntArrayPtr;
|
||||
|
||||
typedef PVArrayData<uint64> ULongArrayData;
|
||||
typedef PVValueArray<uint64> PVULongArray;
|
||||
typedef std::tr1::shared_ptr<PVULongArray> PVULongArrayPtr;
|
||||
|
||||
typedef PVArrayData<float> FloatArrayData;
|
||||
typedef PVValueArray<float> PVFloatArray;
|
||||
typedef std::tr1::shared_ptr<PVFloatArray> PVFloatArrayPtr;
|
||||
|
||||
typedef PVArrayData<double> DoubleArrayData;
|
||||
typedef PVValueArray<double> PVDoubleArray;
|
||||
typedef std::tr1::shared_ptr<PVDoubleArray> PVDoubleArrayPtr;
|
||||
|
||||
typedef PVArrayData<String> StringArrayData;
|
||||
typedef PVValueArray<String> PVStringArray;
|
||||
typedef std::tr1::shared_ptr<PVStringArray> PVStringArrayPtr;
|
||||
|
||||
@@ -1673,7 +1437,12 @@ typedef std::tr1::shared_ptr<PVStringArray> PVStringArrayPtr;
|
||||
*/
|
||||
class epicsShareClass PVDataCreate {
|
||||
public:
|
||||
/**
|
||||
* get the singleton
|
||||
* @return The PVDataCreate implementation
|
||||
*/
|
||||
static PVDataCreatePtr getPVDataCreate();
|
||||
|
||||
/**
|
||||
* Create a PVField using given Field introspection data.
|
||||
* @param field The introspection data to be used to create PVField.
|
||||
@@ -1706,6 +1475,56 @@ public:
|
||||
* @return The PVScalar implementation.
|
||||
*/
|
||||
PVScalarPtr createPVScalar(PVScalarPtr const & scalarToClone);
|
||||
/**
|
||||
* template version
|
||||
* @param PVT must ve a valid pvType
|
||||
* @return The PVScalar implementation.
|
||||
*/
|
||||
template<typename PVT>
|
||||
std::tr1::shared_ptr<PVT> createPVScalar()
|
||||
{
|
||||
return std::tr1::static_pointer_cast<PVT>(createPVScalar(PVT::typeCode));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create implementation for PVStructure.
|
||||
* @param structure The introspection interface.
|
||||
* @return The PVStructure implementation
|
||||
*/
|
||||
PVStructurePtr createPVStructure(StructureConstPtr const & structure);
|
||||
/**
|
||||
* Create implementation for PVStructure.
|
||||
* @param fieldNames The field names.
|
||||
* @param pvFields Array of PVFields
|
||||
* @return The PVStructure implementation
|
||||
*/
|
||||
PVStructurePtr createPVStructure(
|
||||
StringArray const & fieldNames,PVFieldPtrArray const & pvFields);
|
||||
/**
|
||||
* Create implementation for PVStructure.
|
||||
* @param structToClone A structure. Each subfield and any auxInfo is cloned and added to the newly created structure.
|
||||
* @return The PVStructure implementation.
|
||||
*/
|
||||
PVStructurePtr createPVStructure(PVStructurePtr const & structToClone);
|
||||
|
||||
/**
|
||||
* Create implementation for PVUnion.
|
||||
* @param union The introspection interface.
|
||||
* @return The PVUnion implementation
|
||||
*/
|
||||
PVUnionPtr createPVUnion(UnionConstPtr const & punion);
|
||||
/**
|
||||
* Create implementation for PVUnion.
|
||||
* @param unionToClone A union. Each subfield is cloned and added to the newly created union.
|
||||
* @return The PVUnion implementation.
|
||||
*/
|
||||
PVUnionPtr createPVUnion(PVUnionPtr const & unionToClone);
|
||||
/**
|
||||
* Create variant union implementation.
|
||||
* @return The variant PVUnion implementation.
|
||||
*/
|
||||
PVUnionPtr createPVVariantUnion();
|
||||
|
||||
/**
|
||||
* Create an implementation of an array field reusing the Array introspection interface.
|
||||
* @param array The introspection interface.
|
||||
@@ -1726,6 +1545,17 @@ public:
|
||||
* @return The PVScalarArray implementation.
|
||||
*/
|
||||
PVScalarArrayPtr createPVScalarArray(PVScalarArrayPtr const & scalarArrayToClone);
|
||||
/**
|
||||
* template version
|
||||
* @param PVT must ve a valid pvType
|
||||
* @return The PVScalarArray implementation.
|
||||
*/
|
||||
template<typename PVAT>
|
||||
std::tr1::shared_ptr<PVAT> createPVScalarArray()
|
||||
{
|
||||
return std::tr1::static_pointer_cast<PVAT>(createPVScalarArray(PVAT::typeCode));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an implementation of an array with structure elements.
|
||||
* @param structureArray The introspection interface.
|
||||
@@ -1734,25 +1564,16 @@ public:
|
||||
*/
|
||||
PVStructureArrayPtr createPVStructureArray(StructureArrayConstPtr const & structureArray);
|
||||
/**
|
||||
* Create implementation for PVStructure.
|
||||
* @param structure The introspection interface.
|
||||
* @return The PVStructure implementation
|
||||
* Create an implementation of an array with structure elements.
|
||||
* @param structure The introspection interface that is used to create StructureArrayConstPtr.
|
||||
* All elements share the same introspection interface.
|
||||
* @return The PVStructureArray implementation.
|
||||
*/
|
||||
PVStructurePtr createPVStructure(StructureConstPtr const & structure);
|
||||
/**
|
||||
* Create implementation for PVStructure.
|
||||
* @param fieldNames The field names.
|
||||
* @param pvFields Array of PVFields
|
||||
* @return The PVStructure implementation
|
||||
*/
|
||||
PVStructurePtr createPVStructure(
|
||||
StringArray const & fieldNames,PVFieldPtrArray const & pvFields);
|
||||
/**
|
||||
* Create implementation for PVStructure.
|
||||
* @param structToClone A structure. Each subfield and any auxInfo is cloned and added to the newly created structure.
|
||||
* @return The PVStructure implementation.
|
||||
*/
|
||||
PVStructurePtr createPVStructure(PVStructurePtr const & structToClone);
|
||||
PVStructureArrayPtr createPVStructureArray(StructureConstPtr const & structure)
|
||||
{
|
||||
return createPVStructureArray(fieldCreate->createStructureArray(structure));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an implementation of an array with union elements.
|
||||
* @param unionArray The introspection interface.
|
||||
@@ -1761,51 +1582,21 @@ public:
|
||||
*/
|
||||
PVUnionArrayPtr createPVUnionArray(UnionArrayConstPtr const & unionArray);
|
||||
/**
|
||||
* Create implementation for PVUnion.
|
||||
* @param union The introspection interface.
|
||||
* @return The PVUnion implementation
|
||||
* Create an implementation of an array with union elements.
|
||||
* @param punion The introspection interface tht is used to create UnionArrayConstPtr.
|
||||
* All elements share the same introspection interface.
|
||||
* @return The PVUnionArray implementation.
|
||||
*/
|
||||
PVUnionPtr createPVUnion(UnionConstPtr const & punion);
|
||||
/**
|
||||
* Create implementation for PVUnion.
|
||||
* @param unionToClone A union. Each subfield is cloned and added to the newly created union.
|
||||
* @return The PVUnion implementation.
|
||||
*/
|
||||
PVUnionPtr createPVUnion(PVUnionPtr const & unionToClone);
|
||||
/**
|
||||
* Create variant union implementation.
|
||||
* @return The variant PVUnion implementation.
|
||||
*/
|
||||
PVUnionPtr createPVVariantUnion();
|
||||
PVUnionArrayPtr createPVUnionArray(UnionConstPtr const & punion)
|
||||
{
|
||||
return createPVUnionArray(fieldCreate->createUnionArray(punion));
|
||||
}
|
||||
/**
|
||||
* Create variant union array implementation.
|
||||
* @return The variant PVUnionArray implementation.
|
||||
*/
|
||||
PVUnionArrayPtr createPVVariantUnionArray();
|
||||
|
||||
|
||||
template<typename PVT>
|
||||
std::tr1::shared_ptr<PVT> createPVScalar()
|
||||
{
|
||||
return std::tr1::static_pointer_cast<PVT>(createPVScalar(PVT::typeCode));
|
||||
}
|
||||
|
||||
template<typename PVAT>
|
||||
std::tr1::shared_ptr<PVAT> createPVScalarArray()
|
||||
{
|
||||
return std::tr1::static_pointer_cast<PVAT>(createPVScalarArray(PVAT::typeCode));
|
||||
}
|
||||
|
||||
PVStructureArrayPtr createPVStructureArray(StructureConstPtr const & structure)
|
||||
{
|
||||
return createPVStructureArray(fieldCreate->createStructureArray(structure));
|
||||
}
|
||||
|
||||
PVUnionArrayPtr createPVUnionArray(UnionConstPtr const & punion)
|
||||
{
|
||||
return createPVUnionArray(fieldCreate->createUnionArray(punion));
|
||||
}
|
||||
|
||||
private:
|
||||
PVDataCreate();
|
||||
FieldCreatePtr fieldCreate;
|
||||
@@ -1818,7 +1609,5 @@ private:
|
||||
|
||||
epicsShareExtern PVDataCreatePtr getPVDataCreate();
|
||||
|
||||
#undef USAGE_ERROR
|
||||
|
||||
}}
|
||||
#endif /* PVDATA_H */
|
||||
|
||||
@@ -24,6 +24,7 @@ namespace epics { namespace pvData {
|
||||
|
||||
class Field;
|
||||
class Scalar;
|
||||
class Array;
|
||||
class ScalarArray;
|
||||
class Structure;
|
||||
class StructureArray;
|
||||
@@ -42,6 +43,10 @@ typedef std::vector<FieldConstPtr> FieldConstPtrArray;
|
||||
* typedef for a shared pointer to an immutable Scalar.
|
||||
*/
|
||||
typedef std::tr1::shared_ptr<const Scalar> ScalarConstPtr;
|
||||
/**
|
||||
* typedef for a shared pointer to an immutable Array.
|
||||
*/
|
||||
typedef std::tr1::shared_ptr<const Array> ArrayConstPtr;
|
||||
/**
|
||||
* typedef for a shared pointer to an immutable ScalarArray.
|
||||
*/
|
||||
@@ -314,10 +319,39 @@ private:
|
||||
friend class FieldCreate;
|
||||
};
|
||||
|
||||
/**
|
||||
* This class implements introspection object for Array.
|
||||
*/
|
||||
class epicsShareClass Array : public Field{
|
||||
public:
|
||||
POINTER_DEFINITIONS(Array);
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
virtual ~Array();
|
||||
typedef Array& reference;
|
||||
typedef const Array& const_reference;
|
||||
|
||||
/* fixed-size array support
|
||||
// 0 not valid value, means undefined
|
||||
std::size_t getMaximumCapacity() const;
|
||||
|
||||
// 0 not valid value, means undefined
|
||||
std::size_t getFixedLength() const;
|
||||
*/
|
||||
protected:
|
||||
/**
|
||||
* Constructor
|
||||
* @param fieldName The field type.
|
||||
*/
|
||||
Array(Type type);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* This class implements introspection object for field.
|
||||
*/
|
||||
class epicsShareClass ScalarArray : public Field{
|
||||
class epicsShareClass ScalarArray : public Array{
|
||||
public:
|
||||
POINTER_DEFINITIONS(ScalarArray);
|
||||
typedef ScalarArray& reference;
|
||||
@@ -332,7 +366,7 @@ public:
|
||||
* Get the scalarType for the elements.
|
||||
* @return the scalarType
|
||||
*/
|
||||
ScalarType getElementType() const {return elementType;}
|
||||
ScalarType getElementType() const {return elementType;}
|
||||
/**
|
||||
* Convert the scalarType to a string and add it to builder.
|
||||
* @param builder The string builder.
|
||||
@@ -365,7 +399,7 @@ private:
|
||||
/**
|
||||
* This class implements introspection object for a structureArray
|
||||
*/
|
||||
class epicsShareClass StructureArray : public Field{
|
||||
class epicsShareClass StructureArray : public Array{
|
||||
public:
|
||||
POINTER_DEFINITIONS(StructureArray);
|
||||
typedef StructureArray& reference;
|
||||
@@ -375,7 +409,7 @@ public:
|
||||
* Get the introspection interface for the array elements.
|
||||
* @return The introspection interface.
|
||||
*/
|
||||
StructureConstPtr getStructure() const {return pstructure;}
|
||||
StructureConstPtr getStructure() const {return pstructure;}
|
||||
|
||||
/**
|
||||
* Convert the scalarType to a string and add it to builder.
|
||||
@@ -407,7 +441,7 @@ private:
|
||||
/**
|
||||
* This class implements introspection object for a unionArray
|
||||
*/
|
||||
class epicsShareClass UnionArray : public Field{
|
||||
class epicsShareClass UnionArray : public Array{
|
||||
public:
|
||||
POINTER_DEFINITIONS(UnionArray);
|
||||
typedef UnionArray& reference;
|
||||
@@ -417,7 +451,7 @@ public:
|
||||
* Get the introspection interface for the array elements.
|
||||
* @return The introspection interface.
|
||||
*/
|
||||
UnionConstPtr getUnion() const {return punion;}
|
||||
UnionConstPtr getUnion() const {return punion;}
|
||||
|
||||
/**
|
||||
* Convert the scalarType to a string and add it to builder.
|
||||
@@ -500,8 +534,6 @@ public:
|
||||
* @return The array of fieldNames.
|
||||
*/
|
||||
StringArray const & getFieldNames() const {return fieldNames;}
|
||||
void renameField(std::size_t fieldIndex,String const & newName)
|
||||
{fieldNames[fieldIndex] = newName;}
|
||||
/**
|
||||
* Get the name of the field with the specified index;
|
||||
* @param fieldIndex The index of the desired field.
|
||||
@@ -595,8 +627,6 @@ public:
|
||||
* @return The array of fieldNames.
|
||||
*/
|
||||
StringArray const & getFieldNames() const {return fieldNames;}
|
||||
void renameField(std::size_t fieldIndex,String const & newName)
|
||||
{fieldNames[fieldIndex] = newName;}
|
||||
/**
|
||||
* Get the name of the field with the specified index;
|
||||
* @param fieldIndex The index of the desired field.
|
||||
@@ -637,9 +667,6 @@ private:
|
||||
friend class Structure;
|
||||
};
|
||||
|
||||
/**
|
||||
* This is a singlton class for creating introspection interfaces.
|
||||
*/
|
||||
class FieldCreate;
|
||||
typedef std::tr1::shared_ptr<FieldCreate> FieldCreatePtr;
|
||||
|
||||
@@ -784,6 +811,9 @@ private:
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* This is a singleton class for creating introspection interfaces.
|
||||
*/
|
||||
class epicsShareClass FieldCreate {
|
||||
public:
|
||||
static FieldCreatePtr getFieldCreate();
|
||||
@@ -812,6 +842,11 @@ public:
|
||||
* @return An {@code Array} Interface for the newly created object.
|
||||
*/
|
||||
StructureArrayConstPtr createStructureArray(StructureConstPtr const & structure) const;
|
||||
/**
|
||||
* Create a {@code Structure} field.
|
||||
* @return a {@code Structure} interface for the newly created object.
|
||||
*/
|
||||
StructureConstPtr createStructure () const;
|
||||
/**
|
||||
* Create a {@code Structure} field.
|
||||
* @param fieldNames The array of {@code fieldNames} for the structure.
|
||||
|
||||
@@ -17,68 +17,104 @@
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
/** @brief Copy a subarray from one PVValueArray to another.
|
||||
* @warning The two PVValueArrays must both the same type
|
||||
* @param from The source
|
||||
* @param fromOffset The offset in the source
|
||||
* @param to The destination
|
||||
* @param toOffset The offset in the destination
|
||||
* @param len The total number of elements to copy
|
||||
/** @brief Copy a subarray from one scalar array to another.
|
||||
* @warning The two scalar arrays must both be PVValueArrays of the same type.
|
||||
* @param pvFrom The source array.
|
||||
* @param fromOffset The offset in the source.
|
||||
* @param fromStride The interval between elements in pvFrom.
|
||||
* @param pvTo The destination array.
|
||||
* @param toOffset The offset in the destination.
|
||||
* @param toStride The interval between elements in pvTo.
|
||||
* @param count The total number of elements to copy from pvFrom to pvTo.
|
||||
*/
|
||||
template<typename T>
|
||||
void copy(
|
||||
epicsShareExtern void copy(
|
||||
PVValueArray<T> & pvFrom,
|
||||
size_t fromOffset,
|
||||
size_t fromStride,
|
||||
PVValueArray<T> & pvTo,
|
||||
size_t toOffset,
|
||||
size_t len);
|
||||
size_t toStride,
|
||||
size_t count);
|
||||
|
||||
/** @brief Copy a subarray from one scalar array to another.
|
||||
* @warning The two scalar arrays must both be PVValueArrays of the same type
|
||||
* @param from The source
|
||||
* @param fromOffset The offset in the source
|
||||
* @param to The destination
|
||||
* @param toOffset The offset in the destination
|
||||
* @param len The total number of elements to copy
|
||||
* @warning The two scalar arrays must both be PVValueArrays of the same type.
|
||||
* @param pvFrom The source array.
|
||||
* @param fromOffset The offset in the source.
|
||||
* @param fromStride The interval between elements in pvFrom.
|
||||
* @param pvTo The destination array.
|
||||
* @param toOffset The offset in the destination.
|
||||
* @param toStride The interval between elements in pvTo.
|
||||
* @param count The total number of elements to copy from pvFrom to pvTo.
|
||||
*/
|
||||
epicsShareExtern void copy(
|
||||
PVScalarArray & from,
|
||||
PVScalarArray & pvFrom,
|
||||
size_t fromOffset,
|
||||
PVScalarArray & to,
|
||||
size_t fromStride,
|
||||
PVScalarArray & pvTo,
|
||||
size_t toOffset,
|
||||
size_t len);
|
||||
size_t toStride,
|
||||
size_t count);
|
||||
|
||||
/** @brief Copy a subarray from one structure array to another.
|
||||
* @warning The two structure arrays must have the same
|
||||
* structure introspection interface.
|
||||
* @param from The source
|
||||
* @param fromOffset The offset in the source
|
||||
* @param to The destination
|
||||
* @param toOffset The offset in the destination
|
||||
* @param len The total number of elements to copy
|
||||
* @param pvFrom The source array.
|
||||
* @param fromOffset The offset in the source.
|
||||
* @param fromStride The interval between elements in pvFrom.
|
||||
* @param pvTo The destination array.
|
||||
* @param toOffset The offset in the destination.
|
||||
* @param toStride The interval between elements in pvTo.
|
||||
* @param count The total number of elements to copy from pvFrom to pvTo.
|
||||
*/
|
||||
epicsShareExtern void copy(
|
||||
PVStructureArray & from,
|
||||
PVStructureArray & pvFrom,
|
||||
size_t fromOffset,
|
||||
PVStructureArray & to,
|
||||
size_t fromStride,
|
||||
PVStructureArray & pvToo,
|
||||
size_t toOffset,
|
||||
size_t len);
|
||||
size_t toStride,
|
||||
size_t count);
|
||||
|
||||
/** @brief Copy a subarray from one array to another.
|
||||
* @warning The two arrays must have the same
|
||||
* introspection interface.
|
||||
* @param from The source
|
||||
* @param fromOffset The offset in the source
|
||||
* @param to The destination
|
||||
* @param toOffset The offset in the destination
|
||||
* @param len The total number of elements to copy
|
||||
* @param pvFrom The source array.
|
||||
* @param fromOffset The offset in the source.
|
||||
* @param fromStride The interval between elements in pvFrom.
|
||||
* @param pvTo The destination array.
|
||||
* @param toOffset The offset in the destination.
|
||||
* @param toStride The interval between elements in pvTo.
|
||||
* @param count The total number of elements to copy from pvFrom to pvTo.
|
||||
*/
|
||||
epicsShareExtern void copy(
|
||||
PVArray & from,
|
||||
PVArray & pvFrom,
|
||||
size_t fromOffset,
|
||||
PVArray & to,
|
||||
size_t fromStride,
|
||||
PVArray & pvToo,
|
||||
size_t toOffset,
|
||||
size_t len);
|
||||
size_t toStride,
|
||||
size_t count);
|
||||
|
||||
/** @brief Copy a subarray from one array to another.
|
||||
* @warning The two arrays must have the same
|
||||
* introspection interface.
|
||||
* @param pvFrom The source array.
|
||||
* @param fromOffset The offset in the source.
|
||||
* @param fromStride The interval between elements in pvFrom.
|
||||
* @param pvTo The destination array.
|
||||
* @param toOffset The offset in the destination.
|
||||
* @param toStride The interval between elements in pvTo.
|
||||
* @param count The total number of elements to copy from pvFrom to pvTo.
|
||||
*/
|
||||
epicsShareExtern void copy(
|
||||
PVArray::shared_pointer const & pvFrom,
|
||||
size_t fromOffset,
|
||||
size_t fromStride,
|
||||
PVArray::shared_pointer & pvToo,
|
||||
size_t toOffset,
|
||||
size_t toStride,
|
||||
size_t count);
|
||||
|
||||
}}
|
||||
|
||||
|
||||
329
src/pv/pvType.h
329
src/pv/pvType.h
@@ -98,335 +98,6 @@ typedef uint64_t uint64;
|
||||
*/
|
||||
typedef std::string String;
|
||||
|
||||
/**
|
||||
* A boolean array.
|
||||
*/
|
||||
typedef std::vector<uint8> BooleanArray;
|
||||
typedef std::tr1::shared_ptr<BooleanArray> BooleanArrayPtr;
|
||||
/* get is same is ubyte*/
|
||||
typedef std::vector<uint8>::iterator BooleanArray_iterator;
|
||||
typedef std::vector<uint8>::const_iterator BooleanArray_const_iterator;
|
||||
|
||||
/**
|
||||
* A byte array.
|
||||
*/
|
||||
typedef std::vector<int8> ByteArray;
|
||||
typedef std::tr1::shared_ptr<ByteArray> ByteArrayPtr;
|
||||
inline int8 * get(ByteArray &value)
|
||||
{
|
||||
return &value[0];
|
||||
}
|
||||
inline int8 const * get(ByteArray const &value)
|
||||
{
|
||||
return static_cast<int8 const *>(&value[0]);
|
||||
}
|
||||
inline int8 * get(ByteArrayPtr &value)
|
||||
{
|
||||
return get(*value.get());
|
||||
}
|
||||
inline int8 const * get(ByteArrayPtr const &value)
|
||||
{
|
||||
return get(*value.get());
|
||||
}
|
||||
inline ByteArray & getVector(ByteArrayPtr &value)
|
||||
{
|
||||
return *value.get();
|
||||
}
|
||||
inline ByteArray const & getVector(ByteArrayPtr const &value)
|
||||
{
|
||||
return *value.get();
|
||||
}
|
||||
typedef std::vector<int8>::iterator ByteArray_iterator;
|
||||
typedef std::vector<int8>::const_iterator ByteArray_const_iterator;
|
||||
|
||||
/**
|
||||
* A short array.
|
||||
*/
|
||||
typedef std::vector<int16> ShortArray;
|
||||
typedef std::tr1::shared_ptr<ShortArray> ShortArrayPtr;
|
||||
inline int16 * get(ShortArray &value)
|
||||
{
|
||||
return &value[0];
|
||||
}
|
||||
inline int16 const * get(ShortArray const &value)
|
||||
{
|
||||
return static_cast<int16 const *>(&value[0]);
|
||||
}
|
||||
inline int16 * get(ShortArrayPtr &value)
|
||||
{
|
||||
return get(*value.get());
|
||||
}
|
||||
inline int16 const * get(ShortArrayPtr const &value)
|
||||
{
|
||||
return get(*value.get());
|
||||
}
|
||||
inline ShortArray & getVector(ShortArrayPtr &value)
|
||||
{
|
||||
return *value.get();
|
||||
}
|
||||
inline ShortArray const & getVector(ShortArrayPtr const &value)
|
||||
{
|
||||
return *value.get();
|
||||
}
|
||||
typedef std::vector<int16>::iterator ShortArray_iterator;
|
||||
typedef std::vector<int16>::const_iterator ShortArray_const_iterator;
|
||||
|
||||
/**
|
||||
* A int array.
|
||||
*/
|
||||
typedef std::vector<int32> IntArray;
|
||||
typedef std::tr1::shared_ptr<IntArray> IntArrayPtr;
|
||||
inline int32 * get(IntArray &value)
|
||||
{
|
||||
return &value[0];
|
||||
}
|
||||
inline int32 const * get(IntArray const &value)
|
||||
{
|
||||
return static_cast<int32 const *>(&value[0]);
|
||||
}
|
||||
inline int32 * get(IntArrayPtr &value)
|
||||
{
|
||||
return get(*value.get());
|
||||
}
|
||||
inline int32 const * get(IntArrayPtr const &value)
|
||||
{
|
||||
return get(*value.get());
|
||||
}
|
||||
inline IntArray & getVector(IntArrayPtr &value)
|
||||
{
|
||||
return *value.get();
|
||||
}
|
||||
inline IntArray const & getVector(IntArrayPtr const &value)
|
||||
{
|
||||
return *value.get();
|
||||
}
|
||||
typedef std::vector<int32>::iterator IntArray_iterator;
|
||||
typedef std::vector<int32>::const_iterator IntArray_const_iterator;
|
||||
|
||||
/**
|
||||
* A long array.
|
||||
*/
|
||||
typedef std::vector<int64> LongArray;
|
||||
typedef std::tr1::shared_ptr<LongArray> LongArrayPtr;
|
||||
inline int64 * get(LongArray &value)
|
||||
{
|
||||
return &value[0];
|
||||
}
|
||||
inline int64 const * get(LongArray const &value)
|
||||
{
|
||||
return static_cast<int64 const *>(&value[0]);
|
||||
}
|
||||
inline int64 * get(LongArrayPtr &value)
|
||||
{
|
||||
return get(*value.get());
|
||||
}
|
||||
inline int64 const * get(LongArrayPtr const &value)
|
||||
{
|
||||
return get(*value.get());
|
||||
}
|
||||
inline LongArray & getVector(LongArrayPtr &value)
|
||||
{
|
||||
return *value.get();
|
||||
}
|
||||
inline LongArray const & getVector(LongArrayPtr const &value)
|
||||
{
|
||||
return *value.get();
|
||||
}
|
||||
typedef std::vector<int64>::iterator LongArray_iterator;
|
||||
typedef std::vector<int64>::const_iterator LongArray_const_iterator;
|
||||
|
||||
/**
|
||||
* An unsigned byte array.
|
||||
*/
|
||||
typedef std::vector<uint8> UByteArray;
|
||||
typedef std::tr1::shared_ptr<UByteArray> UByteArrayPtr;
|
||||
inline uint8 * get(UByteArray &value)
|
||||
{
|
||||
return &value[0];
|
||||
}
|
||||
inline uint8 const * get(UByteArray const &value)
|
||||
{
|
||||
return static_cast<uint8 const *>(&value[0]);
|
||||
}
|
||||
inline uint8 * get(UByteArrayPtr &value)
|
||||
{
|
||||
return get(*value.get());
|
||||
}
|
||||
inline uint8 const * get(UByteArrayPtr const &value)
|
||||
{
|
||||
return get(*value.get());
|
||||
}
|
||||
inline UByteArray & getVector(UByteArrayPtr &value)
|
||||
{
|
||||
return *value.get();
|
||||
}
|
||||
inline UByteArray const & getVector(UByteArrayPtr const &value)
|
||||
{
|
||||
return *value.get();
|
||||
}
|
||||
typedef std::vector<uint8>::iterator UByteArray_iterator;
|
||||
typedef std::vector<uint8>::const_iterator UByteArray_const_iterator;
|
||||
|
||||
/**
|
||||
* An unsigned short array.
|
||||
*/
|
||||
typedef std::vector<uint16> UShortArray;
|
||||
typedef std::tr1::shared_ptr<UShortArray> UShortArrayPtr;
|
||||
inline uint16 * get(UShortArray &value)
|
||||
{
|
||||
return &value[0];
|
||||
}
|
||||
inline uint16 const * get(UShortArray const &value)
|
||||
{
|
||||
return static_cast<uint16 const *>(&value[0]);
|
||||
}
|
||||
inline uint16 * get(UShortArrayPtr &value)
|
||||
{
|
||||
return get(*value.get());
|
||||
}
|
||||
inline uint16 const * get(UShortArrayPtr const &value)
|
||||
{
|
||||
return get(*value.get());
|
||||
}
|
||||
inline UShortArray & getVector(UShortArrayPtr &value)
|
||||
{
|
||||
return *value.get();
|
||||
}
|
||||
inline UShortArray const & getVector(UShortArrayPtr const &value)
|
||||
{
|
||||
return *value.get();
|
||||
}
|
||||
typedef std::vector<uint16>::iterator UShortArray_iterator;
|
||||
typedef std::vector<uint16>::const_iterator UShortArray_const_iterator;
|
||||
|
||||
/**
|
||||
* An unsigned int array.
|
||||
*/
|
||||
typedef std::vector<uint32> UIntArray;
|
||||
typedef std::tr1::shared_ptr<UIntArray> UIntArrayPtr;
|
||||
inline uint32 * get(UIntArray &value)
|
||||
{
|
||||
return &value[0];
|
||||
}
|
||||
inline uint32 const * get(UIntArray const &value)
|
||||
{
|
||||
return static_cast<uint32 const *>(&value[0]);
|
||||
}
|
||||
inline uint32 * get(UIntArrayPtr &value)
|
||||
{
|
||||
return get(*value.get());
|
||||
}
|
||||
inline uint32 const * get(UIntArrayPtr const &value)
|
||||
{
|
||||
return get(*value.get());
|
||||
}
|
||||
inline UIntArray & getVector(UIntArrayPtr &value)
|
||||
{
|
||||
return *value.get();
|
||||
}
|
||||
inline UIntArray const & getVector(UIntArrayPtr const &value)
|
||||
{
|
||||
return *value.get();
|
||||
}
|
||||
typedef std::vector<uint32>::iterator UIntArray_iterator;
|
||||
typedef std::vector<uint32>::const_iterator UIntArray_const_iterator;
|
||||
|
||||
/**
|
||||
* An unsigned long array.
|
||||
*/
|
||||
typedef std::vector<uint64> ULongArray;
|
||||
typedef std::tr1::shared_ptr<ULongArray> ULongArrayPtr;
|
||||
inline uint64 * get(ULongArray &value)
|
||||
{
|
||||
return &value[0];
|
||||
}
|
||||
inline uint64 const * get(ULongArray const &value)
|
||||
{
|
||||
return static_cast<uint64 const *>(&value[0]);
|
||||
}
|
||||
inline uint64 * get(ULongArrayPtr &value)
|
||||
{
|
||||
return get(*value.get());
|
||||
}
|
||||
inline uint64 const * get(ULongArrayPtr const &value)
|
||||
{
|
||||
return get(*value.get());
|
||||
}
|
||||
inline ULongArray & getVector(ULongArrayPtr &value)
|
||||
{
|
||||
return *value.get();
|
||||
}
|
||||
inline ULongArray const & getVector(ULongArrayPtr const &value)
|
||||
{
|
||||
return *value.get();
|
||||
}
|
||||
typedef std::vector<uint64>::iterator ULongArray_iterator;
|
||||
typedef std::vector<uint64>::const_iterator ULongArray_const_iterator;
|
||||
|
||||
/**
|
||||
* A float array.
|
||||
*/
|
||||
typedef std::vector<float> FloatArray;
|
||||
typedef std::tr1::shared_ptr<FloatArray> FloatArrayPtr;
|
||||
inline float * get(FloatArray &value)
|
||||
{
|
||||
return &value[0];
|
||||
}
|
||||
inline float const * get(FloatArray const &value)
|
||||
{
|
||||
return static_cast<float const *>(&value[0]);
|
||||
}
|
||||
inline float * get(FloatArrayPtr &value)
|
||||
{
|
||||
return get(*value.get());
|
||||
}
|
||||
inline float const * get(FloatArrayPtr const &value)
|
||||
{
|
||||
return get(*value.get());
|
||||
}
|
||||
inline FloatArray & getVector(FloatArrayPtr &value)
|
||||
{
|
||||
return *value.get();
|
||||
}
|
||||
inline FloatArray const & getVector(FloatArrayPtr const &value)
|
||||
{
|
||||
return *value.get();
|
||||
}
|
||||
typedef std::vector<float>::iterator FloatArray_iterator;
|
||||
typedef std::vector<float>::const_iterator FloatArray_const_iterator;
|
||||
|
||||
/**
|
||||
* A double array.
|
||||
*/
|
||||
typedef std::vector<double> DoubleArray;
|
||||
typedef std::tr1::shared_ptr<DoubleArray> DoubleArrayPtr;
|
||||
inline double * get(DoubleArray &value)
|
||||
{
|
||||
return &value[0];
|
||||
}
|
||||
inline double const * get(DoubleArray const &value)
|
||||
{
|
||||
return static_cast<double const *>(&value[0]);
|
||||
}
|
||||
inline double * get(DoubleArrayPtr &value)
|
||||
{
|
||||
return get(*value.get());
|
||||
}
|
||||
inline double const * get(DoubleArrayPtr const &value)
|
||||
{
|
||||
return get(*value.get());
|
||||
}
|
||||
inline DoubleArray & getVector(DoubleArrayPtr &value)
|
||||
{
|
||||
return *value.get();
|
||||
}
|
||||
inline DoubleArray const & getVector(DoubleArrayPtr const &value)
|
||||
{
|
||||
return *value.get();
|
||||
}
|
||||
typedef std::vector<double>::iterator DoubleArray_iterator;
|
||||
typedef std::vector<double>::const_iterator DoubleArray_const_iterator;
|
||||
|
||||
/**
|
||||
* A string array.
|
||||
*/
|
||||
|
||||
@@ -20,6 +20,10 @@
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
|
||||
class StandardField;
|
||||
typedef std::tr1::shared_ptr<StandardField> StandardFieldPtr;
|
||||
|
||||
/**
|
||||
* Standard Fields is a class or creating or sharing Field objects for standard fields.
|
||||
* For each type of standard object two methods are defined:s
|
||||
@@ -57,39 +61,158 @@ namespace epics { namespace pvData {
|
||||
StandardField *standardField = getStandardField();
|
||||
* }
|
||||
*/
|
||||
|
||||
class StandardField;
|
||||
typedef std::tr1::shared_ptr<StandardField> StandardFieldPtr;
|
||||
|
||||
class epicsShareClass StandardField {
|
||||
public:
|
||||
/**
|
||||
* getStandardField returns the singleton.
|
||||
* @return Shared pointer to StandardField.
|
||||
*/
|
||||
static StandardFieldPtr getStandardField();
|
||||
~StandardField();
|
||||
/** Create a structure that has a scalar value field.
|
||||
* @param type The type.
|
||||
* @param properties A comma separated list of properties.
|
||||
* This is some combination of "alarm,timeStamp,display,control,valueAlarm".
|
||||
* @return The const shared pointer to the structure.
|
||||
*/
|
||||
StructureConstPtr scalar(ScalarType type,String const & properties);
|
||||
/** Create a structure that has a union value field.
|
||||
* @param punion The interface for value field.
|
||||
* @param properties A comma separated list of properties.
|
||||
* This is some combination of "alarm,timeStamp,display,control,valueAlarm".
|
||||
* @return The const shared pointer to the structure.
|
||||
*/
|
||||
StructureConstPtr regUnion(
|
||||
UnionConstPtr const & punion,
|
||||
String const & properties);
|
||||
/** Create a structure that has a varient union value field.
|
||||
* @param properties A comma separated list of properties.
|
||||
* This is some combination of "alarm,timeStamp,display,control,valueAlarm".
|
||||
* @return The const shared pointer to the structure.
|
||||
*/
|
||||
StructureConstPtr variantUnion(String const & properties);
|
||||
/** Create a structure that has a scalarArray value field.
|
||||
* @param type The type.
|
||||
* @param properties A comma separated list of properties.
|
||||
* This is some combination of "alarm,timeStamp,display,control,valueAlarm".
|
||||
* @return The const shared pointer to the structure.
|
||||
*/
|
||||
StructureConstPtr scalarArray(ScalarType elementType, String const & properties);
|
||||
StructureConstPtr structureArray(StructureConstPtr const & structure,String const & properties);
|
||||
/** Create a structure that has a structureArray value field.
|
||||
* @param type The type.
|
||||
* @param properties A comma separated list of properties.
|
||||
* This is some combination of "alarm,timeStamp,display,control,valueAlarm".
|
||||
* @return The const shared pointer to the structure.
|
||||
*/
|
||||
StructureConstPtr structureArray(
|
||||
StructureConstPtr const & structure,
|
||||
String const & properties);
|
||||
/** Create a structure that has a unionArray value field.
|
||||
* @param type The type.
|
||||
* @param properties A comma separated list of properties.
|
||||
* This is some combination of "alarm,timeStamp,display,control".
|
||||
* @return The const shared pointer to the structure.
|
||||
*/
|
||||
StructureConstPtr unionArray(
|
||||
UnionConstPtr const & punion,
|
||||
String const & properties);
|
||||
/** Create a structure that has an enumerated structure value field.
|
||||
* The id for the structure is "enum-t".
|
||||
* @return The const shared pointer to the structure.
|
||||
*/
|
||||
StructureConstPtr enumerated();
|
||||
/** Create a structure that has an enumerated structure value field
|
||||
* The id for the structure is "uri:ev4:nt/2012/pwd:NTEnum".
|
||||
* @param properties A comma separated list of properties.
|
||||
* This is some combination of "alarm,timeStamp,display,control,valueAlarm".
|
||||
* @return The const shared pointer to the structure.
|
||||
*/
|
||||
StructureConstPtr enumerated(String const & properties);
|
||||
/**
|
||||
* create an alarm structure
|
||||
* @return The const shared pointer to the structure.
|
||||
*/
|
||||
StructureConstPtr alarm();
|
||||
/**
|
||||
* create a timeStamp structure
|
||||
* @return The const shared pointer to the structure.
|
||||
*/
|
||||
StructureConstPtr timeStamp();
|
||||
/**
|
||||
* create a display structure
|
||||
* @return The const shared pointer to the structure.
|
||||
*/
|
||||
StructureConstPtr display();
|
||||
/**
|
||||
* create a control structure
|
||||
* @return The const shared pointer to the structure.
|
||||
*/
|
||||
StructureConstPtr control();
|
||||
/**
|
||||
* create a boolean alarm structure
|
||||
* @return The const shared pointer to the structure.
|
||||
*/
|
||||
StructureConstPtr booleanAlarm();
|
||||
/**
|
||||
* create a byte alarm structure
|
||||
* @return The const shared pointer to the structure.
|
||||
*/
|
||||
StructureConstPtr byteAlarm();
|
||||
/**
|
||||
* create a unsigned byte alarm structure
|
||||
* @return The const shared pointer to the structure.
|
||||
*/
|
||||
StructureConstPtr ubyteAlarm();
|
||||
/**
|
||||
* create a short alarm structure
|
||||
* @return The const shared pointer to the structure.
|
||||
*/
|
||||
StructureConstPtr shortAlarm();
|
||||
/**
|
||||
* create a unsigned short alarm structure
|
||||
* @return The const shared pointer to the structure.
|
||||
*/
|
||||
StructureConstPtr ushortAlarm();
|
||||
/**
|
||||
* create an int alarm structure
|
||||
* @return The const shared pointer to the structure.
|
||||
*/
|
||||
StructureConstPtr intAlarm();
|
||||
/**
|
||||
* create a unsigned int alarm structure
|
||||
* @return The const shared pointer to the structure.
|
||||
*/
|
||||
StructureConstPtr uintAlarm();
|
||||
/**
|
||||
* create a long alarm structure
|
||||
* @return The const shared pointer to the structure.
|
||||
*/
|
||||
StructureConstPtr longAlarm();
|
||||
/**
|
||||
* create a unsigned long alarm structure
|
||||
* @return The const shared pointer to the structure.
|
||||
*/
|
||||
StructureConstPtr ulongAlarm();
|
||||
/**
|
||||
* create a float alarm structure
|
||||
* @return The const shared pointer to the structure.
|
||||
*/
|
||||
StructureConstPtr floatAlarm();
|
||||
/**
|
||||
* create a double alarm structure
|
||||
* @return The const shared pointer to the structure.
|
||||
*/
|
||||
StructureConstPtr doubleAlarm();
|
||||
/**
|
||||
* create an enumerated alarm structure
|
||||
* @return The const shared pointer to the structure.
|
||||
*/
|
||||
StructureConstPtr enumeratedAlarm();
|
||||
private:
|
||||
StandardField();
|
||||
void init();
|
||||
StructureConstPtr createProperties(String id,FieldConstPtr field,String properties);
|
||||
StructureConstPtr createProperties(
|
||||
String id,FieldConstPtr field,String properties);
|
||||
FieldCreatePtr fieldCreate;
|
||||
String notImplemented;
|
||||
String valueFieldName;
|
||||
|
||||
@@ -20,6 +20,10 @@
|
||||
#include <shareLib.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
class StandardPVField;
|
||||
typedef std::tr1::shared_ptr<StandardPVField> StandardPVFieldPtr;
|
||||
|
||||
/**
|
||||
* StandardPVField is a class or creating standard data fields.
|
||||
* Like class StandardField it has two forms of the methods which create a fields:
|
||||
@@ -31,18 +35,60 @@ namespace epics { namespace pvData {
|
||||
StandardPVField *standardPVField = getStandardPVField();
|
||||
* }
|
||||
*/
|
||||
|
||||
class StandardPVField;
|
||||
typedef std::tr1::shared_ptr<StandardPVField> StandardPVFieldPtr;
|
||||
|
||||
class epicsShareClass StandardPVField : private NoDefaultMethods {
|
||||
public:
|
||||
/**
|
||||
* getStandardPVField returns the singleton.
|
||||
* @return Shared pointer to StandardPVField.
|
||||
*/
|
||||
static StandardPVFieldPtr getStandardPVField();
|
||||
~StandardPVField();
|
||||
/**
|
||||
* Create a structure that has a scalar value field.
|
||||
* @param type The type.
|
||||
* @param properties A comma separated list of properties.
|
||||
* This is some combination of "alarm,timeStamp,display,control,valueAlarm".
|
||||
* @return The const shared pointer to the structure.
|
||||
*/
|
||||
PVStructurePtr scalar(ScalarType type,String const & properties);
|
||||
/**
|
||||
* Create a structure that has a scalar array value field.
|
||||
* @param type The type.
|
||||
* @param properties A comma separated list of properties.
|
||||
* This is some combination of "alarm,timeStamp,display,control,valueAlarm".
|
||||
* @return The const shared pointer to the structure.
|
||||
*/
|
||||
PVStructurePtr scalarArray(ScalarType elementType, String const & properties);
|
||||
/**
|
||||
* Create a structure that has a structure array value field.
|
||||
* @param type The type.
|
||||
* @param properties A comma separated list of properties.
|
||||
* This is some combination of "alarm,timeStamp,display,control,valueAlarm".
|
||||
* @return The const shared pointer to the structure.
|
||||
*/
|
||||
PVStructurePtr structureArray(StructureConstPtr const &structure,String const & properties);
|
||||
/**
|
||||
* Create a structure that has a union array value field.
|
||||
* @param type The type.
|
||||
* @param properties A comma separated list of properties.
|
||||
* This is some combination of "alarm,timeStamp,display,control,valueAlarm".
|
||||
* @return The const shared pointer to the structure.
|
||||
*/
|
||||
PVStructurePtr unionArray(UnionConstPtr const &punion,String const & properties);
|
||||
/**
|
||||
* Create a structure that has an enumerated structure value field.
|
||||
* The id for the structure is "enum_t".
|
||||
* @param choices This is a StringArray of choices.
|
||||
* @return The const shared pointer to the structure.
|
||||
*/
|
||||
PVStructurePtr enumerated(StringArray const &choices);
|
||||
/**
|
||||
* Create a structure that has an enumerated structure value field.
|
||||
* The id for the structure is "uri:ev4:nt/2012/pwd:NTEnum".
|
||||
* @param choices This is a StringArray of choices.
|
||||
* @param properties A comma separated list of properties.
|
||||
* @return The const shared pointer to the structure.
|
||||
*/
|
||||
PVStructurePtr enumerated(StringArray const &choices, String const & properties);
|
||||
private:
|
||||
StandardPVField();
|
||||
|
||||
@@ -3,5 +3,6 @@ include $(TOP)/configure/CONFIG
|
||||
DIRS += misc
|
||||
DIRS += pv
|
||||
DIRS += property
|
||||
DIRS += copy
|
||||
include $(TOP)/configure/RULES_DIRS
|
||||
|
||||
|
||||
22
testApp/copy/Makefile
Normal file
22
testApp/copy/Makefile
Normal file
@@ -0,0 +1,22 @@
|
||||
TOP=../..
|
||||
|
||||
include $(TOP)/configure/CONFIG
|
||||
|
||||
PROD_HOST += testCreateRequest
|
||||
testCreateRequest_SRCS = testCreateRequest.cpp
|
||||
testCreateRequest_LIBS = pvData Com
|
||||
TESTS += testCreateRequest
|
||||
|
||||
PROD_HOST += testPVCopy
|
||||
testPVCopy_SRCS += testPVCopy.cpp
|
||||
testPVCopy_LIBS += pvData Com
|
||||
TESTS += testPVCopy
|
||||
|
||||
TESTSCRIPTS_HOST += $(TESTS:%=%.t)
|
||||
|
||||
|
||||
|
||||
include $(TOP)/configure/RULES
|
||||
#----------------------------------------
|
||||
# ADD RULES AFTER THIS LINE
|
||||
|
||||
327
testApp/copy/testCreateRequest.cpp
Normal file
327
testApp/copy/testCreateRequest.cpp
Normal file
@@ -0,0 +1,327 @@
|
||||
/* testCreateRequest.cpp */
|
||||
/* Author: Matej Sekoranja Date: 2010.12.27 */
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
|
||||
#include <epicsUnitTest.h>
|
||||
#include <testMain.h>
|
||||
|
||||
#include <pv/createRequest.h>
|
||||
|
||||
using namespace epics::pvData;
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
static bool debug = false;
|
||||
|
||||
void testCreateRequest() {
|
||||
printf("testCreateRequest... \n");
|
||||
CreateRequest::shared_pointer createRequest = CreateRequest::create();
|
||||
|
||||
String out;
|
||||
String request = "";
|
||||
if(debug) { cout << "request " << request <<endl;}
|
||||
PVStructurePtr pvRequest = createRequest->createRequest(request);
|
||||
if(debug) { cout<< createRequest->getMessage() << endl;}
|
||||
testOk1(pvRequest!=NULL);
|
||||
if(debug) { cout << pvRequest->dumpValue(cout) << endl;}
|
||||
testOk1(pvRequest->getStructure()->getNumberFields()==0);
|
||||
testPass("request %s",request.c_str());
|
||||
|
||||
|
||||
request = "record[a=b,x=y]field(a) putField(a),getField(a)";
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
if(pvRequest==NULL) {
|
||||
cout << createRequest->getMessage() << endl;
|
||||
}
|
||||
if(debug) { cout << "request " << request <<endl;}
|
||||
testOk1(pvRequest!=NULL);
|
||||
if(debug) { cout << pvRequest->dumpValue(cout) << endl;}
|
||||
PVStringPtr pvString = pvRequest->getSubField<PVString>("record.a");
|
||||
String sval = pvString->get();
|
||||
testOk(sval.compare("b")==0,"record.a = b");
|
||||
pvString = pvRequest->getSubField<PVString>("record.x");
|
||||
sval = pvString->get();
|
||||
testOk(sval.compare("y")==0,"record.x = y");
|
||||
testOk1(pvRequest->getSubField("field.a")!=NULL);
|
||||
testOk1(pvRequest->getSubField("putField.a")!=NULL);
|
||||
testOk1(pvRequest->getSubField("getField.a")!=NULL);
|
||||
testPass("request %s",request.c_str());
|
||||
|
||||
request = "field(a.b[x=y])";
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
if(pvRequest==NULL) {
|
||||
cout << createRequest->getMessage() << endl;
|
||||
}
|
||||
if(debug) { cout << "request " << request <<endl;}
|
||||
testOk1(pvRequest!=NULL);
|
||||
if(debug) { cout << pvRequest->dumpValue(cout) << endl;}
|
||||
pvString = pvRequest->getSubField<PVString>("field.a.b._options.x");
|
||||
sval = pvString->get();
|
||||
testOk(sval.compare("y")==0,"field.a.b._options.x = y");
|
||||
testPass("request %s",request.c_str());
|
||||
|
||||
request = "field(a.b{c.d})";
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
if(debug) { cout << "request " << request <<endl;}
|
||||
if(pvRequest==NULL) {
|
||||
cout << createRequest->getMessage() << endl;
|
||||
}
|
||||
testOk1(pvRequest!=NULL);
|
||||
testOk1(pvRequest->getSubField("field.a.b.c.d")!=NULL);
|
||||
if(debug) { cout << pvRequest->dumpValue(cout) << endl;}
|
||||
testPass("request %s",request.c_str());
|
||||
|
||||
request = "field(a.b[x=y]{c.d})";
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
if(debug) { cout << "request " << request <<endl;}
|
||||
if(pvRequest==NULL) {
|
||||
cout << createRequest->getMessage() << endl;
|
||||
}
|
||||
testOk1(pvRequest!=NULL);
|
||||
pvString = pvRequest->getSubField<PVString>("field.a.b._options.x");
|
||||
sval = pvString->get();
|
||||
testOk(sval.compare("y")==0,"field.a.b._options.x = y");
|
||||
testOk1(pvRequest->getSubField("field.a.b.c.d")!=NULL);
|
||||
if(debug) { cout << pvRequest->dumpValue(cout) << endl;}
|
||||
testPass("request %s",request.c_str());
|
||||
|
||||
request = "field(a.b[x=y]{c.d[x=y]})";
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
if(debug) { cout << "request " << request <<endl;}
|
||||
if(pvRequest==NULL) {
|
||||
cout << createRequest->getMessage() << endl;
|
||||
}
|
||||
testOk1(pvRequest!=NULL);
|
||||
pvString = pvRequest->getSubField<PVString>("field.a.b._options.x");
|
||||
sval = pvString->get();
|
||||
testOk(sval.compare("y")==0,"field.a.b._options.x = y");
|
||||
pvString = pvRequest->getSubField<PVString>("field.a.b.c.d._options.x");
|
||||
sval = pvString->get();
|
||||
testOk(sval.compare("y")==0,"field.a.b.c.d._options.x = y");
|
||||
if(debug) { cout << pvRequest->dumpValue(cout) << endl;}
|
||||
testPass("request %s",request.c_str());
|
||||
|
||||
request = "record[a=b,c=d] field(a.a[a=b]{a.a[a=b]},b.a[a=b]{a,b})";
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
if(debug) { cout << "request " << request <<endl;}
|
||||
if(pvRequest==NULL) {
|
||||
cout << createRequest->getMessage() << endl;
|
||||
}
|
||||
testOk1(pvRequest!=NULL);
|
||||
pvString = pvRequest->getSubField<PVString>("field.a.a._options.a");
|
||||
sval = pvString->get();
|
||||
testOk(sval.compare("b")==0,"field.a.a._options.a = b");
|
||||
pvString = pvRequest->getSubField<PVString>("field.a.a.a.a._options.a");
|
||||
sval = pvString->get();
|
||||
testOk(sval.compare("b")==0,"field.a.a.a.a._options.a = b");
|
||||
pvString = pvRequest->getSubField<PVString>("field.b.a._options.a");
|
||||
sval = pvString->get();
|
||||
testOk(sval.compare("b")==0,"field.b.a._options.a = b");
|
||||
testOk1(pvRequest->getSubField("field.b.a.a")!=NULL);
|
||||
testOk1(pvRequest->getSubField("field.b.a.b")!=NULL);
|
||||
if(debug) { cout << pvRequest->dumpValue(cout) << endl;}
|
||||
testPass("request %s",request.c_str());
|
||||
|
||||
|
||||
request = "alarm,timeStamp,power.value";
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
if(debug) { cout << endl << String("request") <<endl << request <<endl;}
|
||||
if(pvRequest==NULL) {
|
||||
cout << "reason " << createRequest->getMessage() << endl;
|
||||
}
|
||||
testOk1(pvRequest!=NULL);
|
||||
testOk1(pvRequest->getSubField("field.alarm")!=NULL);
|
||||
testOk1(pvRequest->getSubField("field.timeStamp")!=NULL);
|
||||
testOk1(pvRequest->getSubField("field.power.value")!=NULL);
|
||||
if(debug) { cout << pvRequest->dumpValue(cout) << endl;}
|
||||
testPass("request %s",request.c_str());
|
||||
|
||||
request = "record[process=true]field(alarm,timeStamp,power.value)";
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
if(debug) { cout << endl << String("request") <<endl << request <<endl;}
|
||||
if(pvRequest==NULL) {
|
||||
cout << "reason " << createRequest->getMessage() << endl;
|
||||
}
|
||||
testOk1(pvRequest!=NULL);
|
||||
pvString = pvRequest->getSubField<PVString>("record.process");
|
||||
sval = pvString->get();
|
||||
testOk(sval.compare("true")==0,"record.process = true");
|
||||
testOk1(pvRequest->getSubField("field.alarm")!=NULL);
|
||||
testOk1(pvRequest->getSubField("field.timeStamp")!=NULL);
|
||||
testOk1(pvRequest->getSubField("field.power.value")!=NULL);
|
||||
if(debug) {cout << pvRequest->dumpValue(cout) << endl;}
|
||||
testPass("request %s",request.c_str());
|
||||
|
||||
request = "record[process=true]field(alarm,timeStamp[algorithm=onChange,causeMonitor=false],power{value,alarm})";
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
if(debug) { cout << String("request") <<endl << request <<endl;}
|
||||
if(pvRequest==NULL) {
|
||||
cout << "reason " << createRequest->getMessage() << endl;
|
||||
}
|
||||
testOk1(pvRequest!=NULL);
|
||||
pvString = pvRequest->getSubField<PVString>("record.process");
|
||||
sval = pvString->get();
|
||||
testOk(sval.compare("true")==0,"record.process = true");
|
||||
testOk1(pvRequest->getSubField("field.alarm")!=NULL);
|
||||
testOk1(pvRequest->getSubField("field.timeStamp")!=NULL);
|
||||
pvString = pvRequest->getSubField<PVString>("field.timeStamp._options.algorithm");
|
||||
sval = pvString->get();
|
||||
testOk(sval.compare("onChange")==0,"field.timeStamp._options.algorithm = onChange");
|
||||
pvString = pvRequest->getSubField<PVString>("field.timeStamp._options.causeMonitor");
|
||||
sval = pvString->get();
|
||||
testOk(sval.compare("false")==0,"field.timeStamp._options.causeMonitor = false");
|
||||
testOk1(pvRequest->getSubField("field.power.value")!=NULL);
|
||||
testOk1(pvRequest->getSubField("field.power.alarm")!=NULL);
|
||||
if(debug) {cout << pvRequest->dumpValue(cout) << endl;}
|
||||
testPass("request %s",request.c_str());
|
||||
|
||||
request = "record[int=2,float=3.14159]field(alarm,timeStamp[shareData=true],power.value)";
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
if(debug) { cout << String("request") <<endl << request <<endl;}
|
||||
if(pvRequest==NULL) {
|
||||
cout << "reason " << createRequest->getMessage() << endl;
|
||||
}
|
||||
testOk1(pvRequest!=NULL);
|
||||
pvString = pvRequest->getSubField<PVString>("record.int");
|
||||
sval = pvString->get();
|
||||
testOk(sval.compare("2")==0,"record.int = 2");
|
||||
pvString = pvRequest->getSubField<PVString>("record.float");
|
||||
sval = pvString->get();
|
||||
testOk(sval.compare("3.14159")==0,"record.float = 3.14159");
|
||||
testOk1(pvRequest->getSubField("field.alarm")!=NULL);
|
||||
pvString = pvRequest->getSubField<PVString>("field.timeStamp._options.shareData");
|
||||
sval = pvString->get();
|
||||
testOk(sval.compare("true")==0,"field.timeStamp._options.shareData = true");
|
||||
testOk1(pvRequest->getSubField("field.power.value")!=NULL);
|
||||
if(debug) {cout << pvRequest->dumpValue(cout) << endl;}
|
||||
testPass("request %s",request.c_str());
|
||||
|
||||
request = String("record[process=true,xxx=yyy]")
|
||||
+ "putField(power.value)"
|
||||
+ "getField(alarm,timeStamp,power{value,alarm},"
|
||||
+ "current{value,alarm},voltage{value,alarm})";
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
if(debug) { cout << String("request") <<endl << request <<endl;}
|
||||
if(pvRequest==NULL) {
|
||||
cout << "reason " << createRequest->getMessage() << endl;
|
||||
}
|
||||
testOk1(pvRequest!=NULL);
|
||||
testOk1(pvRequest->getSubField("putField.power.value")!=NULL);
|
||||
testOk1(pvRequest->getSubField("getField.alarm")!=NULL);
|
||||
testOk1(pvRequest->getSubField("getField.timeStamp")!=NULL);
|
||||
testOk1(pvRequest->getSubField("getField.power.value")!=NULL);
|
||||
testOk1(pvRequest->getSubField("getField.power.alarm")!=NULL);
|
||||
testOk1(pvRequest->getSubField("getField.current.value")!=NULL);
|
||||
testOk1(pvRequest->getSubField("getField.current.alarm")!=NULL);
|
||||
testOk1(pvRequest->getSubField("getField.voltage.value")!=NULL);
|
||||
testOk1(pvRequest->getSubField("getField.voltage.alarm")!=NULL);
|
||||
if(debug) {cout << pvRequest->dumpValue(cout) << endl;}
|
||||
testPass("request %s",request.c_str());
|
||||
|
||||
request = String("field(alarm,timeStamp,supply{")
|
||||
+ "0{voltage.value,current.value,power.value},"
|
||||
+ "1{voltage.value,current.value,power.value}"
|
||||
+ "})";
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
if(debug) { cout << String("request") <<endl << request <<endl;}
|
||||
if(pvRequest==NULL) {
|
||||
cout << "reason " << createRequest->getMessage() << endl;
|
||||
}
|
||||
testOk1(pvRequest!=NULL);
|
||||
testOk1(pvRequest->getSubField("field.alarm")!=NULL);
|
||||
testOk1(pvRequest->getSubField("field.timeStamp")!=NULL);
|
||||
testOk1(pvRequest->getSubField("field.supply.0.voltage.value")!=NULL);
|
||||
testOk1(pvRequest->getSubField("field.supply.0.current.value")!=NULL);
|
||||
testOk1(pvRequest->getSubField("field.supply.0.power.value")!=NULL);
|
||||
testOk1(pvRequest->getSubField("field.supply.1.voltage.value")!=NULL);
|
||||
testOk1(pvRequest->getSubField("field.supply.1.current.value")!=NULL);
|
||||
testOk1(pvRequest->getSubField("field.supply.1.power.value")!=NULL);
|
||||
if(debug) {cout << pvRequest->dumpValue(cout) << endl;}
|
||||
testPass("request %s",request.c_str());
|
||||
|
||||
request = String("record[process=true,xxx=yyy]")
|
||||
+ "putField(power.value)"
|
||||
+ "getField(alarm,timeStamp,power{value,alarm},"
|
||||
+ "current{value,alarm},voltage{value,alarm},"
|
||||
+ "ps0{alarm,timeStamp,power{value,alarm},current{value,alarm},voltage{value,alarm}},"
|
||||
+ "ps1{alarm,timeStamp,power{value,alarm},current{value,alarm},voltage{value,alarm}}"
|
||||
+ ")";
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
if(debug) { cout << String("request") <<endl << request <<endl;}
|
||||
if(pvRequest==NULL) {
|
||||
cout << "reason " << createRequest->getMessage() << endl;
|
||||
}
|
||||
testOk1(pvRequest!=NULL);
|
||||
testOk1(pvRequest->getSubField("putField.power.value")!=NULL);
|
||||
testOk1(pvRequest->getSubField("getField.alarm")!=NULL);
|
||||
testOk1(pvRequest->getSubField("getField.timeStamp")!=NULL);
|
||||
testOk1(pvRequest->getSubField("getField.power.value")!=NULL);
|
||||
testOk1(pvRequest->getSubField("getField.power.alarm")!=NULL);
|
||||
testOk1(pvRequest->getSubField("getField.current.value")!=NULL);
|
||||
testOk1(pvRequest->getSubField("getField.current.alarm")!=NULL);
|
||||
testOk1(pvRequest->getSubField("getField.voltage.value")!=NULL);
|
||||
testOk1(pvRequest->getSubField("getField.voltage.alarm")!=NULL);
|
||||
testOk1(pvRequest->getSubField("getField.ps0.alarm")!=NULL);
|
||||
testOk1(pvRequest->getSubField("getField.ps0.timeStamp")!=NULL);
|
||||
testOk1(pvRequest->getSubField("getField.ps0.power.value")!=NULL);
|
||||
testOk1(pvRequest->getSubField("getField.ps0.power.alarm")!=NULL);
|
||||
testOk1(pvRequest->getSubField("getField.ps0.current.value")!=NULL);
|
||||
testOk1(pvRequest->getSubField("getField.ps0.current.alarm")!=NULL);
|
||||
testOk1(pvRequest->getSubField("getField.ps0.voltage.value")!=NULL);
|
||||
testOk1(pvRequest->getSubField("getField.ps0.voltage.alarm")!=NULL);
|
||||
testOk1(pvRequest->getSubField("getField.ps1.alarm")!=NULL);
|
||||
testOk1(pvRequest->getSubField("getField.ps1.timeStamp")!=NULL);
|
||||
testOk1(pvRequest->getSubField("getField.ps1.power.value")!=NULL);
|
||||
testOk1(pvRequest->getSubField("getField.ps1.power.alarm")!=NULL);
|
||||
testOk1(pvRequest->getSubField("getField.ps1.current.value")!=NULL);
|
||||
testOk1(pvRequest->getSubField("getField.ps1.current.alarm")!=NULL);
|
||||
testOk1(pvRequest->getSubField("getField.ps1.voltage.value")!=NULL);
|
||||
testOk1(pvRequest->getSubField("getField.ps1.voltage.alarm")!=NULL);
|
||||
if(debug) {cout << pvRequest->dumpValue(cout) << endl;}
|
||||
testPass("request %s",request.c_str());
|
||||
|
||||
request = "a{b{c{d}}}";
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
if(debug) { cout << String("request") <<endl << request <<endl;}
|
||||
testOk1(pvRequest!=NULL);
|
||||
testOk1(pvRequest->getSubField("field.a.b.c.d")!=NULL);
|
||||
if(debug) {cout << pvRequest->dumpValue(cout) << endl;}
|
||||
testPass("request %s",request.c_str());
|
||||
|
||||
request = String("record[process=true,xxx=yyy]")
|
||||
+ "putField(power.value)"
|
||||
+ "getField(alarm,timeStamp,power{value,alarm},"
|
||||
+ "current{value,alarm},voltage{value,alarm},"
|
||||
+ "ps0{alarm,timeStamp,power{value,alarm},current{value,alarm},voltage{value,alarm}},"
|
||||
+ "ps1{alarm,timeStamp,power{value,alarm},current{value,alarm},voltage{value,alarm}"
|
||||
+ ")";
|
||||
if(debug) { cout << endl << "Error Expected for next call!!" << endl;}
|
||||
if(debug) { cout << String("request") <<endl << request <<endl;}
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
assert(pvRequest.get()==NULL);
|
||||
if(debug) {cout << "reason " << createRequest->getMessage() << endl;}
|
||||
testPass("request %s",request.c_str());
|
||||
|
||||
request = "record[process=true,power.value";
|
||||
if(debug) { cout << String("request") <<endl << request <<endl;}
|
||||
if(debug) { cout << endl << "Error Expected for next call!!" << endl;}
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
assert(pvRequest.get()==NULL);
|
||||
if(debug) { cout << "reason " << createRequest->getMessage() << endl;}
|
||||
testPass("request %s",request.c_str());
|
||||
}
|
||||
|
||||
MAIN(testCreateRequest)
|
||||
{
|
||||
testPlan(111);
|
||||
testCreateRequest();
|
||||
return testDone();
|
||||
}
|
||||
|
||||
|
||||
393
testApp/copy/testPVCopy.cpp
Normal file
393
testApp/copy/testPVCopy.cpp
Normal file
@@ -0,0 +1,393 @@
|
||||
/*testPVCopyMain.cpp */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
*/
|
||||
|
||||
/* Author: Marty Kraimer */
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <memory>
|
||||
#include <iostream>
|
||||
|
||||
#include <epicsUnitTest.h>
|
||||
#include <testMain.h>
|
||||
|
||||
#include <pv/standardField.h>
|
||||
#include <pv/standardPVField.h>
|
||||
#include <pv/convert.h>
|
||||
#include <pv/pvCopy.h>
|
||||
#include <pv/createRequest.h>
|
||||
|
||||
|
||||
using namespace std;
|
||||
using std::tr1::static_pointer_cast;
|
||||
using namespace epics::pvData;
|
||||
|
||||
static bool debug = true;
|
||||
|
||||
static void testPVScalar(
|
||||
String const & valueNameMaster,
|
||||
String const & valueNameCopy,
|
||||
PVStructurePtr const & pvMaster,
|
||||
PVCopyPtr const & pvCopy)
|
||||
{
|
||||
PVStructurePtr pvStructureCopy;
|
||||
PVFieldPtr pvField;
|
||||
PVScalarPtr pvValueMaster;
|
||||
PVScalarPtr pvValueCopy;
|
||||
BitSetPtr bitSet;
|
||||
String builder;
|
||||
size_t offset;
|
||||
ConvertPtr convert = getConvert();
|
||||
|
||||
pvField = pvMaster->getSubField(valueNameMaster);
|
||||
pvValueMaster = static_pointer_cast<PVScalar>(pvField);
|
||||
convert->fromDouble(pvValueMaster,.04);
|
||||
StructureConstPtr structure = pvCopy->getStructure();
|
||||
builder.clear(); structure->toString(&builder);
|
||||
if(debug) { cout << "structure from copy" << endl << builder << endl; }
|
||||
pvStructureCopy = pvCopy->createPVStructure();
|
||||
pvField = pvStructureCopy->getSubField(valueNameCopy);
|
||||
pvValueCopy = static_pointer_cast<PVScalar>(pvField);
|
||||
bitSet = BitSetPtr(new BitSet(pvStructureCopy->getNumberFields()));
|
||||
pvCopy->initCopy(pvStructureCopy, bitSet);
|
||||
if(debug) { cout << "after initCopy pvValueCopy " << convert->toDouble(pvValueCopy); }
|
||||
if(debug) { cout << endl; }
|
||||
convert->fromDouble(pvValueMaster,.06);
|
||||
testOk1(convert->toDouble(pvValueCopy)==.04);
|
||||
pvCopy->updateCopySetBitSet(pvStructureCopy,bitSet);
|
||||
testOk1(convert->toDouble(pvValueCopy)==.06);
|
||||
testOk1(bitSet->get(pvValueCopy->getFieldOffset()));
|
||||
if(debug) { cout << "after put(.06) pvValueCopy " << convert->toDouble(pvValueCopy); }
|
||||
builder.clear();
|
||||
bitSet->toString(&builder);
|
||||
if(debug) { cout << " bitSet " << builder; }
|
||||
if(debug) { cout << endl; }
|
||||
offset = pvCopy->getCopyOffset(pvValueMaster);
|
||||
if(debug) { cout << "getCopyOffset() " << offset; }
|
||||
if(debug) { cout << " pvValueCopy->getOffset() " << pvValueCopy->getFieldOffset(); }
|
||||
if(debug) { cout << " pvValueMaster->getOffset() " << pvValueMaster->getFieldOffset(); }
|
||||
if(debug) { cout << " bitSet " << builder; }
|
||||
if(debug) { cout << endl; }
|
||||
bitSet->clear();
|
||||
convert->fromDouble(pvValueMaster,1.0);
|
||||
builder.clear();
|
||||
bitSet->toString(&builder);
|
||||
if(debug) { cout << "before updateCopyFromBitSet"; }
|
||||
if(debug) { cout << " masterValue " << convert->toDouble(pvValueMaster); }
|
||||
if(debug) { cout << " copyValue " << convert->toDouble(pvValueCopy); }
|
||||
if(debug) { cout << " bitSet " << builder; }
|
||||
if(debug) { cout << endl; }
|
||||
bitSet->set(0);
|
||||
testOk1(convert->toDouble(pvValueCopy)==0.06);
|
||||
pvCopy->updateCopyFromBitSet(pvStructureCopy,bitSet);
|
||||
testOk1(convert->toDouble(pvValueCopy)==1.0);
|
||||
if(debug) { cout << "after updateCopyFromBitSet"; }
|
||||
if(debug) { cout << " masterValue " << convert->toDouble(pvValueMaster); }
|
||||
if(debug) { cout << " copyValue " << convert->toDouble(pvValueCopy); }
|
||||
if(debug) { cout << " bitSet " << builder; }
|
||||
if(debug) { cout << endl; }
|
||||
convert->fromDouble(pvValueCopy,2.0);
|
||||
bitSet->set(0);
|
||||
if(debug) { cout << "before updateMaster"; }
|
||||
if(debug) { cout << " masterValue " << convert->toDouble(pvValueMaster); }
|
||||
if(debug) { cout << " copyValue " << convert->toDouble(pvValueCopy); }
|
||||
if(debug) { cout << " bitSet " << builder; }
|
||||
if(debug) { cout << endl; }
|
||||
testOk1(convert->toDouble(pvValueMaster)==1.0);
|
||||
pvCopy->updateMaster(pvStructureCopy,bitSet);
|
||||
testOk1(convert->toDouble(pvValueMaster)==2.0);
|
||||
if(debug) { cout << "after updateMaster"; }
|
||||
if(debug) { cout << " masterValue " << convert->toDouble(pvValueMaster); }
|
||||
if(debug) { cout << " copyValue " << convert->toDouble(pvValueCopy); }
|
||||
if(debug) { cout << " bitSet " << builder; }
|
||||
if(debug) { cout << endl; }
|
||||
}
|
||||
|
||||
static void testPVScalarArray(
|
||||
ScalarType scalarType,
|
||||
String const & valueNameMaster,
|
||||
String const & valueNameCopy,
|
||||
PVStructurePtr const & pvMaster,
|
||||
PVCopyPtr const & pvCopy)
|
||||
{
|
||||
PVStructurePtr pvStructureCopy;
|
||||
PVScalarArrayPtr pvValueMaster;
|
||||
PVScalarArrayPtr pvValueCopy;
|
||||
BitSetPtr bitSet;
|
||||
String builder;
|
||||
size_t offset;
|
||||
size_t n = 5;
|
||||
shared_vector<double> values(n);
|
||||
shared_vector<const double> cvalues;
|
||||
|
||||
pvValueMaster = pvMaster->getScalarArrayField(valueNameMaster,scalarType);
|
||||
for(size_t i=0; i<n; i++) values[i] = i;
|
||||
const shared_vector<const double> xxx(freeze(values));
|
||||
pvValueMaster->putFrom(xxx);
|
||||
StructureConstPtr structure = pvCopy->getStructure();
|
||||
builder.clear(); structure->toString(&builder);
|
||||
if(debug) { cout << "structure from copy" << endl << builder << endl;}
|
||||
pvStructureCopy = pvCopy->createPVStructure();
|
||||
pvValueCopy = pvStructureCopy->getScalarArrayField(valueNameCopy,scalarType);
|
||||
bitSet = BitSetPtr(new BitSet(pvStructureCopy->getNumberFields()));
|
||||
pvCopy->initCopy(pvStructureCopy, bitSet);
|
||||
builder.clear(); pvValueCopy->toString(&builder);
|
||||
if(debug) { cout << "after initCopy pvValueCopy " << builder << endl; }
|
||||
if(debug) { cout << endl; }
|
||||
values.resize(n);
|
||||
for(size_t i=0; i<n; i++) values[i] = i + .06;
|
||||
const shared_vector<const double> yyy(freeze(values));
|
||||
pvValueMaster->putFrom(yyy);
|
||||
pvValueCopy->getAs(cvalues);
|
||||
testOk1(cvalues[0]==0.0);
|
||||
pvCopy->updateCopySetBitSet(pvStructureCopy,bitSet);
|
||||
pvValueCopy->getAs(cvalues);
|
||||
testOk1(cvalues[0]==0.06);
|
||||
builder.clear(); pvValueCopy->toString(&builder);
|
||||
if(debug) { cout << "after put(i+ .06) pvValueCopy " << builder << endl; }
|
||||
builder.clear();
|
||||
bitSet->toString(&builder);
|
||||
if(debug) { cout << " bitSet " << builder; }
|
||||
if(debug) { cout << endl; }
|
||||
offset = pvCopy->getCopyOffset(pvValueMaster);
|
||||
if(debug) { cout << "getCopyOffset() " << offset; }
|
||||
if(debug) { cout << " pvValueCopy->getOffset() " << pvValueCopy->getFieldOffset(); }
|
||||
if(debug) { cout << " pvValueMaster->getOffset() " << pvValueMaster->getFieldOffset(); }
|
||||
builder.clear();
|
||||
bitSet->toString(&builder);
|
||||
if(debug) { cout << " bitSet " << builder; }
|
||||
if(debug) { cout << endl; }
|
||||
bitSet->clear();
|
||||
values.resize(n);
|
||||
for(size_t i=0; i<n; i++) values[i] = i + 1.0;
|
||||
const shared_vector<const double> zzz(freeze(values));
|
||||
pvValueMaster->putFrom(zzz);
|
||||
builder.clear();
|
||||
bitSet->toString(&builder);
|
||||
if(debug) { cout << "before updateCopyFromBitSet"; }
|
||||
builder.clear(); pvValueMaster->toString(&builder);
|
||||
if(debug) { cout << " masterValue " << builder << endl; }
|
||||
builder.clear(); pvValueCopy->toString(&builder);
|
||||
if(debug) { cout << " copyValue " << builder << endl; }
|
||||
if(debug) { cout << " bitSet " << builder; }
|
||||
builder.clear();
|
||||
bitSet->toString(&builder);
|
||||
if(debug) { cout << endl; }
|
||||
bitSet->set(0);
|
||||
pvValueCopy->getAs(cvalues);
|
||||
testOk1(cvalues[0]==0.06);
|
||||
pvCopy->updateCopyFromBitSet(pvStructureCopy,bitSet);
|
||||
pvValueCopy->getAs(cvalues);
|
||||
testOk1(cvalues[0]==1.0);
|
||||
if(debug) { cout << "after updateCopyFromBitSet"; }
|
||||
builder.clear(); pvValueMaster->toString(&builder);
|
||||
if(debug) { cout << " masterValue " << builder << endl; }
|
||||
builder.clear(); pvValueCopy->toString(&builder);
|
||||
if(debug) { cout << " copyValue " << builder << endl; }
|
||||
builder.clear();
|
||||
bitSet->toString(&builder);
|
||||
if(debug) { cout << " bitSet " << builder; }
|
||||
if(debug) { cout << endl; }
|
||||
values.resize(n);
|
||||
for(size_t i=0; i<n; i++) values[i] = i + 2.0;
|
||||
const shared_vector<const double> ttt(freeze(values));
|
||||
pvValueMaster->putFrom(ttt);
|
||||
bitSet->set(0);
|
||||
if(debug) { cout << "before updateMaster"; }
|
||||
builder.clear(); pvValueMaster->toString(&builder);
|
||||
if(debug) { cout << " masterValue " << builder << endl; }
|
||||
builder.clear(); pvValueCopy->toString(&builder);
|
||||
if(debug) { cout << " copyValue " << builder << endl; }
|
||||
builder.clear();
|
||||
bitSet->toString(&builder);
|
||||
if(debug) { cout << " bitSet " << builder; }
|
||||
if(debug) { cout << endl; }
|
||||
pvValueMaster->getAs(cvalues);
|
||||
testOk1(cvalues[0]==2.0);
|
||||
pvCopy->updateMaster(pvStructureCopy,bitSet);
|
||||
pvValueMaster->getAs(cvalues);
|
||||
testOk1(cvalues[0]==1.0);
|
||||
if(debug) { cout << "after updateMaster"; }
|
||||
builder.clear(); pvValueMaster->toString(&builder);
|
||||
if(debug) { cout << " masterValue " << builder << endl; }
|
||||
builder.clear(); pvValueCopy->toString(&builder);
|
||||
if(debug) { cout << " copyValue " << builder << endl; }
|
||||
builder.clear();
|
||||
bitSet->toString(&builder);
|
||||
if(debug) { cout << " bitSet " << builder; }
|
||||
if(debug) { cout << endl; }
|
||||
}
|
||||
|
||||
static void scalarTest()
|
||||
{
|
||||
if(debug) { cout << endl << endl << "****scalarTest****" << endl; }
|
||||
PVStructurePtr pvMaster;
|
||||
String request;
|
||||
PVStructurePtr pvRequest;
|
||||
PVFieldPtr pvMasterField;
|
||||
PVCopyPtr pvCopy;
|
||||
String valueNameMaster;
|
||||
String valueNameCopy;
|
||||
|
||||
StandardPVFieldPtr standardPVField = getStandardPVField();
|
||||
pvMaster = standardPVField->scalar(pvDouble,"alarm,timeStamp,display");
|
||||
|
||||
valueNameMaster = request = "value";
|
||||
CreateRequest::shared_pointer createRequest = CreateRequest::create();
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
if(debug) { cout << "request " << request << endl; }
|
||||
if(debug) { cout << "pvRequest\n" << pvRequest->dumpValue(cout) << endl; }
|
||||
pvCopy = PVCopy::create(pvMaster,pvRequest,"");
|
||||
valueNameCopy = "value";
|
||||
testPVScalar(valueNameMaster,valueNameCopy,pvMaster,pvCopy);
|
||||
request = "";
|
||||
valueNameMaster = "value";
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
if(debug) { cout << "request " << request << endl; }
|
||||
if(debug) { cout << "pvRequest\n" << pvRequest->dumpValue(cout) << endl; }
|
||||
pvCopy = PVCopy::create(pvMaster,pvRequest,"");
|
||||
valueNameCopy = "value";
|
||||
testPVScalar(valueNameMaster,valueNameCopy,pvMaster,pvCopy);
|
||||
request = "alarm,timeStamp,value";
|
||||
valueNameMaster = "value";
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
if(debug) { cout << "request " << request << endl; }
|
||||
if(debug) { cout << "pvRequest\n" << pvRequest->dumpValue(cout) << endl; }
|
||||
pvCopy = PVCopy::create(pvMaster,pvRequest,"");
|
||||
valueNameCopy = "value";
|
||||
testPVScalar(valueNameMaster,valueNameCopy,pvMaster,pvCopy);
|
||||
}
|
||||
|
||||
static void arrayTest()
|
||||
{
|
||||
if(debug) { cout << endl << endl << "****arrayTest****" << endl; }
|
||||
PVStructurePtr pvMaster;
|
||||
String request;
|
||||
PVStructurePtr pvRequest;
|
||||
PVFieldPtr pvMasterField;
|
||||
PVCopyPtr pvCopy;
|
||||
String valueNameMaster;
|
||||
String valueNameCopy;
|
||||
|
||||
CreateRequest::shared_pointer createRequest = CreateRequest::create();
|
||||
StandardPVFieldPtr standardPVField = getStandardPVField();
|
||||
pvMaster = standardPVField->scalarArray(pvDouble,"alarm,timeStamp");
|
||||
valueNameMaster = request = "value";
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
if(debug) { cout << "request " << request << endl; }
|
||||
if(debug) { cout << "pvRequest\n" << pvRequest->dumpValue(cout) << endl; }
|
||||
pvCopy = PVCopy::create(pvMaster,pvRequest,"");
|
||||
valueNameCopy = "value";
|
||||
testPVScalarArray(pvDouble,valueNameMaster,valueNameCopy,pvMaster,pvCopy);
|
||||
request = "";
|
||||
valueNameMaster = "value";
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
if(debug) { cout << "request " << request << endl; }
|
||||
if(debug) { cout << "pvRequest\n" << pvRequest->dumpValue(cout) << endl; }
|
||||
pvCopy = PVCopy::create(pvMaster,pvRequest,"");
|
||||
valueNameCopy = "value";
|
||||
testPVScalarArray(pvDouble,valueNameMaster,valueNameCopy,pvMaster,pvCopy);
|
||||
request = "alarm,timeStamp,value";
|
||||
valueNameMaster = "value";
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
if(debug) { cout << "request " << request << endl; }
|
||||
if(debug) { cout << "pvRequest\n" << pvRequest->dumpValue(cout) << endl; }
|
||||
pvCopy = PVCopy::create(pvMaster,pvRequest,"");
|
||||
valueNameCopy = "value";
|
||||
testPVScalarArray(pvDouble,valueNameMaster,valueNameCopy,pvMaster,pvCopy);
|
||||
}
|
||||
|
||||
static PVStructurePtr createPowerSupply()
|
||||
{
|
||||
FieldCreatePtr fieldCreate = getFieldCreate();
|
||||
StandardFieldPtr standardField = getStandardField();
|
||||
PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
||||
|
||||
size_t nfields = 5;
|
||||
StringArray names;
|
||||
names.reserve(nfields);
|
||||
FieldConstPtrArray powerSupply;
|
||||
powerSupply.reserve(nfields);
|
||||
names.push_back("alarm");
|
||||
powerSupply.push_back(standardField->alarm());
|
||||
names.push_back("timeStamp");
|
||||
powerSupply.push_back(standardField->timeStamp());
|
||||
String properties("alarm,display");
|
||||
names.push_back("voltage");
|
||||
powerSupply.push_back(standardField->scalar(pvDouble,properties));
|
||||
names.push_back("power");
|
||||
powerSupply.push_back(standardField->scalar(pvDouble,properties));
|
||||
names.push_back("current");
|
||||
powerSupply.push_back(standardField->scalar(pvDouble,properties));
|
||||
return pvDataCreate->createPVStructure(
|
||||
fieldCreate->createStructure(names,powerSupply));
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void powerSupplyTest()
|
||||
{
|
||||
if(debug) { cout << endl << endl << "****powerSupplyTest****" << endl; }
|
||||
PVStructurePtr pvMaster;
|
||||
String request;
|
||||
PVStructurePtr pvRequest;
|
||||
PVFieldPtr pvMasterField;
|
||||
PVCopyPtr pvCopy;
|
||||
String builder;
|
||||
String valueNameMaster;
|
||||
String valueNameCopy;
|
||||
|
||||
CreateRequest::shared_pointer createRequest = CreateRequest::create();
|
||||
pvMaster = createPowerSupply();
|
||||
valueNameMaster = request = "power.value";
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
if(debug) { cout << "request " << request << endl; }
|
||||
if(debug) { cout << "pvRequest\n" << pvRequest->dumpValue(cout) << endl; }
|
||||
pvCopy = PVCopy::create(pvMaster,pvRequest,"");
|
||||
valueNameCopy = "power.value";
|
||||
testPVScalar(valueNameMaster,valueNameCopy,pvMaster,pvCopy);
|
||||
request = "";
|
||||
valueNameMaster = "power.value";
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
if(debug) { cout << "request " << request << endl; }
|
||||
if(debug) { cout << "pvRequest\n" << pvRequest->dumpValue(cout) << endl; }
|
||||
pvCopy = PVCopy::create(pvMaster,pvRequest,"");
|
||||
valueNameCopy = "power.value";
|
||||
testPVScalar(valueNameMaster,valueNameCopy,pvMaster,pvCopy);
|
||||
request = "alarm,timeStamp,voltage.value,power.value,current.value";
|
||||
valueNameMaster = "power.value";
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
if(debug) { cout << "request " << request << endl; }
|
||||
if(debug) { cout << "pvRequest\n" << pvRequest->dumpValue(cout) << endl; }
|
||||
pvCopy = PVCopy::create(pvMaster,pvRequest,"");
|
||||
valueNameCopy = "power.value";
|
||||
testPVScalar(valueNameMaster,valueNameCopy,pvMaster,pvCopy);
|
||||
request = "alarm,timeStamp,voltage{value,alarm},power{value,alarm,display},current.value";
|
||||
valueNameMaster = "power.value";
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
if(debug) { cout << "request " << request << endl; }
|
||||
if(debug) { cout << "pvRequest\n" << pvRequest->dumpValue(cout) << endl; }
|
||||
pvCopy = PVCopy::create(pvMaster,pvRequest,"");
|
||||
valueNameCopy = "power.value";
|
||||
testPVScalar(valueNameMaster,valueNameCopy,pvMaster,pvCopy);
|
||||
}
|
||||
|
||||
MAIN(testPVCopy)
|
||||
{
|
||||
testPlan(67);
|
||||
scalarTest();
|
||||
arrayTest();
|
||||
powerSupplyTest();
|
||||
return testDone();
|
||||
}
|
||||
|
||||
@@ -307,8 +307,6 @@ void testScalar() {
|
||||
template<typename PVT>
|
||||
void testArrayType(const typename PVT::value_type* rdata, size_t len)
|
||||
{
|
||||
typedef typename PVT::value_type value_type;
|
||||
|
||||
typename PVT::svector empty(0), data(len);
|
||||
|
||||
std::copy(rdata, rdata+len, data.begin());
|
||||
|
||||
@@ -12,21 +12,11 @@ testIntrospect_SRCS += testIntrospect.cpp
|
||||
testIntrospect_LIBS += pvData Com
|
||||
TESTS += testIntrospect
|
||||
|
||||
PROD_HOST += testPVAppend
|
||||
testPVAppend_SRCS += testPVAppend.cpp
|
||||
testPVAppend_LIBS += pvData Com
|
||||
TESTS += testPVAppend
|
||||
|
||||
PROD_HOST += testPVType
|
||||
testPVType_SRCS += testPVType.cpp
|
||||
testPVType_LIBS += pvData Com
|
||||
TESTS += testPVType
|
||||
|
||||
PROD_HOST += testPVAuxInfo
|
||||
testPVAuxInfo_SRCS += testPVAuxInfo.cpp
|
||||
testPVAuxInfo_LIBS += pvData Com
|
||||
TESTS += testPVAuxInfo
|
||||
|
||||
PROD_HOST += testStandardField
|
||||
testStandardField_SRCS += testStandardField.cpp
|
||||
testStandardField_LIBS += pvData Com
|
||||
|
||||
@@ -1,224 +0,0 @@
|
||||
/* testPVAppend.cpp */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/* Author: Marty Kraimer Date: 2010.11 */
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
|
||||
#include <epicsUnitTest.h>
|
||||
#include <testMain.h>
|
||||
|
||||
#include <pv/requester.h>
|
||||
#include <pv/pvIntrospect.h>
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/convert.h>
|
||||
#include <pv/standardField.h>
|
||||
#include <pv/standardPVField.h>
|
||||
|
||||
using namespace epics::pvData;
|
||||
using std::tr1::static_pointer_cast;
|
||||
using std::size_t;
|
||||
|
||||
static bool debug = false;
|
||||
|
||||
static FieldCreatePtr fieldCreate;
|
||||
static PVDataCreatePtr pvDataCreate;
|
||||
static StandardFieldPtr standardField;
|
||||
static StandardPVFieldPtr standardPVField;
|
||||
static ConvertPtr convert;
|
||||
static String builder("");
|
||||
static String alarmTimeStamp("alarm,timeStamp");
|
||||
static String alarmTimeStampValueAlarm("alarm,timeStamp,valueAlarm");
|
||||
static String allProperties("alarm,timeStamp,display,control,valueAlarm");
|
||||
|
||||
static void checkNameAndParent(
|
||||
PVStructurePtr & pvStructure, int indentLevel)
|
||||
{
|
||||
builder.clear();
|
||||
if(debug) {
|
||||
convert->newLine(&builder,indentLevel);
|
||||
printf("%s this %p indentLevel %d",
|
||||
builder.c_str(),pvStructure.get(),indentLevel);
|
||||
}
|
||||
PVFieldPtrArray pvFields = pvStructure->getPVFields();
|
||||
StringArray fieldNames = pvStructure->getStructure()->getFieldNames();
|
||||
for(size_t i = 0; i<pvFields.size(); i++) {
|
||||
PVFieldPtr pvField = pvFields[i];
|
||||
testOk1(pvField->getParent()==pvStructure.get());
|
||||
testOk1(pvField->getFieldName().compare(fieldNames[i])==0);
|
||||
builder.clear();
|
||||
if(debug) {
|
||||
convert->newLine(&builder,indentLevel);
|
||||
printf("%s this %p name %s parent %p",
|
||||
builder.c_str(),
|
||||
pvField.get(),
|
||||
pvField->getFieldName().c_str(),
|
||||
pvField->getParent());
|
||||
}
|
||||
if(pvField->getField()->getType()==structure) {
|
||||
PVStructurePtr xxx = static_pointer_cast<PVStructure>(pvField);
|
||||
checkNameAndParent(xxx,indentLevel+1);
|
||||
}
|
||||
}
|
||||
builder.clear();
|
||||
}
|
||||
|
||||
static void testAppendSimple()
|
||||
{
|
||||
if(debug) printf("\ntestAppendSimple\n");
|
||||
PVFieldPtrArray fields;
|
||||
StringArray names;
|
||||
PVStructurePtr pvParent = pvDataCreate->createPVStructure(names,fields);
|
||||
PVStringPtr pvStringField = static_pointer_cast<PVString>(
|
||||
pvDataCreate->createPVScalar(pvString));
|
||||
pvStringField->put("value,timeStamp");
|
||||
PVFieldPtr pvField = pvStringField;
|
||||
pvParent->appendPVField("fieldlist",pvField);
|
||||
pvStringField = static_pointer_cast<PVString>(
|
||||
pvDataCreate->createPVScalar(pvString));
|
||||
pvStringField->put("junk");
|
||||
pvField = pvStringField;
|
||||
pvParent->appendPVField("extra",pvField);
|
||||
builder.clear();
|
||||
pvParent->toString(&builder);
|
||||
if(debug) printf("%s\n",builder.c_str());
|
||||
printf("testAppendSimple PASSED\n");
|
||||
}
|
||||
|
||||
static void testAppendMore()
|
||||
{
|
||||
if(debug) printf("\ntestAppendMore\n");
|
||||
PVFieldPtrArray fields;
|
||||
StringArray names;
|
||||
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(names,fields);
|
||||
PVStructurePtr pvChild1 = pvDataCreate->createPVStructure(names,fields);
|
||||
PVStringPtr pvStringField = static_pointer_cast<PVString>(
|
||||
pvDataCreate->createPVScalar(pvString));
|
||||
pvStringField->put("bla");
|
||||
PVFieldPtr pvField = pvStringField;
|
||||
pvChild1->appendPVField("value",pvField);
|
||||
pvField = pvChild1;
|
||||
pvStructure->appendPVField("child1",pvField);
|
||||
PVStructurePtr pvChild2 = pvDataCreate->createPVStructure(names,fields);
|
||||
pvStringField = static_pointer_cast<PVString>(
|
||||
pvDataCreate->createPVScalar(pvString));
|
||||
pvStringField->put("blabla");
|
||||
pvField = pvStringField;
|
||||
pvChild2->appendPVField("value",pvField);
|
||||
pvField = pvChild2;
|
||||
pvStructure->appendPVField("child2",pvField);
|
||||
builder.clear();
|
||||
pvStructure->toString(&builder);
|
||||
if(debug) printf("%s\n",builder.c_str());
|
||||
checkNameAndParent(pvStructure,0);
|
||||
printf("testAppendMore PASSED\n");
|
||||
}
|
||||
|
||||
static void testAppendStructures()
|
||||
{
|
||||
if(debug) printf("\ntestAppendStructures\n");
|
||||
PVFieldPtrArray fields;
|
||||
StringArray names;
|
||||
PVStructurePtr pvParent = pvDataCreate->createPVStructure(names,fields);
|
||||
PVFieldPtrArray topFields;
|
||||
StringArray topNames;
|
||||
PVStructurePtr pvTop = pvDataCreate->createPVStructure(topNames,topFields);
|
||||
pvParent->appendPVField("top",pvTop);
|
||||
PVFieldPtrArray valueFields;
|
||||
StringArray valueNames;
|
||||
PVStructurePtr pvValue = pvDataCreate->createPVStructure(valueNames,valueFields);
|
||||
pvTop->appendPVField("value",pvValue);
|
||||
PVFieldPtrArray indexFields;
|
||||
StringArray indexNames;
|
||||
PVStructurePtr pvIndex = pvDataCreate->createPVStructure(indexNames,indexFields);
|
||||
pvValue->appendPVField("index",pvIndex);
|
||||
builder.clear();
|
||||
pvParent->toString(&builder);
|
||||
if(debug) printf("%s\n",builder.c_str());
|
||||
builder.clear();
|
||||
pvParent->getField()->toString(&builder);
|
||||
if(debug) printf("field\n%s\n",builder.c_str());
|
||||
printf("testAppendStructures PASSED\n");
|
||||
}
|
||||
|
||||
static void append2(PVStructurePtr &pvStructure,
|
||||
const char *oneName,const char *twoName,
|
||||
const char *oneValue,const char *twoValue)
|
||||
{
|
||||
PVFieldPtrArray pvFields;
|
||||
pvFields.reserve(2);
|
||||
StringArray names;
|
||||
names.reserve(2);
|
||||
PVStringPtr pvStringField = static_pointer_cast<PVString>(
|
||||
pvDataCreate->createPVScalar(pvString));
|
||||
pvStringField->put(oneValue);
|
||||
names.push_back(oneName);
|
||||
pvFields.push_back(pvStringField);
|
||||
pvStringField = static_pointer_cast<PVString>(
|
||||
pvDataCreate->createPVScalar(pvString));
|
||||
pvStringField->put(twoValue);
|
||||
names.push_back(twoName);
|
||||
pvFields.push_back(pvStringField);
|
||||
pvStructure->appendPVFields(names,pvFields);
|
||||
}
|
||||
static void testAppends()
|
||||
{
|
||||
if(debug) printf("\ntestAppends\n");
|
||||
PVFieldPtrArray emptyPVFields;
|
||||
StringArray emptyNames;
|
||||
PVFieldPtrArray pvFields;
|
||||
pvFields.reserve(2);
|
||||
StringArray names;
|
||||
names.reserve(2);
|
||||
names.push_back("child1");
|
||||
PVStructurePtr pvChild = pvDataCreate->createPVStructure(
|
||||
emptyNames,emptyPVFields);
|
||||
append2(pvChild,"Joe","Mary","Good Guy","Good Girl");
|
||||
pvFields.push_back(pvChild);
|
||||
names.push_back("child2");
|
||||
pvChild = pvDataCreate->createPVStructure(
|
||||
emptyNames,emptyPVFields);
|
||||
append2(pvChild,"Bill","Jane","Bad Guy","Bad Girl");
|
||||
pvFields.push_back(pvChild);
|
||||
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(
|
||||
names,pvFields);
|
||||
builder.clear();
|
||||
pvStructure->toString(&builder);
|
||||
if(debug) printf("%s\n",builder.c_str());
|
||||
checkNameAndParent(pvStructure,0);
|
||||
PVFieldPtr pvField = pvStructure->getSubField("child2.Bill");
|
||||
testOk1(pvField.get()!=NULL);
|
||||
pvField->renameField("Joe");
|
||||
builder.clear();
|
||||
pvStructure->toString(&builder);
|
||||
if(debug) printf("%s\n",builder.c_str());
|
||||
pvField->getParent()->removePVField("Joe");
|
||||
builder.clear();
|
||||
pvStructure->toString(&builder);
|
||||
if(debug) printf("%s\n",builder.c_str());
|
||||
checkNameAndParent(pvStructure,0);
|
||||
printf("testAppends PASSED\n");
|
||||
}
|
||||
|
||||
MAIN(testPVAppend)
|
||||
{
|
||||
testPlan(31);
|
||||
fieldCreate = getFieldCreate();
|
||||
pvDataCreate = getPVDataCreate();
|
||||
standardField = getStandardField();
|
||||
standardPVField = getStandardPVField();
|
||||
convert = getConvert();
|
||||
testAppendStructures();
|
||||
testAppendSimple();
|
||||
testAppendMore();
|
||||
testAppends();
|
||||
return testDone();
|
||||
}
|
||||
|
||||
@@ -1,97 +0,0 @@
|
||||
/* testPVAuxInfo.cpp */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/* Author: Marty Kraimer Date: 2010.11 */
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
|
||||
#include <epicsUnitTest.h>
|
||||
#include <testMain.h>
|
||||
|
||||
#include <pv/requester.h>
|
||||
#include <pv/pvIntrospect.h>
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/convert.h>
|
||||
#include <pv/standardField.h>
|
||||
#include <pv/standardPVField.h>
|
||||
|
||||
using namespace epics::pvData;
|
||||
using std::tr1::static_pointer_cast;
|
||||
|
||||
static bool debug = false;
|
||||
|
||||
static FieldCreatePtr fieldCreate;
|
||||
static PVDataCreatePtr pvDataCreate;
|
||||
static StandardFieldPtr standardField;
|
||||
static StandardPVFieldPtr standardPVField;
|
||||
static ConvertPtr convert;
|
||||
static String buffer;
|
||||
|
||||
static void printOffsets(PVStructurePtr pvStructure)
|
||||
{
|
||||
printf("%s offset %lu next %lu number %lu\n",
|
||||
pvStructure->getFieldName().c_str(),
|
||||
(long unsigned)pvStructure->getFieldOffset(),
|
||||
(long unsigned)pvStructure->getNextFieldOffset(),
|
||||
(long unsigned)pvStructure->getNumberFields());
|
||||
PVFieldPtrArray fields = pvStructure->getPVFields();
|
||||
int number = (int)pvStructure->getStructure()->getNumberFields();
|
||||
for(int i=0; i<number; i++) {
|
||||
PVFieldPtr pvField = fields[i];
|
||||
if(pvField->getField()->getType()==structure) {
|
||||
PVStructurePtr xxx = static_pointer_cast<PVStructure>(pvField);
|
||||
printOffsets(xxx);
|
||||
continue;
|
||||
}
|
||||
printf("%s offset %lli next %lli number %lli\n",
|
||||
pvField->getFieldName().c_str(),
|
||||
(long long)pvField->getFieldOffset(),
|
||||
(long long)pvField->getNextFieldOffset(),
|
||||
(long long)pvField->getNumberFields());
|
||||
}
|
||||
}
|
||||
|
||||
static void testPVAuxInfo()
|
||||
{
|
||||
if(debug) printf("\ntestPVAuxInfo\n");
|
||||
PVStructurePtr pvStructure = standardPVField->scalar(
|
||||
pvDouble,"alarm,timeStamp,display,control");
|
||||
PVStructurePtr display
|
||||
= pvStructure->getStructureField("display");
|
||||
testOk1(display.get()!=NULL);
|
||||
PVAuxInfoPtr auxInfo = display->getPVAuxInfo();
|
||||
auxInfo->createInfo("factory",pvString);
|
||||
auxInfo->createInfo("junk",pvDouble);
|
||||
PVScalarPtr pscalar = auxInfo->getInfo(String("factory"));
|
||||
testOk1(pscalar.get()!=0);
|
||||
convert->fromString(pscalar,"factoryName");
|
||||
pscalar = auxInfo->getInfo("junk");
|
||||
testOk1(pscalar.get()!=0);
|
||||
convert->fromString(pscalar,"3.0");
|
||||
buffer.clear();
|
||||
pvStructure->toString(&buffer);
|
||||
if(debug) printf("%s\n",buffer.c_str());
|
||||
// now show field offsets
|
||||
if(debug) printOffsets(pvStructure);
|
||||
printf("testPVAuxInfo PASSED\n");
|
||||
}
|
||||
|
||||
MAIN(testPVAuxInfo)
|
||||
{
|
||||
testPlan(3);
|
||||
fieldCreate = getFieldCreate();
|
||||
pvDataCreate = getPVDataCreate();
|
||||
standardField = getStandardField();
|
||||
standardPVField = getStandardPVField();
|
||||
convert = getConvert();
|
||||
testPVAuxInfo();
|
||||
return testDone();
|
||||
}
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
|
||||
using namespace epics::pvData;
|
||||
using std::tr1::static_pointer_cast;
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
static bool debug = false;
|
||||
|
||||
@@ -37,24 +39,6 @@ static String alarmTimeStamp("alarm,timeStamp");
|
||||
static String alarmTimeStampValueAlarm("alarm,timeStamp,valueAlarm");
|
||||
static String allProperties("alarm,timeStamp,display,control,valueAlarm");
|
||||
|
||||
static void testAppend()
|
||||
{
|
||||
if(debug) printf("\ntestAppend\n");
|
||||
PVFieldPtrArray pvFields;
|
||||
StringArray fieldNames;
|
||||
PVStructurePtr pvParent = pvDataCreate->createPVStructure(
|
||||
fieldNames,pvFields);
|
||||
PVStringPtr pvStringField = static_pointer_cast<PVString>(
|
||||
pvDataCreate->createPVScalar(pvString));
|
||||
pvStringField->put(String("value,timeStamp"));
|
||||
PVFieldPtr pvField = pvStringField;
|
||||
pvParent->appendPVField("request",pvField);
|
||||
builder.clear();
|
||||
pvParent->toString(&builder);
|
||||
if(debug) printf("%s\n",builder.c_str());
|
||||
printf("testAppend PASSED\n");
|
||||
}
|
||||
|
||||
static void testCreatePVStructure()
|
||||
{
|
||||
if(debug) printf("\ntestCreatePVStructure\n");
|
||||
@@ -360,7 +344,7 @@ static void testScalarArrayCommon(String /*fieldName*/,ScalarType stype)
|
||||
pvStructure->toString(&builder);
|
||||
if(debug) printf("%s\n",builder.c_str());
|
||||
PVFieldPtr pvField = pvStructure->getSubField("alarm.status");
|
||||
pvField->message("this is a test",infoMessage);
|
||||
testOk1(pvField!=NULL);
|
||||
}
|
||||
|
||||
static void testScalarArray()
|
||||
@@ -377,18 +361,81 @@ static void testScalarArray()
|
||||
printf("testScalarArray PASSED\n");
|
||||
}
|
||||
|
||||
static void testRequest()
|
||||
{
|
||||
if(debug) printf("\ntestScalarArray\n");
|
||||
StringArray nullNames;
|
||||
FieldConstPtrArray nullFields;
|
||||
StringArray optionNames(1);
|
||||
FieldConstPtrArray optionFields(1);
|
||||
optionNames[0] = "process";
|
||||
optionFields[0] = fieldCreate->createScalar(pvString);
|
||||
StringArray recordNames(1);
|
||||
FieldConstPtrArray recordFields(1);
|
||||
recordNames[0] = "_options";
|
||||
recordFields[0] = fieldCreate->createStructure(optionNames,optionFields);
|
||||
StringArray fieldNames(2);
|
||||
FieldConstPtrArray fieldFields(2);
|
||||
fieldNames[0] = "alarm";
|
||||
fieldFields[0] = fieldCreate->createStructure(nullNames,nullFields);
|
||||
fieldNames[1] = "timeStamp";
|
||||
fieldFields[1] = fieldCreate->createStructure(nullNames,nullFields);
|
||||
StringArray topNames(2);
|
||||
FieldConstPtrArray topFields(2);
|
||||
topNames[0] = "record";
|
||||
topFields[0] = fieldCreate->createStructure(recordNames,recordFields);
|
||||
topNames[1] = "field";
|
||||
topFields[1] = fieldCreate->createStructure(fieldNames,fieldFields);
|
||||
StructureConstPtr topStructure = fieldCreate->createStructure(
|
||||
topNames,topFields);
|
||||
String buffer;
|
||||
topStructure->toString(&buffer);
|
||||
cout << buffer.c_str() << endl;
|
||||
PVStructurePtr pvTop = pvDataCreate->createPVStructure(topStructure);
|
||||
buffer.clear();
|
||||
pvTop->toString(&buffer);
|
||||
cout << buffer.c_str() << endl;
|
||||
buffer.clear();
|
||||
pvTop->getStructure()->toString(&buffer);
|
||||
cout << buffer.c_str() << endl;
|
||||
PVStructurePtr xxx = pvTop->getSubField<PVStructure>("record");
|
||||
buffer.clear();
|
||||
xxx->toString(&buffer);
|
||||
cout << buffer.c_str() << endl;
|
||||
xxx = pvTop->getSubField<PVStructure>("field");
|
||||
buffer.clear();
|
||||
xxx->toString(&buffer);
|
||||
cout << buffer.c_str() << endl;
|
||||
PVStringPtr pvString = pvTop->getSubField<PVString>("record._options.process");
|
||||
pvString->put("true");
|
||||
buffer.clear();
|
||||
pvTop->toString(&buffer);
|
||||
cout << buffer.c_str() << endl;
|
||||
cout << pvTop->dumpValue(cout) << endl;
|
||||
|
||||
String subName("record._options.process");
|
||||
PVFieldPtr pvField = pvTop->getSubField(subName);
|
||||
String fieldName = pvField->getFieldName();
|
||||
String fullName = pvField->getFullName();
|
||||
cout << "fieldName " << fieldName << " fullName " << fullName << endl;
|
||||
|
||||
testOk1(fieldName.compare("process")==0);
|
||||
testOk1(fullName.compare(subName)==0);
|
||||
|
||||
}
|
||||
|
||||
MAIN(testPVData)
|
||||
{
|
||||
testPlan(179);
|
||||
testPlan(189);
|
||||
fieldCreate = getFieldCreate();
|
||||
pvDataCreate = getPVDataCreate();
|
||||
standardField = getStandardField();
|
||||
standardPVField = getStandardPVField();
|
||||
convert = getConvert();
|
||||
testAppend();
|
||||
testCreatePVStructure();
|
||||
testPVScalar();
|
||||
testScalarArray();
|
||||
testRequest();
|
||||
return testDone();
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
|
||||
using namespace epics::pvData;
|
||||
using std::tr1::static_pointer_cast;
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
@@ -66,6 +66,17 @@ MAIN(testStandardField)
|
||||
builder.clear();
|
||||
structureArrayValue->toString(&builder);
|
||||
print("structureArrayValue");
|
||||
|
||||
StructureConstPtr punion = standardField->regUnion(
|
||||
fieldCreate->createFieldBuilder()->
|
||||
add("doubleValue", pvDouble)->
|
||||
add("intValue", pvInt)->
|
||||
add("timeStamp",standardField->timeStamp())->
|
||||
createUnion(),
|
||||
"alarm,timeStamp");
|
||||
builder.clear();
|
||||
punion->toString(&builder);
|
||||
print("unionValue");
|
||||
testPass("testStandardField");
|
||||
return testDone();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user