66 Commits
3.1.0 ... 4.0.3

Author SHA1 Message Date
dhickin
354fdd412f make "local" *.local files take precedence over those in TOP/.. 2014-12-03 16:55:27 +00:00
dhickin
f3f6141e6a include CONFIG_SITE.local instead of CONFIG.local at top-level. 2014-12-03 16:10:25 +00:00
Marty Kraimer
b9592eeb8c Added tag 4.0.2 for changeset af82285f71aa 2014-11-24 06:55:18 -05:00
Marty Kraimer
6a62f9c082 catch std::exception and return NULL PVStructurePtr 2014-11-24 06:54:28 -05:00
Marty Kraimer
c5112ffa11 Added tag 4.0.1 for changeset b0d39d12d743 2014-11-11 07:05:19 -05:00
Matej Sekoranja
7b9fda4e81 merge 2014-11-10 21:33:47 +01:00
Matej Sekoranja
278e531806 PVUnion copy allways shallow 2014-11-10 21:30:48 +01:00
Marty Kraimer
047de40642 change date, this version, and previous version 2014-11-10 09:06:35 -05:00
Matej Sekoranja
4e671a1c21 win32 indent problem: local static DLL saga 2014-11-06 22:18:58 +01:00
Matej Sekoranja
f36c8ce280 testByteOrder: use MAIN instead of main 2014-11-06 14:28:49 +01:00
Matej Sekoranja
e77f2c91d7 fixed undeterministic serialization test on clang 2014-11-06 13:03:59 +01:00
Matej Sekoranja
82b0d5ce5f merge 2014-11-06 12:50:04 +01:00
Matej Sekoranja
6117035863 null element handling for structure/union array 2014-11-06 12:48:57 +01:00
Matej Sekoranja
c86e31ad99 vxWorks: type cast fixes 2014-11-06 12:38:01 +01:00
Matej Sekoranja
f506fe1c0e int/int32 compilation fix; now all test spass on RTEMS-i386 2014-11-05 14:05:28 +01:00
Matej Sekoranja
554dc06eda ScalarTypeID mapping fixed in case 'int' == 'long', e.g. RTEMS-i386 2014-11-05 13:52:10 +01:00
Matej Sekoranja
80e1dfd142 removed forces NE2K card or non i386 builds 2014-11-03 13:51:21 +01:00
Matej Sekoranja
6db5cf60dc removing file should not have been commited 2014-11-03 12:41:09 +01:00
Matej Sekoranja
63d181a0ac RTEMS QEMU tests 2014-11-03 12:37:12 +01:00
Matej Sekoranja
73c4896cce tests: VxWorks tests are now ready to be run 2014-10-31 17:49:10 -04:00
Matej Sekoranja
5b1b5ab904 tests: refactored test building so that one test object can be created for VxWorks and RTEMS 2014-10-31 18:29:55 +01:00
Matej Sekoranja
80a537bc4c vxWork tests for all subtests; still need to combine them all to one 2014-10-31 07:57:20 -04:00
Matej Sekoranja
2a8a1d3736 tests: PROD_HOST to TESTPROD_HOST; VxWorks tests for testApp/pv PASSES 2014-10-31 06:42:52 -04:00
Matej Sekoranja
61fbfa0684 Added tag 4.0.0 for changeset f9f187685032 2014-10-29 12:59:39 +01:00
Matej Sekoranja
f06a6bfe7b merge to default branch 2014-10-28 19:37:34 +01:00
Matej Sekoranja
587f81f511 win32 in vs2013 compilation fix 2014-10-28 19:36:57 +01:00
Matej Sekoranja
435ca63d1b ev4 to epics URI 2014-10-28 18:53:11 +01:00
Marty Kraimer
64bb660f44 Added tag 4.0.0 for changeset 9c62aaa83b9d 2014-10-15 14:47:48 -04:00
Marty Kraimer
8bf24de0b3 removed pvArray.html and pvDataDiscussion.html; good ideas now implemented 2014-10-08 15:03:52 -04:00
Marty Kraimer
943ea633a4 more work on pvDataCPP.html; minor changes to examples 2014-10-08 14:48:30 -04:00
dhickin
b1d5f7d7e5 Corrected NTUnio to NTUnion 2014-10-07 15:32:26 +01:00
dhickin
188b94ce19 Corrected spelling of synchrotron in licence. 2014-10-04 02:45:53 +01:00
dhickin
515282abfe Spelling and typos. 2014-10-04 01:33:59 +01:00
dhickin
efbdb722e7 Made sub-field/subfield consistent by changing to subfield. 2014-10-04 01:28:19 +01:00
dhickin
e980823294 Corrected NTUnio->NTUnion. 2014-10-04 00:22:46 +01:00
dhickin
3692f4fb3c Correctly produce <> for templates in code samples for PVUnionArray in pvDataCPP.html. 2014-10-03 15:58:55 +01:00
dhickin
3e645f3c79 Corrected spelling in pvDataCPP.html. 2014-10-03 15:24:20 +01:00
Marty Kraimer
6127763302 Added tag 4.0.0 for changeset 1348c22b1258 2014-09-30 16:59:37 -04:00
Marty Kraimer
19a181b38f change ev4:nt: to 3v4:nt/ 2014-09-30 15:26:23 -04:00
Marty Kraimer
2818b0384c flow: Created branch 'release/4.0'. 2014-09-30 15:06:43 -04:00
Marty Kraimer
36faf8c2ea change URI naming 2014-09-30 15:05:18 -04:00
Marty Kraimer
a208171250 change uri:ev4:nt/2012 to uri:ev4:nt/2014 2014-09-23 14:34:21 -04:00
Marty Kraimer
b8a2b7cff6 get documantation ready for pre release 2014-09-03 09:01:15 -04:00
Marty Kraimer
2a08cbc1a0 add static 2014-08-25 08:09:28 -04:00
Matej Sekoranja
62bc6c1fb1 PVControl::minStep implemented 2014-08-22 22:22:38 +02:00
Matej Sekoranja
1098650421 clang fix 2014-08-20 21:42:29 +02:00
Marty Kraimer
15d85c2f87 fix misspelled field names: nanoSecond => nanosecond; hystersis=>hysteresis 2014-08-20 06:27:24 -04:00
Matej Sekoranja
16fb3f0339 clang fixes 2014-08-19 20:58:12 +02:00
Matej Sekoranja
37f6dff065 bounded string 2014-08-19 20:42:15 +02:00
Marty Kraimer
baf8832fc9 allow record[] field() getField() putField() 2014-08-19 09:15:06 -04:00
Marty Kraimer
b558e11ede major changes to CreateRequest; now compatible with Java version 2014-08-19 08:25:38 -04:00
Matej Sekoranja
103cdabff1 fixed clang std::tr1 import by adding include 2014-08-13 21:53:15 +02:00
Matej Sekoranja
57e33c8f7d clang porting 2014-08-13 09:36:37 +02:00
Matej Sekoranja
da0f65c2d3 fixed size array serialization test 2014-08-12 13:20:00 +02:00
Matej Sekoranja
6535c075f3 fixed sized arrays 2014-08-12 13:17:17 +02:00
Matej Sekoranja
f3c0b9544c dumpValue for boolean fix 2014-08-11 22:09:46 +02:00
Matej Sekoranja
3609fd4745 fixed testCreateRequest, still fails 2014-07-30 21:49:52 +02:00
Matej Sekoranja
622e140622 Fixed/bounded scalar array impl. 2014-07-30 21:41:08 +02:00
Marty Kraimer
a4954c3825 fixed bug in createRequest.cpp 2014-07-30 06:50:22 -04:00
Matej Sekoranja
b6e1b9c203 reuse existing PVField instance on PVUnion::deserialize 2014-07-28 23:23:01 +02:00
Matej Sekoranja
34a35c2658 fixed/bounded array introspection data serialization 2014-07-28 23:05:49 +02:00
Marty Kraimer
90b7c9a17c change in TODO.md; add RELEASE_NOTES.html and TODO.html 2014-07-22 08:49:02 -04:00
Marty Kraimer
c72297020b update documentation 2014-07-10 13:17:26 -04:00
Matej Sekoranja
f07b601dce merge 2014-07-07 20:55:49 +02:00
Matej Sekoranja
63c62a2aae Union::dump indentification fixed 2014-07-07 20:54:38 +02:00
Matej Sekoranja
6888a9d340 Added tag 3.1.0 for changeset 260f35b9c6ca 2014-07-02 00:09:01 +02:00
74 changed files with 19687 additions and 4404 deletions

View File

@@ -10,3 +10,11 @@ d70c5ad29163306f50979a95b5aebbe9a93cfe76 2.0-BETA
2a289ff41e2ed3a0247877306c2db7b266f3b6b8 3.0.1
58092712d092ee521d1e1c8fa596a67f7d113ee9 3.0.2
40b681ffc5cd609320e3f8ffc8eb6aa3bfdfbf19 before_merge_changesAfter3_0_2
260f35b9c6cad113f242c83c89be9cdac802f610 3.1.0
1348c22b125861ecb9da95b23f20314b167ee155 4.0.0
1348c22b125861ecb9da95b23f20314b167ee155 4.0.0
9c62aaa83b9db6ad69740a6bb46d6529e0e60b78 4.0.0
9c62aaa83b9db6ad69740a6bb46d6529e0e60b78 4.0.0
f9f187685032ebf4b108c759be196fda055c9e42 4.0.0
b0d39d12d743b82038066955db6bb957b1f2f767 4.0.1
af82285f71aae5d08fa8cf333b03772c5e689aff 4.0.2

View File

@@ -2,7 +2,7 @@
Copyright (c) 2008 Martin R. Kraimer
Copyright (c) 2006 The University of Chicago, as Operator of Argonne
National Laboratory.
Copyright (c) 2006 Deutsches Elektronen-Synchroton,
Copyright (c) 2006 Deutsches Elektronen-Synchrotron,
Member of the Helmholtz Association, (DESY), HAMBURG, GERMANY.
Copyright (c) 2007 Control System Laboratory,
(COSYLAB) Ljubljana Slovenia

View File

@@ -20,8 +20,8 @@ CHECK_RELEASE = YES
# INSTALL_LOCATION here.
#INSTALL_LOCATION=</path/name/to/install/top>
-include $(TOP)/../CONFIG_SITE.local
-include $(TOP)/configure/CONFIG_SITE.local
-include $(TOP)/../CONFIG.local
ifdef WITH_COVERAGE
USR_CPPFLAGS += --coverage

View File

@@ -580,7 +580,7 @@ WARN_LOGFILE =
# directories like "/usr/src/myproject". Separate the files or directories
# with spaces.
INPUT = ../pvDataApp
INPUT = ../include/pv
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is

View File

@@ -0,0 +1,58 @@
<h1>Release 4.0 IN DEVELOPMENT</h1>
<p>The main changes since release 3.0.2 are:</p>
<ul>
<li>array semantics now enforce Copy On Write.</li>
<li>String no longer defined.</li>
<li>timeStamp and valueAlarm name changes</li>
<li>toString replaced by stream I/O </li>
<li>union is new type.</li>
<li>copy is new.</li>
<li>monitorPlugin is new.</li>
</ul>
<h2>New Semantics for Arrays</h2>
<p>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.</p>
<h2>String no longer defined</h2>
<p>This is replaced by std::string.</p>
<h2>timeStamp and valueAlarm name changes</h2>
<p>In timeStamp nanoSeconds is changed to nanoseconds.</p>
<p>In valueAlarm hystersis is changed to hysteresis</p>
<h2>toString replaced by stream I/O</h2>
<p>pvData.h and pvIntrospect no longer defines toString
Instead they have stream support.
pvIntrospect uses method dump and pvData uses dumpValue.
For example:</p>
<pre><code> PVDoublePtr pvValue;
String buffer;
pvValue-&gt;toString(&amp;buffer);
cout &lt;&lt; buffer &lt;&lt; endl;
buffer.clear();
pvValue-&gt;getField()-&gt;toString(&amp;buffer);
cout &lt;&lt; buffer &lt;&lt; evdl;
</code></pre>
<p>is replaced by</p>
<pre><code> PVDoublePtr pvValue;
cout &lt;&lt; *pvValue &lt;&lt; endl
cout &lt;&lt; *pvValue-&gt;getField() &lt;&lt; endl;
</code></pre>
<h2>union is a new basic type.</h2>
<p>There are two new basic types: union_t and unionArray.</p>
<p>A union is like a structure that has a single subfield.
There are two flavors:</p>
<ul>
<li><b>varient union</b> The field can have any type.</li>
<li><b>union</b> The field can any of specified set of types.</li>
</ul>
<p>The field type can be dynamically changed.</p>
<h2>copy</h2>
<p>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.</p>
<h2>monitorPlugin</h2>
<p>This is for is for use by code that implements pvAccess monitors.
This is prototype and is subject to debate.</p>
<h1>Release 3.0.2</h1>
<p>This was the starting point for RELEASE_NOTES</p>

View File

@@ -1,9 +1,12 @@
Release release/3.1 IN DEVELOPMENT
Release 4.0 IN DEVELOPMENT
===========
The main changes since release 3.0.2 are:
* array semantics now enforce Copy On Write.
* String no longer defined.
* timeStamp and valueAlarm name changes
* toString replaced by stream I/O
* union is new type.
* copy is new.
* monitorPlugin is new.
@@ -16,6 +19,44 @@ In order to limit memory usage the storage for raw data is managed via a new sha
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.
String no longer defined
---------
This is replaced by std::string.
timeStamp and valueAlarm name changes
--------------
In timeStamp nanoSeconds is changed to nanoseconds.
In valueAlarm hystersis is changed to hysteresis
toString replaced by stream I/O
---------
pvData.h and pvIntrospect no longer defines toString
Instead they have stream support.
pvIntrospect uses method dump and pvData uses dumpValue.
For example:
PVDoublePtr pvValue;
String buffer;
pvValue->toString(&buffer);
cout << buffer << endl;
buffer.clear();
pvValue->getField()->toString(&buffer);
cout << buffer << evdl;
is replaced by
PVDoublePtr pvValue;
cout << *pvValue << endl
cout << *pvValue->getField() << endl;
union is a new basic type.
------------
@@ -41,6 +82,7 @@ monitorPlugin
-------------
This is for is for use by code that implements pvAccess monitors.
This is prototype and is subject to debate.
Release 3.0.2
==========

17
documentation/TODO.html Normal file
View File

@@ -0,0 +1,17 @@
<h1>TODO</h1>
<h2>printer</h2>
<p>pv/printer.h is not used.</p>
<h2>doxygen</h2>
<p>There is a lot of public code that does not have doxygen tags.</p>
<h2>postMonitor: PVUnion, PVUnionArray, and PVStructureArray</h2>
<p>PVUnion, PVUnionArray, and PVStructureArray all have elements
that are treated like a top level field.</p>
<p>Currently if a subField of any of these is changed postMonitor is not called for the field itself.</p>
<p>David asked if this could be changed so that it is called.
Marty thinks this may not be a good idea.</p>
<h2>valueAlarm</h2>
<p>normativeTypes.html describes valueAlarm only for a value field that has type
double.
The implementation also supports all the numeric scalar types.</p>
<h2>monitorPlugin</h2>
<p>A debate is on-going about what semantics should be.</p>

View File

@@ -1,33 +1,10 @@
TODO
===========
toString, dumpValue, printer, and streams
printer
------------
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.
pv/printer.h is not used.
doxygen
-------
@@ -35,20 +12,27 @@ doxygen
There is a lot of public code that does not have doxygen tags.
postMonitor: PVUnion, PVUnionArray, and PVStructureArray
--------
PVUnion, PVUnionArray, and PVStructureArray all have elements
that are treated like a top level field.
Currently if a subField of any of these is changed postMonitor is not called for the field itself.
David asked if this could be changed so that it is called.
Marty thinks this may not be a good idea.
valueAlarm
---------
normativeTypes.html describes valueAlarm only for a value field that has type
double.
The implementation also supports all the numeric scalar types.
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

View File

@@ -52,7 +52,7 @@ 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
had knowledge 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>
@@ -65,13 +65,13 @@ At present only the C++ version of the new API for pvCopy is implemented.
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
The information in a pvRequest selects an arbitrary 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.
<dd>This is a facility 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
@@ -185,7 +185,7 @@ where
This is the method for creating a PVCopy instance.<br/>
<dl>
<dt>pvMaster</dt>
<dd>the top level sructure managed by the server.</dd>
<dd>the top level structure managed by the server.</dd>
<dt>pvRequest</dt>
<dd>selects the set of subfields desired
and options for each field.</dd>
@@ -241,12 +241,12 @@ where
<dt>updateCopyFromBitSet</dt>
<dd>
For each set bit in bitSet set the field in copyPVStructure to the value
of the corrseponding field in pvMaster.
of the corresponding 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.
of the corresponding field in copyPVStructure.
</dd>
<dt>getOptions</dt>
@@ -266,7 +266,7 @@ where
<p>This consists of two components:
<dl>
<dt>monitor</dt>
<dd>Used by code that implements pvAccess montors.</dd>
<dd>Used by code that implements pvAccess monitors.</dd>
<dt>monitorPlugin</dt>
<dd>Code that provides special semantics for monitors.</dd>
</dl>
@@ -346,7 +346,7 @@ Note that each client has it's own queue that is not shared with other client.
<dt>start</dt>
<dd>
Start monitoring.
This will result in a an inital monitor that has the current value
This will result in a an initial monitor that has the current value
of all fields.
</dd>
<dt>stop</dt>
@@ -356,11 +356,11 @@ Note that each client has it's own queue that is not shared with other client.
<dt>poll</dt>
<dd>
Called to get a monitor element.
If no new elemants are available then a null pointer is returned.
If no new elements are available then a null pointer is returned.
</dd>
<dt>release</dt>
<dd>
Release the monotor element.
Release the monitor element.
The caller owns the monitor element between the calls to poll and release.
</dd>
<dl>
@@ -488,7 +488,7 @@ It has methods:</p>
<dd>
MonitorPluginManager is a singleton.
The first call to get will create the single instance.
Further calls will rerurn the single instance.
Further calls will return the single instance.
</dd>
<dt>addPlugin</dt>
<dd>
@@ -496,18 +496,18 @@ It has methods:</p>
</dd>
<dt>findPlugin</dt>
<dd>
Find a plugin. A NULL shared pointer is reurned if it has not been added.
Find a plugin. A NULL shared pointer is returned if it has not been added.
</dd>
<dt>showNames</dt>
<dd>
Show the names of all puugins that have been added.
Show the names of all plugins 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:
be defined so that they can not be modified.
This would be possible if the following was defined:
<pre>
typedef std::tr1::shared_ptr&lt;const PVField&gt; PVFieldConstPtr;
typedef std::tr1::shared_ptr&lt;const PVStructure&gt; PVStructureConstPtr;
@@ -519,7 +519,7 @@ virtual bool causeMonitor(
PVStructureConstPtr const &amp;pvTop,
MonitorElementPtr const &amp;monitorElement) = 0;
</pre>
But just adding these definitions is not sufficent.
But just adding these definitions is not sufficient.
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.
@@ -545,15 +545,15 @@ structure powerSupply
structure power
double value
structure alarm
struvture display
structure display
structure voltage
double value
structure alarm
struvture display
structure display
structure current
double value
structure alarm
struvture display
structure 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:
@@ -578,7 +578,7 @@ client wants. It can be attached to any field via the following options:
[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
value. In addition <b>value</b> equals <b>false</b> means do not raise a monitor
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.

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -28,11 +28,11 @@ StructureConstPtr enum_t =
// create a structure (cntd.)
StructureConstPtr ntEnum =
getFieldCreate()->createFieldBuilder()->
setId("uri:ev4:nt/2012/pwd/NTEnum")->
setId("epics:nt/NTEnum:1.0")->
add("value", enum_t)->
addNestedStructure("timeStamp")->
setId("time_t")->
add("secsPastEpoch", pvLong)->
add("secondsPastEpoch", pvLong)->
add("nanoseconds", pvInt)->
add("userTag", pvInt)->
endNested()->

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,792 +0,0 @@
<?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 pvDataDiscussion</title>
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/base.css" />
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/epicsv4.css" />
<style type="text/css">
/*<![CDATA[*/
.about { margin-left: 3em; margin-right: 3em; font-size: .83em}
table { margin-left: auto; margin-right: auto }
.diagram { text-align: center; margin: 2.5em 0 }
span.opt { color: grey }
span.nterm { font-style:italic }
span.term { font-family:courier }
span.user { font-family:courier }
span.user:before { content:"<" }
span.user:after { content:">" }
.nonnorm { font-style:italic }
p.ed { color: #AA0000 }
span.ed { color: #AA0000 }
p.ed.priv { display: inline; }
span.ed.priv { display: inline; }
/*]]>*/</style>
<!-- Script that generates the Table of Contents -->
<script type="text/javascript"
src="http://epics-pvdata.sourceforge.net/script/tocgen.js">
</script>
</head>
<body>
<div class="head">
<h1>EPICS pvDataDiscussion</h1>
<!-- Maturity: Working Draft or Request for Comments, or Recommendation, and date. -->
<h2 class="nocount">EPICS v4 Working Group, Working Draft, 03-Jul-2013</h2>
<dl>
<dt>Latest version:</dt>
<dd><a
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvDataCPP/raw-file/tip/documentation/pvDataDiscussion.html">pvDataDiscussion.html</a>
</dd>
<dt>This version:</dt>
<dd>none</dd>
<dt>Previous version:</dt>
<dd>None</dd>
<dt>Editors:</dt>
<dd>Marty Kraimer, BNL<dd />
</dl>
<p class="copyright">This product is made available subject to acceptance of the <a
href="http://epics-pvdata.sourceforge.net/LICENSE.html">EPICS open source
license.</a></p>
<hr />
</div>
<div id="toc">
<h2 class="nocount" style="page-break-before: always">Table of Contents</h2>
</div>
<div id="contents" class="contents">
<h2>Introduction</h2>
<p>As pvDataCPP progressed PVField and derived classes accumulated
more and more member functions.
These member functions have nothing to do with the primary primary
purpose for pvData:
<blockquote>pvData (Process Variable Data) defines and implements an efficent
way to store, access, and communicate memory resident data structures.</blockquote>
This statement appears as the first sentence of pvDataJava.html.
A few sentances later the document makes it clear that communication
includes efficent network communication.
Thus pvData provides an interface for network accessible structured data.
The problem of adding member functions that have nothing to do with the primary purpose
started with the Java API.
It already had extra methods that solved problems that should have had a different solution.
This document removes the extra methods so that when new problems arise in the future
the solution will not involve adding new member functions to the introspection and data API.
</p>
<p>The introspection and data API for pvData should only encapuslate methods that support the primary purpose
stated above.
The interfaces for C++ and Java should be similar so that
someone who understands the interface in one of the languages
and knows both languages will quickly understand the interface of the other language.</p>
<p>There is another problem with the existing API. There are methods that allow the "structure"
to change after an pvData object is created. An example is PVField::renameField(std::string newName).
Such methods should not exist.</p>
<p>There are methods regarding immutability: setImmutable, isImmutablei, setCapacityMutable, and isCapacityMutable.
Should they exists? For now lets assume no.
</p>
<p>One last issue is the interface for array data. This document proposes a simplified
version of what currently exists. It requires that the implementation always provides storage for
the complete raw array. The existing APIs allow the implementation to provide the data in
"chunks". Giving up this requirement simplifies the array interfaces.
The existing C++ implementation of PVValueArray has serious problems.
The shared_vector that is implemented in pvDataCP-md provides the solution to fixing
the problems. This document describes an API that is very similar to the new Java API
except that raw arrays are replaced by shared_vector.</p>
<p>This document will first describe changes to the existing Java interfaces
and then the corresponding C++ API.</p>
<h2>Java API</h2>
<p>The following shows which methods will be removed from the existing interfaces
and what will be added.
The methods to be removed are in <font color = "red">red</font>
and methods to add are in <font color = "blue">blue</font>
Also the removed methods are at the end with a comment above.
The new methods also have a comment.
</p>
<h3>Introspection Interfaces</h3>
<pre>interface Field extends Serializable {
std::string getId();
Type getType();
// following will be removed
<font color = "red">void toString(StringBuilder buf);</font>
<font color = "red">void toString(StringBuilder buf,int indentLevel);</font>
<font color = "red">std::string toString();</font>
}
<font color = "blue">
// new interface
interface FieldTostd::string {
std::string toString(Field field);
}</font>
interface Scalar extends Field {
ScalarType getScalarType();
}
interface ScalarArray extends Field {
ScalarType getElementType();
}
interface Structure extends Field {
Field getField(std::string fieldName);
int getFieldIndex(std::string fieldName);
Field[] getFields();
Field getField(int fieldIndex);
std::string[] getFieldNames();
std::string getFieldName(int fieldIndex)
}
interface StructureArray extends Field {
Structure getStructure();
}
interface FieldCreate {
Scalar createScalar(ScalarType scalarType);
ScalarArray createScalarArray(ScalarType elementType);
StructureArray createStructureArray(Structure elementStructure);
Structure createStructure(std::string[] fieldNames, Field[] field);
Structure createStructure(std::string id,std::string[] fieldNames, Field[] field);
Structure createStructure(Structure structToClone);
Field deserialize(ByteBuffer buffer, DeserializableControl control);
// following will be removed
<font color = "red">Structure appendField(Structure structure,std::string fieldName, Field field);</font>
<font color = "red">Structure appendFields(Structure structure,std::string[] fieldNames, Field[] fields);</font>
}
</pre>
<h3>Data Interfaces</h3>
<pre>
interface PVField extends Requester, Serializable {
std::string getFieldName();
void setRequester(Requester requester);
int getFieldOffset();
int getNextFieldOffset();
int getNumberFields();
Field getField();
PVStructure getParent();
void postPut();
void setPostHandler(PostHandler postHandler);
// following will be removed
<font color = "red">PVAuxInfo getPVAuxInfo();</font>
<font color = "red">boolean isImmutable();</font>
<font color = "red">void setImmutable();</font>
<font color = "red">void renameField(std::string newName);</font>
<font color = "red">void toString(StringBuilder buf);</font>
<font color = "red">void toString(StringBuilder buf,int indentLevel);</font>
<font color = "red">std::string toString();</font>
}
<font color = "blue">
// The following is a new interface
interface PVFieldTostd::string {
std::string toString(PVField pvField);
void setMaxInitialArrayElements(int num);
void setMaxFinalArrayElements(int num);
int getMaxInitialArrayElements();
int getMaxFinalArrayElements();
}</font>
interface PVScalar extends PVField{
Scalar getScalar();
}
interface PVDouble extends PVScalar{
double get();
void put(double value);
}
// also PVBoolean, PVByte, PVShort, PVInt, PVLong, PVFloat, and PVString
interface PVArray extends PVField, SerializableArray {
int getLength();
void setLength(int length);
int getCapacity();
void setCapacity(int length);
// following will be removed
<font color = "red">boolean isCapacityMutable();</font>
<font color = "red">void setCapacityMutable(boolean isMutable);</font>
}
interface PVScalarArray extends PVArray {
ScalarArray getScalarArray();
}
<font color = "red">
//following will be removed
public class DoubleArrayData {
public double[] data;
public int offset;
}</font>
interface PVDoubleArray extends PVArray {
// following are new
<font color = "blue"> double[] get();</font>
<font color = "blue"> void swap(double[] value);</font>
//following will be removed
<font color = "red"> int get(int offset, int len, DoubleArrayData data);</font>
<font color = "red"> int put(int offset,int len, double[] from, int fromOffset)</font>;
<font color = "red"> void shareData(double[] from);</font>
}
// also PVBooleanArray, ..., PVStringArray
interface PVStructure extends PVField , BitSetSerializable{
Structure getStructure();
PVField[] getPVFields();
PVField getSubField(std::string fieldName);
PVField getSubField(int fieldOffset);
// The following are convenience methods
PVBoolean getBooleanField(std::string fieldName);
PVByte getByteField(std::string fieldName);
PVShort getShortField(std::string fieldName);
PVInt getIntField(std::string fieldName);
PVLong getLongField(std::string fieldName);
PVFloat getFloatField(std::string fieldName);
PVDouble getDoubleField(std::string fieldName);
PVString getStringField(std::string fieldName);
PVScalarArray getScalarArrayField(std::string fieldName);
PVStructureArray getStructureArrayField(std::string fieldName);
PVStructure getStructureField(std::string fieldName);
PVArray getArrayField(std::string fieldName,ScalarType elementType);
// following will be removed
<font color = "red"> void appendPVField(std::string fieldName,PVField pvField);</font>
<font color = "red"> void appendPVFields(std::string[] fieldNames,PVField[] pvFields);</font>
<font color = "red"> void removePVField(std::string fieldName);</font>
<font color = "red"> void replacePVField(PVField oldPVField,PVField newPVField);</font>
<font color = "red"> std::string getExtendsStructureName();</font>
<font color = "red"> boolean putExtendsStructureName(std::string extendsStructureName);</font>
<font color = "red"> public boolean checkValid();</font>
}
<font color = "red">
//following will be removed
public class StructureArrayData {
public PVStructure[] data;
public int offset;
}
</font>
interface PVStructureArray extends PVArray{
StructureArray getStructureArray();
// following are new
<font color = "blue"> PVStructure[] get();</font>
<font color = "blue"> void swap(PVStructure[] value);</font>
// following will be removed
<font color = "red"> int get(int offset, int length, StructureArrayData data);</font>
<font color = "red"> int put(int offset,int length, PVStructure[] from, int fromOffset);</font>
<font color = "red"> void shareData(PVStructure[] from);</font>
}
public interface PVDataCreate {
PVField createPVField(Field field);
PVField createPVField(PVField fieldToClone);
PVScalar createPVScalar(Scalar scalar);
PVScalar createPVScalar(ScalarType fieldType);
PVScalar createPVScalar(PVScalar scalarToClone);
PVScalarArray createPVScalarArray(ScalarArray array);
PVScalarArray createPVScalarArray(ScalarType elementType);
PVScalarArray createPVScalarArray(PVScalarArray arrayToClone;
PVStructureArray createPVStructureArray(StructureArray structureArray);
PVStructure createPVStructure(Structure structure);
PVStructure createPVStructure(std::string[] fieldNames,Field[] fields);
PVStructure createPVStructure(PVStructure structToClone);
// following will be removed
<font color = "red">PVField[] flattenPVStructure(PVStructure pvStructure);</font>
}
</pre>
<h3>PVFieldTostd::string</h3>
<p>In addition to toString this has methods to limit the number of array element to display.
The existing Java implementation of toString displayed all elements.
For large arrays this is not desirable.
The new methods provide a way for the client to limit the number of elements.
The default might be set to something like display up to 10 elements with 5 fron the beginning and 5 from the end.</p>
<p>For C++ this can be a replacement for dumpValue.</p>
<h3>PVBooleanArray, ..., PVStructureArray</h3>
<p>The old get and put are replaced by two new and simpler methods:
<dl>
<dt>get</dt>
<dd>Returns the raw array. If the client code modifies the elements in the array then
the client must call postPut. The client also has to realize that if the raw array held by the PVXXXArray changes
then the client is no longer sharing data
<dt>swap</dt>
<dd>This exchanges the old raw data with the new raw data.</dd>
</dl>
</p>
<p>
The method <b>setCapacity</b> will always create a new raw array and copy old data from the old to the new array.
This is not true now since the implementation does not create a new array if the old capacity is equal to the requested capacity.
</p>
<h2>C++ API</h2>
<p>The C++ class definitions are similar to the Java definitions with two main exceptions:
<dl>
<dt>toString</dt>
<dd>In c++ this is replaced by std::ostream.</dd>
<dt>raw array data</dt>
<dd>Java supports array data like <b>double[]</b>
The C++ replacement is shared_vector&lt;double&gt;, which is implemented
in pvDataCPP-md.</dd
</dl>
<h3>Introspection Interfaces</h3>
<pre>
class Field :
virtual public Serializable,
public std::tr1::enable_shared_from_this&lt;Field&gt;
{
public:
POINTER_DEFINITIONS(Field);
virtual ~Field();
Type getType() const{return m_type;}
virtual std::string getID() const = 0;
<font color = "red">
// following will be removed
virtual void toString(StringBuilder buf) const{toString(buf,0);}
virtual void toString(StringBuilder buf,int indentLevel) const;
</font>
...
};
<font color = "blue">
// new function
std::ostream &amp;toString(Field::const_reference field, std::ostream&amp; o);
</font>
class Scalar : public Field{
public:
POINTER_DEFINITIONS(Scalar);
virtual ~Scalar();
typedef Scalar&amp; reference;
typedef const Scalar&amp; const_reference;
ScalarType getScalarType() const {return scalarType;}
virtual void serialize(ByteBuffer *buffer, SerializableControl *control) const;
virtual void deserialize(ByteBuffer *buffer, DeserializableContol *control);
<font color = "red">
// following will be removed
virtual void toString(StringBuilder buf) const{toString(buf,0);}
virtual void toString(StringBuilder buf,int indentLevel) const;
virtual std::string getID() const;
</font>
...
};
class ScalarArray : public Field{
public:
POINTER_DEFINITIONS(ScalarArray);
typedef ScalarArray&amp; reference;
typedef const ScalarArray&amp; const_reference;
ScalarArray(ScalarType scalarType);
ScalarType getElementType() const {return elementType;}
virtual void serialize(ByteBuffer *buffer, SerializableControl *control) const;
virtual void deserialize(ByteBuffer *buffer, DeserializableControl *control);
<font color = "red">
// following will be removed
virtual void toString(StringBuilder buf) const{toString(buf,0);}
virtual void toString(StringBuilder buf,int indentLevel) const;
virtual std::string getID() const;
</font>
...
};
class Structure : public Field {
public:
POINTER_DEFINITIONS(Structure);
typedef Structure&amp; reference;
typedef const Structure&amp; const_reference;
std::size_t getNumberFields() const {return numberFields;}
FieldConstPtr getField(std::string const &amp; fieldName) const;
FieldConstPtr getField(std::size_t index) const;
std::size_t getFieldIndex(std::string const &amp;fieldName) const;
FieldConstPtrArray const &amp; getFields() const {return fields;}
StringArray const &amp; getFieldNames() const;
std::string getFieldName(std::size_t fieldIndex);
virtual void serialize(ByteBuffer *buffer, SerializableControl *control) const;
virtual void deserialize(ByteBuffer *buffer, DeserializableControl *control);
<font color = "red">
// following will be removed
void renameField(std::size_t fieldIndex,std::string const &amp;newName);
virtual void toString(StringBuilder buf,int indentLevel) const;
virtual std::string getID() const;
</font>
...
};
class StructureArray : public Field{
public:
POINTER_DEFINITIONS(StructureArray);
typedef StructureArray&amp; reference;
typedef const StructureArray&amp; const_reference;
StructureConstPtr getStructure() const {return pstructure;}
virtual void serialize(ByteBuffer *buffer, SerializableControl *control) const;
virtual void deserialize(ByteBuffer *buffer, DeserializableControl *control);
<font color = "red">
// following will be removed
virtual void toString(StringBuilder buf,int indentLevel=0) const;
virtual std::string getID() const;
</font>
...
};
class FieldCreate {
public:
static FieldCreatePtr getFieldCreate();
ScalarConstPtr createScalar(ScalarType scalarType) const
ScalarArrayConstPtr createScalarArray(ScalarType elementType) const;
StructureArrayConstPtr createStructureArray(StructureConstPtr const &amp; structure) const;
StructureConstPtr createStructure (
StringArray const &amp; fieldNames,
FieldConstPtrArray const &amp; fields) const;
StructureConstPtr createStructure (
std::string const &amp;id,
StringArray const &amp; fieldNames,
FieldConstPtrArray const &amp; fields) const;
FieldConstPtr deserialize(ByteBuffer* buffer, DeserializableControl* control) const;
<font color = "red">
// following will be removed
StructureConstPtr appendField(
StructureConstPtr const &amp; structure,
std::string const &amp;fieldName, FieldConstPtr const &amp; field) const;
StructureConstPtr appendFields(
StructureConstPtr const &amp; structure,
StringArray const &amp; fieldNames,
FieldConstPtrArray const &amp; fields) const;
</font>
...
};
extern FieldCreatePtr getFieldCreate();
</pre>
<h3>Data Interfaces</h3>
<pre>
class PVField
: virtual public Serializable,
public std::tr1::enable_shared_from_this&lt;PVField&gt;
{
public:
POINTER_DEFINITIONS(PVField);
virtual ~PVField();
inline const std::string &amp;getFieldName() const ;
virtual void setRequester(RequesterPtr const &amp;prequester);
std::size_t getFieldOffset() const;
std::size_t getNextFieldOffset() const;
std::size_t getNumberFields() const;
const FieldConstPtr &amp; getField() const ;
PVStructure * getParent() const
void postPut() ;
void setPostHandler(PostHandlerPtr const &amp;postHandler);
// following will be removed
<font color = "red">
virtual void message(std::string message,MessageType messageType);
void replacePVField(const PVFieldPtr&amp; newPVField);
std::string getFullName() const;
virtual bool equals(PVField &amp;pv);
PVAuxInfoPtr &amp; getPVAuxInfo()
bool isImmutable() const;
virtual void setImmutable();
void replacePVField(const PVFieldPtr&amp; newPVField);
void renameField(std::string const &amp;newName);
virtual void toString(StringBuilder buf) ;
virtual void toString(StringBuilder buf,int indentLevel);
std::ostream&amp; dumpValue(std::ostream&amp; o) const;
</font>
...
};
<font color = "blue">
// The following is a new class
class PVFieldTostd::string {
std::string toString(const PVFieldPtr &amp;pvField);
void setMaxInitialArrayElements(size_t num);
void setMaxFinalArrayElements(size_t num);
size_t getMaxInitialArrayElements();
size_t getMaxFinalArrayElements();
...
}</font>
class PVScalar : public PVField {
public:
POINTER_DEFINITIONS(PVScalar);
virtual ~PVScalar();
typedef PVScalar &amp;reference;
typedef const PVScalar&amp; const_reference;
const ScalarConstPtr getScalar() const ;
...
}
template&lt;typename T&gt;
class PVScalarValue : public PVScalar {
public:
POINTER_DEFINITIONS(PVScalarValue);
typedef T value_type;
typedef T* pointer;
typedef const T* const_pointer;
virtual ~PVScalarValue() {}
virtual T get() const = 0;
virtual void put(T value) = 0;
<font color = "red">
// following will be removed
std::ostream&amp; dumpValue(std::ostream&amp; o)
void operator&gt;&gt;=(T&amp; value) const;
void operator&lt;&lt;=(T value);
</font>
...
}
// PVString is special case, since it implements SerializableArray
class PVString : public PVScalarValue&lt;std::string&gt;, SerializableArray {
public:
virtual ~PVString() {}
...
}
class PVArray : public PVField, public SerializableArray {
public:
POINTER_DEFINITIONS(PVArray);
virtual ~PVArray();
std::size_t getLength() const;
virtual void setLength(std::size_t length);
std::size_t getCapacity() const;
virtual void setCapacity(std::size_t capacity) = 0;
<font color = "red">
// following will be removed
virtual void setImmutable();
bool isCapacityMutable() const;
void setCapacityMutable(bool isMutable);
virtual std::ostream&amp; dumpValue(std::ostream&amp; o, std::size_t index) const = 0;
</font>
...
};
class PVScalarArray : public PVArray {
public:
POINTER_DEFINITIONS(PVScalarArray);
virtual ~PVScalarArray();
typedef PVScalarArray &amp;reference;
typedef const PVScalarArray&amp; const_reference;
const ScalarArrayConstPtr getScalarArray() const ;
<font color = "red">
// following will be removed
virtual std::ostream&amp; dumpValue(std::ostream&amp; o, size_t index) const = 0;
</font>
...
}
<font color = "red">
// following will be removed
template&lt;typename T&gt;
class PVArrayData {
private:
std::vector&lt;T&gt; init;
public:
POINTER_DEFINITIONS(PVArrayData);
typedef T value_type;
typedef T* pointer;
typedef const T* const_pointer;
std::vector&lt;T&gt; &amp; data;
std::size_t offset;
PVArrayData()
: data(init)
{}
};
</font>
template&lt;typename T&gt;
class PVValueArray : public PVScalarArray {
public:
POINTER_DEFINITIONS(PVValueArray);
typedef T value_type;
typedef T* pointer;
typedef const T* const_pointer;
// following are new typeDefs
<font color = "blue">typedef shared_vector&lt;T&gt; svector;</font>
<font color = "blue">typedef shared_vector&lt;const T&gt; const_svector; </font>
virtual ~PVValueArray() {}
// following are added
<font color = "blue">svector get();</font>
<font color = "blue">void swap(svector&amp; value);</font>
<font color = "red">
// following are removed
typedef PVValueArray &amp; reference;
typedef const PVValueArray &amp; const_reference;
typedef PVArrayData&lt;T&gt; ArrayDataType;
typedef std::vector&lt;T&gt; vector;
typedef const std::vector&lt;T&gt; const_vector;
typedef std::tr1::shared_ptr&lt;vector&gt; shared_vector;
virtual std::size_t get(
std::size_t offset, std::size_t length, ArrayDataType &amp;data) = 0;
virtual std::size_t put(std::size_t offset,
std::size_t length, const_pointer from, std::size_t fromOffset) = 0;
virtual std::size_t put(std::size_t offset,
std::size_t length, const_vector &amp;from, std::size_t fromOffset);
virtual void shareData(
shared_vector const &amp; value,
std::size_t capacity,
std::size_t length) = 0;
virtual pointer get() = 0;
virtual pointer get() const = 0;
virtual vector const &amp; getVector() = 0;
virtual shared_vector const &amp; getSharedVector() = 0;
std::ostream&amp; dumpValue(std::ostream&amp; o) const;
std::ostream&amp; dumpValue(std::ostream&amp; o, size_t index) const;
</font>
...
};
typedef PVValueArray&lt;uint8&gt; PVBooleanArray;
typedef std::tr1::shared_ptr&lt;PVBooleanArray&gt; PVBooleanArrayPtr;
...
typedef PVValueArray&lt;std::string&gt; PVStringArray;
typedef std::tr1::shared_ptr&lt;PVStringArray&gt; PVStringArrayPtr;
class PVStructure : public PVField,public BitSetSerializable {
public:
POINTER_DEFINITIONS(PVStructure);
virtual ~PVStructure();
typedef PVStructure &amp; reference;
typedef const PVStructure &amp; const_reference;
StructureConstPtr getStructure() const;
const PVFieldPtrArray &amp; getPVFields() const;
PVFieldPtr getSubField(std::string const &amp;fieldName) const;
PVFieldPtr getSubField(std::size_t fieldOffset) const;
PVBooleanPtr getBooleanField(std::string const &amp;fieldName) ;
PVBytePtr getByteField(std::string const &amp;fieldName) ;
PVShortPtr getShortField(std::string const &amp;fieldName) ;
PVIntPtr getIntField(std::string const &amp;fieldName) ;
PVLongPtr getLongField(std::string const &amp;fieldName) ;
PVUBytePtr getUByteField(std::string const &amp;fieldName) ;
PVUShortPtr getUShortField(std::string const &amp;fieldName) ;
PVUIntPtr getUIntField(std::string const &amp;fieldName) ;
PVULongPtr getULongField(std::string const &amp;fieldName) ;
PVFloatPtr getFloatField(std::string const &amp;fieldName) ;
PVDoublePtr getDoubleField(std::string const &amp;fieldName) ;
PVStringPtr getStringField(std::string const &amp;fieldName) ;
PVStructurePtr getStructureField(std::string const &amp;fieldName) ;
PVScalarArrayPtr getScalarArrayField(
std::string const &amp;fieldName,ScalarType elementType) ;
PVStructureArrayPtr getStructureArrayField(std::string const &amp;fieldName) ;
virtual void serialize(
ByteBuffer *pbuffer,SerializableControl *pflusher) const ;
virtual void deserialize(
ByteBuffer *pbuffer,DeserializableControl *pflusher);
virtual void serialize(ByteBuffer *pbuffer,
SerializableControl *pflusher,BitSet *pbitSet) const;
virtual void deserialize(ByteBuffer *pbuffer,
DeserializableControl*pflusher,BitSet *pbitSet);
PVStructure(StructureConstPtr const &amp; structure);
PVStructure(StructureConstPtr const &amp; structure,PVFieldPtrArray const &amp; pvFields);
<font color = "red">
// following are removed
void appendPVField(
std::string const &amp;fieldName,
PVFieldPtr const &amp; pvField);
void appendPVFields(
StringArray const &amp; fieldNames,
PVFieldPtrArray const &amp; pvFields);
void removePVField(std::string const &amp;fieldName);
virtual void setImmutable();
std::string getExtendsStructureName() const;
bool putExtendsStructureName(
std::string const &amp;extendsStructureName);
</font>
};
<font color = "red">
// following will be removed
typedef PVArrayData&lt;PVStructurePtr&gt; StructureArrayData;
</font>
class PVStructureArray : public PVArray
{
public:
POINTER_DEFINITIONS(PVStructureArray);
typedef PVStructurePtr value_type;
typedef PVStructurePtr* pointer;
typedef const PVStructurePtr* const_pointer;
<font color = "blue">
// following are new typeDefs
typedef shared_vector&lt;PVStructurePtr&gt; svector;
typedef shared_vector&lt;const PVStructurePtr&gt; const_svector;
</font>
virtual ~PVStructureArray() {}
virtual void setCapacity(size_t capacity);
virtual void setLength(std::size_t length);
virtual StructureArrayConstPtr getStructureArray() const ;
virtual void serialize(ByteBuffer *pbuffer,
SerializableControl *pflusher) const;
virtual void deserialize(ByteBuffer *buffer,
virtual void serialize(ByteBuffer *pbuffer,
SerializableControl *pflusher, std::size_t offset, std::size_t count) const ;
// following are new
<font color = "blue"> svector get();</font>
<font color = "blue"> void swap(svector &amp; value);</font>
<font color = "red">
// following are removed
typedef PVArrayData&lt;PVStructurePtr&gt; ArrayDataType;
typedef std::vector&lt;PVStructurePtr&gt; vector;
typedef const std::vector&lt;PVStructurePtr&gt; const_vector;
typedef std::tr1::shared_ptr&lt;vector&gt; shared_vector;
typedef PVStructureArray &amp;reference;
typedef const PVStructureArray&amp; const_reference;
virtual std::size_t append(std::size_t number);
virtual bool remove(std::size_t offset,std::size_t number);
virtual void compress();
virtual std::size_t get(std::size_t offset, std::size_t length,
StructureArrayData &amp;data);
virtual std::size_t put(std::size_t offset,std::size_t length,
const_vector const &amp; from, std::size_t fromOffset);
virtual void shareData(
shared_vector const &amp; value,
std::size_t capacity,
std::size_t length);
virtual pointer get() { return &amp;((*value.get())[0]); }
virtual pointer get() const { return &amp;((*value.get())[0]); }
virtual vector const &amp; getVector() {return *value;}
virtual shared_vector const &amp; getSharedVector() {return value;}
</font>
...
};
class PVDataCreate {
public:
static PVDataCreatePtr getPVDataCreate();
PVFieldPtr createPVField(FieldConstPtr const &amp; field);
PVFieldPtr createPVField(PVFieldPtr const &amp; fieldToClone);
PVScalarPtr createPVScalar(ScalarConstPtr const &amp; scalar);
PVScalarPtr createPVScalar(ScalarType scalarType);
PVScalarPtr createPVScalar(PVScalarPtr const &amp; scalarToClone);
PVScalarArrayPtr createPVScalarArray(ScalarArrayConstPtr const &amp; scalarArray);
PVScalarArrayPtr createPVScalarArray(ScalarType elementType);
PVScalarArrayPtr createPVScalarArray(PVScalarArrayPtr const &amp; scalarArrayToClone);
PVStructureArrayPtr createPVStructureArray(StructureArrayConstPtr const &amp; structureArray);
PVStructurePtr createPVStructure(StructureConstPtr const &amp; structure);
PVStructurePtr createPVStructure(
StringArray const &amp; fieldNames,PVFieldPtrArray const &amp; pvFields);
PVStructurePtr createPVStructure(PVStructurePtr const &amp; structToClone);
...
};
extern PVDataCreatePtr getPVDataCreate();
</pre>
</div>
</body>
</html>

View File

@@ -62,42 +62,6 @@ pvDataApp/misc/timeFunction.h
pvDataApp/misc/timer.cpp
pvDataApp/misc/timer.h
pvDataApp/monitor/monitor.h
pvDataApp/O.linux-x86_64/alarm.d
pvDataApp/O.linux-x86_64/bitSet.d
pvDataApp/O.linux-x86_64/bitSetUtil.d
pvDataApp/O.linux-x86_64/byteBuffer.d
pvDataApp/O.linux-x86_64/Compare.d
pvDataApp/O.linux-x86_64/Convert.d
pvDataApp/O.linux-x86_64/epicsException.d
pvDataApp/O.linux-x86_64/event.d
pvDataApp/O.linux-x86_64/executor.d
pvDataApp/O.linux-x86_64/FieldCreateFactory.d
pvDataApp/O.linux-x86_64/libpvData.a
pvDataApp/O.linux-x86_64/libpvData.so
pvDataApp/O.linux-x86_64/localStaticLock.d
pvDataApp/O.linux-x86_64/messageQueue.d
pvDataApp/O.linux-x86_64/pvAlarm.d
pvDataApp/O.linux-x86_64/PVArray.d
pvDataApp/O.linux-x86_64/PVAuxInfoImpl.d
pvDataApp/O.linux-x86_64/pvControl.d
pvDataApp/O.linux-x86_64/PVDataCreateFactory.d
pvDataApp/O.linux-x86_64/pvDisplay.d
pvDataApp/O.linux-x86_64/pvEnumerated.d
pvDataApp/O.linux-x86_64/PVField.d
pvDataApp/O.linux-x86_64/PVScalar.d
pvDataApp/O.linux-x86_64/PVScalarArray.d
pvDataApp/O.linux-x86_64/PVStructure.d
pvDataApp/O.linux-x86_64/PVStructureArray.d
pvDataApp/O.linux-x86_64/pvTimeStamp.d
pvDataApp/O.linux-x86_64/requester.d
pvDataApp/O.linux-x86_64/serializeHelper.d
pvDataApp/O.linux-x86_64/StandardField.d
pvDataApp/O.linux-x86_64/StandardPVField.d
pvDataApp/O.linux-x86_64/status.d
pvDataApp/O.linux-x86_64/timeFunction.d
pvDataApp/O.linux-x86_64/timer.d
pvDataApp/O.linux-x86_64/timeStamp.d
pvDataApp/O.linux-x86_64/TypeFunc.d
pvDataApp/property/alarm.cpp
pvDataApp/property/alarm.h
pvDataApp/property/alarm.h.orig
@@ -117,45 +81,15 @@ pvDataApp/property/timeStamp.cpp
pvDataApp/property/timeStamp.h
pvDataApp/property/timeStamp.h.orig
pvDataApp/pv/convert.h
pvDataApp/pv/convert.h.orig
pvDataApp/pv/pvData.h
pvDataApp/pv/pvData.h.orig
pvDataApp/pv/pvIntrospect.h
pvDataApp/pv/pvIntrospect.h.orig
pvDataApp/pv/pvType.h
pvDataApp/pv/standardField.h
pvDataApp/pv/standardField.h.orig
pvDataApp/pv/standardPVField.h
pvDataApp/pv/standardPVField.h.orig
pvDataApp/pvMisc/bitSetUtil.cpp
pvDataApp/pvMisc/bitSetUtil.h
testApp/capi/O.linux-x86_64/libtestc.a
testApp/capi/O.linux-x86_64/libtestc.so
testApp/capi/O.linux-x86_64/testc.d
testApp/capi/testc.cpp
testApp/capi/testc.py
testApp/mb/O.linux-x86_64/mb_test
testApp/mb/O.linux-x86_64/mb_test.d
testApp/misc/O.linux-x86_64/testBaseException
testApp/misc/O.linux-x86_64/testBaseException.d
testApp/misc/O.linux-x86_64/testBitSet
testApp/misc/O.linux-x86_64/testBitSet.d
testApp/misc/O.linux-x86_64/testByteBuffer
testApp/misc/O.linux-x86_64/testByteBuffer.d
testApp/misc/O.linux-x86_64/testByteOrder
testApp/misc/O.linux-x86_64/testByteOrder.d
testApp/misc/O.linux-x86_64/testMessageQueue
testApp/misc/O.linux-x86_64/testMessageQueue.d
testApp/misc/O.linux-x86_64/testQueue
testApp/misc/O.linux-x86_64/testQueue.d
testApp/misc/O.linux-x86_64/testSerialization
testApp/misc/O.linux-x86_64/testSerialization.d
testApp/misc/O.linux-x86_64/testThread
testApp/misc/O.linux-x86_64/testThread.d
testApp/misc/O.linux-x86_64/testTimer
testApp/misc/O.linux-x86_64/testTimer.d
testApp/misc/O.linux-x86_64/testTimeStamp
testApp/misc/O.linux-x86_64/testTimeStamp.d
testApp/misc/testBaseException.cpp
testApp/misc/testBitSet.cpp
testApp/misc/testByteBuffer.cpp
@@ -166,34 +100,8 @@ testApp/misc/testSerialization.cpp
testApp/misc/testThread.cpp
testApp/misc/testTimer.cpp
testApp/misc/testTimeStamp.cpp
testApp/monitor/O.linux-x86_64/testMonitor
testApp/monitor/O.linux-x86_64/testMonitor.d
testApp/monitor/testMonitor.cpp
testApp/property/O.linux-x86_64/testProperty
testApp/property/O.linux-x86_64/testProperty.d
testApp/property/testProperty.cpp
testApp/pv/O.linux-x86_64/testConvert
testApp/pv/O.linux-x86_64/testConvert.d
testApp/pv/O.linux-x86_64/testIntrospect
testApp/pv/O.linux-x86_64/testIntrospect.d
testApp/pv/O.linux-x86_64/testOperators
testApp/pv/O.linux-x86_64/testOperators.d
testApp/pv/O.linux-x86_64/testPVAppend
testApp/pv/O.linux-x86_64/testPVAppend.d
testApp/pv/O.linux-x86_64/testPVAuxInfo
testApp/pv/O.linux-x86_64/testPVAuxInfo.d
testApp/pv/O.linux-x86_64/testPVData
testApp/pv/O.linux-x86_64/testPVData.d
testApp/pv/O.linux-x86_64/testPVScalarArray
testApp/pv/O.linux-x86_64/testPVScalarArray.d
testApp/pv/O.linux-x86_64/testPVStructureArray
testApp/pv/O.linux-x86_64/testPVStructureArray.d
testApp/pv/O.linux-x86_64/testPVType
testApp/pv/O.linux-x86_64/testPVType.d
testApp/pv/O.linux-x86_64/testStandardField
testApp/pv/O.linux-x86_64/testStandardField.d
testApp/pv/O.linux-x86_64/testStandardPVField
testApp/pv/O.linux-x86_64/testStandardPVField.d
testApp/pv/testConvert.cpp
testApp/pv/testIntrospect.cpp
testApp/pv/testOperators.cpp
@@ -208,4 +116,376 @@ testApp/pv/testStandardPVField.cpp
COPYRIGHT
Doxyfile
LICENSE
README.html
README.html
src/copy/createRequest.cpp
src/copy/createRequest.h
src/copy/pvCopy.cpp
src/copy/pvCopy.h
src/factory/Compare.cpp
src/factory/Convert.cpp
src/factory/factory.h
src/factory/FieldCreateFactory.cpp
src/factory/printer.cpp
src/factory/PVArray.cpp
src/factory/PVDataCreateFactory.cpp
src/factory/PVField.cpp
src/factory/PVScalar.cpp
src/factory/PVScalarArray.cpp
src/factory/PVStructure.cpp
src/factory/PVStructureArray.cpp
src/factory/pvSubArrayCopy.cpp
src/factory/PVUnion.cpp
src/factory/PVUnionArray.cpp
src/factory/StandardField.cpp
src/factory/StandardPVField.cpp
src/factory/TypeFunc.cpp
src/misc/bitSet.cpp
src/misc/bitSet.h
src/misc/byteBuffer.cpp
src/misc/byteBuffer.h
src/misc/current_function.h
src/misc/destroyable.h
src/misc/epicsException.cpp
src/misc/epicsException.h
src/misc/event.cpp
src/misc/event.h
src/misc/executor.cpp
src/misc/executor.h
src/misc/localStaticLock.cpp
src/misc/localStaticLock.h
src/misc/lock.h
src/misc/messageQueue.cpp
src/misc/messageQueue.h
src/misc/noDefaultMethods.h
src/misc/parseToPOD.cpp
src/misc/queue.h
src/misc/requester.cpp
src/misc/requester.h
src/misc/serialize.h
src/misc/serializeHelper.cpp
src/misc/serializeHelper.h
src/misc/sharedPtr.h
src/misc/sharedVector.h
src/misc/status.cpp
src/misc/status.h
src/misc/templateMeta.h
src/misc/thread.h
src/misc/timeFunction.cpp
src/misc/timeFunction.h
src/misc/timer.cpp
src/misc/timer.h
src/misc/typeCast.cpp
src/misc/typeCast.h
src/monitor/monitor.cpp
src/monitor/monitor.h
src/monitor/monitorPlugin.cpp
src/monitor/monitorPlugin.h
src/property/alarm.cpp
src/property/alarm.h
src/property/control.h
src/property/display.h
src/property/pvAlarm.cpp
src/property/pvAlarm.h
src/property/pvControl.cpp
src/property/pvControl.h
src/property/pvDisplay.cpp
src/property/pvDisplay.h
src/property/pvEnumerated.cpp
src/property/pvEnumerated.h
src/property/pvTimeStamp.cpp
src/property/pvTimeStamp.h
src/property/timeStamp.cpp
src/property/timeStamp.h
src/pv/convert.h
src/pv/printer.h
src/pv/pvData.h
src/pv/pvIntrospect.h
src/pv/pvSubArrayCopy.h
src/pv/pvType.h
src/pv/standardField.h
src/pv/standardPVField.h
src/pvMisc/bitSetUtil.cpp
src/pvMisc/bitSetUtil.h
testApp/copy/testCreateRequest.cpp
testApp/copy/testPVCopy.cpp
testApp/misc/testBaseException.cpp
testApp/misc/testBitSet.cpp
testApp/misc/testByteBuffer.cpp
testApp/misc/testByteOrder.cpp
testApp/misc/testMessageQueue.cpp
testApp/misc/testOverrunBitSet.cpp
testApp/misc/testQueue.cpp
testApp/misc/testSerialization.cpp
testApp/misc/testSharedVector.cpp
testApp/misc/testThread.cpp
testApp/misc/testTimer.cpp
testApp/misc/testTimeStamp.cpp
testApp/misc/testTypeCast.cpp
testApp/property/testProperty.cpp
testApp/pv/testBitSetUtil.cpp
testApp/pv/testConvert.cpp
testApp/pv/testFieldBuilder.cpp
testApp/pv/testIntrospect.cpp
testApp/pv/testOperators.cpp
testApp/pv/testPVData.cpp
testApp/pv/testPVScalarArray.cpp
testApp/pv/testPVStructureArray.cpp
testApp/pv/testPVType.cpp
testApp/pv/testStandardField.cpp
testApp/pv/testStandardPVField.cpp
src/factory/printer.cpp
configure/O.darwin-x86/Makefile
configure/Makefile
include/pv/alarm.h
include/pv/bitSet.h
include/pv/bitSetUtil.h
include/pv/byteBuffer.h
include/pv/control.h
include/pv/convert.h
include/pv/createRequest.h
include/pv/current_function.h
include/pv/destroyable.h
include/pv/display.h
include/pv/epicsException.h
include/pv/event.h
include/pv/executor.h
include/pv/factory.h
include/pv/localStaticLock.h
include/pv/lock.h
include/pv/messageQueue.h
include/pv/monitor.h
include/pv/monitorPlugin.h
include/pv/noDefaultMethods.h
include/pv/printer.h
include/pv/pvAlarm.h
include/pv/pvControl.h
include/pv/pvCopy.h
include/pv/pvData.h
include/pv/pvDisplay.h
include/pv/pvEnumerated.h
include/pv/pvIntrospect.h
include/pv/pvSubArrayCopy.h
include/pv/pvTimeStamp.h
include/pv/pvType.h
include/pv/queue.h
include/pv/requester.h
include/pv/serialize.h
include/pv/serializeHelper.h
include/pv/sharedPtr.h
include/pv/sharedVector.h
include/pv/standardField.h
include/pv/standardPVField.h
include/pv/status.h
include/pv/templateMeta.h
include/pv/thread.h
include/pv/timeFunction.h
include/pv/timer.h
include/pv/timeStamp.h
include/pv/typeCast.h
src/copy/createRequest.cpp
src/copy/createRequest.h
src/copy/Makefile
src/copy/pvCopy.cpp
src/copy/pvCopy.h
src/factory/Compare.cpp
src/factory/Convert.cpp
src/factory/factory.h
src/factory/FieldCreateFactory.cpp
src/factory/Makefile
src/factory/printer.cpp
src/factory/PVArray.cpp
src/factory/PVDataCreateFactory.cpp
src/factory/PVField.cpp
src/factory/PVScalar.cpp
src/factory/PVScalarArray.cpp
src/factory/PVStructure.cpp
src/factory/PVStructureArray.cpp
src/factory/pvSubArrayCopy.cpp
src/factory/PVUnion.cpp
src/factory/PVUnionArray.cpp
src/factory/StandardField.cpp
src/factory/StandardPVField.cpp
src/factory/TypeFunc.cpp
src/misc/bitSet.cpp
src/misc/bitSet.h
src/misc/byteBuffer.cpp
src/misc/byteBuffer.h
src/misc/current_function.h
src/misc/destroyable.h
src/misc/epicsException.cpp
src/misc/epicsException.h
src/misc/event.cpp
src/misc/event.h
src/misc/executor.cpp
src/misc/executor.h
src/misc/localStaticLock.cpp
src/misc/localStaticLock.h
src/misc/lock.h
src/misc/Makefile
src/misc/messageQueue.cpp
src/misc/messageQueue.h
src/misc/noDefaultMethods.h
src/misc/parseToPOD.cpp
src/misc/queue.h
src/misc/requester.cpp
src/misc/requester.h
src/misc/serialize.h
src/misc/serializeHelper.cpp
src/misc/serializeHelper.h
src/misc/sharedPtr.h
src/misc/sharedVector.h
src/misc/status.cpp
src/misc/status.h
src/misc/templateMeta.h
src/misc/thread.h
src/misc/timeFunction.cpp
src/misc/timeFunction.h
src/misc/timer.cpp
src/misc/timer.h
src/misc/typeCast.cpp
src/misc/typeCast.h
src/monitor/Makefile
src/monitor/monitor.cpp
src/monitor/monitor.h
src/monitor/monitorPlugin.cpp
src/monitor/monitorPlugin.h
src/O.darwin-x86/Makefile
src/property/alarm.cpp
src/property/alarm.h
src/property/control.h
src/property/display.h
src/property/Makefile
src/property/pvAlarm.cpp
src/property/pvAlarm.h
src/property/pvControl.cpp
src/property/pvControl.h
src/property/pvDisplay.cpp
src/property/pvDisplay.h
src/property/pvEnumerated.cpp
src/property/pvEnumerated.h
src/property/pvTimeStamp.cpp
src/property/pvTimeStamp.h
src/property/timeStamp.cpp
src/property/timeStamp.h
src/pv/convert.h
src/pv/Makefile
src/pv/printer.h
src/pv/pvData.h
src/pv/pvIntrospect.h
src/pv/pvSubArrayCopy.h
src/pv/pvType.h
src/pv/standardField.h
src/pv/standardPVField.h
src/pvMisc/bitSetUtil.cpp
src/pvMisc/bitSetUtil.h
src/pvMisc/Makefile
src/Makefile
testApp/copy/epicsRunPVDataTests.c
testApp/copy/Makefile
testApp/copy/testCreateRequest.cpp
testApp/copy/testPVCopy.cpp
testApp/misc/epicsRunPVDataTests.c
testApp/misc/Makefile
testApp/misc/testBaseException.cpp
testApp/misc/testBitSet.cpp
testApp/misc/testByteBuffer.cpp
testApp/misc/testByteOrder.cpp
testApp/misc/testMessageQueue.cpp
testApp/misc/testOverrunBitSet.cpp
testApp/misc/testQueue.cpp
testApp/misc/testSerialization.cpp
testApp/misc/testSharedVector.cpp
testApp/misc/testThread.cpp
testApp/misc/testTimer.cpp
testApp/misc/testTimeStamp.cpp
testApp/misc/testTypeCast.cpp
testApp/property/epicsRunPVDataTests.c
testApp/property/Makefile
testApp/property/testProperty.cpp
testApp/pv/epicsRunPVDataTests.c
testApp/pv/Makefile
testApp/pv/testBitSetUtil.cpp
testApp/pv/testConvert.cpp
testApp/pv/testFieldBuilder.cpp
testApp/pv/testIntrospect.cpp
testApp/pv/testOperators.cpp
testApp/pv/testPVData.cpp
testApp/pv/testPVScalarArray.cpp
testApp/pv/testPVStructureArray.cpp
testApp/pv/testPVType.cpp
testApp/pv/testPVUnion.cpp
testApp/pv/testStandardField.cpp
testApp/pv/testStandardPVField.cpp
testApp/Makefile
Makefile
testApp/copy/epicsRunPVDataTests.c
testApp/copy/Makefile
testApp/copy/testCreateRequest.cpp
testApp/copy/testPVCopy.cpp
testApp/misc/epicsRunPVDataTests.c
testApp/misc/Makefile
testApp/misc/testBaseException.cpp
testApp/misc/testBitSet.cpp
testApp/misc/testByteBuffer.cpp
testApp/misc/testByteOrder.cpp
testApp/misc/testMessageQueue.cpp
testApp/misc/testOverrunBitSet.cpp
testApp/misc/testQueue.cpp
testApp/misc/testSerialization.cpp
testApp/misc/testSharedVector.cpp
testApp/misc/testThread.cpp
testApp/misc/testTimer.cpp
testApp/misc/testTimeStamp.cpp
testApp/misc/testTypeCast.cpp
testApp/O.darwin-x86/Makefile
testApp/property/epicsRunPVDataTests.c
testApp/property/Makefile
testApp/property/testProperty.cpp
testApp/pv/epicsRunPVDataTests.c
testApp/pv/Makefile
testApp/pv/testBitSetUtil.cpp
testApp/pv/testConvert.cpp
testApp/pv/testFieldBuilder.cpp
testApp/pv/testIntrospect.cpp
testApp/pv/testOperators.cpp
testApp/pv/testPVData.cpp
testApp/pv/testPVScalarArray.cpp
testApp/pv/testPVStructureArray.cpp
testApp/pv/testPVType.cpp
testApp/pv/testPVUnion.cpp
testApp/pv/testStandardField.cpp
testApp/pv/testStandardPVField.cpp
testApp/Makefile
testApp/pvDataAllTests.c
testApp/copy/testCreateRequest.cpp
testApp/copy/testPVCopy.cpp
testApp/misc/testBaseException.cpp
testApp/misc/testBitSet.cpp
testApp/misc/testByteBuffer.cpp
testApp/misc/testByteOrder.cpp
testApp/misc/testMessageQueue.cpp
testApp/misc/testOverrunBitSet.cpp
testApp/misc/testQueue.cpp
testApp/misc/testSerialization.cpp
testApp/misc/testSharedVector.cpp
testApp/misc/testThread.cpp
testApp/misc/testTimer.cpp
testApp/misc/testTimeStamp.cpp
testApp/misc/testTypeCast.cpp
testApp/property/testProperty.cpp
testApp/pv/testBitSetUtil.cpp
testApp/pv/testConvert.cpp
testApp/pv/testFieldBuilder.cpp
testApp/pv/testIntrospect.cpp
testApp/pv/testOperators.cpp
testApp/pv/testPVData.cpp
testApp/pv/testPVScalarArray.cpp
testApp/pv/testPVStructureArray.cpp
testApp/pv/testPVType.cpp
testApp/pv/testPVUnion.cpp
testApp/pv/testStandardField.cpp
testApp/pv/testStandardPVField.cpp
testApp/pvDataAllTests.c
testApp/rtemsConfig.c
testApp/rtemsNetworking.h
testApp/rtemsTestHarness.c

View File

@@ -3,4 +3,9 @@
/home/msekoranja/epicsV4/pvDataCPP/pvDataApp/monitor
/home/msekoranja/epicsV4/pvDataCPP/pvDataApp/property
/home/msekoranja/epicsV4/pvDataCPP/pvDataApp/pv
/home/msekoranja/epicsV4/pvDataCPP/pvDataApp/pvMisc
/home/msekoranja/epicsV4/pvDataCPP/pvDataApp/pvMisc
testApp/pv
testApp/copy
testApp/misc
testApp
testApp/property

View File

@@ -14,10 +14,12 @@
#include <pv/createRequest.h>
using namespace epics::pvData;
using std::ostringstream;
using std::tr1::static_pointer_cast;
using std::cout;
using std::endl;
using std::string;
using std::vector;
namespace epics { namespace pvData {
@@ -27,6 +29,38 @@ static FieldCreatePtr fieldCreate = getFieldCreate();
class CreateRequestImpl : public CreateRequest {
private:
struct Node
{
string name;
vector<Node> nodes;
Node(string name)
: name(name)
{}
};
struct OptionPair
{
string name;
string value;
OptionPair(string name,string value)
: name(name),
value(value)
{}
};
vector<OptionPair> optionList;
string fullFieldName;
public:
CreateRequestImpl()
{
fullFieldName = "";
}
private:
void removeBlanks(string& str)
{
while(true) {
@@ -40,8 +74,8 @@ private:
size_t openBrace = request.find('{', index+1);
size_t closeBrace = request.find('}', index+1);
if(openBrace == string::npos && closeBrace == string::npos){
message = request + " missing }";
return string::npos;
message = request + " mismatched {}";
throw std::logic_error("message");
}
if (openBrace != string::npos && openBrace!=0) {
if(openBrace<closeBrace) return findMatchingBrace(request,openBrace,numOpen+1);
@@ -56,14 +90,14 @@ private:
for(size_t i=index+1; i< request.size(); ++i) {
if(request[i] == ']') {
if(i==index+1) {
message = request + " illegal []";
return string::npos;
message = request + " mismatched []";
throw std::logic_error("message");
}
return i;
}
}
message = request + " missing ]";
return string::npos;
message = request + " missing ]";
throw std::logic_error("message");
}
size_t findEndField(string& request) {
@@ -84,13 +118,17 @@ private:
ind = closeBrace;
continue;
}
if(request[ind]=='.') {
++ind;
continue;
}
if(ind>=maxind) break;
++ind;
}
return request.size();
}
std::vector<string> split(string const & commaSeparatedList) {
vector<string> split(string const & commaSeparatedList) {
string::size_type numValues = 1;
string::size_type index=0;
while(true) {
@@ -99,7 +137,7 @@ private:
numValues++;
index = pos +1;
}
std::vector<string> valueList(numValues,"");
vector<string> valueList(numValues,"");
index=0;
for(size_t i=0; i<numValues; i++) {
size_t pos = commaSeparatedList.find(',',index);
@@ -110,417 +148,329 @@ private:
return valueList;
}
StructureConstPtr createRequestOptions(
string request)
Node createRequestOptions(
string const & request)
{
if(request.length()<=1) return StructureConstPtr();
std::vector<string> items = split(request);
if(request.length()<=1) {
throw std::logic_error("logic error empty options");
}
vector<Node> top;
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;
message = item + " illegal option " + request;
throw std::logic_error("message");
}
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);
top.push_back(Node(item.substr(0,equals)));
string name = fullFieldName + "._options." + item.substr(0,equals);
string value = item.substr(equals+1);
PVStringPtr pvValue = pvParent->getSubField<PVString>(name);
pvValue->put(value);
optionList.push_back(OptionPair(name,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();
Node node("_options");
node.nodes = top;
return node;
}
StructureConstPtr createFieldRequest(
StructureConstPtr parent,
string request)
void createSubNode(Node &node,string const & crequest)
{
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]);
}
string request = crequest;
size_t end = 0;
for(size_t i=0; i<request.size(); ++i) {
if(request[i]=='[') { end = i; break;}
if(request[i]=='.') { end = i; break;}
if(request[i]=='{') { end = i; break;}
if(request[i]==',') { end = i; break;}
}
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;
char chr = request[end];
Node optionNode("");
if(chr=='[') {
string saveFullName = fullFieldName;
fullFieldName += "." + request.substr(0,end);
size_t endBracket = findMatchingBracket(request,end);
string options = request.substr(end+1,endBracket -end -1);
optionNode = createRequestOptions(options);
fullFieldName = saveFullName;
size_t next = endBracket+1;
if(next<request.size()) {
request = request.substr(0, end) + request.substr(endBracket+1);
} else {
request = request.substr(0, end);
}
end = 0;
for(size_t i=0; i<request.size(); ++i) {
if(request[i]=='.') { end = i; break;}
if(request[i]=='{') { end = i; break;}
if(request[i]==',') { end = i; break;}
}
chr = request[end];
}
// 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));
if(end==0) end = request.size();
string name = request.substr(0,end);
if(name.size()<1) {
throw std::logic_error("null field name " + request);
}
string saveFullName = fullFieldName;
fullFieldName += "." + name;
if(end==request.size()) {
Node subNode(name);
if(optionNode.name.size()>0) subNode.nodes.push_back(optionNode);
node.nodes.push_back(subNode);
fullFieldName = saveFullName;
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);
if(chr==',') {
Node subNode(name);
if(optionNode.name.size()>0) subNode.nodes.push_back(optionNode);
node.nodes.push_back(subNode);
string rest = request.substr(end+1);
fullFieldName = saveFullName;
createSubNode(node,rest);
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));
if(chr=='.') {
request = request.substr(end+1);
if(request.size()==string::npos || request.size()<1) {
throw std::logic_error("null field name " + request);
}
Node subNode(name);
if(optionNode.name.size()>0) subNode.nodes.push_back(optionNode);
size_t endField = findEndField(request);
string subRequest = request.substr(0, endField);
createSubNode(subNode,subRequest);
node.nodes.push_back(subNode);
size_t next = endField+1;
if(next>=request.size()) {
fullFieldName = saveFullName;
return;
}
request = request.substr(next);
fullFieldName = saveFullName;
createSubNode(node,request);
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);
if(chr=='{') {
size_t endBrace = findEndField(request);
if((end+1)>=(endBrace-1)) {
throw std::logic_error("illegal syntax " + request);
}
string subRequest = request.substr(end+1,endBrace-1 -end -1);
if(subRequest.size()<1) {
throw std::logic_error("empty {} " + request);
}
Node subNode(name);
if(optionNode.name.size()>0) subNode.nodes.push_back(optionNode);
createSubNode(subNode,subRequest);
node.nodes.push_back(subNode);
size_t next = endBrace + 1;
if(next>=request.size()) {
fullFieldName = saveFullName;
return;
}
request = request.substr(next);
fullFieldName = saveFullName;
createSubNode(node,request);
return;
}
throw std::logic_error("logic error");
}
void initFieldOptions(
PVStructurePtr const & pvParent,
string request)
FieldConstPtr createSubStructure(vector<Node> & nodes)
{
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;
size_t num = nodes.size();
StringArray names(num);
FieldConstPtrArray fields(num);
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;
Node node = nodes[i];
names[i] = node.name;
if(node.name.compare("_options")==0) {
fields[i] = createOptions(node.nodes);
} else {
vector<Node> subNode = node.nodes;
if(subNode.empty()) {
fields[i] = fieldCreate->createStructure();
} else {
fields[i] = createSubStructure(subNode);
}
}
}
StructureConstPtr structure = fieldCreate->createStructure(
names, fields);
return structure;
}
StructureConstPtr createOptions(vector<Node> &nodes)
{
size_t num = nodes.size();
StringArray names(num);
FieldConstPtrArray fields(num);
for(size_t i=0; i<num; ++i) {
Node node = nodes[i];
names[i] = node.name;
fields[i] = fieldCreate->createScalar(pvString);
}
StructureConstPtr structure = fieldCreate->createStructure(names, fields);
return structure;
}
public:
virtual PVStructure::shared_pointer createRequest(
virtual PVStructurePtr 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)
try {
string request = crequest;
if (!request.empty()) removeBlanks(request);
if (request.empty())
{
return PVStructurePtr();
return pvDataCreate->createPVStructure(fieldCreate->createStructure());
}
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)
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(" + request + ")";
offsetField = request.find("field(");
}
int numParan = 0;
int numBrace = 0;
int numBracket = 0;
for(size_t i=0; i< request.length() ; ++i) {
char chr = request[i];
if(chr=='(') numParan++;
if(chr==')') numParan--;
if(chr=='{') numBrace++;
if(chr=='}') numBrace--;
if(chr=='[') numBracket++;
if(chr==']') numBracket--;
}
if(numParan!=0) {
ostringstream oss;
oss << "mismatched () " << numParan;
message = oss.str();
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 )";
if(numBrace!=0) {
ostringstream oss;
oss << "mismatched {} " << numBrace;
message = oss.str();
return PVStructurePtr();
}
StructureConstPtr structure = fieldCreate->createStructure();
structure = createFieldRequest(structure,request.substr(openBrace+1,closeBrace-openBrace-1));
if(structure==NULL)
{
if(numBracket!=0) {
ostringstream oss;
oss << "mismatched [] " << numBracket;
message = oss.str();
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 )";
vector<Node> top;
try {
if(offsetRecord!=string::npos) {
fullFieldName = "record";
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();
}
if(closeBracket-openBracket > 3) {
Node node("record");
Node optNode = createRequestOptions(
request.substr(openBracket+1,closeBracket-openBracket-1));
node.nodes.push_back(optNode);
top.push_back(node);
}
}
if(offsetField!=string::npos) {
fullFieldName = "field";
Node node("field");
size_t openParan = request.find('(', offsetField);
size_t closeParan = request.find(')', openParan);
if(closeParan==string::npos) {
message = request.substr(offsetField)
+ " field( does not have matching )";
return PVStructurePtr();
}
if(closeParan>openParan+1) {
createSubNode(node,request.substr(openParan+1,closeParan-openParan-1));
}
top.push_back(node);
}
if(offsetGetField!=string::npos) {
fullFieldName = "getField";
Node node("getField");
size_t openParan = request.find('(', offsetGetField);
size_t closeParan = request.find(')', openParan);
if(closeParan==string::npos) {
message = request.substr(offsetField)
+ " getField( does not have matching )";
return PVStructurePtr();
}
if(closeParan>openParan+1) {
createSubNode(node,request.substr(openParan+1,closeParan-openParan-1));
}
top.push_back(node);
}
if(offsetPutField!=string::npos) {
fullFieldName = "putField";
Node node("putField");
size_t openParan = request.find('(', offsetPutField);
size_t closeParan = request.find(')', openParan);
if(closeParan==string::npos) {
message = request.substr(offsetField)
+ " putField( does not have matching )";
return PVStructurePtr();
}
if(closeParan>openParan+1) {
createSubNode(node,request.substr(openParan+1,closeParan-openParan-1));
}
top.push_back(node);
}
} catch (std::exception &e) {
string xxx = e.what();
message = "while creating Structure exception " + xxx;
return PVStructurePtr();
}
StructureConstPtr structure = fieldCreate->createStructure();
structure = createFieldRequest(structure,request.substr(openBrace+1,closeBrace-openBrace-1));
if(structure==NULL)
{
return PVStructurePtr();
size_t num = top.size();
StringArray names(num);
FieldConstPtrArray fields(num);
for(size_t i=0; i<num; ++i) {
Node node = top[i];
names[i] = node.name;
vector<Node> subNode = node.nodes;
if(subNode.empty()) {
fields[i] = fieldCreate->createStructure();
} else {
fields[i] = createSubStructure(subNode);
}
}
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]);
StructureConstPtr structure = fieldCreate->createStructure(names, fields);
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(structure);
for(size_t i=0; i<optionList.size(); ++i) {
OptionPair pair = optionList[i];
string name = pair.name;
string value = pair.value;
PVStringPtr pvField = pvStructure->getSubField<PVString>(name);
pvField->put(value);
}
if(pvSub!=NULL) initFieldOptions(pvSub,request.substr(openParam+1,closeParam-openParam-1));
optionList.clear();
return pvStructure;
} catch (std::exception &e) {
message = e.what();
return PVStructurePtr();
}
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()

View File

@@ -68,9 +68,9 @@ PVCopyPtr PVCopy::create(
if(structureName.size()>0) {
if(pvRequest->getStructure()->getNumberFields()>0) {
pvStructure = pvRequest->getStructureField(structureName);
if(pvStructure.get()==NULL) return NULLPVCopy;
if(!pvStructure) return NULLPVCopy;
}
} else if(pvStructure->getSubField("field")!=NULL) {
} else if(pvStructure->getSubField("field")) {
pvStructure = pvRequest->getStructureField("field");
}
PVCopyPtr pvCopy = PVCopyPtr(new PVCopy(pvMaster));
@@ -118,7 +118,7 @@ StructureConstPtr PVCopy::getStructure()
PVStructurePtr PVCopy::createPVStructure()
{
if(cacheInitStructure.get()!=NULL) {
if(cacheInitStructure) {
PVStructurePtr save = cacheInitStructure;
cacheInitStructure.reset();
return save;
@@ -174,7 +174,7 @@ size_t PVCopy::getCopyOffset(PVFieldPtr const &masterPVField)
}
CopyStructureNodePtr node = static_pointer_cast<CopyStructureNode>(headNode);
CopyMasterNodePtr masterNode = getCopyOffset(node,masterPVField);
if(masterNode.get()!=NULL) return masterNode->structureOffset;
if(masterNode) return masterNode->structureOffset;
return string::npos;
}
@@ -190,7 +190,7 @@ size_t PVCopy::getCopyOffset(
CopyStructureNodePtr node = static_pointer_cast<CopyStructureNode>(headNode);
masterNode = getCopyOffset(node,masterPVField);
}
if(masterNode.get()==NULL) return string::npos;
if(!masterNode) return string::npos;
size_t diff = masterPVField->getFieldOffset()
- masterPVStructure->getFieldOffset();
return masterNode->structureOffset + diff;
@@ -205,7 +205,7 @@ PVFieldPtr PVCopy::getMasterPVField(size_t structureOffset)
CopyStructureNodePtr node = static_pointer_cast<CopyStructureNode>(headNode);
masterNode = getMasterNode(node,structureOffset);
}
if(masterNode.get()==NULL) {
if(!masterNode) {
throw std::invalid_argument(
"PVCopy::getMasterPVField: setstructureOffset not valid");
}
@@ -299,7 +299,7 @@ void PVCopy::dump(string *builder,CopyNodePtr const &node,int indentLevel)
ss << " nfields " << node->nfields;
*builder += ss.str();
PVStructurePtr options = node->options;
if(options.get()!=NULL) {
if(options) {
getConvert()->newLine(builder,indentLevel +1);
// TODO !!! ugly
@@ -338,7 +338,7 @@ bool PVCopy::init(epics::pvData::PVStructurePtr const &pvRequest)
if(len==string::npos) entireMaster = true;
if(len==0) entireMaster = true;
PVStructurePtr pvOptions;
if(len==1 && pvRequest->getSubField("_options")!=NULL) {
if(len==1 && pvRequest->getSubField("_options")) {
pvOptions = pvRequest->getStructureField("_options");
}
if(entireMaster) {
@@ -353,7 +353,7 @@ bool PVCopy::init(epics::pvData::PVStructurePtr const &pvRequest)
return true;
}
structure = createStructure(pvMasterStructure,pvRequest);
if(structure==NULL) return false;
if(!structure) return false;
cacheInitStructure = createPVStructure();
headNode = createStructureNodes(
pvMaster,
@@ -387,7 +387,7 @@ StructureConstPtr PVCopy::createStructure(
for(size_t i=0; i<length; ++i) {
string const &fieldName = fromRequestFieldNames[i];
PVFieldPtr pvMasterField = pvMaster->getSubField(fieldName);
if(pvMasterField==NULL) continue;
if(!pvMasterField) continue;
FieldConstPtr field = pvMasterField->getField();
if(field->getType()==epics::pvData::structure) {
PVStructurePtr pvRequestStructure = static_pointer_cast<PVStructure>(
@@ -423,7 +423,7 @@ CopyNodePtr PVCopy::createStructureNodes(
PVFieldPtrArray const & copyPVFields = pvFromCopy->getPVFields();
PVStructurePtr pvOptions;
PVFieldPtr pvField = pvFromRequest->getSubField("_options");
if(pvField!=NULL) pvOptions = static_pointer_cast<PVStructure>(pvField);
if(pvField) pvOptions = static_pointer_cast<PVStructure>(pvField);
size_t number = copyPVFields.size();
CopyNodePtrArrayPtr nodes(new CopyNodePtrArray());
nodes->reserve(number);
@@ -435,7 +435,7 @@ CopyNodePtr PVCopy::createStructureNodes(
pvFromRequest->getSubField(fieldName));
PVStructurePtr pvSubFieldOptions;
PVFieldPtr pvField = requestPVStructure->getSubField("_options");
if(pvField!=NULL) pvSubFieldOptions = static_pointer_cast<PVStructure>(pvField);
if(pvField) pvSubFieldOptions = static_pointer_cast<PVStructure>(pvField);
PVFieldPtr pvMasterField;
PVFieldPtrArray const & pvMasterFields = pvMasterStructure->getPVFields();
for(size_t j=0; i<pvMasterFields.size(); j++ ) {
@@ -445,7 +445,7 @@ CopyNodePtr PVCopy::createStructureNodes(
}
}
size_t numberRequest = requestPVStructure->getPVFields().size();
if(pvSubFieldOptions!=NULL) numberRequest--;
if(pvSubFieldOptions) numberRequest--;
if(numberRequest>0) {
nodes->push_back(createStructureNodes(
static_pointer_cast<PVStructure>(pvMasterField),
@@ -621,7 +621,7 @@ CopyMasterNodePtr PVCopy::getCopyOffset(
static_pointer_cast<CopyStructureNode>(node);
CopyMasterNodePtr masterNode =
getCopyOffset(subNode,masterPVField);
if(masterNode.get()!=NULL) return masterNode;
if(masterNode) return masterNode;
}
}
return NULLCopyMasterNode;

View File

@@ -134,6 +134,13 @@ bool operator==(const UnionArray& a, const UnionArray& b)
return *(a.getUnion().get())==*(b.getUnion().get());
}
bool operator==(const BoundedString& a, const BoundedString& b)
{
if(&a==&b)
return true;
return a.getMaximumLength()==b.getMaximumLength();
}
// PVXXX object comparison
namespace {
@@ -244,7 +251,13 @@ bool compareField(const PVStructureArray* left, const PVStructureArray* right)
lit!=lend;
++lit, ++rit)
{
if(**lit != **rit)
// element can be null
if (!(*lit) || !(*rit))
{
if (*lit || *rit)
return false;
}
else if (**lit != **rit)
return false;
}
return true;
@@ -297,7 +310,13 @@ bool compareField(const PVUnionArray* left, const PVUnionArray* right)
lit!=lend;
++lit, ++rit)
{
if(**lit != **rit)
// element can be null
if (!(*lit) || !(*rit))
{
if (*lit || *rit)
return false;
}
else if (**lit != **rit)
return false;
}
return true;

View File

@@ -18,7 +18,6 @@
#include <pv/pvIntrospect.h>
#include <pv/pvData.h>
#include <pv/convert.h>
#include <pv/printer.h>
using std::tr1::static_pointer_cast;
using std::size_t;
@@ -51,7 +50,8 @@ void Convert::getString(string *buf,PVField const *pvField,int /*indentLevel*/)
{
// TODO indextLevel ignored
std::ostringstream strm;
strm << pvField->dumpValue(strm) << std::endl;
pvField->dumpValue(strm);
strm << std::endl;
// PrinterPlain p;
// p.setStream(strm);
// p.print(*pvField);
@@ -462,17 +462,14 @@ void Convert::copyUnion(PVUnionPtr const & from, PVUnionPtr const & to)
PVFieldPtr fromValue = from->get();
if (from->getUnion()->isVariant())
{
if (fromValue.get() == 0)
to->set(PVFieldPtr());
else
to->set(getPVDataCreate()->createPVField(fromValue)); // clone value // TODO cache getPVDataCreate()
to->set(from->get());
}
else
{
if (fromValue.get() == 0)
to->select(PVUnion::UNDEFINED_INDEX);
else
to->set(from->getSelectedFieldName(),from->get());
to->set(from->getSelectedIndex(),from->get());
}
}

View File

@@ -17,6 +17,7 @@
#include <string>
#include <cstdio>
#include <stdexcept>
#include <sstream>
#define epicsExportSharedSymbols
#include <pv/lock.h>
@@ -80,7 +81,7 @@ string Scalar::getID() const
return idScalarLUT[scalarType];
}
int8 Scalar::getTypeCodeLUT() const
int8 Scalar::getTypeCodeLUT(ScalarType scalarType)
{
static const int8 typeCodeLUT[] = {
0x00, // pvBoolean
@@ -88,10 +89,10 @@ int8 Scalar::getTypeCodeLUT() const
0x21, // pvShort
0x22, // pvInt
0x23, // pvLong
0x28, // pvUByte
0x29, // pvUShort
0x2A, // pvUInt
0x2B, // pvULong
0x24, // pvUByte
0x25, // pvUShort
0x26, // pvUInt
0x27, // pvULong
0x42, // pvFloat
0x43, // pvDouble
0x60 // pvString
@@ -102,7 +103,7 @@ int8 Scalar::getTypeCodeLUT() const
void Scalar::serialize(ByteBuffer *buffer, SerializableControl *control) const {
control->ensureBuffer(1);
buffer->putByte(getTypeCodeLUT());
buffer->putByte(getTypeCodeLUT(scalarType));
}
void Scalar::deserialize(ByteBuffer* /*buffer*/, DeserializableControl* /*control*/) {
@@ -110,6 +111,38 @@ void Scalar::deserialize(ByteBuffer* /*buffer*/, DeserializableControl* /*contro
throw std::runtime_error("not valid operation, use FieldCreate::deserialize instead");
}
std::string BoundedString::getID() const
{
std::ostringstream id;
id << Scalar::getID() << '(' << maxLength << ')';
return id.str();
}
void BoundedString::serialize(ByteBuffer *buffer, SerializableControl *control) const
{
control->ensureBuffer(1);
buffer->putByte(0x83);
SerializeHelper::writeSize(maxLength, buffer, control);
}
std::size_t BoundedString::getMaximumLength() const
{
return maxLength;
}
BoundedString::BoundedString(std::size_t maxStringLength) :
Scalar(pvString), maxLength(maxStringLength)
{
if (maxLength == 0)
throw std::invalid_argument("maxLength == 0");
}
BoundedString::~BoundedString() {}
static string emptyStringtring;
static void serializeStructureField(const Structure* structure, ByteBuffer* buffer, SerializableControl* control)
@@ -198,7 +231,8 @@ Array::Array(Type type)
Array::~Array() {}
ScalarArray::ScalarArray(ScalarType elementType)
: Array(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");
@@ -206,31 +240,12 @@ ScalarArray::ScalarArray(ScalarType elementType)
ScalarArray::~ScalarArray() {}
int8 ScalarArray::getTypeCodeLUT() const
{
static const int8 typeCodeLUT[] = {
0x00, // pvBoolean
0x20, // pvByte
0x21, // pvShort
0x22, // pvInt
0x23, // pvLong
0x28, // pvUByte
0x29, // pvUShort
0x2A, // pvUInt
0x2B, // pvULong
0x42, // pvFloat
0x43, // pvDouble
0x60 // pvString
};
return typeCodeLUT[elementType];
}
const string ScalarArray::getIDScalarArrayLUT() const
{
static const string idScalarArrayLUT[] = {
"boolean[]", // pvBoolean
"byte[]", // pvByte
"short[]", // pvShort
"boolean[]", // pvBoolean
"byte[]", // pvByte
"short[]", // pvShort
"int[]", // pvInt
"long[]", // pvLong
"ubyte[]", // pvUByte
@@ -256,13 +271,59 @@ std::ostream& ScalarArray::dump(std::ostream& o) const
void ScalarArray::serialize(ByteBuffer *buffer, SerializableControl *control) const {
control->ensureBuffer(1);
buffer->putByte((int8)0x10 | getTypeCodeLUT());
buffer->putByte((int8)0x08 | Scalar::getTypeCodeLUT(elementType));
}
void ScalarArray::deserialize(ByteBuffer* /*buffer*/, DeserializableControl* /*control*/) {
throw std::runtime_error("not valid operation, use FieldCreate::deserialize instead");
}
BoundedScalarArray::~BoundedScalarArray() {}
BoundedScalarArray::BoundedScalarArray(ScalarType elementType, size_t size)
: ScalarArray(elementType),
size(size)
{
}
string BoundedScalarArray::getID() const
{
char buffer[32];
sprintf(buffer, "%s<%zu>", ScalarTypeFunc::name(getElementType()), size);
return string(buffer);
}
void BoundedScalarArray::serialize(ByteBuffer *buffer, SerializableControl *control) const {
control->ensureBuffer(1);
buffer->putByte((int8)0x10 | Scalar::getTypeCodeLUT(getElementType()));
SerializeHelper::writeSize(size, buffer, control);
}
FixedScalarArray::~FixedScalarArray() {}
FixedScalarArray::FixedScalarArray(ScalarType elementType, size_t size)
: ScalarArray(elementType),
size(size)
{
}
string FixedScalarArray::getID() const
{
char buffer[32];
sprintf(buffer, "%s[%zu]", ScalarTypeFunc::name(getElementType()), size);
return string(buffer);
}
void FixedScalarArray::serialize(ByteBuffer *buffer, SerializableControl *control) const {
control->ensureBuffer(1);
buffer->putByte((int8)0x18 | Scalar::getTypeCodeLUT(getElementType()));
SerializeHelper::writeSize(size, buffer, control);
}
StructureArray::StructureArray(StructureConstPtr const & structure)
: Array(structureArray),pstructure(structure)
{
@@ -289,7 +350,7 @@ std::ostream& StructureArray::dump(std::ostream& o) const
void StructureArray::serialize(ByteBuffer *buffer, SerializableControl *control) const {
control->ensureBuffer(1);
buffer->putByte((int8)0x90);
buffer->putByte((int8)0x88);
control->cachedSerialize(pstructure, buffer);
}
@@ -326,11 +387,11 @@ void UnionArray::serialize(ByteBuffer *buffer, SerializableControl *control) con
if (punion->isVariant())
{
// unrestricted/variant union
buffer->putByte((int8)0x92);
buffer->putByte((int8)0x8A);
}
else
{
buffer->putByte((int8)0x91);
buffer->putByte((int8)0x89);
control->cachedSerialize(punion, buffer);
}
}
@@ -552,7 +613,7 @@ size_t Union::getFieldIndex(string const &fieldName) const {
std::ostream& Union::dump(std::ostream& o) const
{
o << getID() << std::endl;
o << format::indent() << getID() << std::endl;
{
format::indent_scope s(o);
dumpFields(o);
@@ -655,6 +716,12 @@ FieldBuilderPtr FieldBuilder::add(string const & name, ScalarType scalarType)
return shared_from_this();
}
FieldBuilderPtr FieldBuilder::addBoundedString(std::string const & name, std::size_t maxLength)
{
fields.push_back(fieldCreate->createBoundedString(maxLength)); fieldNames.push_back(name);
return shared_from_this();
}
FieldBuilderPtr FieldBuilder::add(string const & name, FieldConstPtr const & field)
{
fields.push_back(field); fieldNames.push_back(name);
@@ -667,6 +734,18 @@ FieldBuilderPtr FieldBuilder::addArray(string const & name, ScalarType scalarTyp
return shared_from_this();
}
FieldBuilderPtr FieldBuilder::addFixedArray(string const & name, ScalarType scalarType, size_t size)
{
fields.push_back(fieldCreate->createFixedScalarArray(scalarType, size)); fieldNames.push_back(name);
return shared_from_this();
}
FieldBuilderPtr FieldBuilder::addBoundedArray(string const & name, ScalarType scalarType, size_t size)
{
fields.push_back(fieldCreate->createBoundedScalarArray(scalarType, size)); fieldNames.push_back(name);
return shared_from_this();
}
FieldBuilderPtr FieldBuilder::addArray(string const & name, FieldConstPtr const & element)
{
switch (element->getType())
@@ -678,10 +757,17 @@ FieldBuilderPtr FieldBuilder::addArray(string const & name, FieldConstPtr const
fields.push_back(fieldCreate->createUnionArray(static_pointer_cast<const Union>(element)));
break;
case scalar:
if (std::tr1::dynamic_pointer_cast<const BoundedString>(element).get())
throw std::invalid_argument("bounded string arrays are not supported");
fields.push_back(fieldCreate->createScalarArray(static_pointer_cast<const Scalar>(element)->getScalarType()));
break;
// scalarArray?
default:
throw std::invalid_argument("unsupported array element type:" + element->getType());
std::ostringstream msg("unsupported array element type: ");
msg << element->getType();
throw std::invalid_argument(msg.str());
}
fieldNames.push_back(name);
@@ -707,7 +793,11 @@ FieldConstPtr FieldBuilder::createFieldInternal(Type type)
fieldCreate->createUnion(fieldNames, fields);
}
else
throw std::invalid_argument("unsupported type: " + type);
{
std::ostringstream msg("unsupported type: ");
msg << type;
throw std::invalid_argument(msg.str());
}
}
@@ -780,7 +870,15 @@ ScalarConstPtr FieldCreate::createScalar(ScalarType scalarType) const
return scalars[scalarType];
}
BoundedStringConstPtr FieldCreate::createBoundedString(std::size_t maxLength) const
{
// TODO use std::make_shared
std::tr1::shared_ptr<BoundedString> s(new BoundedString(maxLength), Field::Deleter());
BoundedStringConstPtr sa = s;
return sa;
}
ScalarArrayConstPtr FieldCreate::createScalarArray(ScalarType elementType) const
{
if(elementType<0 || elementType>MAX_SCALAR_TYPE)
@@ -789,6 +887,28 @@ ScalarArrayConstPtr FieldCreate::createScalarArray(ScalarType elementType) const
return scalarArrays[elementType];
}
ScalarArrayConstPtr FieldCreate::createFixedScalarArray(ScalarType elementType, size_t size) const
{
if(elementType<0 || elementType>MAX_SCALAR_TYPE)
throw std::invalid_argument("Can't construct ScalarArray from invalid ScalarType");
// TODO use std::make_shared
std::tr1::shared_ptr<ScalarArray> s(new FixedScalarArray(elementType, size), Field::Deleter());
ScalarArrayConstPtr sa = s;
return sa;
}
ScalarArrayConstPtr FieldCreate::createBoundedScalarArray(ScalarType elementType, size_t size) const
{
if(elementType<0 || elementType>MAX_SCALAR_TYPE)
throw std::invalid_argument("Can't construct ScalarArray from invalid ScalarType");
// TODO use std::make_shared
std::tr1::shared_ptr<ScalarArray> s(new BoundedScalarArray(elementType, size), Field::Deleter());
ScalarArrayConstPtr sa = s;
return sa;
}
StructureConstPtr FieldCreate::createStructure () const
{
StringArray fieldNames;
@@ -799,8 +919,9 @@ StructureConstPtr FieldCreate::createStructure () const
StructureConstPtr FieldCreate::createStructure (
StringArray const & fieldNames,FieldConstPtrArray const & fields) const
{
StructureConstPtr structure(
new Structure(fieldNames,fields), Field::Deleter());
// TODO use std::make_shared
std::tr1::shared_ptr<Structure> sp(new Structure(fieldNames,fields), Field::Deleter());
StructureConstPtr structure = sp;
return structure;
}
@@ -809,24 +930,27 @@ StructureConstPtr FieldCreate::createStructure (
StringArray const & fieldNames,
FieldConstPtrArray const & fields) const
{
StructureConstPtr structure(
new Structure(fieldNames,fields,id), Field::Deleter());
// TODO use std::make_shared
std::tr1::shared_ptr<Structure> sp(new Structure(fieldNames,fields,id), Field::Deleter());
StructureConstPtr structure = sp;
return structure;
}
StructureArrayConstPtr FieldCreate::createStructureArray(
StructureConstPtr const & structure) const
{
StructureArrayConstPtr structureArray(
new StructureArray(structure), Field::Deleter());
// TODO use std::make_shared
std::tr1::shared_ptr<StructureArray> sp(new StructureArray(structure), Field::Deleter());
StructureArrayConstPtr structureArray = sp;
return structureArray;
}
UnionConstPtr FieldCreate::createUnion (
StringArray const & fieldNames,FieldConstPtrArray const & fields) const
{
UnionConstPtr punion(
new Union(fieldNames,fields), Field::Deleter());
// TODO use std::make_shared
std::tr1::shared_ptr<Union> sp(new Union(fieldNames,fields), Field::Deleter());
UnionConstPtr punion = sp;
return punion;
}
@@ -835,8 +959,9 @@ UnionConstPtr FieldCreate::createUnion (
StringArray const & fieldNames,
FieldConstPtrArray const & fields) const
{
UnionConstPtr punion(
new Union(fieldNames,fields,id), Field::Deleter());
// TODO use std::make_shared
std::tr1::shared_ptr<Union> sp(new Union(fieldNames,fields,id), Field::Deleter());
UnionConstPtr punion = sp;
return punion;
}
@@ -848,8 +973,9 @@ UnionConstPtr FieldCreate::createVariantUnion () const
UnionArrayConstPtr FieldCreate::createUnionArray(
UnionConstPtr const & punion) const
{
UnionArrayConstPtr unionArray(
new UnionArray(punion), Field::Deleter());
// TODO use std::make_shared
std::tr1::shared_ptr<UnionArray> sp(new UnionArray(punion), Field::Deleter());
UnionArrayConstPtr unionArray = sp;
return unionArray;
}
@@ -904,22 +1030,14 @@ static int decodeScalar(int8 code)
{
static const int integerLUT[] =
{
pvByte, // 8-bits
pvShort, // 16-bits
pvInt, // 32-bits
pvLong, // 64-bits
-1,
-1,
-1,
-1,
pvByte, // 8-bits
pvShort, // 16-bits
pvInt, // 32-bits
pvLong, // 64-bits
pvUByte, // unsigned 8-bits
pvUShort, // unsigned 16-bits
pvUInt, // unsigned 32-bits
pvULong, // unsigned 64-bits
-1,
-1,
-1,
-1
pvULong // unsigned 64-bits
};
static const int floatLUT[] =
@@ -931,22 +1049,14 @@ static int decodeScalar(int8 code)
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1
};
// bits 7-5
switch (code >> 5)
{
case 0: return pvBoolean;
case 1: return integerLUT[code & 0x0F];
case 2: return floatLUT[code & 0x0F];
case 1: return integerLUT[code & 0x07];
case 2: return floatLUT[code & 0x07];
case 3: return pvString;
default: return -1;
}
@@ -959,8 +1069,9 @@ FieldConstPtr FieldCreate::deserialize(ByteBuffer* buffer, DeserializableControl
if (code == -1)
return FieldConstPtr();
int typeCode = code & 0xEF;
bool notArray = ((code & 0x10) == 0);
int typeCode = code & 0xE7;
int scalarOrArray = code & 0x18;
bool notArray = (scalarOrArray == 0);
if (notArray)
{
if (typeCode < 0x80)
@@ -986,33 +1097,90 @@ FieldConstPtr FieldCreate::deserialize(ByteBuffer* buffer, DeserializableControl
// Type type = Type.union; variant union (aka any type)
return variantUnion;
}
else if (typeCode == 0x83)
{
// TODO cache?
// bounded string
size_t size = SerializeHelper::readSize(buffer, control);
// TODO use std::make_shared
std::tr1::shared_ptr<Field> sp(
new BoundedString(size),
Field::Deleter());
FieldConstPtr p = sp;
return p;
}
else
throw std::invalid_argument("invalid type encoding");
}
else // array
{
bool isVariable = (scalarOrArray == 0x08);
// bounded == 0x10;
bool isFixed = (scalarOrArray == 0x18);
size_t size = (isVariable ? 0 : SerializeHelper::readSize(buffer, control));
if (typeCode < 0x80)
{
// Type type = Type.scalarArray;
int scalarType = decodeScalar(code);
if (scalarType == -1)
throw std::invalid_argument("invalid scalarArray type encoding");
return scalarArrays[scalarType];
if (isVariable)
return scalarArrays[scalarType];
else if (isFixed)
{
// TODO use std::make_shared
std::tr1::shared_ptr<Field> sp(
new FixedScalarArray(static_cast<epics::pvData::ScalarType>(scalarType), size),
Field::Deleter());
FieldConstPtr p = sp;
return p;
}
else
{
// TODO use std::make_shared
std::tr1::shared_ptr<Field> sp(
new BoundedScalarArray(static_cast<epics::pvData::ScalarType>(scalarType), size),
Field::Deleter());
FieldConstPtr p = sp;
return p;
}
}
else if (typeCode == 0x80)
{
// TODO fixed and bounded array support
if (!isVariable)
throw std::invalid_argument("fixed and bounded structure array not supported");
// Type type = Type.structureArray;
StructureConstPtr elementStructure = std::tr1::static_pointer_cast<const Structure>(control->cachedDeserialize(buffer));
return FieldConstPtr(new StructureArray(elementStructure), Field::Deleter());
// TODO use std::make_shared
std::tr1::shared_ptr<Field> sp(new StructureArray(elementStructure), Field::Deleter());
FieldConstPtr p = sp;
return p;
}
else if (typeCode == 0x81)
{
// TODO fixed and bounded array support
if (!isVariable)
throw std::invalid_argument("fixed and bounded structure array not supported");
// Type type = Type.unionArray;
UnionConstPtr elementUnion = std::tr1::static_pointer_cast<const Union>(control->cachedDeserialize(buffer));
return FieldConstPtr(new UnionArray(elementUnion), Field::Deleter());
// TODO use std::make_shared
std::tr1::shared_ptr<Field> sp(new UnionArray(elementUnion), Field::Deleter());
FieldConstPtr p = sp;
return p;
}
else if (typeCode == 0x82)
{
// TODO fixed and bounded array support
if (!isVariable)
throw std::invalid_argument("fixed and bounded structure array not supported");
// Type type = Type.unionArray; variant union (aka any type)
return variantUnionArray;
}
@@ -1037,11 +1205,24 @@ FieldCreate::FieldCreate()
{
for (int i = 0; i <= MAX_SCALAR_TYPE; i++)
{
scalars.push_back(ScalarConstPtr(new Scalar(static_cast<ScalarType>(i)), Field::Deleter()));
scalarArrays.push_back(ScalarArrayConstPtr(new ScalarArray(static_cast<ScalarType>(i)), Field::Deleter()));
// TODO use std::make_shared
std::tr1::shared_ptr<Scalar> sp(new Scalar(static_cast<ScalarType>(i)), Field::Deleter());
ScalarConstPtr p = sp;
scalars.push_back(p);
// TODO use std::make_shared
std::tr1::shared_ptr<ScalarArray> spa(new ScalarArray(static_cast<ScalarType>(i)), Field::Deleter());
ScalarArrayConstPtr pa = spa;
scalarArrays.push_back(spa);
}
variantUnion = UnionConstPtr(new Union(), Field::Deleter());
variantUnionArray = UnionArrayConstPtr(new UnionArray(variantUnion), Field::Deleter());
// TODO use std::make_shared
std::tr1::shared_ptr<Union> su(new Union(), Field::Deleter());
variantUnion = su;
// TODO use std::make_shared
std::tr1::shared_ptr<UnionArray> sua(new UnionArray(variantUnion), Field::Deleter());
variantUnionArray = sua;
}
FieldCreatePtr getFieldCreate() {

View File

@@ -145,11 +145,18 @@ public:
SerializableControl *pflusher, size_t offset, size_t count) const;
private:
string value;
std::size_t maxLength;
};
BasePVString::BasePVString(ScalarConstPtr const & scalar)
: PVString(scalar),value()
{}
{
BoundedStringConstPtr boundedString = std::tr1::dynamic_pointer_cast<const BoundedString>(scalar);
if (boundedString.get())
maxLength = boundedString->getMaximumLength();
else
maxLength = 0;
}
BasePVString::~BasePVString() {}
@@ -157,6 +164,9 @@ string BasePVString::get() const { return value;}
void BasePVString::put(string val)
{
if (maxLength > 0 && val.length() > maxLength)
throw std::overflow_error("string too long");
value = val;
postPut();
}
@@ -190,6 +200,19 @@ void BasePVString::serialize(ByteBuffer *pbuffer,
SerializeHelper::serializeSubstring(value, offset, count, pbuffer, pflusher);
}
void PVArray::checkLength(size_t len)
{
Array::ArraySizeType type = getArray()->getArraySizeType();
if (type != Array::variable)
{
size_t size = getArray()->getMaximumCapacity();
if (type == Array::fixed && len != size)
throw std::invalid_argument("invalid length for a fixed size array");
else if (type == Array::bounded && len > size)
throw std::invalid_argument("new array capacity too large for a bounded size array");
}
}
/** Default storage for arrays
*/
template<typename T>
@@ -231,7 +254,14 @@ DefaultPVArray<T>::DefaultPVArray(ScalarArrayConstPtr const & scalarArray)
: PVValueArray<T>(scalarArray),
value()
{ }
{
ArrayConstPtr array = this->getArray();
if (array->getArraySizeType() == Array::fixed)
{
// this->setLength(array->getMaximumCapacity());
this->setCapacityMutable(false);
}
}
template<typename T>
DefaultPVArray<T>::~DefaultPVArray()
@@ -240,18 +270,25 @@ template<typename T>
void DefaultPVArray<T>::setCapacity(size_t capacity)
{
if(this->isCapacityMutable()) {
this->checkLength(capacity);
value.reserve(capacity);
}
else
THROW_EXCEPTION2(std::logic_error, "capacity immutable");
}
template<typename T>
void DefaultPVArray<T>::setLength(size_t length)
{
if(this->isImmutable())
THROW_EXCEPTION2(std::logic_error,"Immutable");
if(length == value.size())
THROW_EXCEPTION2(std::logic_error, "immutable");
if (length == value.size())
return;
else if(length < value.size())
this->checkLength(length);
if (length < value.size())
value.slice(0, length);
else
value.resize(length);
@@ -260,6 +297,8 @@ void DefaultPVArray<T>::setLength(size_t length)
template<typename T>
void DefaultPVArray<T>::replace(const const_svector& next)
{
this->checkLength(next.size());
value = next;
this->postPut();
}
@@ -267,8 +306,10 @@ void DefaultPVArray<T>::replace(const const_svector& next)
template<typename T>
void DefaultPVArray<T>::swap(const_svector &other)
{
if(this->isImmutable())
THROW_EXCEPTION2(std::logic_error,"Immutable");
if (this->isImmutable())
THROW_EXCEPTION2(std::logic_error, "immutable");
// no checkLength call here
value.swap(other);
}
@@ -283,7 +324,10 @@ void DefaultPVArray<T>::serialize(ByteBuffer *pbuffer,
template<typename T>
void DefaultPVArray<T>::deserialize(ByteBuffer *pbuffer,
DeserializableControl *pcontrol) {
size_t size = SerializeHelper::readSize(pbuffer, pcontrol);
size_t size = this->getArray()->getArraySizeType() == Array::fixed ?
this->getArray()->getMaximumCapacity() :
SerializeHelper::readSize(pbuffer, pcontrol);
svector nextvalue(thaw(value));
nextvalue.resize(size); // TODO: avoid copy of stuff we will then overwrite
@@ -321,6 +365,7 @@ void DefaultPVArray<T>::deserialize(ByteBuffer *pbuffer,
remaining -= n2read;
}
value = freeze(nextvalue);
// TODO !!!
// inform about the change?
PVField::postPut();
}
@@ -334,7 +379,11 @@ void DefaultPVArray<T>::serialize(ByteBuffer *pbuffer,
temp.slice(offset, count);
count = temp.size();
SerializeHelper::writeSize(temp.size(), pbuffer, pflusher);
ArrayConstPtr array = this->getArray();
if (array->getArraySizeType() != Array::fixed)
SerializeHelper::writeSize(count, pbuffer, pflusher);
else if (count != array->getMaximumCapacity())
throw std::length_error("fixed array cannot be partially serialized");
const T* cur = temp.data();
@@ -368,7 +417,10 @@ void DefaultPVArray<T>::serialize(ByteBuffer *pbuffer,
template<>
void DefaultPVArray<string>::deserialize(ByteBuffer *pbuffer,
DeserializableControl *pcontrol) {
size_t size = SerializeHelper::readSize(pbuffer, pcontrol);
size_t size = this->getArray()->getArraySizeType() == Array::fixed ?
this->getArray()->getMaximumCapacity() :
SerializeHelper::readSize(pbuffer, pcontrol);
svector nextvalue(thaw(value));
@@ -396,7 +448,9 @@ void DefaultPVArray<string>::serialize(ByteBuffer *pbuffer,
const_svector temp(value);
temp.slice(offset, count);
SerializeHelper::writeSize(temp.size(), pbuffer, pflusher);
// TODO if fixed count == getArray()->getMaximumCapacity()
if (this->getArray()->getArraySizeType() != Array::fixed)
SerializeHelper::writeSize(temp.size(), pbuffer, pflusher);
const string * pvalue = temp.data();
for(size_t i = 0; i<temp.size(); i++) {
@@ -649,7 +703,7 @@ PVStructurePtr PVDataCreate::createPVStructure(
PVStructurePtr PVDataCreate::createPVStructure(PVStructurePtr const & structToClone)
{
FieldConstPtrArray field;
if(structToClone==0) {
if(!structToClone) {
// is this correct?!
FieldConstPtrArray fields(0);
StringArray fieldNames(0);

View File

@@ -33,7 +33,7 @@ namespace epics { namespace pvData {
template<>
std::ostream& PVScalarValue<int8>::dumpValue(std::ostream& o) const
{
return o << static_cast<int>(get());
return o << static_cast<int>(get());
}
template<>
@@ -41,4 +41,10 @@ namespace epics { namespace pvData {
{
return o << static_cast<unsigned int>(get());
}
template<>
std::ostream& PVScalarValue<boolean>::dumpValue(std::ostream& o) const
{
return o << std::boolalpha << static_cast<bool>(get());
}
}}

View File

@@ -25,6 +25,8 @@ namespace epics { namespace pvData {
size_t PVStructureArray::append(size_t number)
{
checkLength(value.size()+number);
svector data(reuse());
data.resize(data.size()+number);
@@ -44,9 +46,11 @@ size_t PVStructureArray::append(size_t number)
bool PVStructureArray::remove(size_t offset,size_t number)
{
if(number==0)
if (number==0)
return true;
else if(offset+number>getLength())
else if (offset+number>getLength())
return false;
else if (getArray()->getArraySizeType() == Array::fixed)
return false;
svector vec(reuse());
@@ -65,6 +69,9 @@ bool PVStructureArray::remove(size_t offset,size_t number)
}
void PVStructureArray::compress() {
if (getArray()->getArraySizeType() == Array::fixed)
return;
svector vec(reuse()); // TODO: check for first NULL before realloc
size_t length = vec.size();
@@ -99,7 +106,8 @@ void PVStructureArray::compress() {
void PVStructureArray::setCapacity(size_t capacity)
{
if(this->isCapacityMutable()) {
if (this->isCapacityMutable()) {
checkLength(capacity);
const_svector value;
swap(value);
if(value.capacity()<capacity) {
@@ -109,17 +117,23 @@ void PVStructureArray::setCapacity(size_t capacity)
}
swap(value);
}
else
THROW_EXCEPTION2(std::logic_error, "capacity immutable");
}
void PVStructureArray::setLength(size_t length)
{
if(this->isImmutable())
THROW_EXCEPTION2(std::logic_error,"Immutable");
THROW_EXCEPTION2(std::logic_error, "immutable");
const_svector value;
swap(value);
if(length == value.size()) {
// nothing
} else if(length < value.size()) {
if (length == value.size())
return;
checkLength(length);
if (length < value.size()) {
value.slice(0, length);
} else {
svector mvalue(thaw(value));
@@ -131,8 +145,10 @@ void PVStructureArray::setLength(size_t length)
void PVStructureArray::swap(const_svector &other)
{
if(this->isImmutable())
THROW_EXCEPTION2(std::logic_error,"Immutable");
if (this->isImmutable())
THROW_EXCEPTION2(std::logic_error, "immutable");
// no checkLength call here
value.swap(other);
}
@@ -146,7 +162,10 @@ void PVStructureArray::deserialize(ByteBuffer *pbuffer,
DeserializableControl *pcontrol) {
svector data(reuse());
size_t size = SerializeHelper::readSize(pbuffer, pcontrol);
size_t size = this->getArray()->getArraySizeType() == Array::fixed ?
this->getArray()->getMaximumCapacity() :
SerializeHelper::readSize(pbuffer, pcontrol);
data.resize(size);
StructureConstPtr structure = structureArray->getStructure();
@@ -175,7 +194,11 @@ void PVStructureArray::serialize(ByteBuffer *pbuffer,
const_svector temp(view());
temp.slice(offset, count);
SerializeHelper::writeSize(temp.size(), pbuffer, pflusher);
ArrayConstPtr array = this->getArray();
if (array->getArraySizeType() != Array::fixed)
SerializeHelper::writeSize(temp.size(), pbuffer, pflusher);
else if (count != array->getMaximumCapacity())
throw std::length_error("fixed array cannot be partially serialized");
for(size_t i = 0; i<count; i++) {
if(pbuffer->getRemaining()<1)
@@ -209,8 +232,13 @@ std::ostream& PVStructureArray::dumpValue(std::ostream& o) const
std::ostream& PVStructureArray::dumpValue(std::ostream& o, std::size_t index) const
{
const_svector temp(view());
if(index<temp.size())
o << *temp[index];
if (index<temp.size())
{
if (temp[index])
o << *temp[index];
else
o << format::indent() << "(none)" << std::endl;
}
return o;
}

View File

@@ -169,7 +169,9 @@ void PVUnion::deserialize(ByteBuffer *pbuffer, DeserializableControl *pcontrol)
FieldConstPtr field = pcontrol->cachedDeserialize(pbuffer);
if (field.get())
{
value = getPVDataCreate()->createPVField(field);
// try to reuse existing field instance
if (!value.get() || *value->getField() != *field)
value = getPVDataCreate()->createPVField(field);
value->deserialize(pbuffer, pcontrol);
}
else
@@ -177,11 +179,17 @@ void PVUnion::deserialize(ByteBuffer *pbuffer, DeserializableControl *pcontrol)
}
else
{
int32 previousSelector = selector;
selector = static_cast<int32>(SerializeHelper::readSize(pbuffer, pcontrol));
if (selector != UNDEFINED_INDEX)
{
FieldConstPtr field = unionPtr->getField(selector);
value = getPVDataCreate()->createPVField(field);
if (selector != previousSelector)
{
FieldConstPtr field = unionPtr->getField(selector);
// try to reuse existing field instance
if (!value.get() || *value->getField() != *field)
value = getPVDataCreate()->createPVField(field);
}
value->deserialize(pbuffer, pcontrol);
}
else

View File

@@ -25,6 +25,8 @@ namespace epics { namespace pvData {
size_t PVUnionArray::append(size_t number)
{
checkLength(value.size()+number);
svector data(reuse());
data.resize(data.size()+number);
@@ -44,9 +46,11 @@ size_t PVUnionArray::append(size_t number)
bool PVUnionArray::remove(size_t offset,size_t number)
{
if(number==0)
if (number==0)
return true;
else if(offset+number>getLength())
else if (offset+number>getLength())
return false;
else if (getArray()->getArraySizeType() == Array::fixed)
return false;
svector vec(reuse());
@@ -65,6 +69,9 @@ bool PVUnionArray::remove(size_t offset,size_t number)
}
void PVUnionArray::compress() {
if (getArray()->getArraySizeType() == Array::fixed)
return;
svector vec(reuse()); // TODO: check for first NULL before realloc
size_t length = vec.size();
@@ -100,6 +107,7 @@ void PVUnionArray::compress() {
void PVUnionArray::setCapacity(size_t capacity)
{
if(this->isCapacityMutable()) {
checkLength(capacity);
const_svector value;
swap(value);
if(value.capacity()<capacity) {
@@ -109,17 +117,22 @@ void PVUnionArray::setCapacity(size_t capacity)
}
swap(value);
}
else
THROW_EXCEPTION2(std::logic_error, "capacity immutable");
}
void PVUnionArray::setLength(size_t length)
{
if(this->isImmutable())
THROW_EXCEPTION2(std::logic_error,"Immutable");
THROW_EXCEPTION2(std::logic_error, "immutable");
const_svector value;
swap(value);
if(length == value.size()) {
// nothing
} else if(length < value.size()) {
if (length == value.size())
return;
checkLength(length);
if (length < value.size()) {
value.slice(0, length);
} else {
svector mvalue(thaw(value));
@@ -134,6 +147,8 @@ void PVUnionArray::swap(const_svector &other)
if(this->isImmutable())
THROW_EXCEPTION2(std::logic_error,"Immutable");
// no checkLength call here
value.swap(other);
}
@@ -146,7 +161,10 @@ void PVUnionArray::deserialize(ByteBuffer *pbuffer,
DeserializableControl *pcontrol) {
svector data(reuse());
size_t size = SerializeHelper::readSize(pbuffer, pcontrol);
size_t size = this->getArray()->getArraySizeType() == Array::fixed ?
this->getArray()->getMaximumCapacity() :
SerializeHelper::readSize(pbuffer, pcontrol);
data.resize(size);
UnionConstPtr punion = unionArray->getUnion();
@@ -175,7 +193,11 @@ void PVUnionArray::serialize(ByteBuffer *pbuffer,
const_svector temp(view());
temp.slice(offset, count);
SerializeHelper::writeSize(temp.size(), pbuffer, pflusher);
ArrayConstPtr array = this->getArray();
if (array->getArraySizeType() != Array::fixed)
SerializeHelper::writeSize(temp.size(), pbuffer, pflusher);
else if (count != array->getMaximumCapacity())
throw std::length_error("fixed array cannot be partially serialized");
for(size_t i = 0; i<count; i++) {
if(pbuffer->getRemaining()<1)
@@ -209,8 +231,13 @@ std::ostream& PVUnionArray::dumpValue(std::ostream& o) const
std::ostream& PVUnionArray::dumpValue(std::ostream& o, std::size_t index) const
{
const_svector temp(view());
if(index<temp.size())
o << *temp[index];
if (index<temp.size())
{
if (temp[index])
o << *temp[index];
else
o << format::indent() << "(none)" << std::endl;
}
return o;
}

View File

@@ -162,7 +162,7 @@ void StandardField::createTimeStamp() {
FieldConstPtrArray fields(num);
StringArray names(num);
names[0] = "secondsPastEpoch";
names[1] = "nanoSeconds";
names[1] = "nanoseconds";
names[2] = "userTag";
fields[0] = fieldCreate->createScalar(pvLong);
fields[1] = fieldCreate->createScalar(pvInt);
@@ -228,7 +228,7 @@ void StandardField::createByteAlarm() {
names[6] = "lowWarningSeverity";
names[7] = "highWarningSeverity";
names[8] = "highAlarmSeverity";
names[9] = "hystersis";
names[9] = "hysteresis";
fields[0] = fieldCreate->createScalar(pvBoolean);
fields[1] = fieldCreate->createScalar(pvByte);
fields[2] = fieldCreate->createScalar(pvByte);
@@ -255,7 +255,7 @@ void StandardField::createShortAlarm() {
names[6] = "lowWarningSeverity";
names[7] = "highWarningSeverity";
names[8] = "highAlarmSeverity";
names[9] = "hystersis";
names[9] = "hysteresis";
fields[0] = fieldCreate->createScalar(pvBoolean);
fields[1] = fieldCreate->createScalar(pvShort);
fields[2] = fieldCreate->createScalar(pvShort);
@@ -282,7 +282,7 @@ void StandardField::createIntAlarm() {
names[6] = "lowWarningSeverity";
names[7] = "highWarningSeverity";
names[8] = "highAlarmSeverity";
names[9] = "hystersis";
names[9] = "hysteresis";
fields[0] = fieldCreate->createScalar(pvBoolean);
fields[1] = fieldCreate->createScalar(pvInt);
fields[2] = fieldCreate->createScalar(pvInt);
@@ -309,7 +309,7 @@ void StandardField::createLongAlarm() {
names[6] = "lowWarningSeverity";
names[7] = "highWarningSeverity";
names[8] = "highAlarmSeverity";
names[9] = "hystersis";
names[9] = "hysteresis";
fields[0] = fieldCreate->createScalar(pvBoolean);
fields[1] = fieldCreate->createScalar(pvLong);
fields[2] = fieldCreate->createScalar(pvLong);
@@ -336,7 +336,7 @@ void StandardField::createUByteAlarm() {
names[6] = "lowWarningSeverity";
names[7] = "highWarningSeverity";
names[8] = "highAlarmSeverity";
names[9] = "hystersis";
names[9] = "hysteresis";
fields[0] = fieldCreate->createScalar(pvBoolean);
fields[1] = fieldCreate->createScalar(pvUByte);
fields[2] = fieldCreate->createScalar(pvUByte);
@@ -363,7 +363,7 @@ void StandardField::createUShortAlarm() {
names[6] = "lowWarningSeverity";
names[7] = "highWarningSeverity";
names[8] = "highAlarmSeverity";
names[9] = "hystersis";
names[9] = "hysteresis";
fields[0] = fieldCreate->createScalar(pvBoolean);
fields[1] = fieldCreate->createScalar(pvUShort);
fields[2] = fieldCreate->createScalar(pvUShort);
@@ -390,7 +390,7 @@ void StandardField::createUIntAlarm() {
names[6] = "lowWarningSeverity";
names[7] = "highWarningSeverity";
names[8] = "highAlarmSeverity";
names[9] = "hystersis";
names[9] = "hysteresis";
fields[0] = fieldCreate->createScalar(pvBoolean);
fields[1] = fieldCreate->createScalar(pvUInt);
fields[2] = fieldCreate->createScalar(pvUInt);
@@ -417,7 +417,7 @@ void StandardField::createULongAlarm() {
names[6] = "lowWarningSeverity";
names[7] = "highWarningSeverity";
names[8] = "highAlarmSeverity";
names[9] = "hystersis";
names[9] = "hysteresis";
fields[0] = fieldCreate->createScalar(pvBoolean);
fields[1] = fieldCreate->createScalar(pvULong);
fields[2] = fieldCreate->createScalar(pvULong);
@@ -444,7 +444,7 @@ void StandardField::createFloatAlarm() {
names[6] = "lowWarningSeverity";
names[7] = "highWarningSeverity";
names[8] = "highAlarmSeverity";
names[9] = "hystersis";
names[9] = "hysteresis";
fields[0] = fieldCreate->createScalar(pvBoolean);
fields[1] = fieldCreate->createScalar(pvFloat);
fields[2] = fieldCreate->createScalar(pvFloat);
@@ -471,7 +471,7 @@ void StandardField::createDoubleAlarm() {
names[6] = "lowWarningSeverity";
names[7] = "highWarningSeverity";
names[8] = "highAlarmSeverity";
names[9] = "hystersis";
names[9] = "hysteresis";
fields[0] = fieldCreate->createScalar(pvBoolean);
fields[1] = fieldCreate->createScalar(pvDouble);
fields[2] = fieldCreate->createScalar(pvDouble);
@@ -503,28 +503,28 @@ StructureConstPtr StandardField::scalar(
ScalarType type,string const &properties)
{
ScalarConstPtr field = fieldCreate->createScalar(type); // scalar_t
return createProperties("uri:ev4:nt/2012/pwd:NTScalar",field,properties);
return createProperties("epics:nt/NTScalar:1.0",field,properties);
}
StructureConstPtr StandardField::regUnion(
UnionConstPtr const &field,
string const & properties)
{
return createProperties("uri:ev4:nt/2012/pwd:NTUnion",field,properties);
return createProperties("epics:nt/NTUnion:1.0",field,properties);
}
StructureConstPtr StandardField::variantUnion(
string const & properties)
{
UnionConstPtr field = fieldCreate->createVariantUnion();
return createProperties("uri:ev4:nt/2012/pwd:NTUnion",field,properties);
return createProperties("epics:nt/NTUnion:1.0",field,properties);
}
StructureConstPtr StandardField::scalarArray(
ScalarType elementType, string const &properties)
{
ScalarArrayConstPtr field = fieldCreate->createScalarArray(elementType); // scalar_t[]
return createProperties("uri:ev4:nt/2012/pwd:NTScalarArray",field,properties);
return createProperties("epics:nt/NTScalarArray:1.0",field,properties);
}
@@ -533,7 +533,7 @@ StructureConstPtr StandardField::structureArray(
{
StructureArrayConstPtr field = fieldCreate->createStructureArray(
structure);
return createProperties("uri:ev4:nt/2012/pwd:NTStructureArray",field,properties);
return createProperties("epics:nt/NTStructureArray:1.0",field,properties);
}
StructureConstPtr StandardField::unionArray(
@@ -541,7 +541,7 @@ StructureConstPtr StandardField::unionArray(
{
UnionArrayConstPtr field = fieldCreate->createUnionArray(
punion);
return createProperties("uri:ev4:nt/2012/pwd:NTUnionArray",field,properties);
return createProperties("epics:nt/NTUnionArray:1.0",field,properties);
}
StructureConstPtr StandardField::enumerated()
@@ -560,7 +560,7 @@ StructureConstPtr StandardField::enumerated()
StructureConstPtr StandardField::enumerated(string const &properties)
{
StructureConstPtr field = enumerated(); // enum_t
return createProperties("uri:ev4:nt/2012/pwd:NTEnum",field,properties);
return createProperties("epics:nt/NTEnum:1.0",field,properties);
}
StructureConstPtr StandardField::alarm()

View File

@@ -26,7 +26,14 @@ namespace epics { namespace pvData {
namespace format
{
std::ostream& operator<<(std::ostream& os, indent_level const& indent)
static int indent_index = std::ios_base::xalloc();
long& indent_value(std::ios_base& ios)
{
return ios.iword(indent_index);
}
std::ostream& operator<<(std::ostream& os, indent_level const& indent)
{
indent_value(os) = indent.level;
return os;

View File

@@ -54,14 +54,14 @@ void Executor::run()
{
Lock xx(mutex);
while(true) {
while(head.get()==NULL) {
while(!head.get()) {
xx.unlock();
moreWork.wait();
xx.lock();
}
CommandPtr command = head;
head = command->next;
if(command.get()==NULL) continue;
if(!command.get()) continue;
if(command.get()==shutdown.get()) break;
xx.unlock();
try {
@@ -82,13 +82,13 @@ void Executor::execute(CommandPtr const & command)
{
Lock xx(mutex);
command->next.reset();
if(head.get()==NULL) {
if(!head.get()) {
head = command;
moreWork.signal();
return;
}
CommandPtr tail = head;
while(tail->next!=NULL) tail = tail->next;
while(tail->next) tail = tail->next;
tail->next = command;
}

View File

@@ -17,7 +17,7 @@
using std::string;
// need to use "long long" when sizeof(int)==sizeof(long)
#if (ULONG_MAX == 0xfffffffful) || defined(_WIN32) || defined(__rtems__)
#if (ULONG_MAX == 0xfffffffful) || defined(_WIN32) || defined(__rtems__) || defined(__APPLE__)
#define NEED_LONGLONG
#endif
@@ -27,7 +27,7 @@ using std::string;
#endif
#if EPICS_VERSION_INT < VERSION_INT(3,15,0,1)
/* integer conversion primatives added to epicsStdlib.c in 3.15.0.1 */
/* integer conversion primitives added to epicsStdlib.c in 3.15.0.1 */
#define S_stdlib_noConversion 1 /* No digits to convert */
#define S_stdlib_extraneous 2 /* Extraneous characters */
@@ -249,7 +249,18 @@ epicsParseFloat(const char *str, float *to, char **units)
}
#endif
#if defined(NEED_LONGLONG) && (defined(__vxworks) || defined (_WIN32))
// MS Visual Studio 2013 defines strtoll, etc.
#if defined(_WIN32)
# if (_MSC_VER >= 1800)
# define WIN_NEEDS_OLL_FUNC 0
# else
# define WIN_NEEDS_OLL_FUNC 1
# endif
#else
# define WIN_NEEDS_OLL_FUNC 0
#endif
#if defined(NEED_LONGLONG) && (defined(__vxworks) || WIN_NEEDS_OLL_FUNC)
static
long long strtoll(const char *ptr, char ** endp, int base)
{
@@ -297,6 +308,71 @@ noconvert:
return 0;
}
#if defined(__vxworks)
/* vxworks version of std::istringstream >>uint64_t is buggy, we use out own implementation */
static
unsigned long long strtoull(const char *nptr, char **endptr, int base)
{
const char *s = nptr;
unsigned long long acc;
int c;
unsigned long long cutoff;
int neg = 0, any, cutlim;
do
c = *s++;
while (isspace(c));
if (c == '-')
{
neg = 1;
c = *s++;
}
else if (c == '+')
c = *s++;
if ((base == 0 || base == 16) &&
c == '0' && (*s == 'x' || *s == 'X'))
{
c = s[1];
s += 2;
base = 16;
}
if (base == 0)
base = c == '0' ? 8 : 10;
cutoff = (unsigned long long) UINT64_MAX / (unsigned long long) base;
cutlim = (unsigned long long) UINT64_MAX % (unsigned long long) base;
for (acc = 0, any = 0;; c = *s++)
{
if (isdigit(c))
c -= '0';
else if (isalpha(c))
c -= isupper(c) ? 'A' - 10 : 'a' - 10;
else
break;
if (c >= base)
break;
if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
any = -1;
else
{
any = 1;
acc *= base;
acc += c;
}
}
if (any < 0)
{
acc = UINT64_MAX;
errno = ERANGE;
}
else if (neg)
acc = -acc;
if (endptr != 0)
*endptr = any ? (char *) s - 1 : (char *) nptr;
return (acc);
}
#else
static
unsigned long long strtoull(const char *ptr, char ** endp, int base)
{
@@ -339,7 +415,7 @@ noconvert:
*endp = (char*)ptr;
return 0;
}
#endif
#endif
/* do we need long long? */
@@ -475,6 +551,26 @@ void parseToPOD(const string& in, float *out) {
void parseToPOD(const string& in, double *out) {
int err = epicsParseDouble(in.c_str(), out, NULL);
if(err) handleParseError(err);
#if defined(__vxworks)
/* vxWorks strtod returns [-]epicsINF when it should return ERANGE error
* if [-]epicsINF is returned and first char is a digit then translate this into ERANGE error
*/
else if (*out == epicsINF || *out == -epicsINF) {
const char* s = in.c_str();
int c;
/* skip spaces and the sign */
do {
c = *s++;
} while (isspace(c));
if (c == '-' || c == '+')
c = *s++;
if (isdigit(c))
handleParseError(S_stdlib_overflow);
}
#endif
}
}}}

View File

@@ -65,9 +65,10 @@ namespace epics { namespace pvData {
};
class epicsShareClass SerializableArray : virtual public Serializable {
class epicsShareClass SerializableArray : public virtual Serializable {
public:
virtual ~SerializableArray(){}
using Serializable::serialize;
virtual void serialize(ByteBuffer *buffer,
SerializableControl *flusher, std::size_t offset, std::size_t count) const = 0;
};

View File

@@ -44,6 +44,25 @@
# undef SHARED_FROM_TR1
#endif
#if defined(__clang__)
# undef SHARED_FROM_BOOST
# undef SHARED_FROM_TR1
#include <memory>
// import std classes into std::tr1
namespace std {
namespace tr1 {
using std::shared_ptr;
using std::weak_ptr;
using std::static_pointer_cast;
using std::dynamic_pointer_cast;
using std::const_pointer_cast;
using std::enable_shared_from_this;
}
}
#endif
// go and get it
#if defined(SHARED_FROM_TR1)

View File

@@ -23,7 +23,7 @@ MonitorPluginManagerPtr MonitorPluginManager::get()
static MonitorPluginManagerPtr pluginManager;
static Mutex mutex;
Lock xx(mutex);
if(pluginManager==NULL) {
if(!pluginManager) {
pluginManager = MonitorPluginManagerPtr(new MonitorPluginManager());
}
return pluginManager;

View File

@@ -16,7 +16,7 @@ namespace epics { namespace pvData {
class epicsShareClass Control {
public:
Control() : low(0.0), high(0.0) {}
Control() : low(0.0), high(0.0), minStep(0.0) {}
//default constructors and destructor are OK
double getLow() const {return low;}
double getHigh() const {return high;}

View File

@@ -30,11 +30,17 @@ bool PVControl::attach(PVFieldPtr const & pvField)
PVStructurePtr pvStructure = static_pointer_cast<PVStructure>(pvField);
pvLow = pvStructure->getDoubleField("limitLow");
if(pvLow.get()==NULL) return false;
pvHigh = pvStructure->getDoubleField(string("limitHigh"));
pvHigh = pvStructure->getDoubleField("limitHigh");
if(pvHigh.get()==NULL) {
pvLow.reset();
return false;
}
pvMinStep = pvStructure->getDoubleField("minStep");
if(pvMinStep.get()==NULL) {
pvLow.reset();
pvHigh.reset();
return false;
}
return true;
}
@@ -56,6 +62,7 @@ void PVControl::get(Control &control) const
}
control.setLow(pvLow->get());
control.setHigh(pvHigh->get());
control.setMinStep(pvMinStep->get());
}
bool PVControl::set(Control const & control)
@@ -63,9 +70,10 @@ bool PVControl::set(Control const & control)
if(pvLow.get()==NULL) {
throw std::logic_error(notAttached);
}
if(pvLow->isImmutable() || pvHigh->isImmutable()) return false;
if(pvLow->isImmutable() || pvHigh->isImmutable() || pvMinStep->isImmutable()) return false;
pvLow->put(control.getLow());
pvHigh->put(control.getHigh());
pvMinStep->put(control.getMinStep());
return true;
}

View File

@@ -33,6 +33,7 @@ public:
private:
PVDoublePtr pvLow;
PVDoublePtr pvHigh;
PVDoublePtr pvMinStep;
static std::string noControlFound;
static std::string notAttached;
};

View File

@@ -33,7 +33,7 @@ bool PVTimeStamp::attach(PVFieldPtr const & pvField)
PVLongPtr pvLong = pvStructure->getLongField("secondsPastEpoch");
if(pvLong.get()!=NULL) {
pvSecs = pvLong;
pvNano = pvStructure->getIntField("nanoSeconds");
pvNano = pvStructure->getIntField("nanoseconds");
pvUserTag = pvStructure->getIntField("userTag");
}
if(pvSecs.get()!=NULL
@@ -76,7 +76,7 @@ bool PVTimeStamp::set(TimeStamp const & timeStamp)
if(pvSecs->isImmutable() || pvNano->isImmutable()) return false;
pvSecs->put(timeStamp.getSecondsPastEpoch());
pvUserTag->put(timeStamp.getUserTag());
pvNano->put(timeStamp.getNanoSeconds());
pvNano->put(timeStamp.getNanoseconds());
return true;
}

View File

@@ -27,21 +27,21 @@ int32 microSecPerSec = milliSecPerSec*milliSecPerSec;
int32 nanoSecPerSec = milliSecPerSec*microSecPerSec;
int64 posixEpochAtEpicsEpoch = POSIX_TIME_AT_EPICS_EPOCH;
TimeStamp::TimeStamp(int64 secondsPastEpoch,int32 nanoSeconds,int32 userTag)
: secondsPastEpoch(secondsPastEpoch),nanoSeconds(nanoSeconds),userTag(userTag)
TimeStamp::TimeStamp(int64 secondsPastEpoch,int32 nanoseconds,int32 userTag)
: secondsPastEpoch(secondsPastEpoch),nanoseconds(nanoseconds),userTag(userTag)
{
normalize();
}
void TimeStamp::normalize()
{
if(nanoSeconds>=0 && nanoSeconds<nanoSecPerSec) return;
while(nanoSeconds>=nanoSecPerSec) {
nanoSeconds -= nanoSecPerSec;
if(nanoseconds>=0 && nanoseconds<nanoSecPerSec) return;
while(nanoseconds>=nanoSecPerSec) {
nanoseconds -= nanoSecPerSec;
secondsPastEpoch++;
}
while(nanoSeconds<0) {
nanoSeconds += nanoSecPerSec;
while(nanoseconds<0) {
nanoseconds += nanoSecPerSec;
secondsPastEpoch--;
}
}
@@ -51,21 +51,21 @@ void TimeStamp::fromTime_t(const time_t & tt)
epicsTimeStamp epicsTime;
epicsTimeFromTime_t(&epicsTime,tt);
secondsPastEpoch = epicsTime.secPastEpoch + posixEpochAtEpicsEpoch;
nanoSeconds = epicsTime.nsec;
nanoseconds = epicsTime.nsec;
}
void TimeStamp::toTime_t(time_t &tt) const
{
epicsTimeStamp epicsTime;
epicsTime.secPastEpoch = static_cast<epicsUInt32>(secondsPastEpoch-posixEpochAtEpicsEpoch);
epicsTime.nsec = nanoSeconds;
epicsTime.nsec = nanoseconds;
epicsTimeToTime_t(&tt,&epicsTime);
}
void TimeStamp::put(int64 milliseconds)
{
secondsPastEpoch = milliseconds/1000;
nanoSeconds = (milliseconds%1000)*1000000;
nanoseconds = (milliseconds%1000)*1000000;
}
void TimeStamp::getCurrent()
@@ -74,13 +74,13 @@ void TimeStamp::getCurrent()
epicsTimeGetCurrent(&epicsTime);
secondsPastEpoch = epicsTime.secPastEpoch;
secondsPastEpoch += posixEpochAtEpicsEpoch;
nanoSeconds = epicsTime.nsec;
nanoseconds = epicsTime.nsec;
}
double TimeStamp::toSeconds() const
{
double value = static_cast<double>(secondsPastEpoch);
double nano = nanoSeconds;
double nano = nanoseconds;
value += nano/1e9;
return value;
}
@@ -88,9 +88,9 @@ double TimeStamp::toSeconds() const
int64 TimeStamp::diffInt(TimeStamp const & left,TimeStamp const&right )
{
int64 sl = left.secondsPastEpoch;
int32 nl = left.nanoSeconds;
int32 nl = left.nanoseconds;
int64 sr = right.secondsPastEpoch;
int32 nr = right.nanoSeconds;
int32 nr = right.nanoseconds;
int64 sdiff = sl - sr;
sdiff *= nanoSecPerSec;
sdiff += nl - nr;
@@ -142,7 +142,7 @@ bool TimeStamp::operator>(TimeStamp const &right) const
double TimeStamp::diff(TimeStamp const & a,TimeStamp const & b)
{
double result = static_cast<double>(a.secondsPastEpoch - b.secondsPastEpoch);
result += (a.nanoSeconds - b.nanoSeconds)/1e9;
result += (a.nanoseconds - b.nanoseconds)/1e9;
return result;
}
@@ -163,12 +163,12 @@ TimeStamp & TimeStamp::operator+=(double seconds)
{
int64 secs = static_cast<int64>(seconds);
int64 nano = static_cast<int64>((seconds - secs)*1e9);
nanoSeconds += static_cast<int32>(nano);
if(nanoSeconds>nanoSecPerSec) {
nanoSeconds -= nanoSecPerSec;
nanoseconds += static_cast<int32>(nano);
if(nanoseconds>nanoSecPerSec) {
nanoseconds -= nanoSecPerSec;
secondsPastEpoch += 1;
} else if(nanoSeconds<-nanoSecPerSec) {
nanoSeconds += -nanoSecPerSec;
} else if(nanoseconds<-nanoSecPerSec) {
nanoseconds += -nanoSecPerSec;
secondsPastEpoch -= 1;
}
secondsPastEpoch += secs;
@@ -182,7 +182,7 @@ TimeStamp & TimeStamp::operator-=(double seconds)
int64 TimeStamp::getMilliseconds()
{
return secondsPastEpoch*1000 + nanoSeconds/1000000;
return secondsPastEpoch*1000 + nanoseconds/1000000;
}
}}

View File

@@ -38,8 +38,8 @@ epicsShareExtern int64 posixEpochAtEpicsEpoch;
class epicsShareClass TimeStamp {
public:
TimeStamp()
:secondsPastEpoch(0), nanoSeconds(0), userTag(0) {}
TimeStamp(int64 secondsPastEpoch,int32 nanoSeconds = 0,int32 userTag = 0);
:secondsPastEpoch(0), nanoseconds(0), userTag(0) {}
TimeStamp(int64 secondsPastEpoch,int32 nanoseconds = 0,int32 userTag = 0);
//default constructors and destructor are OK
//This class should not be extended
void normalize();
@@ -49,12 +49,12 @@ public:
int64 getEpicsSecondsPastEpoch() const {
return secondsPastEpoch - posixEpochAtEpicsEpoch;
}
int32 getNanoSeconds() const {return nanoSeconds;}
int32 getNanoseconds() const {return nanoseconds;}
int32 getUserTag() const {return userTag;}
void setUserTag(int userTag) {this->userTag = userTag;}
void put(int64 secondsPastEpoch,int32 nanoSeconds = 0) {
void put(int64 secondsPastEpoch,int32 nanoseconds = 0) {
this->secondsPastEpoch = secondsPastEpoch;
this->nanoSeconds = nanoSeconds;
this->nanoseconds = nanoseconds;
normalize();
}
void put(int64 milliseconds);
@@ -75,7 +75,7 @@ public:
private:
static int64 diffInt(TimeStamp const &left,TimeStamp const &right );
int64 secondsPastEpoch;
int32 nanoSeconds;
int32 nanoseconds;
int32 userTag;
};

View File

@@ -35,6 +35,7 @@ bool epicsShareExtern operator==(const Structure&, const Structure&);
bool epicsShareExtern operator==(const StructureArray&, const StructureArray&);
bool epicsShareExtern operator==(const Union&, const Union&);
bool epicsShareExtern operator==(const UnionArray&, const UnionArray&);
bool epicsShareExtern operator==(const BoundedString&, const BoundedString&);
static inline bool operator!=(const Field& a, const Field& b)
{return !(a==b);}
@@ -50,6 +51,8 @@ static inline bool operator!=(const Union& a, const Union& b)
{return !(a==b);}
static inline bool operator!=(const UnionArray& a, const UnionArray& b)
{return !(a==b);}
static inline bool operator!=(const BoundedString& a, const BoundedString& b)
{return !(a==b);}
/**
@@ -63,9 +66,7 @@ static inline bool operator!=(const UnionArray& a, const UnionArray& b)
* pvUByte, pvUShort, pvUInt, pvULong,
* pvFloat, or pvDouble.</p>
*
* <p>getString converts any supported type to a std::string.
* Code that implements a PVField interface should implement
* method toString by calling this method.</p>
* <p>getString converts any supported type to a std::string.</p>
*
* <p>fromString converts a std::string to a scalar.
* fromStringArray converts an array of std::strings
@@ -478,7 +479,7 @@ public:
inline void fromDouble(PVScalarPtr const & pv, double from) { pv->putFrom<double>(from); }
/**
* Convenience method for implementing toString.
* Convenience method for implementing dump.
* It generates a newline and inserts blanks at the beginning of the newline.
* @param builder The std::string * being constructed.
* @param indentLevel Indent level, Each level is four spaces.

View File

@@ -507,10 +507,12 @@ public:
*/
virtual void setCapacity(std::size_t capacity) = 0;
using PVField::dumpValue;
virtual std::ostream& dumpValue(std::ostream& o, std::size_t index) const = 0;
protected:
PVArray(FieldConstPtr const & field);
void checkLength(size_t length);
private:
bool capacityMutable;
friend class PVDataCreate;
@@ -979,7 +981,6 @@ public:
private:
friend class PVDataCreate;
UnionConstPtr unionPtr;
int32 selector;
@@ -1195,6 +1196,7 @@ public:
virtual const_svector view() const { return value; }
virtual void swap(const_svector &other);
virtual void replace(const const_svector &other) {
checkLength(other.size());
value = other;
PVField::postPut();
}
@@ -1290,6 +1292,7 @@ public:
virtual const_svector view() const { return value; }
virtual void swap(const_svector &other);
virtual void replace(const const_svector &other) {
checkLength(other.size());
value = other;
PVField::postPut();
}

View File

@@ -32,11 +32,7 @@ struct indent_level
indent_level(long l) : level(l) {}
};
inline long& indent_value(std::ios_base& ios)
{
static int indent_index = std::ios_base::xalloc();
return ios.iword(indent_index);
}
epicsShareExtern long& indent_value(std::ios_base& ios);
epicsShareExtern std::ostream& operator<<(std::ostream& os, indent_level const& indent);
@@ -93,6 +89,8 @@ class StructureArray;
class Union;
class UnionArray;
class BoundedString;
/**
* typedef for a shared pointer to an immutable Field.
*/
@@ -129,6 +127,10 @@ typedef std::tr1::shared_ptr<const Union> UnionConstPtr;
* typedef for a shared pointer to an immutable UnionArray.
*/
typedef std::tr1::shared_ptr<const UnionArray> UnionArrayConstPtr;
/**
* typedef for a shared pointer to an immutable BoundedString.
*/
typedef std::tr1::shared_ptr<const BoundedString> BoundedStringConstPtr;
/**
* Definition of support field types.
@@ -360,9 +362,39 @@ public:
protected:
Scalar(ScalarType scalarType);
private:
int8 getTypeCodeLUT() const;
static int8 getTypeCodeLUT(ScalarType scalarType);
ScalarType scalarType;
friend class FieldCreate;
friend class ScalarArray;
friend class BoundedScalarArray;
friend class FixedScalarArray;
friend class BoundedString;
};
/**
* This class implements introspection object for BoundedString.
*/
class epicsShareClass BoundedString : public Scalar{
public:
POINTER_DEFINITIONS(BoundedString);
/**
* Destructor.
*/
virtual ~BoundedString();
typedef BoundedString& reference;
typedef const BoundedString& const_reference;
virtual std::string getID() const;
virtual void serialize(ByteBuffer *buffer, SerializableControl *control) const;
std::size_t getMaximumLength() const;
protected:
BoundedString(std::size_t maxStringLength);
private:
std::size_t maxLength;
friend class FieldCreate;
};
/**
@@ -377,14 +409,21 @@ public:
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;
*/
enum ArraySizeType { variable, fixed, bounded };
/**
* Get array size type (i.e. variable/fixed/bounded size array).
* @return array size type enum.
*/
virtual ArraySizeType getArraySizeType() const = 0;
/**
* Get maximum capacity of the array.
* @return maximum capacity of the array, 0 indicates variable size array.
*/
virtual std::size_t getMaximumCapacity() const = 0;
protected:
/**
* Constructor
@@ -394,8 +433,14 @@ protected:
};
/**
* This class implements introspection object for field.
* This class implements introspection object for scalar array.
*/
class epicsShareClass ScalarArray : public Array{
public:
@@ -414,6 +459,10 @@ public:
*/
ScalarType getElementType() const {return elementType;}
virtual ArraySizeType getArraySizeType() const {return Array::variable;}
virtual std::size_t getMaximumCapacity() const {return 0;}
virtual std::string getID() const;
virtual std::ostream& dump(std::ostream& o) const;
@@ -427,12 +476,85 @@ protected:
*/
virtual ~ScalarArray();
private:
int8 getTypeCodeLUT() const;
const std::string getIDScalarArrayLUT() const;
ScalarType elementType;
friend class FieldCreate;
};
/**
* This class implements introspection object for bounded scalar array.
*/
class epicsShareClass BoundedScalarArray : public ScalarArray{
public:
POINTER_DEFINITIONS(BoundedScalarArray);
typedef BoundedScalarArray& reference;
typedef const BoundedScalarArray& const_reference;
/**
* Constructor
* @param scalarType The scalarType for the field.
* @param size maximum (bound) capacity.
*/
BoundedScalarArray(ScalarType scalarType, std::size_t size);
virtual ArraySizeType getArraySizeType() const {return Array::bounded;}
virtual std::size_t getMaximumCapacity() const {return size;}
virtual std::string getID() const;
virtual void serialize(ByteBuffer *buffer, SerializableControl *control) const;
protected:
/**
* Destructor.
*/
virtual ~BoundedScalarArray();
private:
std::size_t size;
friend class FieldCreate;
};
/**
* This class implements introspection object for bounded scalar array.
*/
class epicsShareClass FixedScalarArray : public ScalarArray{
public:
POINTER_DEFINITIONS(FixedScalarArray);
typedef FixedScalarArray& reference;
typedef const FixedScalarArray& const_reference;
/**
* Constructor
* @param scalarType The scalarType for the field.
* @param size maximum (bound) capacity.
*/
FixedScalarArray(ScalarType scalarType, std::size_t size);
virtual ArraySizeType getArraySizeType() const {return Array::fixed;}
virtual std::size_t getMaximumCapacity() const {return size;}
virtual std::string getID() const;
virtual void serialize(ByteBuffer *buffer, SerializableControl *control) const;
protected:
/**
* Destructor.
*/
virtual ~FixedScalarArray();
private:
std::size_t size;
friend class FieldCreate;
};
/**
* This class implements introspection object for a structureArray
*/
@@ -448,6 +570,10 @@ public:
*/
StructureConstPtr getStructure() const {return pstructure;}
virtual ArraySizeType getArraySizeType() const {return Array::variable;}
virtual std::size_t getMaximumCapacity() const {return 0;}
virtual std::string getID() const;
virtual std::ostream& dump(std::ostream& o) const;
@@ -485,6 +611,10 @@ public:
*/
UnionConstPtr getUnion() const {return punion;}
virtual ArraySizeType getArraySizeType() const {return Array::variable;}
virtual std::size_t getMaximumCapacity() const {return 0;}
virtual std::string getID() const;
virtual std::ostream& dump(std::ostream& o) const;
@@ -711,6 +841,14 @@ public:
*/
FieldBuilderPtr add(std::string const & name, ScalarType scalarType);
/**
* Add a {@code BoundedString}.
* @param name name of the array.
* @param maxLength a string maximum length.
* @return this instance of a {@code FieldBuilder}.
*/
FieldBuilderPtr addBoundedString(std::string const & name, std::size_t maxLength);
/**
* Add a {@code Field} (e.g. {@code Structure}, {@code Union}).
* @param name name of the array.
@@ -720,13 +858,31 @@ public:
FieldBuilderPtr add(std::string const & name, FieldConstPtr const & field);
/**
* Add array of {@code Scalar} elements.
* Add variable size array of {@code Scalar} elements.
* @param name name of the array.
* @param scalarType type of a scalar element.
* @return this instance of a {@code FieldBuilder}.
*/
FieldBuilderPtr addArray(std::string const & name, ScalarType scalarType);
/**
* Add fixed-size array of {@code Scalar} elements.
* @param name name of the array.
* @param scalarType type of a scalar element.
* @param size Array fixed size.
* @return this instance of a {@code FieldBuilder}.
*/
FieldBuilderPtr addFixedArray(std::string const & name, ScalarType scalarType, std::size_t size);
/**
* Add bounded-size array of {@code Scalar} elements.
* @param name name of the array.
* @param scalarType type of a scalar element.
* @param bound Array maximum capacity (size).
* @return this instance of a {@code FieldBuilder}.
*/
FieldBuilderPtr addBoundedArray(std::string const & name, ScalarType scalarType, std::size_t bound);
/**
* Add array of {@code Field} elements.
* @param name name of the array.
@@ -843,11 +999,32 @@ public:
*/
ScalarConstPtr createScalar(ScalarType scalarType) const;
/**
* Create an {@code Array} field.
* Create a {@code BoundedString}.
* @param maxLength a string maximum length.
* @return a {@code BoundedString} interface for the newly created object.
* @throws An {@code IllegalArgumentException} if maxLength == 0.
*/
BoundedStringConstPtr createBoundedString(std::size_t maxLength) const;
/**
* Create an {@code Array} field, variable size array.
* @param elementType The {@code scalarType} for array elements
* @return An {@code Array} Interface for the newly created object.
*/
ScalarArrayConstPtr createScalarArray(ScalarType elementType) const;
/*
* Create an {@code Array} field, fixed size array.
* @param elementType The {@code scalarType} for array elements
* @param size Fixed array size.
* @return An {@code Array} Interface for the newly created object.
*/
ScalarArrayConstPtr createFixedScalarArray(ScalarType elementType, std::size_t size) const;
/**
* Create an {@code Array} field, bounded size array.
* @param elementType The {@code scalarType} for array elements
* @param size Array maximum capacity (bound).
* @return An {@code Array} Interface for the newly created object.
*/
ScalarArrayConstPtr createBoundedScalarArray(ScalarType elementType, std::size_t bound) const;
/**
* Create an {@code Array} field that is has element type <i>Structure</i>
* @param fieldName The field name
@@ -972,7 +1149,7 @@ epicsShareExtern FieldCreatePtr getFieldCreate();
* value (eg -1).
*/
template<typename T>
struct ScalarTypeID { enum {value=-1}; };
struct ScalarTypeID {};
/**
* Static mapping from ScalarType enum to value type.

View File

@@ -29,7 +29,7 @@ typedef int intptr_t;
typedef unsigned int uintptr_t;
#ifndef INT64_MAX
#define INT64_MAX (0x7fffffffffffffffLL)
#define UINT64_MAX (0xffffffffffffffffLL)
#define UINT64_MAX (0xffffffffffffffffULL)
#endif
#else
#include <stdint.h>

View File

@@ -51,7 +51,7 @@ typedef std::tr1::shared_ptr<StandardField> StandardFieldPtr;
string message
structure timeStamp
long secondsPastEpoch
int nanoSeconds
int nanoseconds
int userTag
* }
* In addition there are methods that create each of the property structures,
@@ -122,7 +122,7 @@ public:
*/
StructureConstPtr enumerated();
/** Create a structure that has an enumerated structure value field
* The id for the structure is "uri:ev4:nt/2012/pwd:NTEnum".
* The id for the structure is "epics:nt/NTEnum:1.0".
* @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.

View File

@@ -84,7 +84,7 @@ public:
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".
* The id for the structure is "epics:nt/NTEnum:1.0".
* @param choices This is a StringArray of choices.
* @param properties A comma separated list of properties.
* @return The const shared pointer to the structure.

View File

@@ -1,8 +1,31 @@
# Makefile for the pvData tests
TOP = ..
include $(TOP)/configure/CONFIG
DIRS += misc
DIRS += pv
DIRS += property
DIRS += copy
include $(TOP)/configure/RULES_DIRS
PVDATA_TEST = $(TOP)/testApp
PROD_LIBS += pvData Com
include $(PVDATA_TEST)/misc/Makefile
include $(PVDATA_TEST)/pv/Makefile
include $(PVDATA_TEST)/property/Makefile
include $(PVDATA_TEST)/copy/Makefile
# The testHarness runs all the test programs in a known working order.
testHarness_SRCS += pvDataAllTests.c
PROD_vxWorks = vxTestHarness
vxTestHarness_SRCS += $(testHarness_SRCS)
TESTSPEC_vxWorks = vxTestHarness.$(MUNCH_SUFFIX); pvDataAllTests
PROD_RTEMS += rtemsTestHarness
rtemsTestHarness_SRCS += rtemsTestHarness.c rtemsConfig.c
rtemsTestHarness_SRCS += $(testHarness_SRCS)
TESTSPEC_RTEMS = rtemsTestHarness.$(MUNCH_SUFFIX); pvDataAllTests
TESTSCRIPTS_HOST += $(TESTS:%=%.t)
include $(TOP)/configure/RULES

View File

@@ -1,22 +1,13 @@
TOP=../..
# This is a Makefile fragment, see ../Makefile
include $(TOP)/configure/CONFIG
SRC_DIRS += $(PVDATA_TEST)/copy
PROD_HOST += testCreateRequest
TESTPROD_HOST += testCreateRequest
testCreateRequest_SRCS = testCreateRequest.cpp
testCreateRequest_LIBS = pvData Com
testHarness_SRCS += testCreateRequest.cpp
TESTS += testCreateRequest
PROD_HOST += testPVCopy
TESTPROD_HOST += testPVCopy
testPVCopy_SRCS += testPVCopy.cpp
testPVCopy_LIBS += pvData Com
testHarness_SRCS += testPVCopy.cpp
TESTS += testPVCopy
TESTSCRIPTS_HOST += $(TESTS:%=%.t)
include $(TOP)/configure/RULES
#----------------------------------------
# ADD RULES AFTER THIS LINE

View File

@@ -20,101 +20,102 @@ using std::endl;
static bool debug = false;
void testCreateRequest() {
static void testCreateRequestInternal() {
printf("testCreateRequest... \n");
CreateRequest::shared_pointer createRequest = CreateRequest::create();
PVStringPtr pvString;
string sval;
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;}
if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
if(debug) { cout << *pvRequest << endl;}
testOk1(pvRequest.get()!=NULL);
testOk1(pvRequest->getStructure()->getNumberFields()==0);
testPass("request %s",request.c_str());
request = "record[]field()getField()putField()";
if(debug) { cout << "request " << request <<endl;}
pvRequest = createRequest->createRequest(request);
if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
if(debug) { cout << *pvRequest << endl;}
testOk1(pvRequest.get()!=NULL);
testOk1(pvRequest->getSubField("field").get()!=NULL);
testOk1(pvRequest->getSubField("putField").get()!=NULL);
testOk1(pvRequest->getSubField("getField").get()!=NULL);
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();
pvRequest = createRequest->createRequest(request);
if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
if(debug) { cout << *pvRequest << endl;}
testOk1(pvRequest.get()!=NULL);
pvString = pvRequest->getSubField<PVString>("record._options.a");
sval = pvString->get();
testOk(sval.compare("b")==0,"record.a = b");
pvString = pvRequest->getSubField<PVString>("record.x");
pvString = pvRequest->getSubField<PVString>("record._options.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);
testOk1(pvRequest->getSubField("field.a").get()!=NULL);
testOk1(pvRequest->getSubField("putField.a").get()!=NULL);
testOk1(pvRequest->getSubField("getField.a").get()!=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;}
pvRequest = createRequest->createRequest(request);
if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
if(debug) { cout << *pvRequest << endl;}
testOk1(pvRequest.get()!=NULL);
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;}
pvRequest = createRequest->createRequest(request);
if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
if(debug) { cout << *pvRequest << endl;}
testOk1(pvRequest.get()!=NULL);
testOk1(pvRequest->getSubField("field.a.b.c.d").get()!=NULL);
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);
pvRequest = createRequest->createRequest(request);
if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
if(debug) { cout << *pvRequest << endl;}
testOk1(pvRequest.get()!=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;}
testOk1(pvRequest->getSubField("field.a.b.c.d").get()!=NULL);
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);
pvRequest = createRequest->createRequest(request);
if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
if(debug) { cout << *pvRequest << endl;}
testOk1(pvRequest.get()!=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);
pvRequest = createRequest->createRequest(request);
if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
if(debug) { cout << *pvRequest << endl;}
testOk1(pvRequest.get()!=NULL);
pvString = pvRequest->getSubField<PVString>("field.a.a._options.a");
sval = pvString->get();
testOk(sval.compare("b")==0,"field.a.a._options.a = b");
@@ -124,126 +125,113 @@ void testCreateRequest() {
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;}
testOk1(pvRequest->getSubField("field.b.a.a").get()!=NULL);
testOk1(pvRequest->getSubField("field.b.a.b").get()!=NULL);
testPass("request %s",request.c_str());
request = "alarm,timeStamp,power.value";
if(debug) { cout << "request " << request <<endl;}
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;}
if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
if(debug) { cout << *pvRequest << endl;}
testOk1(pvRequest.get()!=NULL);
testOk1(pvRequest->getSubField("field.alarm").get()!=NULL);
testOk1(pvRequest->getSubField("field.timeStamp").get()!=NULL);
testOk1(pvRequest->getSubField("field.power.value").get()!=NULL);
testPass("request %s",request.c_str());
request = "record[process=true]field(alarm,timeStamp,power.value)";
if(debug) { cout << "request " << request <<endl;}
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");
if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
if(debug) { cout << *pvRequest << endl;}
testOk1(pvRequest.get()!=NULL);
pvString = pvRequest->getSubField<PVString>("record._options.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;}
testOk(sval.compare("true")==0,"record._options.process = true");
testOk1(pvRequest->getSubField("field.alarm").get()!=NULL);
testOk1(pvRequest->getSubField("field.timeStamp").get()!=NULL);
testOk1(pvRequest->getSubField("field.power.value").get()!=NULL);
testPass("request %s",request.c_str());
request = "record[process=true]field(alarm,timeStamp[algorithm=onChange,causeMonitor=false],power{value,alarm})";
if(debug) { cout << "request " << request <<endl;}
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");
if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
if(debug) { cout << *pvRequest << endl;}
testOk1(pvRequest.get()!=NULL);
pvString = pvRequest->getSubField<PVString>("record._options.process");
sval = pvString->get();
testOk(sval.compare("true")==0,"record.process = true");
testOk1(pvRequest->getSubField("field.alarm")!=NULL);
testOk1(pvRequest->getSubField("field.timeStamp")!=NULL);
testOk(sval.compare("true")==0,"record._options.process = true");
testOk1(pvRequest->getSubField("field.alarm").get()!=NULL);
testOk1(pvRequest->getSubField("field.timeStamp").get()!=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;}
testOk1(pvRequest->getSubField("field.power.value").get()!=NULL);
testOk1(pvRequest->getSubField("field.power.alarm").get()!=NULL);
testPass("request %s",request.c_str());
request = "record[int=2,float=3.14159]field(alarm,timeStamp[shareData=true],power.value)";
if(debug) { cout << "request " << request <<endl;}
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");
if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
if(debug) { cout << *pvRequest << endl;}
testOk1(pvRequest.get()!=NULL);
pvString = pvRequest->getSubField<PVString>("record._options.int");
sval = pvString->get();
testOk(sval.compare("2")==0,"record.int = 2");
pvString = pvRequest->getSubField<PVString>("record.float");
testOk(sval.compare("2")==0,"record._options.int = 2");
pvString = pvRequest->getSubField<PVString>("record._options.float");
sval = pvString->get();
testOk(sval.compare("3.14159")==0,"record.float = 3.14159");
testOk1(pvRequest->getSubField("field.alarm")!=NULL);
testOk(sval.compare("3.14159")==0,"record._options.float = 3.14159");
testOk1(pvRequest->getSubField("field.alarm").get()!=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;}
testOk1(pvRequest->getSubField("field.power.value").get()!=NULL);
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})";
if(debug) { cout << "request " << request <<endl;}
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;}
if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
if(debug) { cout << *pvRequest << endl;}
testOk1(pvRequest.get()!=NULL);
testOk1(pvRequest->getSubField("putField.power.value").get()!=NULL);
testOk1(pvRequest->getSubField("getField.alarm").get()!=NULL);
testOk1(pvRequest->getSubField("getField.timeStamp").get()!=NULL);
testOk1(pvRequest->getSubField("getField.power.value").get()!=NULL);
testOk1(pvRequest->getSubField("getField.power.alarm").get()!=NULL);
testOk1(pvRequest->getSubField("getField.current.value").get()!=NULL);
testOk1(pvRequest->getSubField("getField.current.alarm").get()!=NULL);
testOk1(pvRequest->getSubField("getField.voltage.value").get()!=NULL);
testOk1(pvRequest->getSubField("getField.voltage.alarm").get()!=NULL);
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}"
+ "})";
if(debug) { cout << "request " << request <<endl;}
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;}
if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
if(debug) { cout << *pvRequest << endl;}
testOk1(pvRequest.get()!=NULL);
testOk1(pvRequest->getSubField("field.alarm").get()!=NULL);
testOk1(pvRequest->getSubField("field.timeStamp").get()!=NULL);
testOk1(pvRequest->getSubField("field.supply.0.voltage.value").get()!=NULL);
testOk1(pvRequest->getSubField("field.supply.0.current.value").get()!=NULL);
testOk1(pvRequest->getSubField("field.supply.0.power.value").get()!=NULL);
testOk1(pvRequest->getSubField("field.supply.1.voltage.value").get()!=NULL);
testOk1(pvRequest->getSubField("field.supply.1.current.value").get()!=NULL);
testOk1(pvRequest->getSubField("field.supply.1.power.value").get()!=NULL);
testPass("request %s",request.c_str());
request = string("record[process=true,xxx=yyy]")
@@ -253,46 +241,45 @@ void testCreateRequest() {
+ "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 << "request " << request <<endl;}
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;}
if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
if(debug) { cout << *pvRequest << endl;}
testOk1(pvRequest.get()!=NULL);
testOk1(pvRequest->getSubField("putField.power.value").get()!=NULL);
testOk1(pvRequest->getSubField("getField.alarm").get()!=NULL);
testOk1(pvRequest->getSubField("getField.timeStamp").get()!=NULL);
testOk1(pvRequest->getSubField("getField.power.value").get()!=NULL);
testOk1(pvRequest->getSubField("getField.power.alarm").get()!=NULL);
testOk1(pvRequest->getSubField("getField.current.value").get()!=NULL);
testOk1(pvRequest->getSubField("getField.current.alarm").get()!=NULL);
testOk1(pvRequest->getSubField("getField.voltage.value").get()!=NULL);
testOk1(pvRequest->getSubField("getField.voltage.alarm").get()!=NULL);
testOk1(pvRequest->getSubField("getField.ps0.alarm").get()!=NULL);
testOk1(pvRequest->getSubField("getField.ps0.timeStamp").get()!=NULL);
testOk1(pvRequest->getSubField("getField.ps0.power.value").get()!=NULL);
testOk1(pvRequest->getSubField("getField.ps0.power.alarm").get()!=NULL);
testOk1(pvRequest->getSubField("getField.ps0.current.value").get()!=NULL);
testOk1(pvRequest->getSubField("getField.ps0.current.alarm").get()!=NULL);
testOk1(pvRequest->getSubField("getField.ps0.voltage.value").get()!=NULL);
testOk1(pvRequest->getSubField("getField.ps0.voltage.alarm").get()!=NULL);
testOk1(pvRequest->getSubField("getField.ps1.alarm").get()!=NULL);
testOk1(pvRequest->getSubField("getField.ps1.timeStamp").get()!=NULL);
testOk1(pvRequest->getSubField("getField.ps1.power.value").get()!=NULL);
testOk1(pvRequest->getSubField("getField.ps1.power.alarm").get()!=NULL);
testOk1(pvRequest->getSubField("getField.ps1.current.value").get()!=NULL);
testOk1(pvRequest->getSubField("getField.ps1.current.alarm").get()!=NULL);
testOk1(pvRequest->getSubField("getField.ps1.voltage.value").get()!=NULL);
testOk1(pvRequest->getSubField("getField.ps1.voltage.alarm").get()!=NULL);
testPass("request %s",request.c_str());
request = "a{b{c{d}}}";
if(debug) { cout << "request " << request <<endl;}
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;}
if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
if(debug) { cout << *pvRequest << endl;}
testOk1(pvRequest.get()!=NULL);
testOk1(pvRequest->getSubField("field.a.b.c.d").get()!=NULL);
testPass("request %s",request.c_str());
request = string("record[process=true,xxx=yyy]")
@@ -302,26 +289,33 @@ void testCreateRequest() {
+ "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;}
if(debug) { cout << "request " << request <<endl;}
cout << endl << "Error Expected for next call!!" << endl;
pvRequest = createRequest->createRequest(request);
assert(pvRequest.get()==NULL);
if(debug) {cout << "reason " << createRequest->getMessage() << endl;}
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;}
if(debug) { cout << "request " << request <<endl;}
cout << endl << "Error Expected for next call!!" << endl;
pvRequest = createRequest->createRequest(request);
assert(pvRequest.get()==NULL);
if(debug) { cout << "reason " << createRequest->getMessage() << endl;}
cout << "reason " << createRequest->getMessage() << endl;
testOk1(pvRequest.get()==NULL);
testPass("request %s",request.c_str());
request = "field(alarm.status,alarm.severity)";
if(debug) { cout << "request " << request <<endl;}
cout << endl << "Error Expected for next call!!" << endl;
pvRequest = createRequest->createRequest(request);
cout << "reason " << createRequest->getMessage() << endl;
testOk1(pvRequest.get()==NULL);
testPass("request %s",request.c_str());
}
MAIN(testCreateRequest)
{
testPlan(111);
testCreateRequest();
testPlan(119);
testCreateRequestInternal();
return testDone();
}

View File

@@ -214,7 +214,7 @@ static void scalarTest()
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; }
if(debug) { cout << "pvRequest\n" << *pvRequest << endl; }
pvCopy = PVCopy::create(pvMaster,pvRequest,"");
valueNameCopy = "value";
testPVScalar(valueNameMaster,valueNameCopy,pvMaster,pvCopy);
@@ -222,7 +222,7 @@ static void scalarTest()
valueNameMaster = "value";
pvRequest = createRequest->createRequest(request);
if(debug) { cout << "request " << request << endl; }
if(debug) { cout << "pvRequest\n" << pvRequest->dumpValue(cout) << endl; }
if(debug) { cout << "pvRequest\n" << *pvRequest << endl; }
pvCopy = PVCopy::create(pvMaster,pvRequest,"");
valueNameCopy = "value";
testPVScalar(valueNameMaster,valueNameCopy,pvMaster,pvCopy);
@@ -230,7 +230,7 @@ static void scalarTest()
valueNameMaster = "value";
pvRequest = createRequest->createRequest(request);
if(debug) { cout << "request " << request << endl; }
if(debug) { cout << "pvRequest\n" << pvRequest->dumpValue(cout) << endl; }
if(debug) { cout << "pvRequest\n" << *pvRequest << endl; }
pvCopy = PVCopy::create(pvMaster,pvRequest,"");
valueNameCopy = "value";
testPVScalar(valueNameMaster,valueNameCopy,pvMaster,pvCopy);
@@ -253,7 +253,7 @@ static void arrayTest()
valueNameMaster = request = "value";
pvRequest = createRequest->createRequest(request);
if(debug) { cout << "request " << request << endl; }
if(debug) { cout << "pvRequest\n" << pvRequest->dumpValue(cout) << endl; }
if(debug) { cout << "pvRequest\n" << *pvRequest << endl; }
pvCopy = PVCopy::create(pvMaster,pvRequest,"");
valueNameCopy = "value";
testPVScalarArray(pvDouble,valueNameMaster,valueNameCopy,pvMaster,pvCopy);
@@ -261,7 +261,7 @@ static void arrayTest()
valueNameMaster = "value";
pvRequest = createRequest->createRequest(request);
if(debug) { cout << "request " << request << endl; }
if(debug) { cout << "pvRequest\n" << pvRequest->dumpValue(cout) << endl; }
if(debug) { cout << "pvRequest\n" << *pvRequest << endl; }
pvCopy = PVCopy::create(pvMaster,pvRequest,"");
valueNameCopy = "value";
testPVScalarArray(pvDouble,valueNameMaster,valueNameCopy,pvMaster,pvCopy);
@@ -269,7 +269,7 @@ static void arrayTest()
valueNameMaster = "value";
pvRequest = createRequest->createRequest(request);
if(debug) { cout << "request " << request << endl; }
if(debug) { cout << "pvRequest\n" << pvRequest->dumpValue(cout) << endl; }
if(debug) { cout << "pvRequest\n" << *pvRequest << endl; }
pvCopy = PVCopy::create(pvMaster,pvRequest,"");
valueNameCopy = "value";
testPVScalarArray(pvDouble,valueNameMaster,valueNameCopy,pvMaster,pvCopy);
@@ -320,7 +320,7 @@ static void powerSupplyTest()
valueNameMaster = request = "power.value";
pvRequest = createRequest->createRequest(request);
if(debug) { cout << "request " << request << endl; }
if(debug) { cout << "pvRequest\n" << pvRequest->dumpValue(cout) << endl; }
if(debug) { cout << "pvRequest\n" << *pvRequest << endl; }
pvCopy = PVCopy::create(pvMaster,pvRequest,"");
valueNameCopy = "power.value";
testPVScalar(valueNameMaster,valueNameCopy,pvMaster,pvCopy);
@@ -328,7 +328,7 @@ static void powerSupplyTest()
valueNameMaster = "power.value";
pvRequest = createRequest->createRequest(request);
if(debug) { cout << "request " << request << endl; }
if(debug) { cout << "pvRequest\n" << pvRequest->dumpValue(cout) << endl; }
if(debug) { cout << "pvRequest\n" << *pvRequest << endl; }
pvCopy = PVCopy::create(pvMaster,pvRequest,"");
valueNameCopy = "power.value";
testPVScalar(valueNameMaster,valueNameCopy,pvMaster,pvCopy);
@@ -336,7 +336,7 @@ static void powerSupplyTest()
valueNameMaster = "power.value";
pvRequest = createRequest->createRequest(request);
if(debug) { cout << "request " << request << endl; }
if(debug) { cout << "pvRequest\n" << pvRequest->dumpValue(cout) << endl; }
if(debug) { cout << "pvRequest\n" << *pvRequest << endl; }
pvCopy = PVCopy::create(pvMaster,pvRequest,"");
valueNameCopy = "power.value";
testPVScalar(valueNameMaster,valueNameCopy,pvMaster,pvCopy);
@@ -344,7 +344,7 @@ static void powerSupplyTest()
valueNameMaster = "power.value";
pvRequest = createRequest->createRequest(request);
if(debug) { cout << "request " << request << endl; }
if(debug) { cout << "pvRequest\n" << pvRequest->dumpValue(cout) << endl; }
if(debug) { cout << "pvRequest\n" << *pvRequest << endl; }
pvCopy = PVCopy::create(pvMaster,pvRequest,"");
valueNameCopy = "power.value";
testPVScalar(valueNameMaster,valueNameCopy,pvMaster,pvCopy);

View File

@@ -1,63 +1,66 @@
TOP=../..
# This is a Makefile fragment, see ../Makefile
include $(TOP)/configure/CONFIG
SRC_DIRS += $(PVDATA_TEST)/misc
PROD_LIBS += pvData Com
PROD_HOST += testThread
TESTPROD_HOST += testThread
testThread_SRCS += testThread.cpp
testHarness_SRCS += testThread.cpp
TESTS += testThread
PROD_HOST += testTimer
TESTPROD_HOST += testTimer
testTimer_SRCS += testTimer.cpp
testHarness_SRCS += testTimer.cpp
TESTS += testTimer
PROD_HOST += testBitSet
TESTPROD_HOST += testBitSet
testBitSet_SRCS += testBitSet.cpp
testHarness_SRCS += testBitSet.cpp
TESTS += testBitSet
PROD_HOST += testOverrunBitSet
TESTPROD_HOST += testOverrunBitSet
testOverrunBitSet_SRCS += testOverrunBitSet.cpp
testHarness_SRCS += testOverrunBitSet.cpp
TESTS += testOverrunBitSet
PROD_HOST += testByteOrder
TESTPROD_HOST += testByteOrder
testByteOrder_SRCS += testByteOrder.cpp
PROD_HOST += testByteBuffer
TESTPROD_HOST += testByteBuffer
testByteBuffer_SRCS += testByteBuffer.cpp
testHarness_SRCS += testByteBuffer.cpp
TESTS += testByteBuffer
PROD_HOST += testBaseException
TESTPROD_HOST += testBaseException
testBaseException_SRCS += testBaseException.cpp
testHarness_SRCS += testBaseException.cpp
TESTS += testBaseException
PROD_HOST += testSharedVector
TESTPROD_HOST += testSharedVector
testSharedVector_SRCS += testSharedVector.cpp
testHarness_SRCS += testSharedVector.cpp
TESTS += testSharedVector
PROD_HOST += testSerialization
TESTPROD_HOST += testSerialization
testSerialization_SRCS += testSerialization.cpp
testHarness_SRCS += testSerialization.cpp
TESTS += testSerialization
PROD_HOST += testTimeStamp
TESTPROD_HOST += testTimeStamp
testTimeStamp_SRCS += testTimeStamp.cpp
testHarness_SRCS += testTimeStamp.cpp
TESTS += testTimeStamp
PROD_HOST += testQueue
TESTPROD_HOST += testQueue
testQueue_SRCS += testQueue.cpp
testHarness_SRCS += testQueue.cpp
TESTS += testQueue
PROD_HOST += testMessageQueue
TESTPROD_HOST += testMessageQueue
testMessageQueue_SRCS += testMessageQueue.cpp
testHarness_SRCS += testMessageQueue.cpp
TESTS += testMessageQueue
PROD_HOST += testTypeCast
TESTPROD_HOST += testTypeCast
testTypeCast_SRCS += testTypeCast.cpp
testHarness_SRCS += testTypeCast.cpp
TESTS += testTypeCast
TESTSCRIPTS_HOST += $(TESTS:%=%.t)
include $(TOP)/configure/RULES
#----------------------------------------
# ADD RULES AFTER THIS LINE

View File

@@ -42,7 +42,7 @@ void internalTestBaseException(int /*unused*/ = 0)
}
}
void testBaseException() {
void testBaseExceptionTest() {
printf("testBaseException... ");
try {
@@ -86,7 +86,7 @@ MAIN(testBaseException)
testPlan(2);
testDiag("Tests base exception");
testLogicException();
testBaseException();
testBaseExceptionTest();
return testDone();
}

View File

@@ -1,7 +1,8 @@
#include <testMain.h>
#include <epicsEndian.h>
#include <stdio.h>
int main()
MAIN(testByteOrder)
{
printf("EPICS_BYTE_ORDER: %s\n", (EPICS_BYTE_ORDER == EPICS_ENDIAN_LITTLE) ? "little" : "big");
printf("EPICS_FLOAT_WORD_ORDER: %s\n", (EPICS_FLOAT_WORD_ORDER == EPICS_ENDIAN_LITTLE) ? "little" : "big");

View File

@@ -41,11 +41,11 @@ void test()
uint32 messageOffset = (uint32) pvMessage->getFieldOffset();
PVStructurePtr pvTimeStamp = pvStructure->getStructureField("timeStamp");
PVLongPtr pvSeconds = pvTimeStamp->getLongField("secondsPastEpoch");
PVIntPtr pvNanoSeconds = pvTimeStamp->getIntField("nanoSeconds");
PVIntPtr pvNanoseconds = pvTimeStamp->getIntField("nanoseconds");
PVIntPtr pvUserTag = pvTimeStamp->getIntField("userTag");
uint32 timeStampOffset = (uint32) pvTimeStamp->getFieldOffset();
uint32 secondsOffset = (uint32) pvSeconds->getFieldOffset();
uint32 nanoSecondsOffset = (uint32) pvNanoSeconds->getFieldOffset();
uint32 nanosecondsOffset = (uint32) pvNanoseconds->getFieldOffset();
uint32 userTagOffset = (uint32) pvUserTag->getFieldOffset();
uint32 nfields = (uint32) pvStructure->getNumberFields();
BitSetPtr changeBitSet = BitSet::create(nfields);
@@ -55,7 +55,7 @@ void test()
pvSeverity->put(2); changeBitSet->set(severityOffset);
pvMessage->put("error"); changeBitSet->set(messageOffset);
pvSeconds->put(1); changeBitSet->set(secondsOffset);
pvNanoSeconds->put(1000000); changeBitSet->set(nanoSecondsOffset);
pvNanoseconds->put(1000000); changeBitSet->set(nanosecondsOffset);
pvUserTag->put(1); changeBitSet->set(userTagOffset);
userOverrunBitSet->or_and(*changeBitSet.get(),*userChangeBitSet.get());
(*userChangeBitSet)|=(*changeBitSet.get());
@@ -64,7 +64,7 @@ void test()
pvSeverity->put(0); changeBitSet->set(severityOffset);
pvMessage->put(""); changeBitSet->set(messageOffset);
pvSeconds->put(2); changeBitSet->set(secondsOffset);
pvNanoSeconds->put(0); changeBitSet->set(nanoSecondsOffset);
pvNanoseconds->put(0); changeBitSet->set(nanosecondsOffset);
pvUserTag->put(0); changeBitSet->set(userTagOffset);
userOverrunBitSet->or_and(*changeBitSet.get(),*userChangeBitSet.get());
(*userChangeBitSet)|=(*changeBitSet.get());
@@ -73,14 +73,14 @@ void test()
testOk1(userChangeBitSet->get(severityOffset));
testOk1(userChangeBitSet->get(messageOffset));
testOk1(userChangeBitSet->get(secondsOffset));
testOk1(userChangeBitSet->get(nanoSecondsOffset));
testOk1(userChangeBitSet->get(nanosecondsOffset));
testOk1(userChangeBitSet->get(userTagOffset));
testOk1(userOverrunBitSet->cardinality()==6);
testOk1(userOverrunBitSet->get(valueOffset));
testOk1(userOverrunBitSet->get(severityOffset));
testOk1(userOverrunBitSet->get(messageOffset));
testOk1(userOverrunBitSet->get(secondsOffset));
testOk1(userOverrunBitSet->get(nanoSecondsOffset));
testOk1(userOverrunBitSet->get(nanosecondsOffset));
testOk1(userOverrunBitSet->get(userTagOffset));
BitSetUtil::compress(userChangeBitSet,pvStructure);
@@ -101,13 +101,13 @@ void test()
userOverrunBitSet->clear();
pvValue->put(1.0); changeBitSet->set(valueOffset);
pvSeconds->put(3); changeBitSet->set(secondsOffset);
pvNanoSeconds->put(0); changeBitSet->set(nanoSecondsOffset);
pvNanoseconds->put(0); changeBitSet->set(nanosecondsOffset);
userOverrunBitSet->or_and(*changeBitSet.get(),*userChangeBitSet.get());
(*userChangeBitSet)|=(*changeBitSet.get());
testOk1(userChangeBitSet->cardinality()==3);
testOk1(userChangeBitSet->get(valueOffset));
testOk1(userChangeBitSet->get(secondsOffset));
testOk1(userChangeBitSet->get(nanoSecondsOffset));
testOk1(userChangeBitSet->get(nanosecondsOffset));
testOk1(userOverrunBitSet->cardinality()==0);
changeBitSet->clear();
@@ -117,7 +117,7 @@ void test()
testOk1(userChangeBitSet->cardinality()==3);
testOk1(userChangeBitSet->get(valueOffset));
testOk1(userChangeBitSet->get(secondsOffset));
testOk1(userChangeBitSet->get(nanoSecondsOffset));
testOk1(userChangeBitSet->get(nanosecondsOffset));
testOk1(userOverrunBitSet->cardinality()==1);
testOk1(userOverrunBitSet->get(valueOffset));
@@ -126,13 +126,13 @@ void test()
testOk1(userChangeBitSet->cardinality()==3);
testOk1(userChangeBitSet->get(valueOffset));
testOk1(userChangeBitSet->get(secondsOffset));
testOk1(userChangeBitSet->get(nanoSecondsOffset));
testOk1(userChangeBitSet->get(nanosecondsOffset));
testOk1(userOverrunBitSet->cardinality()==1);
testOk1(userOverrunBitSet->get(valueOffset));
}
MAIN(testOverrunBitSet`)
MAIN(testOverrunBitSet)
{
testPlan(41);
testDiag("Tests for changeBitSet and overrunBitSet");

View File

@@ -386,7 +386,7 @@ void testStructure() {
testDiag("\tSimple structure serialization");
PVStructurePtr pvStructure = factory->createPVStructure(getStandardField()->timeStamp());
pvStructure->getLongField("secondsPastEpoch")->put(123);
pvStructure->getIntField("nanoSeconds")->put(456);
pvStructure->getIntField("nanoseconds")->put(456);
pvStructure->getIntField("userTag")->put(789);
serializationTest(pvStructure);
@@ -625,13 +625,13 @@ void testStructureId() {
testOk1(structureWithNoId!=structure1);
testOk1(structure1!=structure2);
//serializationTest(structure1);
//serializationFieldTest(structure1);
PVStructurePtr pvStructure = getPVDataCreate()->createPVStructure(structure1);
serializationTest(pvStructure);
}
void serializatioTest(FieldConstPtr const & field)
void serializationFieldTest(FieldConstPtr const & field)
{
buffer->clear();
@@ -660,27 +660,27 @@ void testIntrospectionSerialization()
ScalarType scalarType = static_cast<ScalarType>(i);
ScalarConstPtr scalar = factory->createScalar(scalarType);
serializatioTest(scalar);
serializationFieldTest(scalar);
ScalarArrayConstPtr array = factory->createScalarArray(scalarType);
serializatioTest(array);
serializationFieldTest(array);
}
// and a structure
StructureConstPtr structure = getStandardField()->timeStamp();
serializatioTest(structure);
serializationFieldTest(structure);
// and a structure array
StructureArrayConstPtr structureArray = factory->createStructureArray(structure);
serializatioTest(structureArray);
serializationFieldTest(structureArray);
// variant union
UnionConstPtr variant = factory->createVariantUnion();
serializatioTest(variant);
serializationFieldTest(variant);
// variant array union
UnionArrayConstPtr variantArray = factory->createVariantUnionArray();
serializatioTest(variantArray);
serializationFieldTest(variantArray);
// union
UnionConstPtr punion = factory->createFieldBuilder()->
@@ -692,11 +692,66 @@ void testIntrospectionSerialization()
endNested()->
addArray("intArray", pvInt)->
createUnion();
serializatioTest(punion);
serializationFieldTest(punion);
// union array
UnionArrayConstPtr punionArray = factory->createUnionArray(punion);
serializatioTest(punionArray);
serializationFieldTest(punionArray);
}
void testArraySizeType() {
testDiag("Testing array size types...");
FieldCreatePtr fieldCreate = getFieldCreate();
StructureConstPtr s = fieldCreate->createFieldBuilder()->
addArray("variableArray", pvDouble)->
addFixedArray("fixedArray", pvDouble, 10)->
addBoundedArray("boundedArray", pvDouble, 1024)->
createStructure();
testOk1(s.get() != 0);
testOk1(Structure::DEFAULT_ID == s->getID());
testOk1(3 == s->getFields().size());
serializationFieldTest(s);
PVStructurePtr pvs = getPVDataCreate()->createPVStructure(s);
PVDoubleArray::shared_pointer pvDA = pvs->getSubField<PVDoubleArray>("fixedArray");
PVDoubleArray::svector vec(10, 42);
pvDA->replace(freeze(vec));
serializationTest(pvs);
}
void testBoundedString() {
testDiag("Testing bounded string...");
FieldCreatePtr fieldCreate = getFieldCreate();
StructureConstPtr s = fieldCreate->createFieldBuilder()->
add("str", pvString)->
addBoundedString("boundedStr", 8)->
add("scalar", pvDouble)->
createStructure();
testOk1(s.get() != 0);
testOk1(Structure::DEFAULT_ID == s->getID());
testOk1(3 == s->getFields().size());
serializationFieldTest(s);
PVStructurePtr pvs = getPVDataCreate()->createPVStructure(s);
serializationTest(pvs);
PVStringPtr pvStr = pvs->getSubField<PVString>("boundedStr");
pvStr->put("");
pvStr->put("small");
pvStr->put("exact123");
try {
pvStr->put("tooLargeString");
testFail("too large string accepted");
} catch (std::overflow_error oe) {
// OK
}
}
void testStringCopy() {
@@ -710,7 +765,7 @@ void testStringCopy() {
MAIN(testSerialization) {
testPlan(213);
testPlan(226);
flusher = new SerializableControlImpl();
control = new DeserializableControlImpl();
@@ -724,16 +779,19 @@ MAIN(testSerialization) {
testScalar();
testArray();
testStructure();
testStructureId();
testStructureArray();
testUnion();
testArraySizeType();
testBoundedString();
delete buffer;
delete control;
delete flusher;
epicsExitCallAtExits();
return testDone();
}

View File

@@ -19,11 +19,12 @@
#include "pv/sharedVector.h"
using std::string;
using namespace epics::pvData;
static void testEmpty()
{
testDiag("Test empty vector");
epics::pvData::shared_vector<int> empty, empty2;
epics::pvData::shared_vector<int32> empty, empty2;
testOk1(empty.size()==0);
testOk1(empty.empty());
@@ -42,7 +43,7 @@ static void testInternalAlloc()
{
testDiag("Test vector alloc w/ new[]");
epics::pvData::shared_vector<int> internal(5);
epics::pvData::shared_vector<int32> internal(5);
testOk1(internal.size()==5);
testOk1(!internal.empty());
@@ -57,7 +58,7 @@ static void testInternalAlloc()
internal[2] = 42;
testOk1(internal[2]==42);
epics::pvData::shared_vector<int> internal2(15, 500);
epics::pvData::shared_vector<int32> internal2(15, 500);
testOk1(internal2.size()==15);
testOk1(internal2[1]==500);
@@ -79,8 +80,8 @@ namespace {
//Note: STL shared_ptr requires that deletors be copy constructable
template<typename E>
struct callCounter {
std::tr1::shared_ptr<int> count;
callCounter():count(new int){*count=0;}
std::tr1::shared_ptr<int32> count;
callCounter():count(new int32){*count=0;}
callCounter(const callCounter& o):count(o.count) {};
callCounter& operator=(const callCounter& o){count=o.count;}
void operator()(E){*count=1;}
@@ -92,8 +93,8 @@ static void testExternalAlloc()
testDiag("Test vector external alloc");
// Simulate a failed malloc() or similar
int *oops=0;
epics::pvData::shared_vector<int> nullPtr(oops, 42, 100);
int32 *oops=0;
epics::pvData::shared_vector<int32> nullPtr(oops, 42, 100);
testOk1(nullPtr.size()==0);
testOk1(nullPtr.empty());
@@ -102,8 +103,8 @@ static void testExternalAlloc()
testOk1(nullPtr.data()==NULL);
int *raw=new int[5];
epics::pvData::shared_vector<int> newData(raw, 1, 4);
int32 *raw=new int32[5];
epics::pvData::shared_vector<int32> newData(raw, 1, 4);
testOk1(newData.size()==4);
testOk1(!newData.empty());
@@ -113,11 +114,11 @@ static void testExternalAlloc()
testOk1(newData[0]==14);
// Check use of custom deleter
int localVar[4] = {1,2,3,4};
callCounter<int*> tracker;
int32 localVar[4] = {1,2,3,4};
callCounter<int32*> tracker;
testOk1(*tracker.count==0);
epics::pvData::shared_vector<int> locvar(localVar,
epics::pvData::shared_vector<int32> locvar(localVar,
tracker,
0, 4);
@@ -137,8 +138,8 @@ static void testShare()
{
testDiag("Test vector Sharing");
epics::pvData::shared_vector<int> one, two(15);
epics::pvData::shared_vector<int> three(two);
epics::pvData::shared_vector<int32> one, two(15);
epics::pvData::shared_vector<int32> three(two);
testOk1(one.unique());
testOk1(!two.unique());
@@ -199,22 +200,22 @@ static void testConst()
{
testDiag("Test constant vector");
epics::pvData::shared_vector<int> writable(15, 100);
epics::pvData::shared_vector<int32> writable(15, 100);
epics::pvData::shared_vector<int>::reference wr = writable[0];
epics::pvData::shared_vector<int>::const_reference ror = writable[0];
epics::pvData::shared_vector<int32>::reference wr = writable[0];
epics::pvData::shared_vector<int32>::const_reference ror = writable[0];
testOk1(wr==ror);
int *compare = writable.data();
int32 *compare = writable.data();
testOk1(writable.unique());
// can re-target container, but data is R/O
epics::pvData::shared_vector<const int> rodata(freeze(writable));
epics::pvData::shared_vector<const int32> rodata(freeze(writable));
epics::pvData::shared_vector<const int>::reference wcr = rodata[0];
epics::pvData::shared_vector<const int>::const_reference rocr = rodata[0];
epics::pvData::shared_vector<const int32>::reference wcr = rodata[0];
epics::pvData::shared_vector<const int32>::const_reference rocr = rodata[0];
testOk1(wcr==rocr);
@@ -227,7 +228,7 @@ static void testConst()
testOk1(rodata.data()==compare);
epics::pvData::shared_vector<const int> rodata2(rodata);
epics::pvData::shared_vector<const int32> rodata2(rodata);
testOk1(rodata.data()==rodata2.data());
@@ -240,9 +241,9 @@ static void testSlice()
{
testDiag("Test vector slicing");
epics::pvData::shared_vector<int> original(10, 100);
epics::pvData::shared_vector<int32> original(10, 100);
epics::pvData::shared_vector<int> half1(original), half2(original), half2a(original);
epics::pvData::shared_vector<int32> half1(original), half2(original), half2a(original);
half1.slice(0, 5);
half2.slice(5, 5);
@@ -290,9 +291,9 @@ static void testCapacity()
{
testDiag("Test vector capacity");
epics::pvData::shared_vector<int> vect(10, 100);
epics::pvData::shared_vector<int32> vect(10, 100);
int *peek = vect.dataPtr().get();
int32 *peek = vect.dataPtr().get();
vect.slice(0, 5);
@@ -330,7 +331,7 @@ static void testCapacity()
static void testPush()
{
epics::pvData::shared_vector<int> vect;
epics::pvData::shared_vector<int32> vect;
testDiag("Test push_back optimizations");
@@ -357,7 +358,7 @@ static void testVoid()
{
testDiag("Test vecter cast to/from void");
epics::pvData::shared_vector<int> typed(4);
epics::pvData::shared_vector<int32> typed(4);
epics::pvData::shared_vector<void> untyped2(epics::pvData::static_shared_vector_cast<void>(typed));
@@ -366,7 +367,7 @@ static void testVoid()
untyped2.slice(sizeof(int), 2*sizeof(int));
typed = epics::pvData::static_shared_vector_cast<int>(untyped2);
typed = epics::pvData::static_shared_vector_cast<int32>(untyped2);
testOk1(typed.dataOffset()==1);
testOk1(typed.size()==2);
@@ -406,7 +407,7 @@ static void testVectorConvert()
{
testDiag("Test shared_vector_convert");
epics::pvData::shared_vector<int> ints(6, 42), moreints;
epics::pvData::shared_vector<int32> ints(6, 42), moreints;
epics::pvData::shared_vector<float> floats;
epics::pvData::shared_vector<string> strings;
epics::pvData::shared_vector<void> voids;
@@ -414,7 +415,7 @@ static void testVectorConvert()
testOk1(ints.unique());
// no-op convert. Just returns another reference
moreints = epics::pvData::shared_vector_convert<int>(ints);
moreints = epics::pvData::shared_vector_convert<int32>(ints);
testOk1(!ints.unique());
moreints.clear();
@@ -432,11 +433,12 @@ static void testVectorConvert()
voids = epics::pvData::shared_vector_convert<void>(ints);
testOk1(!ints.unique());
testOk1(voids.size()==ints.size()*sizeof(int));
testOk1(voids.size()==ints.size()*sizeof(int32));
// convert from void uses shared_vector<void>::original_type()
// to find that the actual type is 'int'.
// to find that the actual type is 'int32'.
// returns a new vector
testOk1(voids.original_type()==epics::pvData::pvInt);
strings = epics::pvData::shared_vector_convert<string>(voids);
voids.clear();
@@ -450,11 +452,11 @@ static void testWeak()
{
testDiag("Test weak_ptr counting");
epics::pvData::shared_vector<int> data(6);
epics::pvData::shared_vector<int32> data(6);
testOk1(data.unique());
std::tr1::shared_ptr<int> pdata(data.dataPtr());
std::tr1::shared_ptr<int32> pdata(data.dataPtr());
testOk1(!data.unique());
@@ -462,7 +464,7 @@ static void testWeak()
testOk1(data.unique());
std::tr1::weak_ptr<int> wdata(data.dataPtr());
std::tr1::weak_ptr<int32> wdata(data.dataPtr());
testOk1(data.unique()); // True, but I wish it wasn't!!!
@@ -475,10 +477,10 @@ static void testICE()
{
testDiag("Test freeze and thaw");
epics::pvData::shared_vector<int> A(6, 42), C;
epics::pvData::shared_vector<const int> B, D;
epics::pvData::shared_vector<int32> A(6, 42), C;
epics::pvData::shared_vector<const int32> B, D;
int *check = A.data();
int32 *check = A.data();
// check freeze w/ unique reference
@@ -537,11 +539,11 @@ static void testICE()
MAIN(testSharedVector)
{
testPlan(162);
testPlan(163);
testDiag("Tests for shared_vector");
testDiag("sizeof(shared_vector<int>)=%lu",
(unsigned long)sizeof(epics::pvData::shared_vector<int>));
testDiag("sizeof(shared_vector<int32>)=%lu",
(unsigned long)sizeof(epics::pvData::shared_vector<int32>));
testEmpty();
testInternalAlloc();

View File

@@ -28,14 +28,14 @@ using namespace epics::pvData;
static bool debug = false;
void testTimeStamp()
void testTimeStampInternal()
{
testOk1(nanoSecPerSec==1000000000);
TimeStamp current;
current.getCurrent();
printf("current %lli %i milliSec %lli\n",
(long long)current.getSecondsPastEpoch(),
current.getNanoSeconds(),
current.getNanoseconds(),
(long long)current.getMilliseconds());
time_t tt;
current.toTime_t(tt);
@@ -45,13 +45,13 @@ void testTimeStamp()
"%4.4d.%2.2d.%2.2d %2.2d:%2.2d:%2.2d %d isDst %s\n",
ctm.tm_year+1900,ctm.tm_mon + 1,ctm.tm_mday,
ctm.tm_hour,ctm.tm_min,ctm.tm_sec,
current.getNanoSeconds(),
current.getNanoseconds(),
(ctm.tm_isdst==0) ? "false" : "true");
tt = time(&tt);
current.fromTime_t(tt);
printf("fromTime_t\ncurrent %lli %i milliSec %lli\n",
(long long)current.getSecondsPastEpoch(),
current.getNanoSeconds(),
current.getNanoseconds(),
(long long)current.getMilliseconds());
current.toTime_t(tt);
memcpy(&ctm,localtime(&tt),sizeof(struct tm));
@@ -59,12 +59,12 @@ void testTimeStamp()
"%4.4d.%2.2d.%2.2d %2.2d:%2.2d:%2.2d %d isDst %s\n",
ctm.tm_year+1900,ctm.tm_mon + 1,ctm.tm_mday,
ctm.tm_hour,ctm.tm_min,ctm.tm_sec,
current.getNanoSeconds(),
current.getNanoseconds(),
(ctm.tm_isdst==0) ? "false" : "true");
TimeStamp right;
TimeStamp left;
right.put(current.getSecondsPastEpoch(),current.getNanoSeconds());
left.put(current.getSecondsPastEpoch(),current.getNanoSeconds());
right.put(current.getSecondsPastEpoch(),current.getNanoseconds());
left.put(current.getSecondsPastEpoch(),current.getNanoseconds());
double diff;
diff = TimeStamp::diff(left,right);
if(debug) printf("diff %e\n",diff);
@@ -75,7 +75,7 @@ void testTimeStamp()
testOk1(!(left<right));
testOk1((left>=right));
testOk1(!(left>right));
left.put(current.getSecondsPastEpoch()+1,current.getNanoSeconds());
left.put(current.getSecondsPastEpoch()+1,current.getNanoseconds());
diff = TimeStamp::diff(left,right);
if(debug) printf("diff %e\n",diff);
testOk1(diff==1.0);
@@ -85,7 +85,7 @@ void testTimeStamp()
testOk1(!(left<right));
testOk1((left>=right));
testOk1((left>right));
left.put(current.getSecondsPastEpoch()-1,current.getNanoSeconds());
left.put(current.getSecondsPastEpoch()-1,current.getNanoseconds());
diff = TimeStamp::diff(left,right);
if(debug) printf("diff %e\n",diff);
testOk1(diff==-1.0);
@@ -95,7 +95,7 @@ void testTimeStamp()
testOk1((left<right));
testOk1(!(left>=right));
testOk1(!(left>right));
left.put(current.getSecondsPastEpoch(),current.getNanoSeconds()-nanoSecPerSec);
left.put(current.getSecondsPastEpoch(),current.getNanoseconds()-nanoSecPerSec);
diff = TimeStamp::diff(left,right);
if(debug) printf("diff %e\n",diff);
testOk1(diff==-1.0);
@@ -105,7 +105,7 @@ void testTimeStamp()
testOk1((left<right));
testOk1(!(left>=right));
testOk1(!(left>right));
left.put(current.getSecondsPastEpoch(),current.getNanoSeconds()-1);
left.put(current.getSecondsPastEpoch(),current.getNanoseconds()-1);
diff = TimeStamp::diff(left,right);
if(debug) printf("diff %e\n",diff);
testOk1(diff<0.0);
@@ -115,11 +115,11 @@ void testTimeStamp()
testOk1((left<right));
testOk1(!(left>=right));
testOk1(!(left>right));
left.put(current.getSecondsPastEpoch(),current.getNanoSeconds());
left.put(current.getSecondsPastEpoch(),current.getNanoseconds());
left += .1;
diff = TimeStamp::diff(left,right);
if(debug) printf("diff %e\n",diff);
left.put(current.getSecondsPastEpoch(),current.getNanoSeconds());
left.put(current.getSecondsPastEpoch(),current.getNanoseconds());
int64 inc = -1;
left += inc;
diff = TimeStamp::diff(left,right);
@@ -131,6 +131,6 @@ MAIN(testTimeStamp)
{
testPlan(37);
testDiag("Tests timeStamp");
testTimeStamp();
testTimeStampInternal();
return testDone();
}

View File

@@ -37,11 +37,11 @@ namespace {
};
template<>
struct testequal<double> {
static bool op(double A, double B) {return fabs(A-B)<1e-300; }
static bool op(double A, double B) {return fabs(A-B)<1e-15; }
};
template<>
struct testequal<float> {
static bool op(float A, float B) {return fabs(A-B)<1e-30; }
static bool op(float A, float B) {return fabs(A-B)<1e-7; }
};
template<typename TO, typename FROM>
@@ -117,7 +117,7 @@ namespace {
MAIN(testTypeCast)
{
testPlan(122);
testPlan(123);
try {
@@ -387,7 +387,8 @@ try {
FAIL(int8_t, string, "1000");
FAIL(int8_t, string, "-1000");
FAIL(double, string, "1e+10000000");
FAIL(double, string, "1e+1000");
FAIL(double, string, "-1e+1000");
FAIL(epics::pvData::boolean, string, "hello");
FAIL(epics::pvData::boolean, string, "1");

View File

@@ -1,16 +1,8 @@
TOP=../..
# This is a Makefile fragment, see ../Makefile
include $(TOP)/configure/CONFIG
SRC_DIRS += $(PVDATA_TEST)/property
TESTPROD_HOST += testProperty
testProperty_SRCS += testProperty.cpp
testHarness_SRCS += testProperty.cpp
TESTS += testProperty
testProperty_LIBS += pvData Com
TESTSCRIPTS_HOST += $(TESTS:%=%.t)
include $(TOP)/configure/RULES
#----------------------------------------
# ADD RULES AFTER THIS LINE

View File

@@ -48,11 +48,15 @@ static string allProperties("alarm,timeStamp,display,control");
static PVStructurePtr doubleRecord;
static PVStructurePtr enumeratedRecord;
static void printRecords()
{
std::cout << "doubleRecord" << std::endl << *doubleRecord << std::endl;
std::cout << "enumeratedRecord" << std::endl << *enumeratedRecord << std::endl;
}
static void createRecords()
{
doubleRecord = standardPVField->scalar(pvDouble,allProperties);
if(debug)
std::cout << "doubleRecord" << std::endl << *doubleRecord << std::endl;
StringArray choices;
choices.reserve(4);
choices.push_back("1");
@@ -60,14 +64,7 @@ static void createRecords()
choices.push_back("3");
choices.push_back("4");
enumeratedRecord = standardPVField->enumerated(choices,alarmTimeStamp);
if(debug)
std::cout << "enumeratedRecord" << std::endl << *doubleRecord << std::endl;
}
static void printRecords()
{
std::cout << "doubleRecord" << std::endl << *doubleRecord << std::endl;
std::cout << "enumeratedRecord" << std::endl << *doubleRecord << std::endl;
if(debug) printRecords();
}
static void testAlarm()
@@ -123,7 +120,7 @@ static void testTimeStamp()
testOk1(result);
pvTimeStamp.get(timeStamp);
testOk1(ts.getSecondsPastEpoch()==timeStamp.getSecondsPastEpoch());
testOk1(ts.getNanoSeconds()==timeStamp.getNanoSeconds());
testOk1(ts.getNanoseconds()==timeStamp.getNanoseconds());
testOk1(ts.getUserTag()==timeStamp.getUserTag());
time_t tt;
timeStamp.toTime_t(tt);
@@ -131,10 +128,10 @@ static void testTimeStamp()
memcpy(&ctm,localtime(&tt),sizeof(struct tm));
if(debug) {
printf(
"%4.4d.%2.2d.%2.2d %2.2d:%2.2d:%2.2d %d nanoSeconds isDst %s userTag %d\n",
"%4.4d.%2.2d.%2.2d %2.2d:%2.2d:%2.2d %d nanoseconds isDst %s userTag %d\n",
ctm.tm_year+1900,ctm.tm_mon + 1,ctm.tm_mday,
ctm.tm_hour,ctm.tm_min,ctm.tm_sec,
timeStamp.getNanoSeconds(),
timeStamp.getNanoseconds(),
(ctm.tm_isdst==0) ? "false" : "true",
timeStamp.getUserTag());
}

View File

@@ -1,65 +1,63 @@
TOP=../..
# This is a Makefile fragment, see ../Makefile
include $(TOP)/configure/CONFIG
SRC_DIRS += $(PVDATA_TEST)/pv
PROD_HOST += testBitSetUtil
TESTPROD_HOST += testBitSetUtil
testBitSetUtil_SRCS += testBitSetUtil.cpp
testBitSetUtil_LIBS += pvData Com
testHarness_SRCS += testBitSetUtil.cpp
TESTS += testBitSetUtil
PROD_HOST += testIntrospect
TESTPROD_HOST += testIntrospect
testIntrospect_SRCS += testIntrospect.cpp
testIntrospect_LIBS += pvData Com
testHarness_SRCS += testIntrospect.cpp
TESTS += testIntrospect
PROD_HOST += testPVType
TESTPROD_HOST += testPVType
testPVType_SRCS += testPVType.cpp
testPVType_LIBS += pvData Com
testHarness_SRCS += testPVType.cpp
TESTS += testPVType
PROD_HOST += testStandardField
TESTPROD_HOST += testStandardField
testStandardField_SRCS += testStandardField.cpp
testStandardField_LIBS += pvData Com
testHarness_SRCS += testStandardField.cpp
TESTS += testStandardField
PROD_HOST += testStandardPVField
TESTPROD_HOST += testStandardPVField
testStandardPVField_SRCS += testStandardPVField.cpp
testStandardPVField_LIBS += pvData Com
testHarness_SRCS += testStandardPVField.cpp
TESTS += testStandardPVField
PROD_HOST += testPVData
TESTPROD_HOST += testPVData
testPVData_SRCS += testPVData.cpp
testPVData_LIBS += pvData Com
testHarness_SRCS += testPVData.cpp
TESTS += testPVData
PROD_HOST += testConvert
TESTPROD_HOST += testPVUnion
testPVUnion_SRCS += testPVUnion.cpp
testHarness_SRCS += testPVUnion.cpp
TESTS += testPVUnion
TESTPROD_HOST += testConvert
testConvert_SRCS += testConvert.cpp
testConvert_LIBS += pvData Com
testHarness_SRCS += testConvert.cpp
TESTS += testConvert
PROD_HOST += testPVScalarArray
TESTPROD_HOST += testPVScalarArray
testPVScalarArray_SRCS += testPVScalarArray.cpp
testPVScalarArray_LIBS += pvData Com
testHarness_SRCS += testPVScalarArray.cpp
TESTS += testPVScalarArray
PROD_HOST += testPVStructureArray
TESTPROD_HOST += testPVStructureArray
testPVStructureArray_SRCS += testPVStructureArray.cpp
testPVStructureArray_LIBS += pvData Com
testHarness_SRCS += testPVStructureArray.cpp
TESTS += testPVStructureArray
PROD_HOST += testOperators
TESTPROD_HOST += testOperators
testOperators_SRCS += testOperators.cpp
testOperators_LIBS += pvData Com
testHarness_SRCS += testOperators.cpp
TESTS += testOperators
PROD_HOST += testFieldBuilder
TESTPROD_HOST += testFieldBuilder
testFieldBuilder_SRCS += testFieldBuilder.cpp
testFieldBuilder_LIBS += pvData Com
testHarness_SRCS += testFieldBuilder.cpp
TESTS += testFieldBuilder
TESTSCRIPTS_HOST += $(TESTS:%=%.t)
include $(TOP)/configure/RULES
#----------------------------------------
# ADD RULES AFTER THIS LINE

View File

@@ -90,7 +90,7 @@ static void test()
int32 offsetTimeStamp = (int32)pvField->getFieldOffset();
pvField = pvs->getSubField("timeStamp.secondsPastEpoch");
int32 offsetSeconds = (int32)pvField->getFieldOffset();
pvField = pvs->getSubField("timeStamp.nanoSeconds");
pvField = pvs->getSubField("timeStamp.nanoseconds");
int32 offsetNano = (int32)pvField->getFieldOffset();
pvField = pvs->getSubField("timeStamp.userTag");
int32 offsetUserTag = (int32)pvField->getFieldOffset();

View File

@@ -60,7 +60,7 @@ void test_structure()
StructureConstPtr s2 = fb->add("s", s)->
addArray("sArray", s)->
createStructure();
testOk1(s2 != 0);
testOk1(s2.get()!=0);
testOk1(Structure::DEFAULT_ID == s2->getID());
testOk1(2 == s2->getFields().size());
@@ -110,6 +110,23 @@ void test_invalid()
}
void test_arraySizeTypes()
{
testDiag("Test test_arraySizeTypes()");
FieldCreatePtr fieldCreate = getFieldCreate();
StructureConstPtr s = fieldCreate->createFieldBuilder()->
addArray("variableArray", pvDouble)->
addFixedArray("fixedArray", pvDouble, 10)->
addBoundedArray("boundedArray", pvDouble, 1024)->
createStructure();
testOk1(s.get() != 0);
testOk1(Structure::DEFAULT_ID == s->getID());
testOk1(3 == s->getFields().size());
}
void test_nestedStructure()
{
testDiag("Test test_nestedStructure()");
@@ -224,11 +241,12 @@ void test_nestedStructureArray()
MAIN(testFieldBuilder)
{
testPlan(65);
testPlan(68);
testDiag("Tests for FieldBuilder");
test_factory();
test_structure();
test_arraySizeTypes();
test_nestedStructure();
test_nestedStructureArray();

View File

@@ -59,9 +59,26 @@ static void testScalar() {
}
static void testScalarArrayCommon(ScalarType stype,
bool isInteger,bool isNumeric,bool isPrimitive)
bool isInteger,bool isNumeric,bool isPrimitive,
Array::ArraySizeType sizeType = Array::variable, size_t size = 0)
{
ScalarArrayConstPtr pscalar = fieldCreate->createScalarArray(stype);
ScalarArrayConstPtr pscalar;
switch (sizeType)
{
case Array::variable:
pscalar = fieldCreate->createScalarArray(stype);
size = 0;
break;
case Array::bounded:
pscalar = fieldCreate->createBoundedScalarArray(stype, size);
break;
case Array::fixed:
pscalar = fieldCreate->createFixedScalarArray(stype, size);
break;
default:
throw std::invalid_argument("unsupported array size type");
}
Type type = pscalar->getType();
testOk1(type==scalarArray);
@@ -69,6 +86,9 @@ static void testScalarArrayCommon(ScalarType stype,
oss << type;
testOk1(oss.str().compare("scalarArray")==0);
testOk1(pscalar->getArraySizeType()==sizeType);
testOk1(pscalar->getMaximumCapacity()==size);
ScalarType scalarType = pscalar->getElementType();
testOk1(scalarType==stype);
testOk1(ScalarTypeFunc::isInteger(scalarType)==isInteger);
@@ -86,6 +106,24 @@ static void testScalarArray() {
testScalarArrayCommon(pvFloat,false,true,true);
testScalarArrayCommon(pvDouble,false,true,true);
testScalarArrayCommon(pvString,false,false,false);
testScalarArrayCommon(pvBoolean,false,false,true,Array::bounded,10);
testScalarArrayCommon(pvByte,true,true,true,Array::bounded,10);
testScalarArrayCommon(pvShort,true,true,true,Array::bounded,10);
testScalarArrayCommon(pvInt,true,true,true,Array::bounded,10);
testScalarArrayCommon(pvLong,true,true,true,Array::bounded,10);
testScalarArrayCommon(pvFloat,false,true,true,Array::bounded,10);
testScalarArrayCommon(pvDouble,false,true,true,Array::bounded,10);
testScalarArrayCommon(pvString,false,false,false,Array::bounded,10);
testScalarArrayCommon(pvBoolean,false,false,true,Array::fixed,16);
testScalarArrayCommon(pvByte,true,true,true,Array::fixed,16);
testScalarArrayCommon(pvShort,true,true,true,Array::fixed,16);
testScalarArrayCommon(pvInt,true,true,true,Array::fixed,16);
testScalarArrayCommon(pvLong,true,true,true,Array::fixed,16);
testScalarArrayCommon(pvFloat,false,true,true,Array::fixed,16);
testScalarArrayCommon(pvDouble,false,true,true,Array::fixed,16);
testScalarArrayCommon(pvString,false,false,false,Array::fixed,16);
}
static void testStructure()
@@ -187,6 +225,21 @@ static void testUnion()
}
static void testBoundedString()
{
testDiag("testBoundedString");
BoundedStringConstPtr bs = fieldCreate->createBoundedString(8);
Type type = bs->getType();
testOk1(type==scalar);
ScalarType scalarType = bs->getScalarType();
testOk1(scalarType==pvString);
testOk1(bs->getMaximumLength()==8);
}
#define testExcept(EXCEPT, CMD) try{ CMD; testFail( "No exception from: " #CMD); } \
catch(EXCEPT& e) {testPass("Got expected exception from: " #CMD);} \
@@ -236,6 +289,9 @@ static void testError()
static void testMapping()
{
#define OP(TYPE, ENUM) \
printf(#TYPE ": sizeof %u typeid '%s' ScalarTypeID %d\n",\
(unsigned)sizeof(TYPE), typeid(TYPE).name(),\
epics::pvData::ScalarTypeID<TYPE>::value);\
testOk1(typeid(ScalarTypeTraits<ENUM>::type)==typeid(TYPE)); \
testOk1(ENUM==(ScalarType)ScalarTypeID<TYPE>::value); \
testOk1(ENUM==(ScalarType)ScalarTypeID<const TYPE>::value);
@@ -253,12 +309,11 @@ static void testMapping()
OP(string, pvString)
#undef OP
testOk1((ScalarType)ScalarTypeID<PVField>::value==(ScalarType)-1);
}
MAIN(testIntrospect)
{
testPlan(180);
testPlan(326);
fieldCreate = getFieldCreate();
pvDataCreate = getPVDataCreate();
standardField = getStandardField();
@@ -266,6 +321,7 @@ MAIN(testIntrospect)
testScalarArray();
testStructure();
testUnion();
testBoundedString();
testError();
testMapping();
return testDone();

View File

@@ -197,45 +197,45 @@ static void testPVScalarWithProperties(
}
PVLongPtr seconds = pvStructure->getLongField(
string("timeStamp.secondsPastEpoch"));
testOk1(seconds!=0);
testOk1(seconds.get()!=0);
seconds->put(123456789);
PVIntPtr nano = pvStructure->getIntField(string("timeStamp.nanoSeconds"));
testOk1(nano!=0);
PVIntPtr nano = pvStructure->getIntField(string("timeStamp.nanoseconds"));
testOk1(nano.get()!=0);
nano->put(1000000);
PVIntPtr severity = pvStructure->getIntField(string("alarm.severity"));
testOk1(severity!=0);
testOk1(severity.get()!=0);
severity->put(2);
PVStringPtr message = pvStructure->getStringField(string("alarm.message"));
testOk1(message!=0);
testOk1(message.get()!=0);
message->put(string("messageForAlarm"));
if(hasDisplayControl) {
PVStringPtr desc = pvStructure->getStringField(
string("display.description"));
testOk1(desc!=0);
testOk1(desc.get()!=0);
desc->put(string("this is a description"));
PVStringPtr format = pvStructure->getStringField(
string("display.format"));
testOk1(format!=0);
testOk1(format.get()!=0);
format->put(string("f10.2"));
PVStringPtr units = pvStructure->getStringField(
string("display.units"));
testOk1(units!=0);
testOk1(units.get()!=0);
units->put(string("SomeUnits"));
PVDoublePtr limit = pvStructure->getDoubleField(
string("display.limitLow"));
testOk1(limit!=0);
testOk1(limit.get()!=0);
limit->put(0.0);
limit = pvStructure->getDoubleField(
string("display.limitHigh"));
testOk1(limit!=0);
testOk1(limit.get()!=0);
limit->put(10.0);
limit = pvStructure->getDoubleField(
string("control.limitLow"));
testOk1(limit!=0);
testOk1(limit.get()!=0);
limit->put(1.0);
limit = pvStructure->getDoubleField(
string("control.limitHigh"));
testOk1(limit!=0);
testOk1(limit.get()!=0);
limit->put(9.0);
}
if(hasValueAlarm) {
@@ -255,15 +255,15 @@ static void testPVScalarWithProperties(
convert->fromDouble(pvtemp,9.0);
severity = pvStructure->getIntField(
string("valueAlarm.lowAlarmSeverity"));
testOk1(severity!=0);
testOk1(severity.get()!=0);
severity->put(2);
severity = pvStructure->getIntField(
string("valueAlarm.highAlarmSeverity"));
testOk1(severity!=0);
testOk1(severity.get()!=0);
severity->put(2);
PVBooleanPtr active = pvStructure->getBooleanField(
string("valueAlarm.active"));
testOk1(active!=0);
testOk1(active.get()!=0);
active->put(true);
}
if(hasBooleanAlarm) {
@@ -273,15 +273,15 @@ static void testPVScalarWithProperties(
pvBoolean->put(true);
severity = pvStructure->getIntField(
string("valueAlarm.falseSeverity"));
testOk1(severity!=0);
testOk1(severity.get()!=0);
severity->put(0);
severity = pvStructure->getIntField(
string("valueAlarm.trueSeverity"));
testOk1(severity!=0);
testOk1(severity.get()!=0);
severity->put(2);
severity = pvStructure->getIntField(
string("valueAlarm.changeStateSeverity"));
testOk1(severity!=0);
testOk1(severity.get()!=0);
severity->put(1);
}
if(debug)
@@ -345,7 +345,7 @@ static void testScalarArrayCommon(string /*fieldName*/,ScalarType stype)
if(debug)
std::cout << *pvStructure << std::endl;
PVFieldPtr pvField = pvStructure->getSubField("alarm.status");
testOk1(pvField!=NULL);
testOk1(pvField.get()!=0);
}
static void testScalarArray()

View File

@@ -108,7 +108,7 @@ static void testBasic()
{
typename PVT::const_svector avoid;
arr1->PVScalarArray::getAs<typename PVT::value_type>(avoid);
arr1->PVScalarArray::template getAs<typename PVT::value_type>(avoid);
testOk1(avoid.data()==cdata.data());
testOk1(avoid.data()==arr1->view().data());
}
@@ -133,7 +133,7 @@ static void testBasic()
testOk1(cdata.size()==arr1->getLength());
PVIntArray::const_svector idata;
arr1->PVScalarArray::getAs<int32>(idata);
arr1->PVScalarArray::template getAs<int32>(idata);
testOk1(idata.at(1)==10);
@@ -143,7 +143,7 @@ static void testBasic()
idata = freeze(wdata);
arr1->PVScalarArray::putFrom<int32>(idata);
arr1->PVScalarArray::template putFrom<int32>(idata);
testOk1(castUnsafe<PVIntArray::value_type>(arr1->view()[1])==42);
}

125
testApp/pv/testPVUnion.cpp Normal file
View File

@@ -0,0 +1,125 @@
/* testPVUnion.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: 2014.07 */
#include <cstddef>
#include <cstdlib>
#include <cstddef>
#include <string>
#include <cstdio>
#include <epicsUnitTest.h>
#include <testMain.h>
#include <pv/pvIntrospect.h>
#include <pv/pvData.h>
#include <pv/convert.h>
#include <pv/standardField.h>
#include <pv/standardPVField.h>
#include <pv/timeStamp.h>
#include <pv/pvTimeStamp.h>
using namespace epics::pvData;
using std::tr1::static_pointer_cast;
using std::string;
using std::cout;
using std::endl;
static bool debug = false;
static FieldCreatePtr fieldCreate = getFieldCreate();
static PVDataCreatePtr pvDataCreate = getPVDataCreate();
static StandardFieldPtr standardField = getStandardField();
static StandardPVFieldPtr standardPVField = getStandardPVField();
static ConvertPtr convert = getConvert();
static void testPVUnionType()
{
if(debug)
std::cout << std::endl << "testPVUnion" << std::endl;
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(
standardField->regUnion(
fieldCreate->createFieldBuilder()->
add("doubleValue", pvDouble)->
add("intValue", pvInt)->
add("timeStamp",standardField->timeStamp())->
createUnion(),
"alarm,timeStamp"));
PVUnionPtr pvValue = pvStructure->getSubField<PVUnion>("value");
PVStructurePtr pvTime= pvValue->select<PVStructure>(2);
TimeStamp timeStamp;
timeStamp.getCurrent();
PVTimeStamp pvTimeStamp;
pvTimeStamp.attach(pvTime);
pvTimeStamp.set(timeStamp);
testOk1(
pvTime->getSubField<PVLong>("secondsPastEpoch")->get()
==
pvValue->get<PVStructure>()->getSubField<PVLong>("secondsPastEpoch")->get()
);
PVDoublePtr pvDouble = pvValue->select<PVDouble>("doubleValue");
pvDouble->put(1e5);
testOk1(pvDouble->get()==pvValue->get<PVDouble>()->get());
PVIntPtr pvInt = pvValue->select<PVInt>("intValue");
pvInt->put(15);
testOk1(pvInt->get()==pvValue->get<PVInt>()->get());
std::cout << "testPVUnion PASSED" << std::endl;
}
static void testPVUnionArray()
{
if(debug)
std::cout << std::endl << "testPVUnion" << std::endl;
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(
standardField->unionArray(
fieldCreate->createFieldBuilder()->
add("doubleValue", pvDouble)->
add("intValue", pvInt)->
add("timeStamp",standardField->timeStamp())->
createUnion(),
"alarm,timeStamp"));
PVUnionArrayPtr pvValue = pvStructure->getSubField<PVUnionArray>("value");
size_t num = 3;
shared_vector<PVUnionPtr> unions(3);
for(size_t i=0; i<num; ++i)
{
unions[i] = pvDataCreate->createPVUnion(pvValue->getUnionArray()->getUnion());
}
unions[0]->select("doubleValue");
unions[1]->select("intValue");
unions[2]->select("timeStamp");
PVDoublePtr pvDouble = unions[0]->get<PVDouble>();
pvDouble->put(1.235);
PVIntPtr pvInt = unions[1]->get<PVInt>();
pvInt->put(5);
PVStructurePtr pvTime = unions[2]->get<PVStructure>();
TimeStamp timeStamp;
timeStamp.getCurrent();
PVTimeStamp pvTimeStamp;
pvTimeStamp.attach(pvTime);
pvTimeStamp.set(timeStamp);
pvValue->replace(freeze(unions));
shared_vector<const PVUnionPtr> sharedUnions = pvValue->view();
testOk1(pvDouble->get()==sharedUnions[0]->get<PVDouble>()->get());
testOk1(pvInt->get()==sharedUnions[1]->get<PVInt>()->get());
testOk1(
pvTime->getSubField<PVLong>("secondsPastEpoch")->get()
==
sharedUnions[2]->get<PVStructure>()->getSubField<PVLong>("secondsPastEpoch")->get()
);
std::cout << "testPVUnionArray PASSED" << std::endl;
}
MAIN(testPVUnion)
{
testPlan(6);
testPVUnionType();
testPVUnionArray();
return testDone();
}

86
testApp/pvDataAllTests.c Normal file
View File

@@ -0,0 +1,86 @@
/*
* Run pvData tests as a batch.
*
* Do *not* include performance measurements here, they don't help to
* prove functionality (which is the point of this convenience routine).
*/
#include <stdio.h>
#include <epicsThread.h>
#include <epicsUnitTest.h>
/* copy */
int testCreateRequest(void);
int testPVCopy(void);
/* misc */
int testBaseException(void);
int testBitSet(void);
int testByteBuffer(void);
int testMessageQueue(void);
int testOverrunBitSet(void);
int testQueue(void);
int testSerialization(void);
int testSharedVector(void);
int testThread(void);
int testTimeStamp(void);
int testTimer(void);
int testTypeCast(void);
/* property */
int testCreateRequest(void);
/* pv */
int testBitSetUtil(void);
int testConvert(void);
int testFieldBuilder(void);
int testIntrospect(void);
int testOperators(void);
int testPVData(void);
int testPVScalarArray(void);
int testPVStructureArray(void);
int testPVType(void);
int testPVUnion(void);
int testStandardField(void);
int testStandardPVField(void);
void pvDataAllTests(void)
{
testHarness();
/* pv */
runTest(testBitSetUtil);
runTest(testConvert);
runTest(testFieldBuilder);
runTest(testIntrospect);
runTest(testOperators);
runTest(testPVData);
runTest(testPVScalarArray);
runTest(testPVStructureArray);
runTest(testPVType);
runTest(testPVUnion);
runTest(testStandardField);
runTest(testStandardPVField);
/* misc */
runTest(testBaseException);
runTest(testBitSet);
runTest(testByteBuffer);
runTest(testMessageQueue);
runTest(testOverrunBitSet);
runTest(testQueue);
runTest(testSerialization);
runTest(testSharedVector);
runTest(testThread);
runTest(testTimeStamp);
runTest(testTimer);
runTest(testTypeCast);
/* copy */
runTest(testCreateRequest);
runTest(testPVCopy);
/* property */
runTest(testCreateRequest);
}

1
testApp/qemuRunTest.sh Executable file
View File

@@ -0,0 +1 @@
qemu-system-i386 --kernel O.RTEMS-pc386/rtemsTestHarness -netdev user,id=mynet0 -device ne2k_isa,netdev=mynet0 -redir tcp:5075::5075 -redir udp:5076::5076 -m 1024 --no-reboot -curses

72
testApp/rtemsConfig.c Normal file
View File

@@ -0,0 +1,72 @@
/*************************************************************************\
* Copyright (c) 2002 The University of Saskatchewan
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
* RTEMS configuration for EPICS
* Revision-Id: anj@aps.anl.gov-20101005192737-disfz3vs0f3fiixd
* Author: W. Eric Norum
* norume@aps.anl.gov
* (630) 252-4793
*/
#include <rtems.h>
/*
***********************************************************************
* RTEMS CONFIGURATION *
***********************************************************************
*/
#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
#if __RTEMS_MAJOR__>4 || (__RTEMS_MAJOR__==4 && __RTEMS_MINOR__>9) || (__RTEMS_MAJOR__==4 && __RTEMS_MINOR__==9 && __RTEMS_REVISION__==99)
# define CONFIGURE_UNIFIED_WORK_AREAS
#else
# define CONFIGURE_EXECUTIVE_RAM_SIZE (2000*1024)
#endif
#define CONFIGURE_MAXIMUM_TASKS rtems_resource_unlimited(30)
#define CONFIGURE_MAXIMUM_SEMAPHORES rtems_resource_unlimited(500)
#define CONFIGURE_MAXIMUM_TIMERS rtems_resource_unlimited(20)
#define CONFIGURE_MAXIMUM_MESSAGE_QUEUES rtems_resource_unlimited(5)
#define CONFIGURE_MAXIMUM_USER_EXTENSIONS 1
#define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 150
#define CONFIGURE_USE_IMFS_AS_BASE_FILESYSTEM
#define CONFIGURE_MAXIMUM_DRIVERS 8
#define CONFIGURE_MICROSECONDS_PER_TICK 20000
#define CONFIGURE_INIT_TASK_PRIORITY 80
#define CONFIGURE_MALLOC_STATISTICS 1
#define CONFIGURE_INIT
#define CONFIGURE_INIT_TASK_INITIAL_MODES (RTEMS_PREEMPT | \
RTEMS_NO_TIMESLICE | \
RTEMS_NO_ASR | \
RTEMS_INTERRUPT_LEVEL(0))
#define CONFIGURE_INIT_TASK_ATTRIBUTES (RTEMS_FLOATING_POINT | RTEMS_LOCAL)
#define CONFIGURE_INIT_TASK_STACK_SIZE (16*1024)
rtems_task Init (rtems_task_argument argument);
#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
#define CONFIGURE_FILESYSTEM_NFS
#define CONFIGURE_FILESYSTEM_IMFS
/*
* This should be made BSP dependent, not CPU dependent but I know of no
* appropriate conditionals to use.
* The new general time support makes including the RTC driverr less important.
*/
#if !defined(mpc604) && !defined(__mc68040__) && !defined(__mcf5200__) && !defined(mpc7455) && !defined(__arm__) /* don't have RTC code */
#define CONFIGURE_APPLICATION_NEEDS_RTC_DRIVER
#endif
#include <bsp.h>
#include <rtems/confdefs.h>

294
testApp/rtemsNetworking.h Normal file
View File

@@ -0,0 +1,294 @@
/*
* Network configuration -- QEMU NOT using DHCP
*
************************************************************
* EDIT THIS FILE TO REFLECT YOUR NETWORK CONFIGURATION *
* BEFORE RUNNING ANY RTEMS PROGRAMS WHICH USE THE NETWORK! *
************************************************************
*
* The dynamic probing is based upon the EPICS network
* configuration file written by:
* W. Eric Norum
* eric.norum@usask.ca
* (306) 966-5394
*/
#ifndef _RTEMS_NETWORKCONFIG_H_
#define _RTEMS_NETWORKCONFIG_H_
/* #define USE_LIBBSDPORT */
#if defined(USE_LIBBSDPORT)
#include <bsp/libbsdport_api.h>
#define CONFIGURE_MAXIMUM_TIMERS 10
#endif
/*
* For TFTP test application
*/
#if (defined (RTEMS_USE_BOOTP))
#define RTEMS_TFTP_TEST_HOST_NAME "BOOTP_HOST"
#define RTEMS_TFTP_TEST_FILE_NAME "BOOTP_FILE"
#else
#define RTEMS_TFTP_TEST_HOST_NAME "XXX.YYY.ZZZ.XYZ"
#define RTEMS_TFTP_TEST_FILE_NAME "tftptest"
#endif
/*
* For NFS test application
*
* NFS mount and a directory to ls once mounted
*/
#define RTEMS_NFS_SERVER "192.168.1.210"
#define RTEMS_NFS_SERVER_PATH "/home"
#define RTEMS_NFS_LS_PATH "/mnt/nfstest"
/*
* This file can be copied to an application source dirctory
* and modified to override the values shown below.
*
* The following CPP symbols may be passed from the Makefile:
*
* symbol default description
*
* NETWORK_TASK_PRIORITY 150 can be read by app from public
* var 'gesysNetworkTaskPriority'
* FIXED_IP_ADDR <undefined> hardcoded IP address (e.g.,
* "192.168.0.10"); disables BOOTP;
* must also define FIXED_NETMASK
* FIXED_NETMASK <undefined> IP netmask string
* (e.g. "255.255.255.0")
* MULTI_NETDRIVER <undefined> ugly hack; if defined try to probe
* a variety of PCI and ISA drivers
* (i386 ONLY) use is discouraged!
* NIC_NAME <undefined> Ethernet driver name (e.g. "pcn1");
* must also define NIC_ATTACH
* NIC_ATTACH <undefined> Ethernet driver attach function
* (e.g., rtems_fxp_attach).
* If these are undefined then
* a) MULTI_NETDRIVER is used
* (if defined)
* b) RTEMS_BSP_NETWORK_DRIVER_NAME/
* RTEMS_BSP_NETWORK_DRIVER_ATTACH
* are tried
* MEMORY_CUSTOM <undefined> Allocate the defined amount of
* memory for mbufs and mbuf clusters,
* respectively. Define to a comma ','
* separated pair of two numerical
* values, e.g: 100*1024,200*1024
* MEMORY_SCARCE <undefined> Allocate few memory for mbufs
* (hint for how much memory the
* board has)
* MEMORY_HUGE <undefined> Allocate a lot of memory for mbufs
* (hint for how much memory the
* board has)
* If none of MEMORY_CUSTOM/
* MEMORY_SCARCE/MEMORY_HUGE are
* defined then a medium amount of
* memory is allocated for mbufs.
*/
#include <rtems/bspIo.h>
#include <bsp.h>
#include <rtems/rtems_bsdnet.h>
#if 0
#ifdef HAVE_CONFIG_H
#include <config.h>
#else
#include "verscheck.h"
#endif
#endif
//#define MULTI_NETDRIVER
//#define RTEMS_BSP_NETWORK_DRIVER_NAME 1
#define FIXED_IP_ADDR "192.168.1.249"
#define FIXED_NETMASK "255.255.255.0"
#ifndef NETWORK_TASK_PRIORITY
#define NETWORK_TASK_PRIORITY 150 /* within EPICS' range */
#endif
/* make publicily available for startup scripts... */
const int gesysNetworkTaskPriority = NETWORK_TASK_PRIORITY;
#ifdef FIXED_IP_ADDR
#define RTEMS_DO_BOOTP 0
#else
#define RTEMS_DO_BOOTP rtems_bsdnet_do_bootp
#define FIXED_IP_ADDR 0
#undef FIXED_NETMASK
#define FIXED_NETMASK 0
#endif
#if !defined(NIC_NAME)
#ifdef MULTI_NETDRIVER
#if 0
#if RTEMS_VERSION_ATLEAST(4,6,99)
#define pcib_init pci_initialize
#endif
#endif
extern int rtems_3c509_driver_attach (struct rtems_bsdnet_ifconfig *, int);
extern int rtems_fxp_attach (struct rtems_bsdnet_ifconfig *, int);
extern int rtems_elnk_driver_attach (struct rtems_bsdnet_ifconfig *, int);
extern int rtems_dec21140_driver_attach (struct rtems_bsdnet_ifconfig *, int);
/* these don't probe and will be used even if there's no device :-( */
extern int rtems_ne_driver_attach (struct rtems_bsdnet_ifconfig *, int);
extern int rtems_wd_driver_attach (struct rtems_bsdnet_ifconfig *, int);
static struct rtems_bsdnet_ifconfig isa_netdriver_config[] = {
{
"ep0", rtems_3c509_driver_attach, isa_netdriver_config + 1,
},
{
"ne1", rtems_ne_driver_attach, 0, irno: 9 /* qemu cannot configure irq-no :-(; has it hardwired to 9 */
},
};
static struct rtems_bsdnet_ifconfig pci_netdriver_config[]={
{
"dc1", rtems_dec21140_driver_attach, pci_netdriver_config+1,
},
#if !defined(USE_LIBBSDPORT)
{
"fxp1", rtems_fxp_attach, pci_netdriver_config+2,
},
#else
{
"", libbsdport_netdriver_attach, pci_netdriver_config+2,
},
#endif
{
"elnk1", rtems_elnk_driver_attach, isa_netdriver_config,
},
};
static int pci_check(struct rtems_bsdnet_ifconfig *ocfg, int attaching)
{
struct rtems_bsdnet_ifconfig *cfg;
int if_index_pre;
extern int if_index;
if ( attaching ) {
cfg = pci_initialize() ?
isa_netdriver_config : pci_netdriver_config;
}
while ( cfg ) {
printk("Probing '%s'", cfg->name);
/* unfortunately, the return value is unreliable - some drivers report
* success even if they fail.
* Check if they chained an interface (ifnet) structure instead
*/
if_index_pre = if_index;
cfg->attach(cfg, attaching);
if ( if_index > if_index_pre ) {
/* assume success */
printk(" .. seemed to work\n");
ocfg->name = cfg->name;
ocfg->attach = cfg->attach;
return 0;
}
printk(" .. failed\n");
cfg = cfg->next;
}
return -1;
}
#define NIC_NAME "dummy"
#define NIC_ATTACH pci_check
#else
#if defined(RTEMS_BSP_NETWORK_DRIVER_NAME) /* Use NIC provided by BSP */
/* force ne2k_isa on i386 for qemu */
#if defined(__i386__)
# define NIC_NAME BSP_NE2000_NETWORK_DRIVER_NAME
# define NIC_ATTACH BSP_NE2000_NETWORK_DRIVER_ATTACH
#else
# define NIC_NAME RTEMS_BSP_NETWORK_DRIVER_NAME
# define NIC_ATTACH RTEMS_BSP_NETWORK_DRIVER_ATTACH
#endif
#endif
#endif /* ifdef MULTI_NETDRIVER */
#endif
#ifdef NIC_NAME
extern int NIC_ATTACH();
#if RTEMS_BSP_NETWORK_DRIVER_ATTACH == BSP_NE2000_NETWORK_DRIVER_ATTACH
static char ethernet_address[6] = { 0x00, 0xab, 0xcd, 0xef, 0x12, 0x34 };
#endif
static struct rtems_bsdnet_ifconfig netdriver_config[1] = {{
NIC_NAME, /* name */
(int (*)(struct rtems_bsdnet_ifconfig*,int))NIC_ATTACH, /* attach function */
0, /* link to next interface */
FIXED_IP_ADDR,
FIXED_NETMASK
#if RTEMS_BSP_NETWORK_DRIVER_ATTACH == BSP_NE2000_NETWORK_DRIVER_ATTACH
,
ethernet_address,
irno:9,
port:0xc100
#endif
}};
#else
#warning "NO KNOWN NETWORK DRIVER FOR THIS BSP -- YOU MAY HAVE TO EDIT networkconfig.h"
#endif
struct rtems_bsdnet_config rtems_bsdnet_config = {
#ifdef NIC_NAME
netdriver_config, /* link to next interface */
RTEMS_DO_BOOTP, /* Use BOOTP to get network configuration */
#else
0,
0,
#endif
NETWORK_TASK_PRIORITY, /* Network task priority */
#if defined(MEMORY_CUSTOM)
MEMORY_CUSTOM,
#elif defined(MEMORY_SCARCE)
100*1024, /* MBUF space */
200*1024, /* MBUF cluster space */
#elif defined(MEMORY_HUGE)
2*1024*1024, /* MBUF space */
5*1024*1024, /* MBUF cluster space */
#else
180*1024, /* MBUF space */
350*1024, /* MBUF cluster space */
#endif
#if (!defined (RTEMS_USE_BOOTP)) && defined(ON_RTEMS_LAB_WINSYSTEMS)
"rtems", /* Host name */
"nodomain.com", /* Domain name */
"192.168.1.14", /* Gateway */
"192.168.1.1", /* Log host */
{"89.212.75.6" }, /* Name server(s) */
{"192.168.1.1" }, /* NTP server(s) */
#else
NULL, /* Host name */
NULL, /* Domain name */
NULL, /* Gateway */
NULL, /* Log host */
{ NULL }, /* Name server(s) */
{ NULL }, /* NTP server(s) */
#endif /* !RTEMS_USE_BOOTP */
0, /* efficiency */
0, /* udp TX buffer */
0, /* udp RX buffer */
0, /* tcp TX buffer */
0, /* tcp RX buffer */
};
#endif /* _RTEMS_NETWORKCONFIG_H_ */

View File

@@ -0,0 +1,37 @@
#include <stdio.h>
#include <stdlib.h>
#include <rtems/rtems_bsdnet.h>
#include <rtems/error.h>
#include "rtemsNetworking.h"
#include <epicsExit.h>
#include <osdTime.h>
rtems_task
Init (rtems_task_argument ignored)
{
rtems_bsdnet_initialize_network ();
//rtems_bsdnet_show_if_stats ();
rtems_time_of_day timeOfDay;
if (rtems_clock_get(RTEMS_CLOCK_GET_TOD,&timeOfDay) != RTEMS_SUCCESSFUL) {
timeOfDay.year = 2014;
timeOfDay.month = 1;
timeOfDay.day = 1;
timeOfDay.hour = 0;
timeOfDay.minute = 0;
timeOfDay.second = 0;
timeOfDay.ticks = 0;
rtems_status_code ret = rtems_clock_set(&timeOfDay);
if (ret != RTEMS_SUCCESSFUL) {
printf("**** Can't set time %s\n", rtems_status_text(ret));
}
}
osdTimeRegister();
extern void pvDataAllTests(void);
pvDataAllTests();
epicsExit(0);
}