91 Commits

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
Matej Sekoranja
72bf9f76a3 forgot to remove friend operator<< 2014-06-19 21:56:56 +02:00
Matej Sekoranja
c0c6213c7c Win32: friend incosistent linkage 2014-06-19 21:24:14 +02:00
Matej Sekoranja
652ef4bc82 merge 2014-06-19 14:29:05 +02:00
Matej Sekoranja
c6eed12139 String -> std::string, toString methods removed 2014-06-19 14:27:48 +02:00
Marty Kraimer
1132e25072 fix bug related to stride 2014-06-13 09:52:30 -04:00
Marty Kraimer
879e3a2b67 support UnionArray 2014-06-12 15:26:31 -04:00
Matej Sekoranja
6ec207141f fixed missing dllimport/dllexport on new code 2014-06-11 11:56:04 +02:00
Matej Sekoranja
45c657ce79 added missing src/copy/Makefile 2014-06-10 13:50:04 +02:00
Matej Sekoranja
888dc11c03 Added tag before_merge_changesAfter3_0_2 for changeset 40b681ffc5cd 2014-06-10 13:39:41 +02:00
Matej Sekoranja
5e3159f800 completed merge 2014-06-09 23:15:57 +02:00
Matej Sekoranja
570ec97eda flow: Closed <feature> 'changesAfter3_0_2'. 2014-06-09 22:53:59 +02:00
Matej Sekoranja
09c75823e6 byteBuffer: wrap support 2014-06-09 08:28:00 +02:00
Marty Kraimer
50c8c3b0bd more work on stride 2014-06-06 11:24:12 -04:00
Marty Kraimer
3fb44312c7 add support for stride 2014-06-05 10:20:01 -04:00
Matej Sekoranja
67bdf2ab8b bitSet <<operator(ostream) 2014-06-01 20:54:07 +02:00
Marty Kraimer
a56ed44e74 fix bugs found by tests in pvIOCJava 2014-05-24 06:47:16 -04:00
Marty Kraimer
3c912c3812 put to union field did not call postPut. 2014-05-21 16:18:38 -04:00
Matej Sekoranja
0ceb87eee1 Array IF added 2014-05-13 00:18:30 +02:00
Marty Kraimer
6510c10884 major update to pvDataCPP.html; minor updates while working on documentation 2014-05-01 10:33:01 -04:00
Marty Kraimer
20345ab0dd forgot monitor.h 2014-04-23 09:16:28 -04:00
Marty Kraimer
d5dfb3de0c added monitorPlugin; fixed bug in PVField::getFullName(); 2014-04-23 09:10:37 -04:00
Marty Kraimer
c2f22a4ad8 make testPVCopy.cpp a proper epicsUnitTest 2014-04-02 10:15:53 -04:00
Marty Kraimer
cb15a8676b remove PVData methods that change introspection interface
remove deprecated methods
move CreateRequest from pvAccessCPP to pvDataCPP
move pvCopy from pvDatabaseCPP to pvDataCPP
2014-04-01 09:35:29 -04:00
Marty Kraimer
34f2d7bc9a created feature branch 2014-03-25 07:23:14 -04:00
Marty Kraimer
fb7f1b622b flow: Created branch 'feature/changesAfter3_0_2'. 2014-03-25 07:04:59 -04:00
130 changed files with 31362 additions and 6420 deletions

View File

@@ -1,11 +1,12 @@
^QtC-
^bin/
^lib/
^doc/
^include/
^db/
^dbd/
^documentation/html
QtC-
bin/
lib/
doc/
include/
db/
dbd/
documentation/html
documentation/*.tag
envPaths
configure/.*\.local
/O\..*

View File

@@ -9,3 +9,12 @@ d70c5ad29163306f50979a95b5aebbe9a93cfe76 2.0-BETA
4cecd4b200f88ab57bbb81978c45df2a67bbece1 3.0.0
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

@@ -0,0 +1,89 @@
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.
New Semantics for Arrays
--------
PVScalarArray, PVStructureArray, and PVUnionArray all enforce COW (Copy On Write) Semantics.
In order to limit memory usage the storage for raw data is managed via a new shared_vector facility.
This allows multiple instances of array data to use the shared raw data.
COW is implemented via shared_vectors of const data, i. e. data that can not be modified.
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.
------------
There are two new basic types: union_t and unionArray.
A union is like a structure that has a single subfield.
There are two flavors:
* <b>varient union</b> The field can have any type.
* <b>union</b> The field can any of specified set of types.
The field type can be dynamically changed.
copy
----
This consists of createRequest and pvCopy.
createRequest was moved from pvAccess to here.
pvCopy is moved from pvDatabaseCPP and now depends
only on pvData, i. e. it no longer has any knowledge of PVRecord.
monitorPlugin
-------------
This is for is for use by code that implements pvAccess monitors.
This is prototype and is subject to debate.
Release 3.0.2
==========
This was the starting point for RELEASE_NOTES

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>

38
documentation/TODO.md Normal file
View File

@@ -0,0 +1,38 @@
TODO
===========
printer
------------
pv/printer.h is not used.
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.

View File

@@ -0,0 +1,679 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
<title>EPICS pvDataCPP: copy and monitor</title>
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/base.css" />
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/epicsv4.css" />
<style type="text/css">
/*<![CDATA[*/
.about { margin-left: 3em; margin-right: 3em; font-size: .83em}
table { margin-left: auto; margin-right: auto }
.diagram { text-align: center; margin: 2.5em 0 }
span.opt { color: grey }
span.nterm { font-style:italic }
span.term { font-family:courier }
span.user { font-family:courier }
span.user:before { content:"<" }
span.user:after { content:">" }
.nonnorm { font-style:italic }
p.ed { color: #AA0000 }
span.ed { color: #AA0000 }
p.ed.priv { display: inline; }
span.ed.priv { display: inline; }
/*]]>*/</style>
<!-- Script that generates the Table of Contents -->
<script type="text/javascript"
src="http://epics-pvdata.sourceforge.net/script/tocgen.js">
</script>
</head>
<body>
<div id="toc">
<h2 class="nocount" style="page-break-before: always">Table of Contents</h2>
</div>
<div id="contents" class="contents">
<h2>support for copy and monitor</h2>
<p><b>copy</b> and <b>monitor</b> are not used in this project.
They are intended for use by pvAccess and by pvAccess servers.
They are provided with this project because the code depends only on
pvData itself.
</p>
<p>This document describes C++ specific code.
<a href="http://epics-pvdata.sourceforge.net/informative/pvRequest.html">
pvRequest.html</a>
provides a language independent overview of <b>copy</b> and <b>monitor</b>.
</p>
<p>
<b>NOTE:pvRequest.html</b> must be updated since it is based on an earlier version of pvCopy that
had 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>
<p>Copy provides:
<dl>
<dt>createRequest</dt>
<dd>
The Channel create methods in pvAccess all have an argument
<b>PVStructure pvRequest</b>.<br />
Given an ascii string createRequest creates a PVStructure that provides
a pvData representation of the information from the ascii string.
It is this structure that can be passed to the channel create methods.<br />
The information in a pvRequest selects an 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 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
by the client.
</dd>
</dl>
Monitor provides:
<dl>
<dt>monitor</dt>
<dd>This is support code for channel providers that implement channel
monitor. It, together with the queue facility, provides support for
monitor queues.
</dd>
<dt>monitorPlugin</dt>
<dd>This is support for implementing monitor plugins.
A monitor plugin can be developed that has no knowledge
of pvAccess but only pvData.
</dd>
</dl>
</p>
<h2>support for copy</h2>
<p><b>copy</b> provides the ability to create a structure that has
a copy of an arbitrary subset of the fields in an existing top level
structure. In addition it allows global options and field specific options.
It has two main components: <b>createRequest</b> and <b>pvCopy</b>.
Given a string createRequest creates a pvRequest, which is a PVStructure
that has the format expected by <b>pvCopy</b>.
</p>
<h3>createRequest</h3>
<p>This is mainly used by pvAccess clients. Given a request string it creates
a pvRequest structure that can be passed to the pvAccess create methods.
In turn pvAccess passes the pvRequest to a local channel provider which
then passes it to pvCopy.
</p>
<p>The definition of the public members is:</p>
<pre>
class CreateRequest {
...
static CreateRequestPtr create();
virtual PVStructurePtr createRequest(std::string const &amp;request);
std::string getMessage();
};
</pre>
<p>An example of how it is used is:</p>
<pre>
CreateRequestPtr createRequest = CreateRequest::create();
PVStructurePtr pvRequest = createRequest-&gt;createRequest(request);
if(pvRequest==NULL) {
std::string error = createRequest-&gt;getMessage();
// take some action
} else {
//success do something
}
</pre>
<h3>pvCopy</h3>
<p>The definition of the public members is:</p>
<pre>
class epicsShareClass PVCopyTraverseMasterCallback
{
...
virtual void nextMasterPVField(PVFieldPtr const &amp;pvField);
};
class class epicsShareClass PVCopy
{
...
static PVCopyPtr create(
PVStructurePtr const &amp;pvMaster,
PVStructurePtr const &amp;pvRequest,
std::string const &amp; structureName);
PVStructurePtr getPVMaster();
void traverseMaster(PVCopyTraverseMasterCallbackPtr const &amp; callback);
StructureConstPtr getStructure();
PVStructurePtr createPVStructure();
size_t getCopyOffset(PVFieldPtr const &amp;masterPVField);
size_t getCopyOffset(
PVStructurePtr const &amp;masterPVStructure,
PVFieldPtr const &amp;masterPVField);
PVFieldPtr getMasterPVField(std::size_t structureOffset);
void initCopy(
PVStructurePtr const &amp;copyPVStructure,
BitSetPtr const &amp;bitSet);
void updateCopySetBitSet(
PVStructurePtr const &amp;copyPVStructure,
BitSetPtr const &amp;bitSet);
void updateCopyFromBitSet(
PVStructurePtr const &amp;copyPVStructure,
BitSetPtr const &amp;bitSet);
void updateMaster(
PVStructurePtr const &amp;copyPVStructure,
BitSetPtr const &amp;bitSet);
PVStructurePtr getOptions(std::size_t fieldOffset);
...
};
</pre>
where
<dl>
<dt>PVCopyTraverseMasterCallback::nextMasterPVField</dt>
<dd>
<b>PVCopyTraverseMasterCallback</b> is a callback which must
be implemented by the code that uses pvCopy, normally
the channel provider. It has the single method <b>nextMasterPVField</b>
<br />
<b>nextMasterPVField</b> is called for each field in the master
as a result of a call to <b>traverseMaster</b>.
</dd>
<dt>create</dt>
<dd>
This is the method for creating a PVCopy instance.<br/>
<dl>
<dt>pvMaster</dt>
<dd>the top level structure managed by the server.</dd>
<dt>pvRequest</dt>
<dd>selects the set of subfields desired
and options for each field.</dd>
<dt>structureName</dt>
<dd>the name for the top level of any PVStructure created.
</dd>
</dl>
</dd>
<dt>getPVMaster</dt>
<dd>
Gets the top level structure from pvMaster.
</dd>
<dt>traverseMaster</dt>
<dd>
Traverse all fields of the top level structure of pvMaster.
For each field the callback is called.
</dd>
<dt>getStructure</dt>
<dd>
Get the introspection interface for a PVStructure for e copy.
</dd>
<dt>createPVStructure</dt>
<dd>Create a copy instance.
Monitors keep a queue of monitor elements.
Since each element needs a PVStructure, multiple top level structures
will be created.
</dd>
<dt>getCopyOffset</dt>
<dd>Given a field in pvMaster.
return the offset in copy for the same field.
A value of std::string::npos means that the copy does not have this field.
Two overloaded methods are provided. The first is called if
the field of master is not a structure. The second is for
subfields of a structure.
</dd>
<dt>getMasterPVField</dt>
<dd>
Given a offset in the copy get the corresponding field in pvMaster.
</dd>
<dt>initCopy</dt>
<dd>
Initialize the fields in copyPVStructure
by giving each field the value from the corresponding field in pvMaster.
bitSet will be set to show that all fields are changed.
This means that bit set will have the value <b>{0}</b>.
</dd>
<dt>updateCopySetBitSet</dt>
<dd>
Set all fields in copyPVStructure to the value of the corresponding field
in pvMaster. Each field that is changed has it's corresponding
bit set in bitSet.
</dd>
<dt>updateCopyFromBitSet</dt>
<dd>
For each set bit in bitSet set the field in copyPVStructure to the value
of the 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 corresponding field in copyPVStructure.
</dd>
<dt>getOptions</dt>
<dd>
Get the options for the field at the specified offset.
A NULL is returned if no options were specified for the field.
If options were specified,PVStructurePtr is
a structure with a set of PVString subfields that specify name,value
pairs. name is the subField name and value is the subField value.
</dd>
</dl>
<h2>support for monitor</h2>
<p>This consists of two components:
<dl>
<dt>monitor</dt>
<dd>Used by code that implements pvAccess monitors.</dd>
<dt>monitorPlugin</dt>
<dd>Code that provides special semantics for monitors.</dd>
</dl>
</p>
<h3>monitor</h3>
<pre>
class MonitorElement {
MonitorElement(PVStructurePtr const &amp; pvStructurePtr);
PVStructurePtr pvStructurePtr;
BitSetPtr changedBitSet;
BitSetPtr overrunBitSet;
};
class Monitor {
virtual Status start() = 0;
virtual Status stop() = 0;
virtual MonitorElementPtr poll() = 0;
virtual void release(MonitorElementPtr const &amp; monitorElement) = 0;
};
class MonitorRequester : public virtual Requester {
virtual void monitorConnect(Status const &amp; status,
MonitorPtr const &amp; monitor, StructureConstPtr const &amp; structure) = 0;
virtual void monitorEvent(MonitorPtr const &amp; monitor) = 0;
virtual void unlisten(MonitorPtr const &amp; monitor) = 0;
};
</pre>
<h4>monitorElement</h4>
<p><b>MonitorElement</b> holds the data for one element of a monitor queue.
It has the fields:
<dl>
<dt>pvStructurePtr</dt>
<dd>A top level structure with data values at the time the monitors occurs.</dd>
<dt>changedBitSet</dt>
<dd>Shows which fields have changed since the previous monitor.</dd>
<dt>overrunBitSet</dt>
<dd>Shows which fields have changed more han once since the previous monitor.</dd>
</dl>
</p>
<h4>monitorElement queue</h4>
<p>
A queue of monitor elements must be implemented by any channel provider that implements
<b>Channel::createMonitor</b>.
For an example implementation look at pvDatabaseCPP.
It has the following:
<pre>
typedef Queue&lt;MonitorElement&gt; MonitorElementQueue;
typedef std::tr1::shared_ptr&lt;MonitorElementQueue&gt; MonitorElementQueuePtr;
class MultipleElementQueue :
public ElementQueue
{
public:
POINTER_DEFINITIONS(MultipleElementQueue);
virtual ~MultipleElementQueue(){}
MultipleElementQueue(
MonitorLocalPtr const &amp;monitorLocal,
MonitorElementQueuePtr const &amp;queue,
size_t nfields);
virtual void destroy(){}
virtual Status start();
virtual Status stop();
virtual bool dataChanged();
virtual MonitorElementPtr poll();
virtual void release(MonitorElementPtr const &amp;monitorElement);
...
};
</pre>
<h4>Monitor</h4>
<p><b>Monitor</b> must be implemented by any channel provider that implements
<b>Channel::createMonitor</b>.
Remote PVAccess also implements Monitor on the client side.
Note that each client has it's own queue that is not shared with other client.
</p>
<p>Monitor has the following methods:</p>
<dl>
<dt>start</dt>
<dd>
Start monitoring.
This will result in a an initial monitor that has the current value
of all fields.
</dd>
<dt>stop</dt>
<dd>
Stop monitoring.
</dd>
<dt>poll</dt>
<dd>
Called to get a monitor element.
If no new elements are available then a null pointer is returned.
</dd>
<dt>release</dt>
<dd>
Release the monitor element.
The caller owns the monitor element between the calls to poll and release.
</dd>
<dl>
</dl>
<h4>MonitorRequester</h4>
<p>This must be implemented by a pvAccess client.
It has the methods:</p>
<dl>
<dt>monitorConnect</dt>
<dd>
A monitor has either connected of disconnected.
</dd>
<dt>monitorEvent</dt>
<dd>
A new monitor element is available.
</dd>
<dt>unlisten</dt>
<dd>
The channel is going away. The client cam no longer access the monitor.
</dd>
</dl>
<h3>monitorPlugin</h3>
<pre>
class MonitorPlugin
{
virtual std::string const &amp; getName() = 0;
virtual bool causeMonitor(
PVFieldPtr const &amp;pvField,
PVStructurePtr const &amp;pvTop,
MonitorElementPtr const &amp;monitorElement) = 0;
virtual void monitorDone(
MonitorElementPtr const &amp;monitorElement);
virtual void startMonitoring();
virtual void stopMonitoring();
virtual void beginGroupPut();
virtual void endGroupPut();
};
class MonitorPluginCreator
{
virtual MonitorPluginPtr create(
FieldConstPtr const &amp;field,
StructureConstPtr const &amp;top,
PVStructurePtr const &amp;pvFieldOptions) = 0;
virtual std::string const &amp; getName() = 0;
}
class MonitorPluginManager
{
static MonitorPluginManagerPtr get();
bool addPlugin(
std::string const &amp;pluginName,
MonitorPluginCreatorPtr const &amp;creator);
MonitorPluginCreatorPtr findPlugin(std::string const &amp;pluginName);
void showNames();
};
</pre>
<h4>MonitorPlugin</h4>
<p><b>MonitorPlugin</b> must be implemented by the plugin implementation.
It has methods:</p>
<dl>
<dt>getName</dt>
<dd>Get the name of the plugin.</dd>
<dt>causeMonitor</dt>
<dd>
Should the value of pvField cause a monitor to be raised.
pvField and pvTop are fields in the top level structure
being monitored. monitorElement has the top level structure
for the copy</b>.
The implementation should <b>not</b> modify the fields in the structure
being monitored.
Called with pvTop locked.
</dd>
<dt>monitorDone</dt>
<dd>
Called just before monitorElement will be given to client.
The plugin can change the data values and bitSets in monitorElement.
Called with pvTop unlocked.
</dd>
<dt>startMonitoring</dt>
<dd>
Monitoring is starting.
</dd>
<dt>stopMonitoring</dt>
<dd>
Monitoring is being stopped.
</dd>
<dt>beginGroupPut</dt>
<dd>
A set of puts is starting.
Called with pvTop locked.
</dd>
<dt>endGroupPut</dt>
<dd>
The set of puts is complete.
Called with pvTop locked.
</dd>
</dl>
<h4>MonitorPluginCreator</h4>
<p><b>MonitorPluginCreator</b> must also be implemented by the plugin implementation.
It is called for each field instance that has options of the from
<b>[plugin=name...]</b> where <b>name</b> is the name of the plugin.
Note that a plugin instance will belong to a single client.
It has methods:</p>
<dl>
<dt>getName</dt>
<dd>Get the name of the plugin.</dd>
<dt>create</dt>
<dd>
Create a new plugin instance.
If the arguments are not compatible with the plugin a NULL shared pointer is
returned.<br/>
pvFieldOptions is
a structure with a set of PVString subfields that specify <b>name,value</b>
pairs. name is the subField name and value is the subField value.<br/>
Note that a plugin will below to a single client.
</dd>
<dl>
<h4>MonitorPluginManager</h4>
<p><b>MonitorPluginManager</b> has the methods:</p>
<dl>
<dt>get</dt>
<dd>
MonitorPluginManager is a singleton.
The first call to get will create the single instance.
Further calls will return the single instance.
</dd>
<dt>addPlugin</dt>
<dd>
Add a new plugin.
</dd>
<dt>findPlugin</dt>
<dd>
Find a plugin. A NULL shared pointer is returned if it has not been added.
</dd>
<dt>showNames</dt>
<dd>
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 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;
</pre>
then the definition for causeMonitor could be:
<pre>
virtual bool causeMonitor(
PVFieldConstPtr const &amp;pvField,
PVStructureConstPtr const &amp;pvTop,
MonitorElementPtr const &amp;monitorElement) = 0;
</pre>
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.
Big job.
</p>
<h2>monitorPlugin example</h2>
<h3>Example Plugin Overview</h3>
<p>This section describes an example plugin that:</p>
<ul>
<li>Only raises monitors when a field changes value.<br />
If no plugin is provided
the default is to raise a monitor when a put is issued to a field.</li>
<li>Optionally a change will not raise a monitor.<br />
The change will, however,
appear if a put to another field raise a monitor.</li>
</ul>
<p>As an example assume that a channel provided by pvAccess has a top level structure
that represents a power supply.</p>
<pre>
structure powerSupply
structure alarm
structure timeStamp
structure power
double value
structure alarm
structure display
structure voltage
double value
structure alarm
structure display
structure current
double value
structure alarm
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:
<pre>
structure powerSupply
structure alarm
structure timeStamp
structure power
double value
structure voltage
double value
structure current
double value
</pre>
In addition the client wants monitors to occur only when one of the monitored
fields changes value but not just because a put occured.
Also if only the timeStamp changes value then that should not cause a monitor.
</p>
<p>The example monitor plugin implements the semantics the
client wants. It can be attached to any field via the following options:
<pre>
[plugin=onChange,raiseMonitor=value]
</pre>
This plugin will trigger a monitor for the field only if the field changes
value. In addition <b>value</b> equals <b>false</b> means do not raise a 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.
</p>
<p>
Assume that the client has already connected to the channel.
The client can then issue the commands:</p>
<pre>
std::string request("field(alarm[plugin=onChange]");
request += ",timeStamp[plugin=onChange,raiseMonitor=false]";
request += ",power.value[plugin=onChange";
request += ",voltage.value[plugin=onChange";
request += ",current.value[plugin=onChange";
PVStructurePtr pvRequest = createRequest-&gt;createRequest(request);
MonitorPtr monitor = channel-&gt;createMonitor(monitorRequester,pvRequest);
</pre>
<h3>Example Plugin Code</h3>
<p>The header file to create the example has the definition:</p>
<pre>
class ExampleMonitorPlugin{
public:
static void create();
};
</pre>
<p>The implementation is:</p>
<pre>
class OnChangePlugin : public MonitorPlugin
{
public:
virtual ~OnChangePlugin(){}
OnChangePlugin() {}
bool init(
FieldConstPtr const &amp;field,
StructureConstPtr const &amp;top,
PVStructurePtr const &amp;pvFieldOptions)
{
pvField = getPVDataCreate()-&gt;createPVField(field);
raiseMonitor = true;
if(pvFieldOptions!=NULL) {
PVStringPtr pvString =
pvFieldOptions-&gt;getSubField&lt;PVString&gt;("raiseMonitor");
if(pvString!=NULL) {
std::string value = pvString-&gt;get();
if(value.compare("false")==0) raiseMonitor = false;
}
}
return true;
}
virtual std::string &amp;getName(){return pluginName;}
virtual bool causeMonitor(
PVFieldPtr const &amp;pvNew,
PVStructurePtr const &amp;pvTop,
MonitorElementPtr const &amp;monitorElement)
{
bool isSame = convert-&gt;equals(pvNew,pvField);
if(isSame) return false;
convert-&gt;copy(pvNew,pvField);
return raiseMonitor;
}
private:
PVFieldPtr pvField;
bool raiseMonitor;
};
class OnChangePluginCreator : public MonitorPluginCreator
{
public:
virtual std::string &amp;getName(){return pluginName;}
virtual MonitorPluginPtr create(
FieldConstPtr const &amp;field,
StructureConstPtr const &amp;top,
PVStructurePtr const &amp;pvFieldOptions)
{
OnChangePluginPtr plugin(new OnChangePlugin());
bool result = plugin-&gt;init(field,top,pvFieldOptions);
if(!result) return MonitorPluginPtr();
return plugin;
}
};
void ExampleMonitorPlugin::create()
{
static OnChangePluginCreatorPtr plugin;
static Mutex mutex;
Lock xx(mutex);
if(plugin==NULL) {
plugin = OnChangePluginCreatorPtr(new OnChangePluginCreator());
MonitorPluginManager::get()-&gt;addPlugin(pluginName,plugin);
}
}
</pre>
</div>
</body>
</html>

BIN
documentation/examples.zip Normal file

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

@@ -18,7 +18,7 @@ getFieldCreate()->createFieldBuilder()->
createStructure();
// create a structure (cntd.)
PVStructure::const_shared_pointer enum_t =
StructureConstPtr enum_t =
getFieldCreate()->createFieldBuilder()->
setId("enum_t")->
add("index", pvInt)->
@@ -26,13 +26,13 @@ PVStructure::const_shared_pointer enum_t =
createStructure();
// create a structure (cntd.)
PVStructure::const_shared_pointer ntEnum =
StructureConstPtr ntEnum =
getFieldCreate()->createFieldBuilder()->
setId("uri:ev4:nt/2012/pwd/NTEnum")->
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

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(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 {
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">String toString();</font>
}
<font color = "blue">
// new interface
interface FieldToString {
String toString(Field field);
}</font>
interface Scalar extends Field {
ScalarType getScalarType();
}
interface ScalarArray extends Field {
ScalarType getElementType();
}
interface Structure extends Field {
Field getField(String fieldName);
int getFieldIndex(String fieldName);
Field[] getFields();
Field getField(int fieldIndex);
String[] getFieldNames();
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(String[] fieldNames, Field[] field);
Structure createStructure(String id,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,String fieldName, Field field);</font>
<font color = "red">Structure appendFields(Structure structure,String[] fieldNames, Field[] fields);</font>
}
</pre>
<h3>Data Interfaces</h3>
<pre>
interface PVField extends Requester, Serializable {
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(String newName);</font>
<font color = "red">void toString(StringBuilder buf);</font>
<font color = "red">void toString(StringBuilder buf,int indentLevel);</font>
<font color = "red">String toString();</font>
}
<font color = "blue">
// The following is a new interface
interface PVFieldToString {
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(String fieldName);
PVField getSubField(int fieldOffset);
// The following are convenience methods
PVBoolean getBooleanField(String fieldName);
PVByte getByteField(String fieldName);
PVShort getShortField(String fieldName);
PVInt getIntField(String fieldName);
PVLong getLongField(String fieldName);
PVFloat getFloatField(String fieldName);
PVDouble getDoubleField(String fieldName);
PVString getStringField(String fieldName);
PVScalarArray getScalarArrayField(String fieldName);
PVStructureArray getStructureArrayField(String fieldName);
PVStructure getStructureField(String fieldName);
PVArray getArrayField(String fieldName,ScalarType elementType);
// following will be removed
<font color = "red"> void appendPVField(String fieldName,PVField pvField);</font>
<font color = "red"> void appendPVFields(String[] fieldNames,PVField[] pvFields);</font>
<font color = "red"> void removePVField(String fieldName);</font>
<font color = "red"> void replacePVField(PVField oldPVField,PVField newPVField);</font>
<font color = "red"> String getExtendsStructureName();</font>
<font color = "red"> boolean putExtendsStructureName(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(String[] fieldNames,Field[] fields);
PVStructure createPVStructure(PVStructure structToClone);
// following will be removed
<font color = "red">PVField[] flattenPVStructure(PVStructure pvStructure);</font>
}
</pre>
<h3>PVFieldToString</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 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 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 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(String const &amp; fieldName) const;
FieldConstPtr getField(std::size_t index) const;
std::size_t getFieldIndex(String const &amp;fieldName) const;
FieldConstPtrArray const &amp; getFields() const {return fields;}
StringArray const &amp; getFieldNames() const;
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,String const &amp;newName);
virtual void toString(StringBuilder buf,int indentLevel) const;
virtual 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 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 (
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,
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 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(String message,MessageType messageType);
void replacePVField(const PVFieldPtr&amp; newPVField);
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(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 PVFieldToString {
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;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;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(String const &amp;fieldName) const;
PVFieldPtr getSubField(std::size_t fieldOffset) const;
PVBooleanPtr getBooleanField(String const &amp;fieldName) ;
PVBytePtr getByteField(String const &amp;fieldName) ;
PVShortPtr getShortField(String const &amp;fieldName) ;
PVIntPtr getIntField(String const &amp;fieldName) ;
PVLongPtr getLongField(String const &amp;fieldName) ;
PVUBytePtr getUByteField(String const &amp;fieldName) ;
PVUShortPtr getUShortField(String const &amp;fieldName) ;
PVUIntPtr getUIntField(String const &amp;fieldName) ;
PVULongPtr getULongField(String const &amp;fieldName) ;
PVFloatPtr getFloatField(String const &amp;fieldName) ;
PVDoublePtr getDoubleField(String const &amp;fieldName) ;
PVStringPtr getStringField(String const &amp;fieldName) ;
PVStructurePtr getStructureField(String const &amp;fieldName) ;
PVScalarArrayPtr getScalarArrayField(
String const &amp;fieldName,ScalarType elementType) ;
PVStructureArrayPtr getStructureArrayField(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(
String const &amp;fieldName,
PVFieldPtr const &amp; pvField);
void appendPVFields(
StringArray const &amp; fieldNames,
PVFieldPtrArray const &amp; pvFields);
void removePVField(String const &amp;fieldName);
virtual void setImmutable();
String getExtendsStructureName() const;
bool putExtendsStructureName(
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

@@ -12,6 +12,7 @@ include $(PVDATA_SRC)/misc/Makefile
include $(PVDATA_SRC)/pv/Makefile
include $(PVDATA_SRC)/factory/Makefile
include $(PVDATA_SRC)/property/Makefile
include $(PVDATA_SRC)/copy/Makefile
include $(PVDATA_SRC)/pvMisc/Makefile
include $(PVDATA_SRC)/monitor/Makefile

9
src/copy/Makefile Normal file
View File

@@ -0,0 +1,9 @@
# This is a Makefile fragment, see ../Makefile
SRC_DIRS += $(PVDATA_SRC)/copy
INC += createRequest.h
INC += pvCopy.h
LIBSRCS += createRequest.cpp
LIBSRCS += pvCopy.cpp

483
src/copy/createRequest.cpp Normal file
View File

@@ -0,0 +1,483 @@
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* pvAccessCPP is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#include <string>
#include <sstream>
#define epicsExportSharedSymbols
#include <pv/pvData.h>
#include <pv/lock.h>
#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 {
static PVDataCreatePtr pvDataCreate = getPVDataCreate();
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) {
string::size_type pos = str.find_first_of(' ');
if(pos==string::npos) return;
str.erase(pos,1);
}
}
size_t findMatchingBrace(string& request, size_t index, int numOpen) {
size_t openBrace = request.find('{', index+1);
size_t closeBrace = request.find('}', index+1);
if(openBrace == string::npos && closeBrace == 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);
if(numOpen==1) return closeBrace;
return findMatchingBrace(request,closeBrace,numOpen-1);
}
if(numOpen==1) return closeBrace;
return findMatchingBrace(request,closeBrace,numOpen-1);
}
size_t findMatchingBracket(string& request, size_t index) {
for(size_t i=index+1; i< request.size(); ++i) {
if(request[i] == ']') {
if(i==index+1) {
message = request + " mismatched []";
throw std::logic_error("message");
}
return i;
}
}
message = request + " missing ]";
throw std::logic_error("message");
}
size_t findEndField(string& request) {
size_t ind = 0;
size_t maxind = request.size() -1;
while(true) {
if(request[ind]==',') return ind;
if(request[ind]=='[') {
size_t closeBracket = findMatchingBracket(request,ind);
if(closeBracket==string::npos) return closeBracket;
ind = closeBracket;
continue;
}
if(request[ind]=='{') {
size_t closeBrace = findMatchingBrace(request,ind,1);
if(closeBrace==string::npos) return closeBrace;
if(ind>=request.size()) return request.size();
ind = closeBrace;
continue;
}
if(request[ind]=='.') {
++ind;
continue;
}
if(ind>=maxind) break;
++ind;
}
return request.size();
}
vector<string> split(string const & commaSeparatedList) {
string::size_type numValues = 1;
string::size_type index=0;
while(true) {
string::size_type pos = commaSeparatedList.find(',',index);
if(pos==string::npos) break;
numValues++;
index = pos +1;
}
vector<string> valueList(numValues,"");
index=0;
for(size_t i=0; i<numValues; i++) {
size_t pos = commaSeparatedList.find(',',index);
string value = commaSeparatedList.substr(index,pos-index);
valueList[i] = value;
index = pos +1;
}
return valueList;
}
Node createRequestOptions(
string const & 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();
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 " + request;
throw std::logic_error("message");
}
top.push_back(Node(item.substr(0,equals)));
string name = fullFieldName + "._options." + item.substr(0,equals);
string value = item.substr(equals+1);
optionList.push_back(OptionPair(name,value));
}
Node node("_options");
node.nodes = top;
return node;
}
void createSubNode(Node &node,string const & crequest)
{
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;}
}
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];
}
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;
}
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;
}
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(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");
}
FieldConstPtr createSubStructure(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;
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 PVStructurePtr createRequest(
string const & crequest)
{
try {
string request = crequest;
if (!request.empty()) removeBlanks(request);
if (request.empty())
{
return pvDataCreate->createPVStructure(fieldCreate->createStructure());
}
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();
}
if(numBrace!=0) {
ostringstream oss;
oss << "mismatched {} " << numBrace;
message = oss.str();
return PVStructurePtr();
}
if(numBracket!=0) {
ostringstream oss;
oss << "mismatched [] " << numBracket;
message = oss.str();
return PVStructurePtr();
}
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();
}
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);
}
}
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);
}
optionList.clear();
return pvStructure;
} catch (std::exception &e) {
message = e.what();
return PVStructurePtr();
}
}
};
CreateRequest::shared_pointer CreateRequest::create()
{
CreateRequest::shared_pointer createRequest(new CreateRequestImpl());
return createRequest;
}
}}

56
src/copy/createRequest.h Normal file
View File

@@ -0,0 +1,56 @@
/*createRequest.h*/
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* pvDataCPP is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#ifndef CREATEREQUEST_H
#define CREATEREQUEST_H
#include <string>
#include <sstream>
#include <pv/pvData.h>
#include <pv/lock.h>
#include <shareLib.h>
namespace epics { namespace pvData {
/**
* Class to create pvRequest structures to pass to pvAccess Channel methods.
*/
class epicsShareClass CreateRequest {
public:
POINTER_DEFINITIONS(CreateRequest);
/**
* Create s new instance of CreateRequest
* @returns A shared pointer to the new instance.
*/
static CreateRequest::shared_pointer create();
virtual ~CreateRequest() {};
/**
* Create a request structure for the create calls in Channel.
* See the package overview documentation for details.
* @param request The field request. See the package overview documentation for details.
* @param requester The requester;
* @return The request PVStructure if a valid request was given.
* If a NULL PVStructure is returned then getMessage will return
* the reason.
*/
virtual PVStructure::shared_pointer createRequest(std::string const & request) = 0;
/**
* Get the error message of createRequest returns NULL
* return the error message
*/
std::string getMessage() {return message;}
protected:
CreateRequest() {}
std::string message;
};
}}
#endif /* CREATEREQUEST_H */

650
src/copy/pvCopy.cpp Normal file
View File

@@ -0,0 +1,650 @@
/* pvCopy.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvData is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
/**
* @author Marty Kraimer
* @date 2013.04
*/
#include <string>
#include <stdexcept>
#include <memory>
#include <sstream>
#define epicsExportSharedSymbols
#include <pv/thread.h>
#include <pv/pvCopy.h>
#include <pv/convert.h>
using std::tr1::static_pointer_cast;
using std::tr1::dynamic_pointer_cast;
using std::string;
using std::size_t;
using std::cout;
using std::endl;
namespace epics { namespace pvData {
static PVCopyPtr NULLPVCopy;
static FieldConstPtr NULLField;
static StructureConstPtr NULLStructure;
static PVStructurePtr NULLPVStructure;
static CopyNodePtr NULLCopyNode;
static CopyMasterNodePtr NULLCopyMasterNode;
struct CopyNode {
CopyNode()
: isStructure(false),
structureOffset(0),
nfields(0)
{}
bool isStructure;
size_t structureOffset; // In the copy
size_t nfields;
PVStructurePtr options;
};
struct CopyMasterNode : public CopyNode{
PVFieldPtr masterPVField;
};
typedef std::vector<CopyNodePtr> CopyNodePtrArray;
typedef std::tr1::shared_ptr<CopyNodePtrArray> CopyNodePtrArrayPtr;
struct CopyStructureNode : public CopyNode {
CopyNodePtrArrayPtr nodes;
};
PVCopyPtr PVCopy::create(
PVStructurePtr const &pvMaster,
PVStructurePtr const &pvRequest,
string const & structureName)
{
PVStructurePtr pvStructure(pvRequest);
if(structureName.size()>0) {
if(pvRequest->getStructure()->getNumberFields()>0) {
pvStructure = pvRequest->getStructureField(structureName);
if(!pvStructure) return NULLPVCopy;
}
} else if(pvStructure->getSubField("field")) {
pvStructure = pvRequest->getStructureField("field");
}
PVCopyPtr pvCopy = PVCopyPtr(new PVCopy(pvMaster));
bool result = pvCopy->init(pvStructure);
if(!result) pvCopy.reset();
return pvCopy;
}
PVCopy::PVCopy(
PVStructurePtr const &pvMaster)
: pvMaster(pvMaster)
{
}
void PVCopy::destroy()
{
headNode.reset();
}
PVStructurePtr PVCopy::getPVMaster()
{
return pvMaster;
}
void PVCopy::traverseMaster(CopyNodePtr const &innode, PVCopyTraverseMasterCallbackPtr const & callback)
{
CopyNodePtr node = innode;
if(!node->isStructure) {
CopyMasterNodePtr masterNode = static_pointer_cast<CopyMasterNode>(node);
callback->nextMasterPVField(masterNode->masterPVField);
return;
}
CopyStructureNodePtr structNode = static_pointer_cast<CopyStructureNode>(node);
CopyNodePtrArrayPtr nodes = structNode->nodes;
for(size_t i=0; i< nodes->size(); i++) {
node = (*nodes)[i];
traverseMaster(node,callback);
}
}
StructureConstPtr PVCopy::getStructure()
{
return structure;
}
PVStructurePtr PVCopy::createPVStructure()
{
if(cacheInitStructure) {
PVStructurePtr save = cacheInitStructure;
cacheInitStructure.reset();
return save;
}
PVStructurePtr pvStructure =
getPVDataCreate()->createPVStructure(structure);
return pvStructure;
}
PVStructurePtr PVCopy::getOptions(std::size_t fieldOffset)
{
if(fieldOffset==0) return headNode->options;
CopyNodePtr node = headNode;
while(true) {
if(!node->isStructure) {
if(node->structureOffset==fieldOffset) return node->options;
return NULLPVStructure;
}
CopyStructureNodePtr structNode = static_pointer_cast<CopyStructureNode>(node);
CopyNodePtrArrayPtr nodes = structNode->nodes;
boolean okToContinue = false;
for(size_t i=0; i< nodes->size(); i++) {
node = (*nodes)[i];
size_t soff = node->structureOffset;
if(fieldOffset>=soff && fieldOffset<soff+node->nfields) {
if(fieldOffset==soff) return node->options;
if(!node->isStructure) {
return NULLPVStructure;
}
okToContinue = true;
break;
}
}
if(okToContinue) continue;
throw std::invalid_argument("fieldOffset not valid");
}
}
size_t PVCopy::getCopyOffset(PVFieldPtr const &masterPVField)
{
if(masterPVField->getFieldOffset()==0) return 0;
if(!headNode->isStructure) {
CopyMasterNodePtr masterNode = static_pointer_cast<CopyMasterNode>(headNode);
if((masterNode->masterPVField.get())==masterPVField.get()) {
return headNode->structureOffset;
}
PVStructure * parent = masterPVField->getParent();
size_t offsetParent = parent->getFieldOffset();
size_t off = masterPVField->getFieldOffset();
size_t offdiff = off -offsetParent;
if(offdiff<masterNode->nfields) return headNode->structureOffset + offdiff;
return string::npos;
}
CopyStructureNodePtr node = static_pointer_cast<CopyStructureNode>(headNode);
CopyMasterNodePtr masterNode = getCopyOffset(node,masterPVField);
if(masterNode) return masterNode->structureOffset;
return string::npos;
}
size_t PVCopy::getCopyOffset(
PVStructurePtr const &masterPVStructure,
PVFieldPtr const &masterPVField)
{
CopyMasterNodePtr masterNode;
if(!headNode->isStructure) {
masterNode = static_pointer_cast<CopyMasterNode>(headNode);
if(masterNode->masterPVField.get()!=masterPVStructure.get()) return string::npos;
} else {
CopyStructureNodePtr node = static_pointer_cast<CopyStructureNode>(headNode);
masterNode = getCopyOffset(node,masterPVField);
}
if(!masterNode) return string::npos;
size_t diff = masterPVField->getFieldOffset()
- masterPVStructure->getFieldOffset();
return masterNode->structureOffset + diff;
}
PVFieldPtr PVCopy::getMasterPVField(size_t structureOffset)
{
CopyMasterNodePtr masterNode;
if(!headNode->isStructure) {
masterNode = static_pointer_cast<CopyMasterNode>(headNode);
} else {
CopyStructureNodePtr node = static_pointer_cast<CopyStructureNode>(headNode);
masterNode = getMasterNode(node,structureOffset);
}
if(!masterNode) {
throw std::invalid_argument(
"PVCopy::getMasterPVField: setstructureOffset not valid");
}
size_t diff = structureOffset - masterNode->structureOffset;
PVFieldPtr pvMasterField = masterNode->masterPVField;
if(diff==0) return pvMasterField;
PVStructurePtr pvStructure
= static_pointer_cast<PVStructure>(pvMasterField);
return pvStructure->getSubField(
pvMasterField->getFieldOffset() + diff);
}
void PVCopy::initCopy(
PVStructurePtr const &copyPVStructure,
BitSetPtr const &bitSet)
{
bitSet->clear();
bitSet->set(0);
updateCopyFromBitSet(copyPVStructure,bitSet);
}
void PVCopy::updateCopySetBitSet(
PVStructurePtr const &copyPVStructure,
BitSetPtr const &bitSet)
{
if(headNode->isStructure) {
CopyStructureNodePtr node = static_pointer_cast<CopyStructureNode>(headNode);
updateStructureNodeSetBitSet(copyPVStructure,node,bitSet);
} else {
CopyMasterNodePtr masterNode = static_pointer_cast<CopyMasterNode>(headNode);
PVFieldPtr pvMasterField= masterNode->masterPVField;
PVFieldPtr copyPVField = copyPVStructure;
PVFieldPtr pvField = pvMasterField;
if(pvField->getField()->getType()==epics::pvData::structure) {
updateSubFieldSetBitSet(copyPVField,pvMasterField,bitSet);
return;
}
ConvertPtr convert = getConvert();
bool isEqual = convert->equals(copyPVField,pvField);
if(!isEqual) {
convert->copy(pvField, copyPVField);
bitSet->set(copyPVField->getFieldOffset());
}
}
}
void PVCopy::updateCopyFromBitSet(
PVStructurePtr const &copyPVStructure,
BitSetPtr const &bitSet)
{
bool doAll = bitSet->get(0);
if(headNode->isStructure) {
CopyStructureNodePtr node = static_pointer_cast<CopyStructureNode>(headNode);
updateStructureNodeFromBitSet(copyPVStructure,node,bitSet,true,doAll);
} else {
CopyMasterNodePtr masterNode = static_pointer_cast<CopyMasterNode>(headNode);
updateSubFieldFromBitSet(copyPVStructure, masterNode->masterPVField,bitSet, true,doAll);
}
}
void PVCopy::updateMaster(
PVStructurePtr const &copyPVStructure,
BitSetPtr const &bitSet)
{
bool doAll = bitSet->get(0);
if(headNode->isStructure) {
CopyStructureNodePtr node =
static_pointer_cast<CopyStructureNode>(headNode);
updateStructureNodeFromBitSet(
copyPVStructure,node,bitSet,false,doAll);
} else {
CopyMasterNodePtr masterNode =
static_pointer_cast<CopyMasterNode>(headNode);
updateSubFieldFromBitSet( copyPVStructure,masterNode->masterPVField,bitSet,false,doAll);
}
}
string PVCopy::dump()
{
string builder;
dump(&builder,headNode,0);
return builder;
}
void PVCopy::dump(string *builder,CopyNodePtr const &node,int indentLevel)
{
getConvert()->newLine(builder,indentLevel);
std::stringstream ss;
ss << (node->isStructure ? "structureNode" : "masterNode");
ss << " structureOffset " << node->structureOffset;
ss << " nfields " << node->nfields;
*builder += ss.str();
PVStructurePtr options = node->options;
if(options) {
getConvert()->newLine(builder,indentLevel +1);
// TODO !!! ugly
std::ostringstream oss;
oss << *options;
*builder += oss.str();
getConvert()->newLine(builder,indentLevel);
}
if(!node->isStructure) {
CopyMasterNodePtr masterNode = static_pointer_cast<CopyMasterNode>(node);
string name = masterNode->masterPVField->getFullName();
*builder += " masterField " + name;
return;
}
CopyStructureNodePtr structureNode =
static_pointer_cast<CopyStructureNode>(node);
CopyNodePtrArrayPtr nodes = structureNode->nodes;
for(size_t i=0; i<nodes->size(); ++i) {
if((*nodes)[i].get()==NULL) {
getConvert()->newLine(builder,indentLevel +1);
ss.str("");
ss << "node[" << i << "] is null";
*builder += ss.str();
continue;
}
dump(builder,(*nodes)[i],indentLevel+1);
}
}
bool PVCopy::init(epics::pvData::PVStructurePtr const &pvRequest)
{
PVStructurePtr pvMasterStructure = pvMaster;
size_t len = pvRequest->getPVFields().size();
bool entireMaster = false;
if(len==string::npos) entireMaster = true;
if(len==0) entireMaster = true;
PVStructurePtr pvOptions;
if(len==1 && pvRequest->getSubField("_options")) {
pvOptions = pvRequest->getStructureField("_options");
}
if(entireMaster) {
structure = pvMasterStructure->getStructure();
CopyMasterNodePtr masterNode(new CopyMasterNode());
headNode = masterNode;
masterNode->options = pvOptions;
masterNode->isStructure = false;
masterNode->structureOffset = 0;
masterNode->masterPVField = pvMasterStructure;
masterNode->nfields = pvMasterStructure->getNumberFields();
return true;
}
structure = createStructure(pvMasterStructure,pvRequest);
if(!structure) return false;
cacheInitStructure = createPVStructure();
headNode = createStructureNodes(
pvMaster,
pvRequest,
cacheInitStructure);
return true;
}
string PVCopy::dump(
string const &value,
CopyNodePtr const &node,
int indentLevel)
{
throw std::logic_error(string("Not Implemented"));
}
StructureConstPtr PVCopy::createStructure(
PVStructurePtr const &pvMaster,
PVStructurePtr const &pvFromRequest)
{
if(pvFromRequest->getStructure()->getNumberFields()==0) {
return pvMaster->getStructure();
}
PVFieldPtrArray const &pvFromRequestFields = pvFromRequest->getPVFields();
StringArray const &fromRequestFieldNames = pvFromRequest->getStructure()->getFieldNames();
size_t length = pvFromRequestFields.size();
if(length==0) return NULLStructure;
FieldConstPtrArray fields; fields.reserve(length);
StringArray fieldNames; fields.reserve(length);
for(size_t i=0; i<length; ++i) {
string const &fieldName = fromRequestFieldNames[i];
PVFieldPtr pvMasterField = pvMaster->getSubField(fieldName);
if(!pvMasterField) continue;
FieldConstPtr field = pvMasterField->getField();
if(field->getType()==epics::pvData::structure) {
PVStructurePtr pvRequestStructure = static_pointer_cast<PVStructure>(
pvFromRequestFields[i]);
if(pvRequestStructure->getNumberFields()>0) {
StringArray const &names = pvRequestStructure->getStructure()->
getFieldNames();
size_t num = names.size();
if(num>0 && names[0].compare("_options")==0) --num;
if(num>0) {
if(pvMasterField->getField()->getType()!=epics::pvData::structure) continue;
fieldNames.push_back(fieldName);
fields.push_back(createStructure(
static_pointer_cast<PVStructure>(pvMasterField),
pvRequestStructure));
continue;
}
}
}
fieldNames.push_back(fieldName);
fields.push_back(field);
}
size_t numsubfields = fields.size();
if(numsubfields==0) return NULLStructure;
return getFieldCreate()->createStructure(fieldNames, fields);
}
CopyNodePtr PVCopy::createStructureNodes(
PVStructurePtr const &pvMasterStructure,
PVStructurePtr const &pvFromRequest,
PVStructurePtr const &pvFromCopy)
{
PVFieldPtrArray const & copyPVFields = pvFromCopy->getPVFields();
PVStructurePtr pvOptions;
PVFieldPtr pvField = pvFromRequest->getSubField("_options");
if(pvField) pvOptions = static_pointer_cast<PVStructure>(pvField);
size_t number = copyPVFields.size();
CopyNodePtrArrayPtr nodes(new CopyNodePtrArray());
nodes->reserve(number);
for(size_t i=0; i<number; i++) {
PVFieldPtr copyPVField = copyPVFields[i];
string fieldName = copyPVField->getFieldName();
PVStructurePtr requestPVStructure = static_pointer_cast<PVStructure>(
pvFromRequest->getSubField(fieldName));
PVStructurePtr pvSubFieldOptions;
PVFieldPtr pvField = requestPVStructure->getSubField("_options");
if(pvField) pvSubFieldOptions = static_pointer_cast<PVStructure>(pvField);
PVFieldPtr pvMasterField;
PVFieldPtrArray const & pvMasterFields = pvMasterStructure->getPVFields();
for(size_t j=0; i<pvMasterFields.size(); j++ ) {
if(pvMasterFields[j]->getFieldName().compare(fieldName)==0) {
pvMasterField = pvMasterFields[j];
break;
}
}
size_t numberRequest = requestPVStructure->getPVFields().size();
if(pvSubFieldOptions) numberRequest--;
if(numberRequest>0) {
nodes->push_back(createStructureNodes(
static_pointer_cast<PVStructure>(pvMasterField),
requestPVStructure,
static_pointer_cast<PVStructure>(copyPVField)));
continue;
}
CopyMasterNodePtr masterNode(new CopyMasterNode());
masterNode->options = pvSubFieldOptions;
masterNode->isStructure = false;
masterNode->masterPVField = pvMasterField;
masterNode->nfields = copyPVField->getNumberFields();
masterNode->structureOffset = copyPVField->getFieldOffset();
nodes->push_back(masterNode);
}
CopyStructureNodePtr structureNode(new CopyStructureNode());
structureNode->isStructure = true;
structureNode->nodes = nodes;
structureNode->structureOffset = pvFromCopy->getFieldOffset();
structureNode->nfields = pvFromCopy->getNumberFields();
structureNode->options = pvOptions;
return structureNode;
}
void PVCopy::updateStructureNodeSetBitSet(
PVStructurePtr const &pvCopy,
CopyStructureNodePtr const &structureNode,
epics::pvData::BitSetPtr const &bitSet)
{
for(size_t i=0; i<structureNode->nodes->size(); i++) {
CopyNodePtr node = (*structureNode->nodes)[i];
PVFieldPtr pvField = pvCopy->getSubField(node->structureOffset);
if(node->isStructure) {
PVStructurePtr xxx = static_pointer_cast<PVStructure>(pvField);
CopyStructureNodePtr yyy =
static_pointer_cast<CopyStructureNode>(node);
updateStructureNodeSetBitSet(xxx,yyy,bitSet);
} else {
CopyMasterNodePtr masterNode =
static_pointer_cast<CopyMasterNode>(node);
updateSubFieldSetBitSet(pvField,masterNode->masterPVField,bitSet);
}
}
}
void PVCopy::updateSubFieldSetBitSet(
PVFieldPtr const &pvCopy,
PVFieldPtr const &pvMaster,
BitSetPtr const &bitSet)
{
FieldConstPtr field = pvCopy->getField();
Type type = field->getType();
if(type!=epics::pvData::structure) {
ConvertPtr convert = getConvert();
bool isEqual = convert->equals(pvCopy,pvMaster);
if(isEqual) {
if(type==structureArray) {
// always act as though a change occurred.
// Note that array elements are shared.
bitSet->set(pvCopy->getFieldOffset());
}
}
if(isEqual) return;
convert->copy(pvMaster, pvCopy);
bitSet->set(pvCopy->getFieldOffset());
return;
}
PVStructurePtr pvCopyStructure = static_pointer_cast<PVStructure>(pvCopy);
PVFieldPtrArray const & pvCopyFields = pvCopyStructure->getPVFields();
PVStructurePtr pvMasterStructure =
static_pointer_cast<PVStructure>(pvMaster);
PVFieldPtrArray const & pvMasterFields =
pvMasterStructure->getPVFields();
size_t length = pvCopyFields.size();
for(size_t i=0; i<length; i++) {
updateSubFieldSetBitSet(pvCopyFields[i],pvMasterFields[i],bitSet);
}
}
void PVCopy::updateStructureNodeFromBitSet(
PVStructurePtr const &pvCopy,
CopyStructureNodePtr const &structureNode,
BitSetPtr const &bitSet,
bool toCopy,
bool doAll)
{
size_t offset = structureNode->structureOffset;
if(!doAll) {
size_t nextSet = bitSet->nextSetBit(offset);
if(nextSet==string::npos) return;
}
if(offset>=pvCopy->getNextFieldOffset()) return;
if(!doAll) doAll = bitSet->get(offset);
CopyNodePtrArrayPtr nodes = structureNode->nodes;
for(size_t i=0; i<nodes->size(); i++) {
CopyNodePtr node = (*nodes)[i];
PVFieldPtr pvField = pvCopy->getSubField(node->structureOffset);
if(node->isStructure) {
PVStructurePtr xxx = static_pointer_cast<PVStructure>(pvField);
CopyStructureNodePtr subStructureNode =
static_pointer_cast<CopyStructureNode>(node);
updateStructureNodeFromBitSet(
xxx,subStructureNode,bitSet,toCopy,doAll);
} else {
CopyMasterNodePtr masterNode =
static_pointer_cast<CopyMasterNode>(node);
updateSubFieldFromBitSet(
pvField,masterNode->masterPVField,bitSet,toCopy,doAll);
}
}
}
void PVCopy::updateSubFieldFromBitSet(
PVFieldPtr const &pvCopy,
PVFieldPtr const &pvMasterField,
BitSetPtr const &bitSet,
bool toCopy,
bool doAll)
{
if(!doAll) {
doAll = bitSet->get(pvCopy->getFieldOffset());
}
if(!doAll) {
size_t offset = pvCopy->getFieldOffset();
size_t nextSet = bitSet->nextSetBit(offset);
if(nextSet==string::npos) return;
if(nextSet>=pvCopy->getNextFieldOffset()) return;
}
ConvertPtr convert = getConvert();
if(pvCopy->getField()->getType()==epics::pvData::structure) {
PVStructurePtr pvCopyStructure =
static_pointer_cast<PVStructure>(pvCopy);
PVFieldPtrArray const & pvCopyFields = pvCopyStructure->getPVFields();
if(pvMasterField->getField()->getType() !=epics::pvData::structure)
{
throw std::logic_error(string("Logic error"));
}
PVStructurePtr pvMasterStructure =
static_pointer_cast<PVStructure>(pvMasterField);
PVFieldPtrArray const & pvMasterFields =
pvMasterStructure->getPVFields();
for(size_t i=0; i<pvCopyFields.size(); i++) {
updateSubFieldFromBitSet(
pvCopyFields[i],
pvMasterFields[i],
bitSet,toCopy,doAll);
}
} else {
if(toCopy) {
convert->copy(pvMasterField, pvCopy);
} else {
convert->copy(pvCopy, pvMasterField);
}
}
}
CopyMasterNodePtr PVCopy::getCopyOffset(
CopyStructureNodePtr const &structureNode,
PVFieldPtr const &masterPVField)
{
size_t offset = masterPVField->getFieldOffset();
CopyNodePtrArrayPtr nodes = structureNode->nodes;
for(size_t i=0; i< nodes->size(); i++) {
CopyNodePtr node = (*nodes)[i];
if(!node->isStructure) {
CopyMasterNodePtr masterNode =
static_pointer_cast<CopyMasterNode>(node);
size_t off = masterNode->masterPVField->getFieldOffset();
size_t nextOffset = masterNode->masterPVField->getNextFieldOffset();
if(offset>= off && offset<nextOffset) return masterNode;
} else {
CopyStructureNodePtr subNode =
static_pointer_cast<CopyStructureNode>(node);
CopyMasterNodePtr masterNode =
getCopyOffset(subNode,masterPVField);
if(masterNode) return masterNode;
}
}
return NULLCopyMasterNode;
}
CopyMasterNodePtr PVCopy::getMasterNode(
CopyStructureNodePtr const &structureNode,
std::size_t structureOffset)
{
CopyNodePtrArrayPtr nodes = structureNode->nodes;
for(size_t i=0; i< nodes->size(); i++) {
CopyNodePtr node = (*nodes)[i];
if(structureOffset>=(node->structureOffset + node->nfields)) continue;
if(!node->isStructure) {
CopyMasterNodePtr masterNode =
static_pointer_cast<CopyMasterNode>(node);
return masterNode;
}
CopyStructureNodePtr subNode =
static_pointer_cast<CopyStructureNode>(node);
return getMasterNode(subNode,structureOffset);
}
return NULLCopyMasterNode;
}
}}

230
src/copy/pvCopy.h Normal file
View File

@@ -0,0 +1,230 @@
/* pvCopy.h */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvData is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
/**
* @author Marty Kraimer
* @date 2013.04
*/
#ifndef PVCOPY_H
#define PVCOPY_H
#include <string>
#include <stdexcept>
#include <memory>
#include <shareLib.h>
#include <pv/pvData.h>
#include <pv/bitSet.h>
namespace epics { namespace pvData{
class PVCopyTraverseMasterCallback;
typedef std::tr1::shared_ptr<PVCopyTraverseMasterCallback> PVCopyTraverseMasterCallbackPtr;
/**
* Callback for traversing master structure
* Must be implemented by code that creates pvCopy.
*/
class epicsShareClass PVCopyTraverseMasterCallback
{
public:
POINTER_DEFINITIONS(PVCopyTraverseMasterCallback);
virtual ~PVCopyTraverseMasterCallback() {}
/**
* Called once for each field in master.
* @param pvField The field in master.
*/
virtual void nextMasterPVField(epics::pvData::PVFieldPtr const &pvField) = 0;
};
class PVCopy;
typedef std::tr1::shared_ptr<PVCopy> PVCopyPtr;
struct CopyNode;
typedef std::tr1::shared_ptr<CopyNode> CopyNodePtr;
struct CopyMasterNode;
typedef std::tr1::shared_ptr<CopyMasterNode> CopyMasterNodePtr;
struct CopyStructureNode;
typedef std::tr1::shared_ptr<CopyStructureNode> CopyStructureNodePtr;
/**
* Class that manages one or more PVStructures that holds an arbitrary subset of the fields
* in another PVStructure called master.
*/
class epicsShareClass PVCopy :
public std::tr1::enable_shared_from_this<PVCopy>
{
public:
POINTER_DEFINITIONS(PVCopy);
/**
* Create a new pvCopy
* @param pvMaster The top level sructure for which a copy of
* an arbritary subset of the fields in master will be created and managed.
* @param pvRequest Selects the set of subfields desired and options for each field.
* @param structureName The name for the top level of any PVStructure created.
*/
static PVCopyPtr create(
PVStructurePtr const &pvMaster,
PVStructurePtr const &pvRequest,
std::string const & structureName);
virtual ~PVCopy(){}
virtual void destroy();
/**
* Get the top level structure of master
* @returns The master top level structure.
* This should not be modified.
*/
PVStructurePtr getPVMaster();
/**
* Traverse all the fields in master.
* @param callback This is called for each field on master.
*/
void traverseMaster(PVCopyTraverseMasterCallbackPtr const & callback)
{
traverseMaster(headNode,callback);
}
/**
* Get the introspection interface for a PVStructure for e copy.
*/
StructureConstPtr getStructure();
/**
* Create a copy instance. Monitors keep a queue of monitor elements.
* Since each element needs a PVStructure, multiple top level structures will be created.
*/
PVStructurePtr createPVStructure();
/**
* Given a field in pvMaster. return the offset in copy for the same field.
* A value of std::string::npos means that the copy does not have this field.
* @param masterPVField The field in master.
*/
std::size_t getCopyOffset(PVFieldPtr const &masterPVField);
/**
* Given a field in pvMaster. return the offset in copy for the same field.
* A value of std::string::npos means that the copy does not have this field.
* @param masterPVStructure A structure in master that has masterPVField.
* @param masterPVField The field in master.
*/
std::size_t getCopyOffset(
PVStructurePtr const &masterPVStructure,
PVFieldPtr const &masterPVField);
/**
* Given a offset in the copy get the corresponding field in pvMaster.
* @param offset The offset in the copy.
*/
PVFieldPtr getMasterPVField(std::size_t structureOffset);
/**
* Initialize the fields in copyPVStructure by giving each field
* the value from the corresponding field in pvMaster.
* bitSet will be set to show that all fields are changed.
* @param copyPVStructure A copy top level structure.
* @param bitSet A bitSet for copyPVStructure.
*/
void initCopy(
PVStructurePtr const &copyPVStructure,
BitSetPtr const &bitSet);
/**
* Set all fields in copyPVStructure to the value of the corresponding field in pvMaster.
* Each field that is changed has it's corresponding bit set in bitSet.
* @param copyPVStructure A copy top level structure.
* @param bitSet A bitSet for copyPVStructure.
*/
void updateCopySetBitSet(
PVStructurePtr const &copyPVStructure,
BitSetPtr const &bitSet);
/**
* For each set bit in bitSet
* set the field in copyPVStructure to the value of the corrseponding field in pvMaster.
* @param copyPVStructure A copy top level structure.
* @param bitSet A bitSet for copyPVStructure.
*/
void updateCopyFromBitSet(
PVStructurePtr const &copyPVStructure,
BitSetPtr const &bitSet);
/**
* For each set bit in bitSet
* set the field in pvMaster to the value of the corrseponding field in copyPVStructure
* @param copyPVStructure A copy top level structure.
* @param bitSet A bitSet for copyPVStructure.
*/
void updateMaster(
PVStructurePtr const &copyPVStructure,
BitSetPtr const &bitSet);
/**
* Get the options for the field at the specified offset.
* @param offset the offset in copy.
* @returns A NULL is returned if no options were specified for the field.
* If options were specified,PVStructurePtr is a structures
* with a set of PVString subfields that specify name,value pairs.s
* name is the subField name and value is the subField value.
*/
PVStructurePtr getOptions(std::size_t fieldOffset);
/**
* For debugging.
*/
std::string dump();
private:
void dump(
std::string *builder,
CopyNodePtr const &node,
int indentLevel);
PVCopyPtr getPtrSelf()
{
return shared_from_this();
}
void traverseMaster(CopyNodePtr const &node, PVCopyTraverseMasterCallbackPtr const & callback);
PVStructurePtr pvMaster;
StructureConstPtr structure;
CopyNodePtr headNode;
PVStructurePtr cacheInitStructure;
PVCopy(PVStructurePtr const &pvMaster);
friend class PVCopyMonitor;
bool init(PVStructurePtr const &pvRequest);
std::string dump(
std::string const &value,
CopyNodePtr const &node,
int indentLevel);
StructureConstPtr createStructure(
PVStructurePtr const &pvMaster,
PVStructurePtr const &pvFromRequest);
CopyNodePtr createStructureNodes(
PVStructurePtr const &pvMasterStructure,
PVStructurePtr const &pvFromRequest,
PVStructurePtr const &pvFromField);
void updateStructureNodeSetBitSet(
PVStructurePtr const &pvCopy,
CopyStructureNodePtr const &structureNode,
BitSetPtr const &bitSet);
void updateSubFieldSetBitSet(
PVFieldPtr const &pvCopy,
PVFieldPtr const &pvMaster,
BitSetPtr const &bitSet);
void updateStructureNodeFromBitSet(
PVStructurePtr const &pvCopy,
CopyStructureNodePtr const &structureNode,
BitSetPtr const &bitSet,
bool toCopy,
bool doAll);
void updateSubFieldFromBitSet(
PVFieldPtr const &pvCopy,
PVFieldPtr const &pvMasterField,
BitSetPtr const &bitSet,
bool toCopy,
bool doAll);
CopyMasterNodePtr getCopyOffset(
CopyStructureNodePtr const &structureNode,
PVFieldPtr const &masterPVField);
CopyMasterNodePtr getMasterNode(
CopyStructureNodePtr const &structureNode,
std::size_t structureOffset);
};
}}
#endif /* PVCOPY_H */

View File

@@ -7,13 +7,15 @@
* @author mes
*/
#define epicsExportSharedSymbols
#include <pv/convert.h>
#include <algorithm>
#include <iterator>
#include <sstream>
#define epicsExportSharedSymbols
#include <pv/convert.h>
using std::string;
namespace epics { namespace pvData {
// Introspection object comparision
@@ -132,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 {
@@ -202,7 +211,7 @@ bool compareField(const PVScalarArray* left, const PVScalarArray* right)
OP(pvLong, int64);
OP(pvFloat, float);
OP(pvDouble, double);
OP(pvString, String);
OP(pvString, string);
#undef OP
}
throw std::logic_error("PVScalarArray with invalid element type!");
@@ -242,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;
@@ -295,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,41 +18,43 @@
#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;
using std::string;
namespace epics { namespace pvData {
static std::vector<String> split(String commaSeparatedList) {
String::size_type numValues = 1;
String::size_type index=0;
static std::vector<string> split(string commaSeparatedList) {
string::size_type numValues = 1;
string::size_type index=0;
while(true) {
String::size_type pos = commaSeparatedList.find(',',index);
if(pos==String::npos) break;
string::size_type pos = commaSeparatedList.find(',',index);
if(pos==string::npos) break;
numValues++;
index = pos +1;
}
std::vector<String> valueList(numValues,"");
std::vector<string> valueList(numValues,"");
index=0;
for(size_t i=0; i<numValues; i++) {
size_t pos = commaSeparatedList.find(',',index);
String value = commaSeparatedList.substr(index,pos);
string value = commaSeparatedList.substr(index,pos);
valueList[i] = value;
index = pos +1;
}
return valueList;
}
void Convert::getString(StringBuilder buf,PVField const *pvField,int /*indentLevel*/)
void Convert::getString(string *buf,PVField const *pvField,int /*indentLevel*/)
{
// TODO indextLevel ignored
std::ostringstream strm;
PrinterPlain p;
p.setStream(strm);
p.print(*pvField);
pvField->dumpValue(strm);
strm << std::endl;
// PrinterPlain p;
// p.setStream(strm);
// p.print(*pvField);
strm.str().swap(*buf);
}
@@ -87,9 +89,9 @@ size_t Convert::fromString(PVStructurePtr const &pvStructure, StringArray const
}
else {
// union, structureArray, unionArray not supported
String message("Convert::fromString unsupported fieldType ");
TypeFunc::toString(&message,type);
throw std::logic_error(message);
std::ostringstream oss;
oss << "Convert::fromString unsupported fieldType " << type;
throw std::logic_error(oss.str());
}
}
}
@@ -97,13 +99,13 @@ size_t Convert::fromString(PVStructurePtr const &pvStructure, StringArray const
return processed;
}
size_t Convert::fromString(PVScalarArrayPtr const &pv, String from)
size_t Convert::fromString(PVScalarArrayPtr const &pv, string from)
{
if(from[0]=='[' && from[from.length()]==']') {
size_t offset = from.rfind(']');
from = from.substr(1, offset);
}
std::vector<String> valueList(split(from));
std::vector<string> valueList(split(from));
size_t length = valueList.size();
size_t num = fromStringArray(pv,0,length,valueList,0);
if(num<length) length = num;
@@ -128,7 +130,7 @@ size_t Convert::fromStringArray(PVScalarArrayPtr const &pv,
data.begin());
PVStringArray::const_svector temp(freeze(data));
pv->putFrom<String>(temp);
pv->putFrom<string>(temp);
return length;
} else {
@@ -142,7 +144,7 @@ size_t Convert::toStringArray(PVScalarArrayPtr const & pv,
StringArray &to, size_t toOffset)
{
PVStringArray::const_svector data;
pv->getAs<String>(data);
pv->getAs<string>(data);
data.slice(offset, length);
if(toOffset+data.size() > to.size())
to.resize(toOffset+data.size());
@@ -191,7 +193,7 @@ bool Convert::isCopyCompatible(FieldConstPtr const &from, FieldConstPtr const &t
return isCopyUnionArrayCompatible(xxx,yyy);
}
}
String message("Convert::isCopyCompatible should never get here");
string message("Convert::isCopyCompatible should never get here");
throw std::logic_error(message);
}
@@ -258,7 +260,7 @@ void Convert::copyScalar(PVScalarPtr const & from, PVScalarPtr const & to)
{
if(to->isImmutable()) {
if(from==to) return;
String message("Convert.copyScalar destination is immutable");
string message("Convert.copyScalar destination is immutable");
throw std::invalid_argument(message);
}
to->assign(*from.get());
@@ -348,13 +350,13 @@ void Convert::copyStructure(PVStructurePtr const & from, PVStructurePtr const &
PVFieldPtrArray const & toDatas = to->getPVFields();
if(from->getStructure()->getNumberFields()
!= to->getStructure()->getNumberFields()) {
String message("Convert.copyStructure Illegal copyStructure");
string message("Convert.copyStructure Illegal copyStructure");
throw std::invalid_argument(message);
}
size_t numberFields = from->getStructure()->getNumberFields();
if(numberFields>=2) {
String name0 = fromDatas[0]->getFieldName();
String name1 = fromDatas[1]->getFieldName();
string name0 = fromDatas[0]->getFieldName();
string name1 = fromDatas[1]->getFieldName();
// look for enumerated structure and copy choices first
if(name0.compare("index")==0 && name1.compare("choices")==0) {
FieldConstPtr fieldIndex = fromDatas[0]->getField();
@@ -382,7 +384,7 @@ void Convert::copyStructure(PVStructurePtr const & from, PVStructurePtr const &
Type fromType = fromData->getField()->getType();
Type toType = toData->getField()->getType();
if(fromType!=toType) {
String message("Convert.copyStructure Illegal copyStructure");
string message("Convert.copyStructure Illegal copyStructure");
throw std::invalid_argument(message);
}
if(toData->isImmutable()) {
@@ -460,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
copy(fromValue, to->select(from->getSelectedIndex()));
to->set(from->getSelectedIndex(),from->get());
}
}
@@ -512,10 +511,10 @@ void Convert::copyUnionArray(
to->replace(from->view());
}
void Convert::newLine(StringBuilder buffer, int indentLevel)
void Convert::newLine(string *buffer, int indentLevel)
{
*buffer += "\n";
*buffer += String(indentLevel*4, ' ');
*buffer += string(indentLevel*4, ' ');
}
ConvertPtr Convert::getConvert()

File diff suppressed because it is too large Load Diff

View File

@@ -5,7 +5,6 @@ SRC_DIRS += $(PVDATA_SRC)/factory
INC += factory.h
LIBSRCS += TypeFunc.cpp
LIBSRCS += FieldCreateFactory.cpp
LIBSRCS += PVAuxInfoImpl.cpp
LIBSRCS += PVField.cpp
LIBSRCS += PVScalar.cpp
LIBSRCS += PVArray.cpp

View File

@@ -1,86 +0,0 @@
/*PVAuxInfo.cpp*/
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvData is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
/**
* @author mrk
*/
#include <cstddef>
#include <cstdlib>
#include <string>
#include <cstdio>
#define epicsExportSharedSymbols
#include <pv/noDefaultMethods.h>
#include <pv/pvData.h>
#include <pv/convert.h>
#include <pv/factory.h>
#include <pv/lock.h>
namespace epics { namespace pvData {
PVAuxInfo::PVAuxInfo(PVField * pvField)
: pvField(pvField),
pvInfos(std::map<String,std::tr1::shared_ptr<PVScalar> > ())
{
}
PVAuxInfo::~PVAuxInfo()
{
}
PVField * PVAuxInfo::getPVField() {
return pvField;
}
PVScalarPtr PVAuxInfo::createInfo(String const & key,ScalarType scalarType)
{
PVInfoIter iter = pvInfos.find(key);
if(iter!=pvInfos.end()) {
String message = key.c_str();
message += " already exists ";
pvField->message(message,errorMessage);
return nullPVScalar;
}
PVScalarPtr pvScalar = getPVDataCreate()->createPVScalar(scalarType);
pvInfos.insert(PVInfoPair(key,pvScalar));
return pvScalar;
}
PVScalarPtr PVAuxInfo::getInfo(String const & key)
{
PVInfoIter iter;
iter = pvInfos.find(key);
if(iter==pvInfos.end()) return nullPVScalar;
return iter->second;
}
PVAuxInfo::PVInfoMap & PVAuxInfo::getInfoMap()
{
return pvInfos;
}
void PVAuxInfo::toString(StringBuilder buf)
{
PVAuxInfo::toString(buf,0);
}
void PVAuxInfo::toString(StringBuilder buf,int indentLevel)
{
if(pvInfos.size()<=0) return;
ConvertPtr convert = getConvert();
convert->newLine(buf,indentLevel);
*buf += "auxInfo";
for(PVInfoIter iter = pvInfos.begin(); iter!= pvInfos.end(); ++iter) {
convert->newLine(buf,indentLevel+1);
PVFieldPtr value = iter->second;
value->toString(buf,indentLevel + 1);
}
}
}}

View File

@@ -27,6 +27,7 @@
using std::tr1::static_pointer_cast;
using std::size_t;
using std::string;
using std::min;
namespace epics { namespace pvData {
@@ -43,7 +44,7 @@ template<> const ScalarType PVUInt::typeCode = pvUInt;
template<> const ScalarType PVULong::typeCode = pvULong;
template<> const ScalarType PVFloat::typeCode = pvFloat;
template<> const ScalarType PVDouble::typeCode = pvDouble;
template<> const ScalarType PVScalarValue<String>::typeCode = pvString;
template<> const ScalarType PVScalarValue<string>::typeCode = pvString;
template<> const ScalarType PVBooleanArray::typeCode = pvBoolean;
template<> const ScalarType PVByteArray::typeCode = pvByte;
@@ -83,7 +84,7 @@ template<typename T>
BasePVScalar<T>::BasePVScalar(ScalarConstPtr const & scalar)
: PVScalarValue<T>(scalar),value(0)
{}
//Note: '0' is a suitable default for all POD types (not String)
//Note: '0' is a suitable default for all POD types (not string)
template<typename T>
BasePVScalar<T>::~BasePVScalar() {}
@@ -128,14 +129,14 @@ typedef BasePVScalar<double> BasePVDouble;
// BasePVString is special case, since it implements SerializableArray
class BasePVString : public PVString {
public:
typedef String value_type;
typedef String* pointer;
typedef const String* const_pointer;
typedef string value_type;
typedef string* pointer;
typedef const string* const_pointer;
BasePVString(ScalarConstPtr const & scalar);
virtual ~BasePVString();
virtual String get() const ;
virtual void put(String val);
virtual string get() const ;
virtual void put(string val);
virtual void serialize(ByteBuffer *pbuffer,
SerializableControl *pflusher) const;
virtual void deserialize(ByteBuffer *pbuffer,
@@ -143,19 +144,29 @@ public:
virtual void serialize(ByteBuffer *pbuffer,
SerializableControl *pflusher, size_t offset, size_t count) const;
private:
String value;
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() {}
String BasePVString::get() const { return value;}
string BasePVString::get() const { return value;}
void BasePVString::put(String val)
void BasePVString::put(string val)
{
if (maxLength > 0 && val.length() > maxLength)
throw std::overflow_error("string too long");
value = val;
postPut();
}
@@ -189,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>
@@ -230,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()
@@ -239,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);
@@ -259,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();
}
@@ -266,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);
}
@@ -282,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
@@ -320,6 +365,7 @@ void DefaultPVArray<T>::deserialize(ByteBuffer *pbuffer,
remaining -= n2read;
}
value = freeze(nextvalue);
// TODO !!!
// inform about the change?
PVField::postPut();
}
@@ -333,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();
@@ -362,12 +412,15 @@ void DefaultPVArray<T>::serialize(ByteBuffer *pbuffer,
}
}
// specializations for String
// specializations for string
template<>
void DefaultPVArray<String>::deserialize(ByteBuffer *pbuffer,
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));
@@ -378,7 +431,7 @@ void DefaultPVArray<String>::deserialize(ByteBuffer *pbuffer,
nextvalue.slice(0, size);
String * pvalue = nextvalue.data();
string * pvalue = nextvalue.data();
for(size_t i = 0; i<size; i++) {
pvalue[i] = SerializeHelper::deserializeString(pbuffer,
pcontrol);
@@ -389,15 +442,17 @@ void DefaultPVArray<String>::deserialize(ByteBuffer *pbuffer,
}
template<>
void DefaultPVArray<String>::serialize(ByteBuffer *pbuffer,
void DefaultPVArray<string>::serialize(ByteBuffer *pbuffer,
SerializableControl *pflusher, size_t offset, size_t count) const {
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();
const string * pvalue = temp.data();
for(size_t i = 0; i<temp.size(); i++) {
SerializeHelper::serializeString(pvalue[i], pbuffer, pflusher);
}
@@ -414,7 +469,7 @@ typedef DefaultPVArray<uint32> BasePVUIntArray;
typedef DefaultPVArray<uint64> BasePVULongArray;
typedef DefaultPVArray<float> BasePVFloatArray;
typedef DefaultPVArray<double> BasePVDoubleArray;
typedef DefaultPVArray<String> BasePVStringArray;
typedef DefaultPVArray<string> BasePVStringArray;
// Factory
@@ -548,16 +603,6 @@ PVScalarPtr PVDataCreate::createPVScalar(PVScalarPtr const & scalarToClone)
ScalarType scalarType = scalarToClone->getScalar()->getScalarType();
PVScalarPtr pvScalar = createPVScalar(scalarType);
getConvert()->copyScalar(scalarToClone, pvScalar);
PVAuxInfoPtr from = scalarToClone->getPVAuxInfo();
PVAuxInfoPtr to = pvScalar->getPVAuxInfo();
PVAuxInfo::PVInfoMap & map = from->getInfoMap();
for(PVAuxInfo::PVInfoIter iter = map.begin(); iter!= map.end(); ++iter) {
String key = iter->first;
PVScalarPtr pvFrom = iter->second;
ScalarConstPtr scalar = pvFrom->getScalar();
PVScalarPtr pvTo = to->createInfo(key,scalar->getScalarType());
getConvert()->copyScalar(pvFrom,pvTo);
}
return pvScalar;
}
@@ -607,16 +652,6 @@ PVScalarArrayPtr PVDataCreate::createPVScalarArray(
PVScalarArrayPtr pvArray = createPVScalarArray(
arrayToClone->getScalarArray()->getElementType());
pvArray->assign(*arrayToClone.get());
PVAuxInfoPtr from = arrayToClone->getPVAuxInfo();
PVAuxInfoPtr to = pvArray->getPVAuxInfo();
PVAuxInfo::PVInfoMap & map = from->getInfoMap();
for(PVAuxInfo::PVInfoIter iter = map.begin(); iter!= map.end(); ++iter) {
String key = iter->first;
PVScalarPtr pvFrom = iter->second;
ScalarConstPtr scalar = pvFrom->getScalar();
PVScalarPtr pvTo = to->createInfo(key,scalar->getScalarType());
getConvert()->copyScalar(pvFrom,pvTo);
}
return pvArray;
}
@@ -668,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

@@ -20,10 +20,10 @@
using std::tr1::const_pointer_cast;
using std::size_t;
using std::string;
namespace epics { namespace pvData {
PVField::PVField(FieldConstPtr field)
: notImplemented("not implemented"),
parent(NULL),field(field),
@@ -35,49 +35,6 @@ PVField::PVField(FieldConstPtr field)
PVField::~PVField()
{ }
void PVField::message(
String message,
MessageType messageType,
String fullFieldName)
{
if(parent!=NULL) {
if(fullFieldName.length()>0) {
fullFieldName = fieldName + '.' + fullFieldName;
} else {
fullFieldName = fieldName;
}
parent->message(message,messageType,fullFieldName);
return;
}
message = fullFieldName + " " + message;
if(requester) {
requester->message(message,messageType);
} else {
printf("%s %s %s\n",
getMessageTypeName(messageType).c_str(),
fieldName.c_str(),
message.c_str());
}
}
void PVField::message(String message,MessageType messageType)
{
PVField::message(message,messageType,"");
}
void PVField::setRequester(RequesterPtr const &req)
{
if(parent!=NULL) {
throw std::logic_error(
"PVField::setRequester only legal for top level structure");
}
if(requester.get()!=NULL) {
if(requester.get()==req.get()) return;
throw std::logic_error(
"PVField::setRequester requester is already present");
}
requester = req;
}
size_t PVField::getFieldOffset() const
{
@@ -97,12 +54,6 @@ size_t PVField::getNumberFields() const
return (nextFieldOffset - fieldOffset);
}
PVAuxInfoPtr & PVField::getPVAuxInfo(){
if(pvAuxInfo.get()==NULL) {
pvAuxInfo = PVAuxInfoPtr(new PVAuxInfo(this));
}
return pvAuxInfo;
}
bool PVField::isImmutable() const {return immutable;}
@@ -112,46 +63,6 @@ const FieldConstPtr & PVField::getField() const {return field;}
PVStructure *PVField::getParent() const {return parent;}
void PVField::replacePVField(const PVFieldPtr & newPVField)
{
if(parent==NULL) {
throw std::logic_error("no parent");
}
PVFieldPtrArray pvFields = parent->getPVFields();
StructureConstPtr structure = parent->getStructure();
StringArray fieldNames = structure->getFieldNames();
for(size_t i=0; i<fieldNames.size(); i++) {
if(newPVField->getFieldName().compare(fieldNames[i]) == 0) {
pvFields[i] = newPVField;
return;
}
}
throw std::logic_error("Did not find field in parent");
}
void PVField::replaceField(FieldConstPtr &xxx)
{
field = xxx;
}
void PVField::renameField(String const & newName)
{
if(parent==NULL) {
throw std::logic_error("no parent");
}
std::tr1::shared_ptr<Structure> parentStructure = const_pointer_cast<Structure>(
parent->getStructure());
PVFieldPtrArray pvFields = parent->getPVFields();
for(size_t i=0; i<pvFields.size(); i++) {
if(pvFields[i].get()==this) {
parentStructure->renameField(i,newName);
fieldName = newName;
return;
}
}
throw std::logic_error("Did not find field in parent");
}
void PVField::postPut()
{
if(postHandler.get()!=NULL) postHandler->postPut();
@@ -168,7 +79,7 @@ void PVField::setPostHandler(PostHandlerPtr const &handler)
postHandler = handler;
}
void PVField::setParentAndName(PVStructure * xxx,String const & name)
void PVField::setParentAndName(PVStructure * xxx,string const & name)
{
parent = xxx;
fieldName = name;
@@ -179,68 +90,19 @@ bool PVField::equals(PVField &pv)
return pv==*this;
}
void PVField::toString(StringBuilder buf)
{
toString(buf,0);
}
void PVField::toString(StringBuilder buf,int indentLevel)
{
Convert().getString(buf,this,indentLevel);
if(pvAuxInfo.get()!=NULL) pvAuxInfo->toString(buf,indentLevel);
}
std::ostream& operator<<(std::ostream& o, const PVField& f)
{
std::ostream& ro = f.dumpValue(o);
// TODO I do not want to call getPVAuxInfo() since it lazily creates a new instance of it
//if (f.pvAuxInfo.get()!=NULL) ro << *(f.pvAuxInfo.get());
return ro;
return f.dumpValue(o);
};
namespace format
string PVField::getFullName() const
{
std::ostream& operator<<(std::ostream& os, indent_level const& indent)
{
indent_value(os) = indent.level;
return os;
}
std::ostream& operator<<(std::ostream& os, indent const&)
{
long il = indent_value(os);
std::size_t spaces = static_cast<std::size_t>(il) * 4;
return os << std::string(spaces, ' ');
}
array_at_internal operator<<(std::ostream& str, array_at const& manip)
{
return array_at_internal(manip.index, str);
}
};
String PVField::getFullName() const
{
size_t size=fieldName.size();
string ret(fieldName);
for(PVField *fld=getParent(); fld; fld=fld->getParent())
{
size+=fld->fieldName.size()+1;
if(fld->getFieldName().size()==0) break;
ret = fld->getFieldName() + '.' + ret;
}
String ret(size, '.');
size_t pos=size - fieldName.size();
ret.replace(pos, String::npos, fieldName);
for(PVField *fld=getParent(); fld; fld=fld->getParent())
{
const String& nref = fld->fieldName;
assert(pos >= nref.size()+1);
pos -= nref.size()+1;
ret.replace(pos, String::npos, nref);
}
assert(pos==0);
return ret;
}

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

@@ -22,6 +22,7 @@
using std::tr1::static_pointer_cast;
using std::size_t;
using std::string;
namespace epics { namespace pvData {
@@ -45,7 +46,7 @@ PVUnionArrayPtr PVStructure::nullPVUnionArray;
PVScalarArrayPtr PVStructure::nullPVScalarArray;
static PVFieldPtr findSubField(
String const &fieldName,
string const &fieldName,
const PVStructure *pvStructure);
PVStructure::PVStructure(StructureConstPtr const & structurePtr)
@@ -60,7 +61,7 @@ PVStructure::PVStructure(StructureConstPtr const & structurePtr)
pvFields.reserve(numberFields);
PVDataCreatePtr pvDataCreate = getPVDataCreate();
for(size_t i=0; i<numberFields; i++) {
pvFields.push_back(pvDataCreate->createPVField(fields[i]));
pvFields.push_back(pvDataCreate->createPVField(fields[i]));
}
for(size_t i=0; i<numberFields; i++) {
pvFields[i]->setParentAndName(this,fieldNames[i]);
@@ -109,7 +110,7 @@ const PVFieldPtrArray & PVStructure::getPVFields() const
return pvFields;
}
PVFieldPtr PVStructure::getSubField(String const &fieldName) const
PVFieldPtr PVStructure::getSubField(string const &fieldName) const
{
return findSubField(fieldName,this);
}
@@ -134,183 +135,79 @@ PVFieldPtr PVStructure::getSubField(size_t fieldOffset) const
throw std::logic_error("PVStructure.getSubField: Logic error");
}
void PVStructure::fixParentStructure()
{
PVStructure *parent = getParent();
if(parent==NULL) return;
StructureConstPtr parentStructure = parent->structurePtr;
String fieldName = getFieldName();
size_t index = parentStructure->getFieldIndex(fieldName);
StringArray const &fieldNames = parentStructure->getFieldNames();
size_t num = fieldNames.size();
FieldConstPtrArray fields(num);
FieldConstPtrArray const & oldFields = parentStructure->getFields();
for(size_t i=0; i< num; i++) {
if(i==index) {
fields[i] = structurePtr;
} else {
fields[i] = oldFields[i];
}
}
FieldConstPtr field = getFieldCreate()->createStructure(
parentStructure->getID(),fieldNames,fields);
parent->replaceField(field);
parent->fixParentStructure();
}
void PVStructure::appendPVField(
String const &fieldName,
PVFieldPtr const & pvField)
{
size_t origLength = pvFields.size();
size_t newLength = origLength+1;
PVFieldPtrArray * xxx = const_cast<PVFieldPtrArray *>(&pvFields);
xxx->push_back(pvField);
FieldConstPtr field = getFieldCreate()->appendField(
structurePtr,fieldName,pvField->getField());
replaceField(field);
structurePtr = static_pointer_cast<const Structure>(field);
StringArray fieldNames = structurePtr->getFieldNames();
for(size_t i=0; i<newLength; i++) {
pvFields[i]->setParentAndName(this,fieldNames[i]);
}
fixParentStructure();
}
void PVStructure::appendPVFields(
StringArray const & fieldNames,
PVFieldPtrArray const & pvFields)
{
size_t origLength = this->pvFields.size();
size_t extra = fieldNames.size();
if(extra==0) return;
size_t newLength = origLength + extra;
PVFieldPtrArray * xxx = const_cast<PVFieldPtrArray *>(&this->pvFields);
xxx->reserve(newLength);
for(size_t i=0; i<extra; i++) {
xxx->push_back(pvFields[i]);
}
FieldConstPtrArray fields;
fields.reserve(extra);
for(size_t i=0; i<extra; i++) fields.push_back(pvFields[i]->getField());
FieldConstPtr field = getFieldCreate()->appendFields(
structurePtr,fieldNames,fields);
replaceField(field);
structurePtr = static_pointer_cast<const Structure>(field);
StringArray names = structurePtr->getFieldNames();
for(size_t i=0; i<newLength; i++) {
(*xxx)[i]->setParentAndName(this,names[i]);
}
fixParentStructure();
}
void PVStructure::removePVField(String const &fieldName)
{
PVFieldPtr pvField = getSubField(fieldName);
if(pvField.get()==NULL) {
return;
}
size_t origLength = pvFields.size();
size_t newLength = origLength - 1;
PVFieldPtrArray const & origPVFields = pvFields;
FieldConstPtrArray origFields = structurePtr->getFields();
PVFieldPtrArray newPVFields;
newPVFields.reserve(newLength);
StringArray newFieldNames;
newFieldNames.reserve(newLength);
FieldConstPtrArray fields;
fields.reserve(newLength);
for(size_t i=0; i<origLength; i++) {
if(origPVFields[i]!=pvField) {
newFieldNames.push_back(origPVFields[i]->getFieldName());
newPVFields.push_back(origPVFields[i]);
fields.push_back(origFields[i]);
}
}
PVFieldPtrArray * xxx = const_cast<PVFieldPtrArray *>(&pvFields);
xxx->swap(newPVFields);
FieldConstPtr field = getFieldCreate()->createStructure(
structurePtr->getID(),newFieldNames,fields);
replaceField(field);
structurePtr = static_pointer_cast<const Structure>(field);
StringArray fieldNames = structurePtr->getFieldNames();
for(size_t i=0; i<newLength; i++) {
pvFields[i]->setParentAndName(this,fieldNames[i]);
}
}
PVBooleanPtr PVStructure::getBooleanField(String const &fieldName)
PVBooleanPtr PVStructure::getBooleanField(string const &fieldName)
{
return getSubField<PVBoolean>(fieldName);
}
PVBytePtr PVStructure::getByteField(String const &fieldName)
PVBytePtr PVStructure::getByteField(string const &fieldName)
{
return getSubField<PVByte>(fieldName);
}
PVShortPtr PVStructure::getShortField(String const &fieldName)
PVShortPtr PVStructure::getShortField(string const &fieldName)
{
return getSubField<PVShort>(fieldName);
}
PVIntPtr PVStructure::getIntField(String const &fieldName)
PVIntPtr PVStructure::getIntField(string const &fieldName)
{
return getSubField<PVInt>(fieldName);
}
PVLongPtr PVStructure::getLongField(String const &fieldName)
PVLongPtr PVStructure::getLongField(string const &fieldName)
{
return getSubField<PVLong>(fieldName);
}
PVUBytePtr PVStructure::getUByteField(String const &fieldName)
PVUBytePtr PVStructure::getUByteField(string const &fieldName)
{
return getSubField<PVUByte>(fieldName);
}
PVUShortPtr PVStructure::getUShortField(String const &fieldName)
PVUShortPtr PVStructure::getUShortField(string const &fieldName)
{
return getSubField<PVUShort>(fieldName);
}
PVUIntPtr PVStructure::getUIntField(String const &fieldName)
PVUIntPtr PVStructure::getUIntField(string const &fieldName)
{
return getSubField<PVUInt>(fieldName);
}
PVULongPtr PVStructure::getULongField(String const &fieldName)
PVULongPtr PVStructure::getULongField(string const &fieldName)
{
return getSubField<PVULong>(fieldName);
}
PVFloatPtr PVStructure::getFloatField(String const &fieldName)
PVFloatPtr PVStructure::getFloatField(string const &fieldName)
{
return getSubField<PVFloat>(fieldName);
}
PVDoublePtr PVStructure::getDoubleField(String const &fieldName)
PVDoublePtr PVStructure::getDoubleField(string const &fieldName)
{
return getSubField<PVDouble>(fieldName);
}
PVStringPtr PVStructure::getStringField(String const &fieldName)
PVStringPtr PVStructure::getStringField(string const &fieldName)
{
return getSubField<PVString>(fieldName);
}
PVStructurePtr PVStructure::getStructureField(String const &fieldName)
PVStructurePtr PVStructure::getStructureField(string const &fieldName)
{
return getSubField<PVStructure>(fieldName);
}
PVUnionPtr PVStructure::getUnionField(String const &fieldName)
PVUnionPtr PVStructure::getUnionField(string const &fieldName)
{
return getSubField<PVUnion>(fieldName);
}
PVScalarArrayPtr PVStructure::getScalarArrayField(
String const &fieldName,ScalarType elementType)
string const &fieldName,ScalarType elementType)
{
PVFieldPtr pvField = findSubField(fieldName,this);
if(pvField.get()==NULL) {
@@ -330,29 +227,17 @@ PVScalarArrayPtr PVStructure::getScalarArrayField(
}
PVStructureArrayPtr PVStructure::getStructureArrayField(
String const &fieldName)
string const &fieldName)
{
return getSubField<PVStructureArray>(fieldName);
}
PVUnionArrayPtr PVStructure::getUnionArrayField(
String const &fieldName)
string const &fieldName)
{
return getSubField<PVUnionArray>(fieldName);
}
String PVStructure::getExtendsStructureName() const
{
return extendsStructureName;
}
bool PVStructure::putExtendsStructureName(
String const &xxx)
{
if(extendsStructureName.length()!=0) return false;
extendsStructureName = xxx;
return true;
}
void PVStructure::serialize(ByteBuffer *pbuffer,
SerializableControl *pflusher) const {
@@ -444,13 +329,13 @@ void PVStructure::deserialize(ByteBuffer *pbuffer,
}
static PVFieldPtr findSubField(
String const & fieldName,
string const & fieldName,
PVStructure const *pvStructure)
{
if( fieldName.length()<1) return PVFieldPtr();
String::size_type index = fieldName.find('.');
String name = fieldName;
String restOfName = String();
string::size_type index = fieldName.find('.');
string name = fieldName;
string restOfName = string();
if(index>0) {
name = fieldName.substr(0, index);
if(fieldName.length()>index) {
@@ -477,10 +362,6 @@ static PVFieldPtr findSubField(
std::ostream& PVStructure::dumpValue(std::ostream& o) const
{
o << format::indent() << getStructure()->getID() << ' ' << getFieldName();
String extendsName = getExtendsStructureName();
if(extendsName.length()>0) {
o << " extends " << extendsName;
}
o << std::endl;
{
format::indent_scope s(o);

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

@@ -22,6 +22,7 @@
using std::tr1::static_pointer_cast;
using std::size_t;
using std::string;
namespace epics { namespace pvData {
@@ -58,11 +59,11 @@ int32 PVUnion::getSelectedIndex() const
return selector;
}
String PVUnion::getSelectedFieldName() const
string PVUnion::getSelectedFieldName() const
{
// no name for undefined and for variant unions
if (selector == UNDEFINED_INDEX)
return String();
return string();
else
return unionPtr->getFieldName(selector);
}
@@ -91,7 +92,7 @@ PVFieldPtr PVUnion::select(int32 index)
return value;
}
PVFieldPtr PVUnion::select(String const & fieldName)
PVFieldPtr PVUnion::select(string const & fieldName)
{
int32 index = variant ? -1 : static_cast<int32>(unionPtr->getFieldIndex(fieldName));
if (index == -1)
@@ -126,9 +127,10 @@ void PVUnion::set(int32 index, PVFieldPtr const & value)
selector = index;
this->value = value;
postPut();
}
void PVUnion::set(String const & fieldName, PVFieldPtr const & value)
void PVUnion::set(string const & fieldName, PVFieldPtr const & value)
{
int32 index = variant ? -1 : static_cast<int32>(unionPtr->getFieldIndex(fieldName));
if (index == -1)
@@ -167,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
@@ -175,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

@@ -17,6 +17,7 @@
#include <pv/standardField.h>
using std::tr1::static_pointer_cast;
using std::string;
namespace epics { namespace pvData {
@@ -49,7 +50,7 @@ void StandardField::init()
StandardField::~StandardField(){}
StructureConstPtr StandardField::createProperties(String id,FieldConstPtr field,String properties)
StructureConstPtr StandardField::createProperties(string id,FieldConstPtr field,string properties)
{
bool gotAlarm = false;
bool gotTimeStamp = false;
@@ -57,11 +58,11 @@ StructureConstPtr StandardField::createProperties(String id,FieldConstPtr field,
bool gotControl = false;
bool gotValueAlarm = false;
int numProp = 0;
if(properties.find("alarm")!=String::npos) { gotAlarm = true; numProp++; }
if(properties.find("timeStamp")!=String::npos) { gotTimeStamp = true; numProp++; }
if(properties.find("display")!=String::npos) { gotDisplay = true; numProp++; }
if(properties.find("control")!=String::npos) { gotControl = true; numProp++; }
if(properties.find("valueAlarm")!=String::npos) { gotValueAlarm = true; numProp++; }
if(properties.find("alarm")!=string::npos) { gotAlarm = true; numProp++; }
if(properties.find("timeStamp")!=string::npos) { gotTimeStamp = true; numProp++; }
if(properties.find("display")!=string::npos) { gotDisplay = true; numProp++; }
if(properties.find("control")!=string::npos) { gotControl = true; numProp++; }
if(properties.find("valueAlarm")!=string::npos) { gotValueAlarm = true; numProp++; }
StructureConstPtr valueAlarm;
Type type= field->getType();
while(gotValueAlarm) {
@@ -82,7 +83,7 @@ StructureConstPtr StandardField::createProperties(String id,FieldConstPtr field,
case pvFloat: valueAlarm = floatAlarmField; break;
case pvDouble: valueAlarm = doubleAlarmField; break;
case pvString:
throw std::logic_error(String("valueAlarm property not supported for pvString"));
throw std::logic_error(string("valueAlarm property not supported for pvString"));
}
break;
}
@@ -93,8 +94,8 @@ StructureConstPtr StandardField::createProperties(String id,FieldConstPtr field,
FieldConstPtrArray fields = structurePtr->getFields();
FieldConstPtr first = fields[0];
FieldConstPtr second = fields[1];
String nameFirst = names[0];
String nameSecond = names[1];
string nameFirst = names[0];
string nameSecond = names[1];
int compareFirst = nameFirst.compare("index");
int compareSecond = nameSecond.compare("choices");
if(compareFirst==0 && compareSecond==0) {
@@ -112,7 +113,7 @@ StructureConstPtr StandardField::createProperties(String id,FieldConstPtr field,
}
}
}
throw std::logic_error(String("valueAlarm property for illegal type"));
throw std::logic_error(string("valueAlarm property for illegal type"));
}
size_t numFields = numProp+1;
FieldConstPtrArray fields(numFields);
@@ -161,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);
@@ -227,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);
@@ -254,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);
@@ -281,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);
@@ -308,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);
@@ -335,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);
@@ -362,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);
@@ -389,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);
@@ -416,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);
@@ -443,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);
@@ -470,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);
@@ -499,26 +500,48 @@ void StandardField::createEnumeratedAlarm() {
StructureConstPtr StandardField::scalar(
ScalarType type,String const &properties)
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("epics:nt/NTUnion:1.0",field,properties);
}
StructureConstPtr StandardField::variantUnion(
string const & properties)
{
UnionConstPtr field = fieldCreate->createVariantUnion();
return createProperties("epics:nt/NTUnion:1.0",field,properties);
}
StructureConstPtr StandardField::scalarArray(
ScalarType elementType, String const &properties)
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);
}
StructureConstPtr StandardField::structureArray(
StructureConstPtr const & structure,String const &properties)
StructureConstPtr const & structure,string const &properties)
{
StructureArrayConstPtr field = fieldCreate->createStructureArray(
structure);
return createProperties("uri:ev4:nt/2012/pwd:NTAny",field,properties);
return createProperties("epics:nt/NTStructureArray:1.0",field,properties);
}
StructureConstPtr StandardField::unionArray(
UnionConstPtr const & punion,string const &properties)
{
UnionArrayConstPtr field = fieldCreate->createUnionArray(
punion);
return createProperties("epics:nt/NTUnionArray:1.0",field,properties);
}
StructureConstPtr StandardField::enumerated()
@@ -534,10 +557,10 @@ StructureConstPtr StandardField::enumerated()
// NOTE: if this method is used to get NTEnum wihtout properties the ID will be wrong!
}
StructureConstPtr StandardField::enumerated(String const &properties)
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

@@ -18,6 +18,8 @@
#include <pv/standardField.h>
#include <pv/standardPVField.h>
using std::string;
namespace epics { namespace pvData {
StandardPVField::StandardPVField()
@@ -30,7 +32,7 @@ StandardPVField::StandardPVField()
StandardPVField::~StandardPVField(){}
PVStructurePtr StandardPVField::scalar(
ScalarType type,String const & properties)
ScalarType type,string const & properties)
{
StructureConstPtr field = standardField->scalar(type,properties);
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(field);
@@ -38,7 +40,7 @@ PVStructurePtr StandardPVField::scalar(
}
PVStructurePtr StandardPVField::scalarArray(
ScalarType elementType, String const & properties)
ScalarType elementType, string const & properties)
{
StructureConstPtr field = standardField->scalarArray(elementType,properties);
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(field);
@@ -46,13 +48,21 @@ PVStructurePtr StandardPVField::scalarArray(
}
PVStructurePtr StandardPVField::structureArray(
StructureConstPtr const & structure,String const & properties)
StructureConstPtr const & structure,string const & properties)
{
StructureConstPtr field = standardField->structureArray(structure,properties);
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(field);
return pvStructure;
}
PVStructurePtr StandardPVField::unionArray(
UnionConstPtr const & punion,string const & properties)
{
StructureConstPtr field = standardField->unionArray(punion,properties);
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(field);
return pvStructure;
}
PVStructurePtr StandardPVField::enumerated(StringArray const &choices)
{
StructureConstPtr field = standardField->enumerated();
@@ -66,7 +76,7 @@ PVStructurePtr StandardPVField::enumerated(StringArray const &choices)
}
PVStructurePtr StandardPVField::enumerated(
StringArray const &choices,String const & properties)
StringArray const &choices,string const & properties)
{
StructureConstPtr field = standardField->enumerated(properties);
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(field);

View File

@@ -19,6 +19,8 @@
#include "dbDefs.h" // for NELEMENTS
using std::string;
namespace epics { namespace pvData {
namespace TypeFunc {
@@ -30,11 +32,13 @@ namespace TypeFunc {
THROW_EXCEPTION2(std::invalid_argument, "logic error unknown Type");
return names[t];
}
void toString(StringBuilder buf,const Type type) {
*buf += name(type);
}
} // namespace TypeFunc
std::ostream& operator<<(std::ostream& o, const Type& type)
{
return o << TypeFunc::name(type);
}
namespace ScalarTypeFunc {
bool isInteger(ScalarType type) {
@@ -63,7 +67,7 @@ namespace ScalarTypeFunc {
"ubyte", "ushort", "uint", "ulong",
"float", "double", "string",
};
ScalarType getScalarType(const String& pvalue) {
ScalarType getScalarType(const string& pvalue) {
for(size_t i=0; i<NELEMENTS(names); i++)
if(pvalue==names[i])
return ScalarType(i);
@@ -76,10 +80,6 @@ namespace ScalarTypeFunc {
return names[t];
}
void toString(StringBuilder buf,const ScalarType scalarType) {
*buf += name(scalarType);
}
size_t elementSize(ScalarType id)
{
switch(id) {
@@ -95,7 +95,7 @@ namespace ScalarTypeFunc {
OP(pvLong, int64);
OP(pvFloat, float);
OP(pvDouble, double);
OP(pvString, String);
OP(pvString, string);
#undef OP
default:
THROW_EXCEPTION2(std::invalid_argument, "error unknown ScalarType");
@@ -117,7 +117,7 @@ namespace ScalarTypeFunc {
OP(pvLong, int64);
OP(pvFloat, float);
OP(pvDouble, double);
OP(pvString, String);
OP(pvString, string);
#undef OP
default:
throw std::bad_alloc();
@@ -126,4 +126,9 @@ namespace ScalarTypeFunc {
} // namespace ScalarTypeFunc
std::ostream& operator<<(std::ostream& o, const ScalarType& scalarType)
{
return o << ScalarTypeFunc::name(scalarType);
}
}}

View File

@@ -10,6 +10,8 @@
#define epicsExportSharedSymbols
#include <pv/printer.h>
using std::string;
namespace {
void indentN(std::ostream& strm, size_t N)
@@ -22,6 +24,34 @@ void indentN(std::ostream& strm, size_t N)
namespace epics { namespace pvData {
namespace format
{
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;
}
std::ostream& operator<<(std::ostream& os, indent const&)
{
long il = indent_value(os);
std::size_t spaces = static_cast<std::size_t>(il) * 4;
return os << string(spaces, ' ');
}
array_at_internal operator<<(std::ostream& str, array_at const& manip)
{
return array_at_internal(manip.index, str);
}
};
PrinterBase::PrinterBase()
:strm(NULL)
{}
@@ -199,9 +229,6 @@ void PrinterPlain::beginStructure(const PVStructure& pv)
{
indentN(S(), ilvl);
S() << pv.getStructure()->getID() << " " << pv.getFieldName();
String ename(pv.getExtendsStructureName());
if(!ename.empty())
S() << " extends " << ename;
S() << std::endl;
ilvl++;
}
@@ -242,14 +269,14 @@ void PrinterPlain::encodeScalar(const PVScalar& pv)
indentN(S(), ilvl);
S() << pv.getScalar()->getID() << " "
<< pv.getFieldName() << " "
<< pv.getAs<String>() << std::endl;
<< pv.getAs<string>() << std::endl;
}
void PrinterPlain::encodeArray(const PVScalarArray& pv)
{
indentN(S(), ilvl);
shared_vector<const String> temp;
pv.getAs<String>(temp);
shared_vector<const string> temp;
pv.getAs<string>(temp);
S() << pv.getScalarArray()->getID() << " "
<< pv.getFieldName() << " [";

View File

@@ -14,31 +14,36 @@
#define epicsExportSharedSymbols
#include <pv/pvSubArrayCopy.h>
using std::cout;
using std::endl;
using std::string;
namespace epics { namespace pvData {
template<typename T>
void copy(
PVValueArray<T> & pvFrom,
size_t fromOffset,
size_t fromStride,
PVValueArray<T> & pvTo,
size_t toOffset,
size_t len)
size_t toStride,
size_t count)
{
if(pvTo.isImmutable()) {
throw std::logic_error("pvSubArrayCopy to is immutable");
}
if(pvTo.isImmutable()) throw std::invalid_argument("pvSubArrayCopy: pvTo is immutable");
if(fromStride<1 || toStride<1) throw std::invalid_argument("stride must be >=1");
size_t fromLength = pvFrom.getLength();
if(fromOffset+len>fromLength) {
throw std::length_error("pvSubArrayCopy from length error");
}
size_t maxcount = (fromLength -fromOffset + fromStride -1)/fromStride;
if(count>maxcount) throw std::invalid_argument("pvSubArrayCopy pvFrom length error");
size_t newLength = toOffset + count*toStride;
size_t capacity = pvTo.getCapacity();
if(toOffset+len>capacity) capacity = toOffset + len;
if(newLength>capacity) capacity = newLength;
shared_vector<T> temp(capacity);
typename PVValueArray<T>::const_svector vecFrom = pvFrom.view();
typename PVValueArray<T>::const_svector vecTo = pvTo.view();
for(size_t i=0; i<toOffset; ++i) temp[i] = vecTo[i];
for(size_t i=0; i<len; ++i) temp[i + toOffset] = vecFrom[i + fromOffset];
for(size_t i=len + toOffset; i<capacity; ++i) temp[i] = vecTo[i];
for(size_t i=0; i<pvTo.getLength(); ++i) temp[i] = vecTo[i];
for(size_t i=pvTo.getLength(); i< capacity; ++i) temp[i] = T();
for(size_t i=0; i<count; ++i) temp[i*toStride + toOffset] = vecFrom[i*fromStride+fromOffset];
shared_vector<const T> temp2(freeze(temp));
pvTo.replace(temp2);
}
@@ -46,9 +51,11 @@ void copy(
void copy(
PVScalarArray & from,
size_t fromOffset,
size_t fromStride,
PVScalarArray & to,
size_t toOffset,
size_t len)
size_t toStride,
size_t count)
{
ScalarType scalarType = from.getScalarArray()->getElementType();
ScalarType otherType = to.getScalarArray()->getElementType();
@@ -59,145 +66,210 @@ void copy(
{
case pvBoolean:
{
copy(dynamic_cast<PVValueArray<boolean> &>(from),fromOffset,
copy(dynamic_cast<PVValueArray<boolean> &>(from),fromOffset,fromStride,
dynamic_cast<PVValueArray<boolean>& >(to),
toOffset,len);
toOffset,toStride,count);
}
break;
case pvByte:
{
copy(dynamic_cast<PVValueArray<int8> &>(from),fromOffset,
copy(dynamic_cast<PVValueArray<int8> &>(from),fromOffset,fromStride,
dynamic_cast<PVValueArray<int8>& >(to),
toOffset,len);
toOffset,toStride,count);
}
break;
case pvShort:
{
copy(dynamic_cast<PVValueArray<int16> &>(from),fromOffset,
copy(dynamic_cast<PVValueArray<int16> &>(from),fromOffset,fromStride,
dynamic_cast<PVValueArray<int16>& >(to),
toOffset,len);
toOffset,toStride,count);
}
break;
case pvInt:
{
copy(dynamic_cast<PVValueArray<int32> &>(from),fromOffset,
copy(dynamic_cast<PVValueArray<int32> &>(from),fromOffset,fromStride,
dynamic_cast<PVValueArray<int32>& >(to),
toOffset,len);
toOffset,toStride,count);
}
break;
case pvLong:
{
copy(dynamic_cast<PVValueArray<int64> &>(from),fromOffset,
copy(dynamic_cast<PVValueArray<int64> &>(from),fromOffset,fromStride,
dynamic_cast<PVValueArray<int64>& >(to),
toOffset,len);
toOffset,toStride,count);
}
break;
case pvUByte:
{
copy(dynamic_cast<PVValueArray<uint8> &>(from),fromOffset,
copy(dynamic_cast<PVValueArray<uint8> &>(from),fromOffset,fromStride,
dynamic_cast<PVValueArray<uint8>& >(to),
toOffset,len);
toOffset,toStride,count);
}
break;
case pvUShort:
{
copy(dynamic_cast<PVValueArray<uint16> &>(from),fromOffset,
copy(dynamic_cast<PVValueArray<uint16> &>(from),fromOffset,fromStride,
dynamic_cast<PVValueArray<uint16>& >(to),
toOffset,len);
toOffset,toStride,count);
}
break;
case pvUInt:
{
copy(dynamic_cast<PVValueArray<uint32> &>(from),fromOffset,
copy(dynamic_cast<PVValueArray<uint32> &>(from),fromOffset,fromStride,
dynamic_cast<PVValueArray<uint32>& >(to),
toOffset,len);
toOffset,toStride,count);
}
break;
case pvULong:
{
copy(dynamic_cast<PVValueArray<uint64> &>(from),fromOffset,
copy(dynamic_cast<PVValueArray<uint64> &>(from),fromOffset,fromStride,
dynamic_cast<PVValueArray<uint64>& >(to),
toOffset,len);
toOffset,toStride,count);
}
break;
case pvFloat:
{
copy(dynamic_cast<PVValueArray<float> &>(from),fromOffset,
copy(dynamic_cast<PVValueArray<float> &>(from),fromOffset,fromStride,
dynamic_cast<PVValueArray<float>& >(to),
toOffset,len);
toOffset,toStride,count);
}
break;
case pvDouble:
{
copy(dynamic_cast<PVValueArray<double> &>(from),fromOffset,
copy(dynamic_cast<PVValueArray<double> &>(from),fromOffset,fromStride,
dynamic_cast<PVValueArray<double>& >(to),
toOffset,len);
toOffset,toStride,count);
}
break;
case pvString:
{
copy(dynamic_cast<PVValueArray<String> &>(from),fromOffset,
dynamic_cast<PVValueArray<String>& >(to),
toOffset,len);
copy(dynamic_cast<PVValueArray<string> &>(from),fromOffset,fromStride,
dynamic_cast<PVValueArray<string>& >(to),
toOffset,toStride,count);
}
break;
}
}
void copy(
PVStructureArray & from,
size_t fromOffset,
PVStructureArray & to,
PVStructureArray & pvFrom,
size_t pvFromOffset,
size_t pvFromStride,
PVStructureArray & pvTo,
size_t toOffset,
size_t len)
size_t toStride,
size_t count)
{
if(to.isImmutable()) {
throw std::logic_error("pvSubArrayCopy to is immutable");
if(pvTo.isImmutable()) {
throw std::logic_error("pvSubArrayCopy pvTo is immutable");
}
StructureArrayConstPtr fromStructure = from.getStructureArray();
StructureArrayConstPtr toStructure = to.getStructureArray();
if(fromStructure!=toStructure) {
if(pvFromStride<1 || toStride<1) throw std::invalid_argument("stride must be >=1");
StructureArrayConstPtr pvFromStructure = pvFrom.getStructureArray();
StructureArrayConstPtr toStructure = pvTo.getStructureArray();
if(pvFromStructure->getStructure()!=toStructure->getStructure()) {
throw std::invalid_argument(
"pvSubArrayCopy structureArray to and from have different structures");
"pvSubArrayCopy structureArray pvTo and pvFrom have different structures");
}
size_t fromLength = from.getLength();
if(fromOffset+len>fromLength) {
throw std::length_error("pvSubArrayCopy from length error");
}
size_t capacity = to.getCapacity();
if(toOffset+len>capacity) capacity = toOffset+len;
size_t pvFromLength = pvFrom.getLength();
size_t maxcount = (pvFromLength -pvFromOffset + pvFromStride -1)/pvFromStride;
if(count>maxcount) throw std::invalid_argument("pvSubArrayCopy pvFrom length error");
size_t newLength = toOffset + count*toStride;
size_t capacity = pvTo.getCapacity();
if(newLength>capacity) capacity = newLength;
shared_vector<PVStructurePtr> temp(capacity);
PVValueArray<PVStructurePtr>::const_svector vecFrom = from.view();
PVValueArray<PVStructurePtr>::const_svector vecTo = to.view();
for(size_t i=0; i<toOffset; ++i) temp[i] = vecTo[i];
for(size_t i=0; i<len; ++i) temp[i + toOffset] = vecFrom[i + fromOffset];
for(size_t i=len + toOffset; i<capacity; ++i) temp[i] = vecTo[i];
PVValueArray<PVStructurePtr>::const_svector vecFrom = pvFrom.view();
PVValueArray<PVStructurePtr>::const_svector vecTo = pvTo.view();
for(size_t i=0; i<pvTo.getLength(); ++i) temp[i] = vecTo[i];
for(size_t i=pvTo.getLength(); i< capacity; ++i)
temp[i] = getPVDataCreate()->createPVStructure(toStructure->getStructure());
for(size_t i=0; i<count; ++i) temp[i*toStride + toOffset] = vecFrom[i*pvFromStride+pvFromOffset];
shared_vector<const PVStructurePtr> temp2(freeze(temp));
to.replace(temp2);
pvTo.replace(temp2);
}
void copy(
PVArray & from,
size_t fromOffset,
PVArray & to,
PVUnionArray & pvFrom,
size_t pvFromOffset,
size_t pvFromStride,
PVUnionArray & pvTo,
size_t toOffset,
size_t len)
size_t toStride,
size_t count)
{
Type type = from.getField()->getType();
Type otherType = to.getField()->getType();
if(type!=otherType) {
throw std::invalid_argument("pvSubArrayCopy types do not match");
if(pvTo.isImmutable()) {
throw std::logic_error("pvSubArrayCopy pvTo is immutable");
}
if(type==scalarArray) {
copy(dynamic_cast<PVScalarArray &>(from) ,fromOffset,
dynamic_cast<PVScalarArray&>(to),
toOffset,len);
if(pvFromStride<1 || toStride<1) throw std::invalid_argument("stride must be >=1");
UnionArrayConstPtr pvFromUnion = pvFrom.getUnionArray();
UnionArrayConstPtr toUnion = pvTo.getUnionArray();
if(pvFromUnion->getUnion()!=toUnion->getUnion()) {
throw std::invalid_argument(
"pvSubArrayCopy unionArray pvTo and pvFrom have different unions");
}
if(type==structureArray) {
copy(dynamic_cast<PVStructureArray &>(from) ,fromOffset,
dynamic_cast<PVStructureArray&>(to),
toOffset,len);
size_t pvFromLength = pvFrom.getLength();
size_t maxcount = (pvFromLength -pvFromOffset + pvFromStride -1)/pvFromStride;
if(count>maxcount) throw std::invalid_argument("pvSubArrayCopy pvFrom length error");
size_t newLength = toOffset + count*toStride;
size_t capacity = pvTo.getCapacity();
if(newLength>capacity) capacity = newLength;
shared_vector<PVUnionPtr> temp(capacity);
PVValueArray<PVUnionPtr>::const_svector vecFrom = pvFrom.view();
PVValueArray<PVUnionPtr>::const_svector vecTo = pvTo.view();
for(size_t i=0; i<pvTo.getLength(); ++i) temp[i] = vecTo[i];
for(size_t i=pvTo.getLength(); i< capacity; ++i)
temp[i] = getPVDataCreate()->createPVUnion(toUnion->getUnion());
for(size_t i=0; i<count; ++i) temp[i*toStride + toOffset] = vecFrom[i*pvFromStride+pvFromOffset];
shared_vector<const PVUnionPtr> temp2(freeze(temp));
pvTo.replace(temp2);
}
void copy(
PVArray & pvFrom,
size_t pvFromOffset,
size_t pvFromStride,
PVArray & pvTo,
size_t pvToOffset,
size_t pvToStride,
size_t count)
{
Type pvFromType = pvFrom.getField()->getType();
Type pvToType = pvTo.getField()->getType();
if(pvFromType!=pvToType) throw std::invalid_argument("pvSubArrayCopy: pvFrom and pvTo different types");
if(pvFromType==scalarArray) {
ScalarType pvFromScalarType= static_cast<ScalarType>(pvFromType);
ScalarType pvToScalarType = static_cast<ScalarType>(pvToType);
if(pvFromScalarType!=pvToScalarType){
throw std::invalid_argument("pvSubArrayCopy: pvFrom and pvTo different types");
}
}
if(pvTo.isImmutable()) throw std::invalid_argument("pvSubArrayCopy: pvTo is immutable");
if(pvFromType==scalarArray) {
copy(dynamic_cast<PVScalarArray &>(pvFrom) ,pvFromOffset,pvFromStride,
dynamic_cast<PVScalarArray&>(pvTo),
pvToOffset,pvToStride,count);
}
if(pvFromType==structureArray) {
copy(dynamic_cast<PVStructureArray &>(pvFrom) ,pvFromOffset,pvFromStride,
dynamic_cast<PVStructureArray&>(pvTo),
pvToOffset,pvToStride,count);
}
if(pvFromType==unionArray) {
copy(dynamic_cast<PVUnionArray &>(pvFrom) ,pvFromOffset,pvFromStride,
dynamic_cast<PVUnionArray&>(pvTo),
pvToOffset,pvToStride,count);
}
}
void copy(
PVArray::shared_pointer const & pvFrom,
size_t pvFromOffset,
size_t pvFromStride,
PVArray::shared_pointer & pvTo,
size_t pvToOffset,
size_t pvToStride,
size_t count)
{
copy(*pvFrom,pvFromOffset,pvFromStride,*pvTo,pvToOffset,pvToStride,count);
}
}}

View File

@@ -309,21 +309,6 @@ namespace epics { namespace pvData {
return !(*this == set);
}
void BitSet::toString(StringBuilder buffer, int /*indentLevel*/) const
{
*buffer += '{';
int32 i = nextSetBit(0);
char tmp[30];
if (i != -1) {
sprintf(tmp,"%d",(int)i); *buffer += tmp;
for (i = nextSetBit(i+1); i >= 0; i = nextSetBit(i+1)) {
int32 endOfRun = nextClearBit(i);
do { *buffer += ", "; sprintf(tmp,"%d",(int)i); *buffer += tmp; } while (++i < endOfRun);
}
}
*buffer += '}';
}
void BitSet::serialize(ByteBuffer* buffer, SerializableControl* flusher) const {
uint32 n = wordsInUse;
@@ -374,5 +359,20 @@ namespace epics { namespace pvData {
words[i] |= (buffer->getByte() & 0xffL) << (8 * j);
}
epicsShareExtern std::ostream& operator<<(std::ostream& o, const BitSet& b)
{
o << '{';
int32 i = b.nextSetBit(0);
if (i != -1) {
o << i;
for (i = b.nextSetBit(i+1); i >= 0; i = b.nextSetBit(i+1)) {
int32 endOfRun = b.nextClearBit(i);
do { o << ", " << i; } while (++i < endOfRun);
}
}
o << '}';
return o;
}
}};

View File

@@ -225,8 +225,6 @@ namespace epics { namespace pvData {
bool operator!=(const BitSet &set) const;
void toString(StringBuilder buffer, int indentLevel = 0) const;
virtual void serialize(ByteBuffer *buffer,
SerializableControl *flusher) const;
virtual void deserialize(ByteBuffer *buffer,
@@ -317,6 +315,8 @@ namespace epics { namespace pvData {
static uint32 bitCount(uint64 i);
};
epicsShareExtern std::ostream& operator<<(std::ostream& o, const BitSet& b);
}}
#endif /* BITSET_H */

View File

@@ -10,10 +10,12 @@
#include <sstream>
#include <cstdio>
#include <cstring>
#include <string>
#define epicsExportSharedSymbols
#include <pv/epicsException.h>
using std::string;
namespace epics{ namespace pvData {
@@ -32,7 +34,7 @@ ExceptionMixin::print(FILE *fp) const
#endif
}
std::string
string
ExceptionMixin::show() const
{
std::ostringstream out;
@@ -62,7 +64,7 @@ BaseException::what() const throw()
try{
if (base_msg.size()==0) {
const char *base=std::logic_error::what();
std::string out, stack;
string out, stack;
const ExceptionMixin *info=dynamic_cast<const ExceptionMixin*>(this);
if(info) {

View File

@@ -26,6 +26,8 @@
#include <pv/lock.h>
#include <pv/event.h>
using std::string;
namespace epics { namespace pvData {
@@ -43,27 +45,27 @@ Event::Event(bool full)
void Event::signal()
{
if(id==0) throw std::logic_error(String("event was deleted"));
if(id==0) throw std::logic_error(string("event was deleted"));
epicsEventSignal(id);
}
bool Event::wait ()
{
if(id==0) throw std::logic_error(String("event was deleted"));
if(id==0) throw std::logic_error(string("event was deleted"));
epicsEventWaitStatus status = epicsEventWait(id);
return status==epicsEventWaitOK ? true : false;
}
bool Event::wait ( double timeOut )
{
if(id==0) throw std::logic_error(String("event was deleted"));
if(id==0) throw std::logic_error(string("event was deleted"));
epicsEventWaitStatus status = epicsEventWaitWithTimeout(id,timeOut);
return status==epicsEventWaitOK ? true : false;
}
bool Event::tryWait ()
{
if(id==0) throw std::logic_error(String("event was deleted"));
if(id==0) throw std::logic_error(string("event was deleted"));
epicsEventWaitStatus status = epicsEventTryWait(id);
return status==epicsEventWaitOK ? true : false;
}

View File

@@ -46,7 +46,7 @@ public:
bool tryWait (); /* false if empty */
private:
epicsEventId id;
String alreadyOn;
std::string alreadyOn;
};
}}

View File

@@ -16,6 +16,8 @@
#define epicsExportSharedSymbols
#include <pv/executor.h>
using std::string;
namespace epics { namespace pvData {
// special instance to stop the executor thread
@@ -31,7 +33,7 @@ static
std::tr1::shared_ptr<Command> shutdown(new ExecutorShutdown());
Executor::Executor(String threadName,ThreadPriority priority)
Executor::Executor(string const & threadName,ThreadPriority priority)
: thread(threadName,priority,this)
{
}
@@ -52,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 {
@@ -80,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

@@ -40,7 +40,7 @@ private:
class epicsShareClass Executor : public Runnable{
public:
POINTER_DEFINITIONS(Executor);
Executor(String threadName,ThreadPriority priority);
Executor(std::string const & threadName,ThreadPriority priority);
~Executor();
void execute(CommandPtr const &node);
virtual void run();

View File

@@ -12,13 +12,15 @@
#define epicsExportSharedSymbols
#include <pv/messageQueue.h>
using std::string;
namespace epics { namespace pvData {
MessageNode::MessageNode()
: messageType(infoMessage)
{}
String MessageNode::getMessage() const
string MessageNode::getMessage() const
{
return message;
}
@@ -59,7 +61,7 @@ void MessageQueue::release() {
releaseUsed(lastGet);
lastGet.reset();
}
bool MessageQueue::put(String message,MessageType messageType,bool replaceLast)
bool MessageQueue::put(string message,MessageType messageType,bool replaceLast)
{
MessageNodePtr node = getFree();
if(node.get()!= NULL) {

View File

@@ -31,10 +31,10 @@ typedef std::tr1::shared_ptr<MessageQueue> MessageQueuePtr;
class epicsShareClass MessageNode {
public:
MessageNode();
String getMessage() const;
std::string getMessage() const;
MessageType getMessageType() const;
private:
String message;
std::string message;
MessageType messageType;
friend class MessageQueue;
};
@@ -49,7 +49,7 @@ public:
// must call release before next get
void release();
// return (false,true) if message (was not, was) put into queue
bool put(String message,MessageType messageType,bool replaceLast);
bool put(std::string message,MessageType messageType,bool replaceLast);
bool isEmpty() ;
bool isFull() ;
int getClearOverrun();

View File

@@ -14,8 +14,10 @@
#define epicsExportSharedSymbols
#include "typeCast.h"
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
@@ -25,7 +27,7 @@
#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 */
@@ -247,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)
{
@@ -295,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)
{
@@ -337,7 +415,7 @@ noconvert:
*endp = (char*)ptr;
return 0;
}
#endif
#endif
/* do we need long long? */
@@ -422,18 +500,18 @@ void handleParseError(int err)
namespace epics { namespace pvData { namespace detail {
void parseToPOD(const std::string & in, boolean *out)
void parseToPOD(const string & in, boolean *out)
{
if(epicsStrCaseCmp(in.c_str(),"true")==0)
*out = 1;
else if(epicsStrCaseCmp(in.c_str(),"false")==0)
*out = 0;
else
throw std::runtime_error("parseToPOD: String no match true/false");
throw std::runtime_error("parseToPOD: string no match true/false");
}
#define INTFN(T, S) \
void parseToPOD(const std::string& in, T *out) { \
void parseToPOD(const string& in, T *out) { \
epics ## S temp; \
int err = epicsParse ## S (in.c_str(), &temp, 0, NULL); \
if(err) handleParseError(err); \
@@ -447,7 +525,7 @@ INTFN(uint16_t, UInt16);
INTFN(int32_t, Int32);
INTFN(uint32_t, UInt32);
void parseToPOD(const std::string& in, int64_t *out) {
void parseToPOD(const string& in, int64_t *out) {
#ifdef NEED_LONGLONG
int err = epicsParseLongLong(in.c_str(), out, 0, NULL);
#else
@@ -456,7 +534,7 @@ void parseToPOD(const std::string& in, int64_t *out) {
if(err) handleParseError(err);
}
void parseToPOD(const std::string& in, uint64_t *out) {
void parseToPOD(const string& in, uint64_t *out) {
#ifdef NEED_LONGLONG
int err = epicsParseULongLong(in.c_str(), out, 0, NULL);
#else
@@ -465,14 +543,34 @@ void parseToPOD(const std::string& in, uint64_t *out) {
if(err) handleParseError(err);
}
void parseToPOD(const std::string& in, float *out) {
void parseToPOD(const string& in, float *out) {
int err = epicsParseFloat(in.c_str(), out, NULL);
if(err) handleParseError(err);
}
void parseToPOD(const std::string& in, double *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

@@ -14,11 +14,13 @@
#include <pv/lock.h>
#include <pv/requester.h>
using std::string;
namespace epics { namespace pvData {
static StringArray messageTypeName(MESSAGE_TYPE_COUNT);
String getMessageTypeName(MessageType messageType)
string getMessageTypeName(MessageType messageType)
{
// TODO not thread-safe
static Mutex mutex;

View File

@@ -26,14 +26,14 @@ enum MessageType {
};
#define MESSAGE_TYPE_COUNT 4
epicsShareExtern String getMessageTypeName(MessageType messageType);
epicsShareExtern std::string getMessageTypeName(MessageType messageType);
class epicsShareClass Requester {
public:
POINTER_DEFINITIONS(Requester);
virtual ~Requester(){}
virtual String getRequesterName() = 0;
virtual void message(String const & message,MessageType messageType) = 0;
virtual std::string getRequesterName() = 0;
virtual void message(std::string const & message,MessageType messageType) = 0;
};
}}

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

@@ -57,7 +57,7 @@ namespace epics {
return (std::size_t)(b<0 ? b+256 : b);
}
void SerializeHelper::serializeString(const String& value,
void SerializeHelper::serializeString(const string& value,
ByteBuffer* buffer, SerializableControl* flusher) {
std::size_t len = value.length();
SerializeHelper::writeSize(len, buffer, flusher);
@@ -74,7 +74,7 @@ namespace epics {
}
}
void SerializeHelper::serializeSubstring(const String& value,
void SerializeHelper::serializeSubstring(const string& value,
std::size_t offset, std::size_t count, ByteBuffer* buffer,
SerializableControl* flusher) {
/*if(offset<0)
@@ -97,9 +97,9 @@ namespace epics {
}
}
static String emptyString;
static string emptyStringtring;
String SerializeHelper::deserializeString(ByteBuffer* buffer,
string SerializeHelper::deserializeString(ByteBuffer* buffer,
DeserializableControl* control) {
std::size_t size = SerializeHelper::readSize(buffer, control);
@@ -109,13 +109,13 @@ namespace epics {
{
// entire string is in buffer, simply create a string out of it (copy)
std::size_t pos = buffer->getPosition();
String str(buffer->getArray()+pos, size);
string str(buffer->getArray()+pos, size);
buffer->setPosition(pos+size);
return str;
}
else
{
String str;
string str;
str.reserve(size);
try {
std::size_t i = 0;
@@ -137,7 +137,7 @@ namespace epics {
}
}
else
return emptyString;
return emptyStringtring;
}
}

View File

@@ -46,30 +46,30 @@ namespace epics {
DeserializableControl* control);
/**
* String serialization helper method.
* std::string serialization helper method.
*
* @param[in] value String to serialize
* @param[in] value std::string to serialize
* @param[in] buffer serialization buffer
* @param[in] flusher flusher
*/
static void serializeString(const String& value, ByteBuffer* buffer,
static void serializeString(const std::string& value, ByteBuffer* buffer,
SerializableControl* flusher);
/**
* String serialization helper method.
* std::string serialization helper method.
*
* @param[in] value String to serialize
* @param[in] value std::string to serialize
* @param[in] offset start of the substring in {@code value}
* @param[in] count the number of characters to write
* @param[in] buffer serialization buffer
* @param[in] flusher flusher
*/
static void serializeSubstring(const String& value, std::size_t offset,
static void serializeSubstring(const std::string& value, std::size_t offset,
std::size_t count, ByteBuffer* buffer,
SerializableControl* flusher);
/**
* String deserialization helper method.
* std::string deserialization helper method.
* TODO This method cannot return "null", but Java implementation
* could have serialized "null" value as well. We need to decide
* how to deserialize "null".
@@ -82,7 +82,7 @@ namespace epics {
* could have serialized "null" value as well. We need to decide
* how to deserialize "null".
*/
static String deserializeString(ByteBuffer* buffer,
static std::string deserializeString(ByteBuffer* buffer,
DeserializableControl* control);
private:

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

@@ -12,10 +12,12 @@
#include <pv/serializeHelper.h>
#include <pv/status.h>
using std::string;
namespace epics { namespace pvData {
const char* Status::StatusTypeName[] = { "OK", "WARNING", "ERROR", "FATAL" };
epics::pvData::String Status::m_emptyString;
string Status::m_emptyStringtring;
Status Status::Ok;
@@ -26,7 +28,7 @@ Status::Status() :
{
}
Status::Status(StatusType type, String const & message) :
Status::Status(StatusType type, string const & message) :
m_statusType(type), m_message(message)
{
if (type == STATUSTYPE_OK)
@@ -35,7 +37,7 @@ Status::Status(StatusType type, String const & message) :
//PVDATA_REFCOUNT_MONITOR_CONSTRUCT(status);
}
Status::Status(StatusType type, String const & message, String const & stackDump) :
Status::Status(StatusType type, string const & message, string const & stackDump) :
m_statusType(type), m_message(message), m_stackDump(stackDump)
{
if (type == STATUSTYPE_OK)
@@ -54,12 +56,12 @@ Status::StatusType Status::getType() const
}
epics::pvData::String Status::getMessage() const
string Status::getMessage() const
{
return m_message;
}
epics::pvData::String Status::getStackDump() const
string Status::getStackDump() const
{
return m_stackDump;
}
@@ -100,7 +102,7 @@ void Status::deserialize(ByteBuffer *buffer, DeserializableControl *flusher)
if (m_statusType != STATUSTYPE_OK)
{
m_statusType = STATUSTYPE_OK;
m_message = m_stackDump = m_emptyString;
m_message = m_stackDump = m_emptyStringtring;
}
}
else
@@ -111,29 +113,26 @@ void Status::deserialize(ByteBuffer *buffer, DeserializableControl *flusher)
}
}
String Status::toString() const
void Status::dump(std::ostream& o) const
{
String str;
toString(&str, 0);
return str;
o << "Status [type=" << Status::StatusTypeName[m_statusType];
if (!m_message.empty())
o << ", message=" << m_message;
if (!m_stackDump.empty())
o << ", stackDump=" << std::endl << m_stackDump;
o << ']';
}
std::ostream& operator<<(std::ostream& o, const Status& status)
{
status.dump(o);
return o;
}
void Status::toString(StringBuilder buffer, int /*indentLevel*/) const
std::ostream& operator<<(std::ostream& o, const Status::StatusType& statusType)
{
*buffer += "Status [type=";
*buffer += StatusTypeName[m_statusType];
if (!m_message.empty())
{
*buffer += ", message=";
*buffer += m_message;
}
if (!m_stackDump.empty())
{
*buffer += ", stackDump=";
*buffer += '\n';
*buffer += m_stackDump;
}
*buffer += ']';
o << Status::StatusTypeName[statusType];
return o;
}
}}

View File

@@ -10,6 +10,8 @@
#ifndef STATUS_H
#define STATUS_H
#include <ostream>
#include <pv/serialize.h>
#include <pv/byteBuffer.h>
#include <pv/sharedPtr.h>
@@ -51,12 +53,12 @@ namespace epics { namespace pvData {
/**
* Create non-OK status.
*/
Status(StatusType type, epics::pvData::String const & message);
Status(StatusType type, std::string const & message);
/**
* Create non-OK status.
*/
Status(StatusType type, epics::pvData::String const & message, epics::pvData::String const & stackDump);
Status(StatusType type, std::string const & message, std::string const & stackDump);
~Status();
@@ -70,13 +72,13 @@ namespace epics { namespace pvData {
* Get error message describing an error. Required if error status.
* @return error message.
*/
epics::pvData::String getMessage() const;
std::string getMessage() const;
/**
* Get stack dump where error (exception) happened. Optional.
* @return stack dump.
*/
epics::pvData::String getStackDump() const;
std::string getStackDump() const;
/**
* Convenient OK test. Same as <code>(getType() == StatusType.OK)</code>.
@@ -93,20 +95,23 @@ namespace epics { namespace pvData {
*/
bool isSuccess() const;
String toString() const;
void toString(StringBuilder buffer, int indentLevel = 0) const;
void serialize(ByteBuffer *buffer, SerializableControl *flusher) const;
void deserialize(ByteBuffer *buffer, DeserializableControl *flusher);
void dump(std::ostream& o) const;
private:
static epics::pvData::String m_emptyString;
static std::string m_emptyStringtring;
StatusType m_statusType;
String m_message;
String m_stackDump;
std::string m_message;
std::string m_stackDump;
};
epicsShareExtern std::ostream& operator<<(std::ostream& o, const Status& status);
epicsShareExtern std::ostream& operator<<(std::ostream& o, const Status::StatusType& statusType);
}}
#endif /* STATUS_H */

View File

@@ -50,7 +50,7 @@ typedef epicsThreadRunable Runnable;
class epicsShareClass Thread : public epicsThread, private NoDefaultMethods {
public:
Thread(String name,
Thread(std::string name,
ThreadPriority priority,
Runnable *runnable,
epicsThreadStackSizeClass stkcls=epicsThreadStackSmall)
@@ -63,7 +63,7 @@ public:
}
Thread(Runnable &runnable,
String name,
std::string name,
unsigned int stksize,
unsigned int priority=lowestPriority)
:epicsThread(runnable,

View File

@@ -13,11 +13,14 @@
#endif
#include <stdexcept>
#include <string>
#define epicsExportSharedSymbols
#include <pv/convert.h>
#include <pv/timer.h>
using std::string;
namespace epics { namespace pvData {
TimerCallback::TimerCallback()
@@ -26,7 +29,7 @@ TimerCallback::TimerCallback()
{
}
Timer::Timer(String threadName,ThreadPriority priority)
Timer::Timer(string threadName,ThreadPriority priority)
: waitForWork(false),
waitForDone(false),
alive(true),
@@ -84,7 +87,7 @@ void Timer::cancel(TimerCallbackPtr const &timerCallback)
prevNode = nextNode;
nextNode = nextNode->next;
}
throw std::logic_error(String(""));
throw std::logic_error(string(""));
}
bool Timer::isScheduled(TimerCallbackPtr const &timerCallback)
@@ -169,7 +172,7 @@ void Timer::schedulePeriodic(
double period)
{
if(isScheduled(timerCallback)) {
throw std::logic_error(String("already queued"));
throw std::logic_error(string("already queued"));
}
{
Lock xx(mutex);
@@ -193,7 +196,7 @@ void Timer::schedulePeriodic(
if(isFirst) waitForWork.signal();
}
void Timer::toString(StringBuilder builder)
void Timer::dump(std::ostream& o)
{
Lock xx(mutex);
if(!alive) return;
@@ -205,11 +208,15 @@ void Timer::toString(StringBuilder builder)
TimeStamp timeToRun = nodeToCall->timeToRun;
double period = nodeToCall->period;
double diff = TimeStamp::diff(timeToRun,currentTime);
char buffer[50];
sprintf(buffer,"timeToRun %f period %f\n",diff,period);
*builder += buffer;
o << "timeToRun " << diff << " period " << period << std::endl;
nodeToCall = nodeToCall->next;
}
}
std::ostream& operator<<(std::ostream& o, Timer& timer)
{
timer.dump(o);
return o;
}
}}

View File

@@ -50,7 +50,7 @@ private:
class epicsShareClass Timer : public Runnable {
public:
POINTER_DEFINITIONS(Timer);
Timer(String threadName, ThreadPriority priority);
Timer(std::string threadName, ThreadPriority priority);
virtual ~Timer();
virtual void run();
void scheduleAfterDelay(
@@ -62,7 +62,9 @@ public:
double period);
void cancel(TimerCallbackPtr const &timerCallback);
bool isScheduled(TimerCallbackPtr const &timerCallback);
void toString(StringBuilder builder);
void dump(std::ostream& o);
private:
void addElement(TimerCallbackPtr const &timerCallback);
TimerCallbackPtr head;
@@ -73,5 +75,7 @@ private:
Thread thread;
};
epicsShareExtern std::ostream& operator<<(std::ostream& o, Timer& timer);
}}
#endif /* TIMER_H */

View File

@@ -11,9 +11,9 @@
#include "typeCast.h"
using epics::pvData::castUnsafe;
using epics::pvData::String;
using epics::pvData::ScalarType;
using epics::pvData::pvString;
using std::string;
namespace {
@@ -77,7 +77,7 @@ static convertfn converters[pvString+1][pvString+1] =
&noconvert,
&noconvert,
&noconvert,
&castVTyped<epics::pvData::boolean, String>,
&castVTyped<epics::pvData::boolean, string>,
},
// to pvByte
{&noconvert,
@@ -91,7 +91,7 @@ static convertfn converters[pvString+1][pvString+1] =
&castVTyped<int8_t, uint64_t>,
&castVTyped<int8_t, float>,
&castVTyped<int8_t, double>,
&castVTyped<int8_t, String>,
&castVTyped<int8_t, string>,
},
// to pvShort
{&noconvert,
@@ -105,7 +105,7 @@ static convertfn converters[pvString+1][pvString+1] =
&castVTyped<int16_t, uint64_t>,
&castVTyped<int16_t, float>,
&castVTyped<int16_t, double>,
&castVTyped<int16_t, String>,
&castVTyped<int16_t, string>,
},
// to pvInt
{&noconvert,
@@ -119,7 +119,7 @@ static convertfn converters[pvString+1][pvString+1] =
&castVTyped<int32_t, uint64_t>,
&castVTyped<int32_t, float>,
&castVTyped<int32_t, double>,
&castVTyped<int32_t, String>,
&castVTyped<int32_t, string>,
},
// to pvLong
{&noconvert,
@@ -133,7 +133,7 @@ static convertfn converters[pvString+1][pvString+1] =
&castVTyped<int64_t, uint64_t>,
&castVTyped<int64_t, float>,
&castVTyped<int64_t, double>,
&castVTyped<int64_t, String>,
&castVTyped<int64_t, string>,
},
// to pvUByte
{&noconvert,
@@ -147,7 +147,7 @@ static convertfn converters[pvString+1][pvString+1] =
&castVTyped<uint8_t, uint64_t>,
&castVTyped<uint8_t, float>,
&castVTyped<uint8_t, double>,
&castVTyped<uint8_t, String>,
&castVTyped<uint8_t, string>,
},
// to pvUShort
{&noconvert,
@@ -161,7 +161,7 @@ static convertfn converters[pvString+1][pvString+1] =
&castVTyped<uint16_t, uint64_t>,
&castVTyped<uint16_t, float>,
&castVTyped<uint16_t, double>,
&castVTyped<uint16_t, String>,
&castVTyped<uint16_t, string>,
},
// to pvUInt
{&noconvert,
@@ -175,7 +175,7 @@ static convertfn converters[pvString+1][pvString+1] =
&castVTyped<uint32_t, uint64_t>,
&castVTyped<uint32_t, float>,
&castVTyped<uint32_t, double>,
&castVTyped<uint32_t, String>,
&castVTyped<uint32_t, string>,
},
// to pvULong
{&noconvert,
@@ -189,7 +189,7 @@ static convertfn converters[pvString+1][pvString+1] =
&copyV<uint64_t>,
&castVTyped<uint64_t, float>,
&castVTyped<uint64_t, double>,
&castVTyped<uint64_t, String>,
&castVTyped<uint64_t, string>,
},
// to pvFloat
{&noconvert,
@@ -203,7 +203,7 @@ static convertfn converters[pvString+1][pvString+1] =
&castVTyped<float, uint64_t>,
&copyV<float>,
&castVTyped<float, double>,
&castVTyped<float, String>,
&castVTyped<float, string>,
},
// to pvDouble
{&noconvert,
@@ -217,21 +217,21 @@ static convertfn converters[pvString+1][pvString+1] =
&castVTyped<double, uint64_t>,
&castVTyped<double, float>,
&copyV<double>,
&castVTyped<double, String>,
&castVTyped<double, string>,
},
// to pvString
{&castVTyped<String, epics::pvData::boolean>,
&castVTyped<String, int8_t>,
&castVTyped<String, int16_t>,
&castVTyped<String, int32_t>,
&castVTyped<String, uint64_t>,
&castVTyped<String, uint8_t>,
&castVTyped<String, uint16_t>,
&castVTyped<String, uint32_t>,
&castVTyped<String, uint64_t>,
&castVTyped<String, float>,
&castVTyped<String, double>,
&copyV<String>,
{&castVTyped<string, epics::pvData::boolean>,
&castVTyped<string, int8_t>,
&castVTyped<string, int16_t>,
&castVTyped<string, int32_t>,
&castVTyped<string, uint64_t>,
&castVTyped<string, uint8_t>,
&castVTyped<string, uint16_t>,
&castVTyped<string, uint32_t>,
&castVTyped<string, uint64_t>,
&castVTyped<string, float>,
&castVTyped<string, double>,
&copyV<string>,
},
};

View File

@@ -30,8 +30,6 @@
namespace epics { namespace pvData {
typedef std::string String;
namespace detail {
// parseToPOD wraps the epicsParse*() functions in one name
// and throws exceptions
@@ -48,12 +46,12 @@ namespace detail {
epicsShareExtern void parseToPOD(const std::string&, double *out);
/* want to pass POD types by value,
* and String by const reference
* and std::string by const reference
*/
template<typename ARG>
struct cast_arg { typedef ARG arg; };
template<>
struct cast_arg<String> { typedef const String& arg; };
struct cast_arg<std::string> { typedef const std::string& arg; };
// Handle mangling of type/value when printing
template<typename T>
@@ -98,10 +96,10 @@ namespace detail {
};
// print POD to string
// when String!=FROM
// when std::string!=FROM
template<typename FROM>
struct cast_helper<String, FROM, typename meta::not_same_type<String,FROM>::type> {
static String op(FROM from) {
struct cast_helper<std::string, FROM, typename meta::not_same_type<std::string,FROM>::type> {
static std::string op(FROM from) {
std::ostringstream strm;
strm << print_convolute<FROM>::op(from);
if(strm.fail())
@@ -111,10 +109,10 @@ namespace detail {
};
// parse POD from string
// TO!=String
// TO!=std::string
template<typename TO>
struct cast_helper<TO, String, typename meta::not_same_type<TO,String>::type> {
static FORCE_INLINE TO op(const String& from) {
struct cast_helper<TO, std::string, typename meta::not_same_type<TO,std::string>::type> {
static FORCE_INLINE TO op(const std::string& from) {
TO ret;
parseToPOD(from, &ret);
return ret;
@@ -127,7 +125,7 @@ namespace detail {
*
* Supported types: uint8_t, int8_t, uint16_t, int16_t,
* uint32_t, int32_t, uint64_t, int64_t,
* float, double, String
* float, double, std::string
*
* As defined in pvType.h
*
@@ -153,9 +151,9 @@ namespace detail {
* Conversions where invalid or out of range inputs result
* in an exception.
*
* - non-String -> String
* - String -> non-String
* - String -> String (throws only std::bad_alloc)
* - non-std::string -> std::string
* - std::string -> non-std::string
* - std::string -> std::string (throws only std::bad_alloc)
*
* Conversions where out of range inputs produce undefined
* results.
@@ -169,7 +167,7 @@ namespace detail {
* too large to be represented by the integer type
* is not defined.
*
@section stringf String formats
@section stringf std::string formats
*
* - Numbers beginning with 1-9 are parsed as base-10.
* - Numbers beginning with '0x' are parsed as base-16

View File

@@ -3,6 +3,7 @@
SRC_DIRS += $(PVDATA_SRC)/monitor
INC += monitor.h
INC += monitorPlugin.h
LIBSRCS += monitor.cpp
LIBSRCS += monitorPlugin.cpp

View File

@@ -15,6 +15,7 @@
#include <pv/pvData.h>
#include <pv/sharedPtr.h>
#include <pv/bitSet.h>
#include <pv/requester.h>
#include <shareLib.h>

View File

@@ -0,0 +1,86 @@
/* monitorPlugin.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvData is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
/**
* @author mrk
*/
#define epicsExportSharedSymbols
#include <pv/monitorPlugin.h>
using std::string;
using std::cout;
using std::endl;
namespace epics { namespace pvData {
MonitorPluginManagerPtr MonitorPluginManager::get()
{
static MonitorPluginManagerPtr pluginManager;
static Mutex mutex;
Lock xx(mutex);
if(!pluginManager) {
pluginManager = MonitorPluginManagerPtr(new MonitorPluginManager());
}
return pluginManager;
}
bool MonitorPluginManager::addPlugin(
string const &pluginName,
MonitorPluginCreatorPtr const &creator)
{
mutex.lock();
std::list<MonitorPluginCreatorPtr>::iterator iter;
for (iter = monitorPluginList.begin();iter!=monitorPluginList.end();iter++)
{
if(*iter==creator)
{
mutex.unlock();
return false;
}
if(((*iter)->getName().compare(pluginName))==0)
{
mutex.unlock();
return false;
}
}
monitorPluginList.push_back(creator);
mutex.unlock();
return true;
}
MonitorPluginCreatorPtr MonitorPluginManager::findPlugin(
string const &pluginName)
{
mutex.lock();
std::list<MonitorPluginCreatorPtr>::iterator iter;
for (iter = monitorPluginList.begin();iter!=monitorPluginList.end();++iter)
{
if(((*iter)->getName().compare(pluginName))==0)
{
mutex.unlock();
return *iter;
}
}
mutex.unlock();
return MonitorPluginCreatorPtr();
}
void MonitorPluginManager::showNames()
{
mutex.lock();
std::list<MonitorPluginCreatorPtr>::iterator iter;
for (iter = monitorPluginList.begin();iter!=monitorPluginList.end();++iter)
{
std::cout << (*iter)->getName() << std::endl;
}
mutex.unlock();
}
}}

177
src/monitor/monitorPlugin.h Normal file
View File

@@ -0,0 +1,177 @@
/* monitorPlugin.h */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvData is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
/**
* @author mrk
*/
#ifndef MONITORPLUGIN_H
#define MONITORPLUGIN_H
#include <list>
#include <pv/pvData.h>
#include <pv/sharedPtr.h>
#include <pv/bitSet.h>
#include <pv/monitor.h>
#include <shareLib.h>
namespace epics { namespace pvData {
/**
* typedef for a pointer to a MonitorPlugin
*/
class MonitorPlugin;
typedef std::tr1::shared_ptr<MonitorPlugin> MonitorPluginPtr;
/**
* typedef for a pointer to a MonitorPluginCreator
*/
class MonitorPluginCreator;
typedef std::tr1::shared_ptr<MonitorPluginCreator> MonitorPluginCreatorPtr;
/**
* typedef for a pointer to a MonitorPluginManager
*/
class MonitorPluginManager;
typedef std::tr1::shared_ptr<MonitorPluginManager> MonitorPluginManagerPtr;
/** A plugin for raising monitors;
* This is for use by pvAccess servers that support monitors.
* Since the interface has only a dependence on pvData it
* can be used for other purposes.
* A monitor is assumed to be associated with a field of a top level
* structure.
*/
class epicsShareClass MonitorPlugin
{
public:
virtual ~MonitorPlugin(){}
/**
* getName
* @returns The name of the plugin
*/
virtual std::string const & getName() = 0;
/**
* Should a monitor be raised?
* @param pvField The field being monitored.
* @param pvTop The top level sructure in which the field resides.
* @param monitorElement The client data and bitSets.
* @returns true or false.
* True is returned if the change to this field should cause a monitor.
* False is returned in a change only to this field should not cause a
* monitor.
*/
virtual bool causeMonitor(
PVFieldPtr const &pvField,
PVStructurePtr const &pvTop,
MonitorElementPtr const &monitorElement) = 0;
/**
* A monitor will be sent to the client.
* @param pvField The copy of the field being monitored.
* The plugin can modify the data.
* @param pvTop The top level sructure in which the field resides.
* @param monitorElement The data for the client.
* The plugin is allowed to change the data values.
*/
virtual void monitorDone(
MonitorElementPtr const &monitorElement)
{}
/**
* Begin monitoring
*/
virtual void startMonitoring(){}
/**
* Stop monitoring
*/
virtual void stopMonitoring(){}
/**
* Begin a set of puts.
*/
virtual void beginGroupPut() {};
/**
* End a set of puts.
*/
virtual void endGroupPut() {};
};
/** A class that creates a plugin.
* Normlly a plugin is created for a single client.
*/
class epicsShareClass MonitorPluginCreator
{
public:
virtual ~MonitorPluginCreator() {}
/**
* Create a monitor plugin.
* @param field The introspection interface for the field monitored.
* @param top The introspsction interface for the client structure.
* @param pvFieldOptions The options the client requested.
* The structure has a set of PVString subfields.
* The options are a set of name,value pairs.
* The subfield name is the name and the subfield value is the value.
* @returns shared pointer to a MonitorPluginCreator.
*/
virtual MonitorPluginPtr create(
FieldConstPtr const &field,
StructureConstPtr const &top,
PVStructurePtr const &pvFieldOptions) = 0;
/**
* getName
* @returns The name of the plugin
*/
virtual std::string const & getName() = 0;
};
/**
* This manages a set of monitor plugins.
* @author mrk
*/
class epicsShareClass MonitorPluginManager
{
public:
POINTER_DEFINITIONS(MonitorPluginManager);
/**
* Factory to get the manager.
* @return shared pointer to manager.
*/
static MonitorPluginManagerPtr get();
/** destructor
*/
~MonitorPluginManager(){}
/* add plugin
* @param pluginName The name of the plugin.
* @param creator The creator.
* @returns true or false
* false is returned if a plugin with that name is already present
*/
bool addPlugin(
std::string const &pluginName,
MonitorPluginCreatorPtr const &creator);
/* find plugin
*
* @param plugin name
* @returns share pointer to plugin creator.
* If a plugin with that name is not found NULL is returned.
*/
MonitorPluginCreatorPtr findPlugin(std::string const &pluginName);
/* showNames
*
*/
void showNames();
private:
MonitorPluginManager(){}
std::list<MonitorPluginCreatorPtr> monitorPluginList;
epics::pvData::Mutex mutex;
};
}}
#endif /* MONITORPLUGIN_H */

View File

@@ -17,12 +17,14 @@
#include <pv/pvData.h>
#include <pv/alarm.h>
using std::string;
namespace epics { namespace pvData {
AlarmSeverity AlarmSeverityFunc::getSeverity(int value)
{
if(value<0 || value>4) {
throw std::logic_error(String("getSeverity value is illegal"));
throw std::logic_error(string("getSeverity value is illegal"));
}
switch (value) {
case 0: return noAlarm;
@@ -31,7 +33,7 @@ AlarmSeverity AlarmSeverityFunc::getSeverity(int value)
case 3: return invalidAlarm;
case 4: return undefinedAlarm;
}
throw std::logic_error(String("should never get here"));
throw std::logic_error(string("should never get here"));
}
StringArrayPtr AlarmSeverityFunc::getSeverityNames()
@@ -61,13 +63,13 @@ AlarmSeverity Alarm::getSeverity() const
case 3: return invalidAlarm;
case 4: return undefinedAlarm;
}
throw std::logic_error(String("should never get here"));
throw std::logic_error(string("should never get here"));
}
AlarmStatus AlarmStatusFunc::getStatus(int value)
{
if(value<0 || value>7) {
throw std::logic_error(String("getStatus value is illegal"));
throw std::logic_error(string("getStatus value is illegal"));
}
switch (value) {
case 0: return noStatus;
@@ -79,7 +81,7 @@ AlarmStatus AlarmStatusFunc::getStatus(int value)
case 6: return undefinedStatus;
case 7: return clientStatus;
}
throw std::logic_error(String("should never get here"));
throw std::logic_error(string("should never get here"));
}
StringArrayPtr AlarmStatusFunc::getStatusNames()
@@ -115,7 +117,7 @@ AlarmStatus Alarm::getStatus() const
case 6: return undefinedStatus;
case 7: return clientStatus;
}
throw std::logic_error(String("should never get here"));
throw std::logic_error(string("should never get here"));
}
}}

View File

@@ -42,10 +42,10 @@ public:
class epicsShareClass Alarm {
public:
Alarm() : severity(0),status(0), message(String("")) {}
Alarm() : severity(0),status(0), message(std::string("")) {}
//default constructors and destructor are OK
String getMessage() const {return message;}
void setMessage(String const &value) {message = value;}
std::string getMessage() const {return message;}
void setMessage(std::string const &value) {message = value;}
AlarmSeverity getSeverity() const;
void setSeverity(AlarmSeverity value) {severity = value;}
AlarmStatus getStatus() const;
@@ -53,7 +53,7 @@ public:
private:
int32 severity;
int32 status;
String message;
std::string message;
};
}}

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

@@ -22,23 +22,23 @@ namespace epics { namespace pvData {
class epicsShareClass Display {
public:
Display()
: description(String("")),format(String("")),units(String("")),
: description(std::string("")),format(std::string("")),units(std::string("")),
low(0.0),high(0.0) {}
//default constructors and destructor are OK
double getLow() const {return low;}
double getHigh() const{ return high;}
void setLow(double value){low = value;}
void setHigh(double value){high = value;}
String getDescription() const {return description;}
void setDescription(String const & value) {description = value;}
String getFormat() const {return format;}
void setFormat(String const & value) {format = value;}
String getUnits() const {return units;}
void setUnits(String const & value) {units = value;}
std::string getDescription() const {return description;}
void setDescription(std::string const & value) {description = value;}
std::string getFormat() const {return format;}
void setFormat(std::string const & value) {format = value;}
std::string getUnits() const {return units;}
void setUnits(std::string const & value) {units = value;}
private:
String description;
String format;
String units;
std::string description;
std::string format;
std::string units;
double low;
double high;
};

View File

@@ -16,34 +16,27 @@
#include <pv/pvData.h>
#include <pv/pvAlarm.h>
using std::tr1::static_pointer_cast;
using std::string;
namespace epics { namespace pvData {
using std::tr1::static_pointer_cast;
String PVAlarm::noAlarmFound("No alarm structure found");
String PVAlarm::notAttached("Not attached to an alarm structure");
string PVAlarm::noAlarmFound("No alarm structure found");
string PVAlarm::notAttached("Not attached to an alarm structure");
bool PVAlarm::attach(PVFieldPtr const & pvField)
{
if(pvField->getField()->getType()!=structure) {
pvField->message(noAlarmFound,errorMessage);
return false;
}
if(pvField->getField()->getType()!=structure) return false;
PVStructurePtr pvStructure = static_pointer_cast<PVStructure>(pvField);
pvSeverity = pvStructure->getIntField("severity");
if(pvSeverity.get()==NULL) {
pvField->message(noAlarmFound,errorMessage);
return false;
}
if(pvSeverity.get()==NULL) return false;
pvStatus = pvStructure->getIntField("status");
if(pvStatus.get()==NULL) {
pvField->message(noAlarmFound,errorMessage);
pvSeverity.reset();
return false;
}
pvMessage = pvStructure->getStringField("message");
if(pvMessage.get()==NULL) {
pvField->message(noAlarmFound,errorMessage);
pvSeverity.reset();
pvStatus.reset();
return false;

View File

@@ -37,8 +37,8 @@ private:
PVIntPtr pvSeverity;
PVIntPtr pvStatus;
PVStringPtr pvMessage;
static String noAlarmFound;
static String notAttached;
static std::string noAlarmFound;
static std::string notAttached;
};
}}

View File

@@ -19,26 +19,26 @@
namespace epics { namespace pvData {
using std::tr1::static_pointer_cast;
using std::string;
String PVControl::noControlFound("No control structure found");
String PVControl::notAttached("Not attached to an control structure");
string PVControl::noControlFound("No control structure found");
string PVControl::notAttached("Not attached to an control structure");
bool PVControl::attach(PVFieldPtr const & pvField)
{
if(pvField->getField()->getType()!=structure) {
pvField->message(noControlFound,errorMessage);
return false;
}
if(pvField->getField()->getType()!=structure) return false;
PVStructurePtr pvStructure = static_pointer_cast<PVStructure>(pvField);
pvLow = pvStructure->getDoubleField("limitLow");
if(pvLow.get()==NULL) {
pvField->message(noControlFound,errorMessage);
return false;
}
pvHigh = pvStructure->getDoubleField(String("limitHigh"));
if(pvLow.get()==NULL) return false;
pvHigh = pvStructure->getDoubleField("limitHigh");
if(pvHigh.get()==NULL) {
pvLow.reset();
pvField->message(noControlFound,errorMessage);
return false;
}
pvMinStep = pvStructure->getDoubleField("minStep");
if(pvMinStep.get()==NULL) {
pvLow.reset();
pvHigh.reset();
return false;
}
return true;
@@ -62,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)
@@ -69,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,8 +33,9 @@ public:
private:
PVDoublePtr pvLow;
PVDoublePtr pvHigh;
static String noControlFound;
static String notAttached;
PVDoublePtr pvMinStep;
static std::string noControlFound;
static std::string notAttached;
};
}}

View File

@@ -16,46 +16,37 @@
#include <pv/pvData.h>
#include <pv/pvDisplay.h>
using std::tr1::static_pointer_cast;
using std::string;
namespace epics { namespace pvData {
using std::tr1::static_pointer_cast;
String PVDisplay::noDisplayFound("No display structure found");
String PVDisplay::notAttached("Not attached to an display structure");
string PVDisplay::noDisplayFound("No display structure found");
string PVDisplay::notAttached("Not attached to an display structure");
bool PVDisplay::attach(PVFieldPtr const & pvField)
{
if(pvField->getField()->getType()!=structure) {
pvField->message(noDisplayFound,errorMessage);
return false;
}
if(pvField->getField()->getType()!=structure) return false;
PVStructurePtr pvStructure = static_pointer_cast<PVStructure>(pvField);
pvDescription = pvStructure->getStringField("description");
if(pvDescription.get()==NULL) {
pvField->message(noDisplayFound,errorMessage);
return false;
}
if(pvDescription.get()==NULL) return false;
pvFormat = pvStructure->getStringField("format");
if(pvFormat.get()==NULL) {
pvField->message(noDisplayFound,errorMessage);
detach();
return false;
}
pvUnits = pvStructure->getStringField("units");
if(pvUnits.get()==NULL) {
pvField->message(noDisplayFound,errorMessage);
detach();
return false;
}
pvLow = pvStructure->getDoubleField(String("limitLow"));
pvLow = pvStructure->getDoubleField(string("limitLow"));
if(pvLow.get()==NULL) {
pvField->message(noDisplayFound,errorMessage);
detach();
return false;
}
pvHigh = pvStructure->getDoubleField(String("limitHigh"));
pvHigh = pvStructure->getDoubleField(string("limitHigh"));
if(pvHigh.get()==NULL) {
pvField->message(noDisplayFound,errorMessage);
detach();
return false;
}

View File

@@ -33,8 +33,8 @@ public:
void get(Display &) const;
bool set(Display const & display);
private:
static String noDisplayFound;
static String notAttached;
static std::string noDisplayFound;
static std::string notAttached;
PVStringPtr pvDescription;
PVStringPtr pvFormat;
PVStringPtr pvUnits;

View File

@@ -16,30 +16,24 @@
#include <pv/pvData.h>
#include <pv/pvEnumerated.h>
using std::tr1::static_pointer_cast;
using std::string;
namespace epics { namespace pvData {
using std::tr1::static_pointer_cast;
String PVEnumerated::notFound("No enumerated structure found");
String PVEnumerated::notAttached("Not attached to an enumerated structure");
string PVEnumerated::notFound("No enumerated structure found");
string PVEnumerated::notAttached("Not attached to an enumerated structure");
bool PVEnumerated::attach(PVFieldPtr const & pvField)
{
if(pvField->getField()->getType()!=structure) {
pvField->message(notFound,errorMessage);
return false;
}
if(pvField->getField()->getType()!=structure) return false;
PVStructurePtr pvStructure = static_pointer_cast<PVStructure>(pvField);
pvIndex = pvStructure->getIntField("index");
if(pvIndex.get()==NULL) {
pvField->message(notFound,errorMessage);
return false;
}
if(pvIndex.get()==NULL) return false;
PVScalarArrayPtr pvScalarArray = pvStructure->getScalarArrayField(
"choices",pvString);
if(pvScalarArray.get()==NULL) {
pvIndex.reset();
pvField->message(notFound,errorMessage);
return false;
}
pvChoices = static_pointer_cast<PVStringArray>(pvScalarArray);
@@ -75,7 +69,7 @@ int32 PVEnumerated::getIndex()
return pvIndex->get();
}
String PVEnumerated::getChoice()
string PVEnumerated::getChoice()
{
if(pvIndex.get()==NULL ) {
throw std::logic_error(notAttached);

View File

@@ -33,14 +33,14 @@ public:
// a set returns false if field is immutable
bool setIndex(int32 index);
int32 getIndex();
String getChoice();
std::string getChoice();
bool choicesMutable();
inline PVStringArray::const_svector getChoices(){return pvChoices->view();}
int32 getNumberChoices();
bool setChoices(const StringArray & choices);
private:
static String notFound;
static String notAttached;
static std::string notFound;
static std::string notAttached;
PVIntPtr pvIndex;
PVStringArrayPtr pvChoices;
};

View File

@@ -16,26 +16,24 @@
#include <pv/pvData.h>
#include <pv/pvTimeStamp.h>
using std::tr1::static_pointer_cast;
using std::string;
namespace epics { namespace pvData {
using std::tr1::static_pointer_cast;
String PVTimeStamp::noTimeStamp("No timeStamp structure found");
String PVTimeStamp::notAttached("Not attached to a timeStamp structure");
string PVTimeStamp::noTimeStamp("No timeStamp structure found");
string PVTimeStamp::notAttached("Not attached to a timeStamp structure");
bool PVTimeStamp::attach(PVFieldPtr const & pvField)
{
if(pvField->getField()->getType()!=structure) {
pvField->message(noTimeStamp,errorMessage);
return false;
}
if(pvField->getField()->getType()!=structure) return false;
PVStructurePtr xxx = static_pointer_cast<PVStructure>(pvField);
PVStructure* pvStructure = xxx.get();
while(true) {
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
@@ -78,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

@@ -36,8 +36,8 @@ public:
void get(TimeStamp &) const;
bool set(TimeStamp const & timeStamp);
private:
static String noTimeStamp;
static String notAttached;
static std::string noTimeStamp;
static std::string notAttached;
PVLongPtr pvSecs;
PVIntPtr pvUserTag;
PVIntPtr pvNano;

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,12 +66,10 @@ 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 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 String to a scalar.
* fromStringArray converts an array of Strings
* <p>fromString converts a std::string to a scalar.
* fromStringArray converts an array of std::strings
* to a pvArray, which must have a scaler element type.
* A scalar field is a numeric field or pvBoolean or pvString.</p>
* <p>All from methods put data into a PVField, e.g. from means where the PVField gets it's data.</p>
@@ -85,7 +86,7 @@ public:
* @param builder The builder that will have the result.
* @param pvField The pvField.
*/
void getFullName(StringBuilder buf,PVFieldPtr const & pvField)
void getFullName(std::string *buf,PVFieldPtr const & pvField)
{
*buf = pvField->getFullName();
}
@@ -121,7 +122,7 @@ public:
* If a PVField is a structure or array be prepared for a very long string.
* @param indentLevel indentation level
*/
inline void getString(StringBuilder buf,PVFieldPtr const & pvField,int indentLevel)
inline void getString(std::string *buf,PVFieldPtr const & pvField,int indentLevel)
{getString(buf, pvField.get(), indentLevel);}
/**
* Convert a PVField to a string.
@@ -129,7 +130,7 @@ public:
* @param pv The PVField to convert to a string.
* If the PVField is a structure or array be prepared for a very long string.
*/
inline void getString(StringBuilder buf,PVFieldPtr const & pvField)
inline void getString(std::string * buf,PVFieldPtr const & pvField)
{getString(buf, pvField.get(), 0);}
/**
* Convert a PVField to a string.
@@ -138,49 +139,49 @@ public:
* If a PVField is a structure or array be prepared for a very long string.
* @param indentLevel indentation level
*/
void getString(StringBuilder buf,PVField const * pvField,int indentLevel);
void getString(std::string * buf,PVField const * pvField,int indentLevel);
/**
* Convert a PVField to a string.
* param buf buffer for the result
* @param pv The PVField to convert to a string.
* If the PVField is a structure or array be prepared for a very long string.
*/
inline void getString(StringBuilder buf,PVField const * pvField)
inline void getString(std::string * buf,PVField const * pvField)
{getString(buf, pvField, 0);}
/**
* Convert from an array of String to a PVScalar
* Convert from an array of std::string to a PVScalar
* @param pv The PV.
* @param from The array of String value to convert and put into a PV.
* @param from The array of std::string value to convert and put into a PV.
* @param fromStartIndex The first element if the array of strings.
* @throws std::logic_error if the array of String does not have a valid values.
* @throws std::logic_error if the array of std::string does not have a valid values.
*/
std::size_t fromString(
PVStructurePtr const &pv,
StringArray const & from,
std::size_t fromStartIndex = 0);
/**
* Convert from a String to a PVScalar
* Convert from a std::string to a PVScalar
* @param pv The PV.
* @param from The String value to convert and put into a PV.
* @throws std::logic_error if the String does not have a valid value.
* @param from The std::string value to convert and put into a PV.
* @throws std::logic_error if the std::string does not have a valid value.
*/
void fromString(PVScalarPtr const & pv, String const & from)
void fromString(PVScalarPtr const & pv, std::string const & from)
{
pv->putFrom<String>(from);
pv->putFrom<std::string>(from);
}
/**
* Convert from a String to a PVScalarArray.
* The String must be a comma separated set of values optionally enclosed in []
* Convert from a std::string to a PVScalarArray.
* The std::string must be a comma separated set of values optionally enclosed in []
* @param pv The PV.
* @param from The String value to convert and put into a PV.
* @param from The std::string value to convert and put into a PV.
* @return The number of elements converted.
* @throws std::invalid_argument if the element Type is not a scalar.
* @throws std::logic_error if the String does not have a valid array values.
* @throws std::logic_error if the std::string does not have a valid array values.
*/
std::size_t fromString(PVScalarArrayPtr const & pv, String from);
std::size_t fromString(PVScalarArrayPtr const & pv, std::string from);
/**
* Convert a PVScalarArray from a String array.
* Convert a PVScalarArray from a std::string array.
* The array element type must be a scalar.
* @param pv The PV.
* @param offset Starting element in a PV.
@@ -189,7 +190,7 @@ public:
* @param fromOffset Starting element in the source array.
* @return The number of elements converted.
* @throws std::invalid_argument if the element Type is not a scalar.
* @throws std::logic_error if the String does not have a valid value.
* @throws std::logic_error if the std::string does not have a valid value.
*/
std::size_t fromStringArray(
PVScalarArrayPtr const & pv,
@@ -197,11 +198,11 @@ public:
StringArray const & from,
std::size_t fromOffset);
/**
* Convert a PVScalarArray to a String array.
* Convert a PVScalarArray to a std::string array.
* @param pv The PV.
* @param offset Starting element in the PV array.
* @param length Number of elements to convert to the string array.
* @param to String array to receive the converted PV data.
* @param to std::string array to receive the converted PV data.
* @param toOffset Starting element in the string array.
* @return Number of elements converted.
*/
@@ -401,11 +402,11 @@ public:
*/
inline double toDouble(PVScalarPtr const & pv) { return pv->getAs<double>();}
/**
* Convert a PV to a String
* Convert a PV to a std::string
* @param pv a PV
* @return converted value
*/
inline String toString(PVScalarPtr const & pv) { return pv->getAs<String>();}
inline std::string toString(PVScalarPtr const & pv) { return pv->getAs<std::string>();}
/**
* Convert a PV from a byte
* @param pv a PV
@@ -478,12 +479,12 @@ 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 StringBuilder being constructed.
* @param builder The std::string * being constructed.
* @param indentLevel Indent level, Each level is four spaces.
*/
void newLine(StringBuilder buf, int indentLevel);
void newLine(std::string * buf, int indentLevel);
};
static inline ConvertPtr getConvert() { return Convert::getConvert(); }

View File

@@ -2,6 +2,7 @@
#define PRINTER_H
#include <ostream>
#include <shareLib.h>
#include "pvData.h"

File diff suppressed because it is too large Load Diff

View File

@@ -12,6 +12,7 @@
#include <string>
#include <stdexcept>
#include <iostream>
#include <pv/noDefaultMethods.h>
#include <pv/pvType.h>
@@ -22,14 +23,74 @@
namespace epics { namespace pvData {
namespace format {
struct indent_level
{
long level;
indent_level(long l) : level(l) {}
};
epicsShareExtern long& indent_value(std::ios_base& ios);
epicsShareExtern std::ostream& operator<<(std::ostream& os, indent_level const& indent);
struct indent_scope
{
long saved_level;
std::ios_base& stream;
indent_scope(std::ios_base& ios) :
stream(ios)
{
long& l = indent_value(ios);
saved_level = l;
l = saved_level + 1;
}
~indent_scope()
{
indent_value(stream) = saved_level;
}
};
struct indent
{
};
epicsShareExtern std::ostream& operator<<(std::ostream& os, indent const&);
struct array_at
{
std::size_t index;
array_at(std::size_t ix) : index(ix) {}
};
struct array_at_internal
{
std::size_t index;
std::ostream& stream;
array_at_internal(std::size_t ix, std::ostream& str) : index(ix), stream(str) {}
};
epicsShareExtern array_at_internal operator<<(std::ostream& str, array_at const& manip);
};
class Field;
class Scalar;
class Array;
class ScalarArray;
class Structure;
class StructureArray;
class Union;
class UnionArray;
class BoundedString;
/**
* typedef for a shared pointer to an immutable Field.
*/
@@ -42,6 +103,10 @@ typedef std::vector<FieldConstPtr> FieldConstPtrArray;
* typedef for a shared pointer to an immutable Scalar.
*/
typedef std::tr1::shared_ptr<const Scalar> ScalarConstPtr;
/**
* typedef for a shared pointer to an immutable Array.
*/
typedef std::tr1::shared_ptr<const Array> ArrayConstPtr;
/**
* typedef for a shared pointer to an immutable ScalarArray.
*/
@@ -62,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.
@@ -103,14 +172,11 @@ namespace TypeFunc {
* @return The name for the type.
*/
epicsShareExtern const char* name(Type type);
/**
* Convert the type to a string and add it to builder.
* @param builder The string builder.
* @param type The type.
*/
epicsShareExtern void toString(StringBuilder builder,const Type type);
};
epicsShareExtern std::ostream& operator<<(std::ostream& o, const Type& type);
/**
* Definition of support scalar types.
*/
@@ -201,24 +267,21 @@ namespace ScalarTypeFunc {
* @return The scalarType.
* An exception is thrown if the name is not the name of a scalar type.
*/
epicsShareExtern ScalarType getScalarType(String const &value);
epicsShareExtern ScalarType getScalarType(std::string const &value);
/**
* Get a name for the scalarType.
* @param scalarType The type.
* @return The name for the scalarType.
*/
epicsShareExtern const char* name(ScalarType scalarType);
/**
* Convert the scalarType to a string and add it to builder.
* @param builder The string builder.
* @param scalarType The type.
*/
epicsShareExtern void toString(StringBuilder builder,ScalarType scalarType);
//! gives sizeof(T) where T depends on the scalar type id.
epicsShareExtern size_t elementSize(ScalarType id);
};
epicsShareExtern std::ostream& operator<<(std::ostream& o, const ScalarType& scalarType);
/**
* This class implements introspection object for field.
*/
@@ -240,18 +303,15 @@ public:
* Get the identification string.
* @return The identification string, can be empty.
*/
virtual String getID() const = 0;
virtual std::string getID() const = 0;
/**
* Convert the scalarType to a string and add it to builder.
* @param builder The string builder.
* Puts the string representation to the stream.
* @param o output stream.
* @return The output stream.
*/
virtual void toString(StringBuilder builder) const{toString(builder,0);}
/**
* Convert the scalarType to a string and add it to builder.
* @param builder The string builder.
* @param indentLevel The number of blanks at the beginning of new lines.
*/
virtual void toString(StringBuilder builder,int indentLevel) const;
virtual std::ostream& dump(std::ostream& o) const = 0;
protected:
/**
* Constructor
@@ -271,6 +331,8 @@ private:
struct Deleter{void operator()(Field *p){delete p;}};
};
epicsShareExtern std::ostream& operator<<(std::ostream& o, const Field& field);
/**
* This class implements introspection object for Scalar.
@@ -289,19 +351,10 @@ public:
* @return the scalarType
*/
ScalarType getScalarType() const {return scalarType;}
/**
* Convert the scalar to a string and add it to builder.
* @param builder The string builder.
*/
virtual void toString(StringBuilder buf) const{toString(buf,0);}
/**
* Convert the scalar to a string and add it to builder.
* @param builder The string builder.
* @param indentLevel The number of blanks at the beginning of new lines.
*/
virtual void toString(StringBuilder buf,int indentLevel) const;
virtual std::string getID() const;
virtual String getID() const;
virtual std::ostream& dump(std::ostream& o) const;
virtual void serialize(ByteBuffer *buffer, SerializableControl *control) const;
virtual void deserialize(ByteBuffer *buffer, DeserializableControl *control);
@@ -309,15 +362,87 @@ 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;
};
/**
* This class implements introspection object for field.
* This class implements introspection object for Array.
*/
class epicsShareClass ScalarArray : public Field{
class epicsShareClass Array : public Field{
public:
POINTER_DEFINITIONS(Array);
/**
* Destructor.
*/
virtual ~Array();
typedef Array& reference;
typedef const Array& const_reference;
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
* @param fieldName The field type.
*/
Array(Type type);
};
/**
* This class implements introspection object for scalar array.
*/
class epicsShareClass ScalarArray : public Array{
public:
POINTER_DEFINITIONS(ScalarArray);
typedef ScalarArray& reference;
@@ -332,20 +457,15 @@ public:
* Get the scalarType for the elements.
* @return the scalarType
*/
ScalarType getElementType() const {return elementType;}
/**
* Convert the scalarType to a string and add it to builder.
* @param builder The string builder.
*/
virtual void toString(StringBuilder buf) const{toString(buf,0);}
/**
* Convert the scalarType to a string and add it to builder.
* @param builder The string builder.
* @param indentLevel The number of blanks at the beginning of new lines.
*/
virtual void toString(StringBuilder buf,int indentLevel) const;
ScalarType getElementType() const {return elementType;}
virtual String getID() const;
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;
virtual void serialize(ByteBuffer *buffer, SerializableControl *control) const;
virtual void deserialize(ByteBuffer *buffer, DeserializableControl *control);
@@ -356,16 +476,89 @@ protected:
*/
virtual ~ScalarArray();
private:
int8 getTypeCodeLUT() const;
const String getIDScalarArrayLUT() 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
*/
class epicsShareClass StructureArray : public Field{
class epicsShareClass StructureArray : public Array{
public:
POINTER_DEFINITIONS(StructureArray);
typedef StructureArray& reference;
@@ -375,16 +568,15 @@ public:
* Get the introspection interface for the array elements.
* @return The introspection interface.
*/
StructureConstPtr getStructure() const {return pstructure;}
StructureConstPtr getStructure() const {return pstructure;}
/**
* Convert the scalarType to a string and add it to builder.
* @param builder The string builder.
* @param indentLevel The number of blanks at the beginning of new lines.
*/
virtual void toString(StringBuilder buf,int indentLevel=0) const;
virtual String getID() const;
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;
virtual void serialize(ByteBuffer *buffer, SerializableControl *control) const;
virtual void deserialize(ByteBuffer *buffer, DeserializableControl *control);
@@ -407,7 +599,7 @@ private:
/**
* This class implements introspection object for a unionArray
*/
class epicsShareClass UnionArray : public Field{
class epicsShareClass UnionArray : public Array{
public:
POINTER_DEFINITIONS(UnionArray);
typedef UnionArray& reference;
@@ -417,16 +609,15 @@ public:
* Get the introspection interface for the array elements.
* @return The introspection interface.
*/
UnionConstPtr getUnion() const {return punion;}
UnionConstPtr getUnion() const {return punion;}
/**
* Convert the scalarType to a string and add it to builder.
* @param builder The string builder.
* @param indentLevel The number of blanks at the beginning of new lines.
*/
virtual void toString(StringBuilder buf,int indentLevel=0) const;
virtual String getID() const;
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;
virtual void serialize(ByteBuffer *buffer, SerializableControl *control) const;
virtual void deserialize(ByteBuffer *buffer, DeserializableControl *control);
@@ -456,7 +647,7 @@ public:
/**
* Default structure ID.
*/
static epics::pvData::String DEFAULT_ID;
static std::string DEFAULT_ID;
/**
* Destructor.
@@ -476,7 +667,7 @@ public:
* @return The introspection interface.
* This will hold a null pointer if the field is not in the structure.
*/
FieldConstPtr getField(String const &fieldName) const;
FieldConstPtr getField(std::string const &fieldName) const;
/**
* Get the field for the specified fieldName.
* @param fieldName The index of the field to get;
@@ -489,7 +680,7 @@ public:
* @return The introspection interface.
* This will be -1 if the field is not in the structure.
*/
std::size_t getFieldIndex(String const &fieldName) const;
std::size_t getFieldIndex(std::string const &fieldName) const;
/**
* Get the fields in the structure.
* @return The array of fields.
@@ -500,40 +691,31 @@ public:
* @return The array of fieldNames.
*/
StringArray const & getFieldNames() const {return fieldNames;}
void renameField(std::size_t fieldIndex,String const & newName)
{fieldNames[fieldIndex] = newName;}
/**
* Get the name of the field with the specified index;
* @param fieldIndex The index of the desired field.
* @return The fieldName.
*/
String getFieldName(std::size_t fieldIndex) const {return fieldNames[fieldIndex];}
/**
* Convert the structure to a string and add it to builder.
* @param builder The string builder.
*/
virtual void toString(StringBuilder buf) const{toString(buf,0);}
/**
* Convert the structure to a string and add it to builder.
* @param builder The string builder.
* @param indentLevel The number of blanks at the beginning of new lines.
*/
virtual void toString(StringBuilder buf,int indentLevel) const;
virtual String getID() const;
std::string getFieldName(std::size_t fieldIndex) const {return fieldNames[fieldIndex];}
virtual std::string getID() const;
virtual std::ostream& dump(std::ostream& o) const;
virtual void serialize(ByteBuffer *buffer, SerializableControl *control) const;
virtual void deserialize(ByteBuffer *buffer, DeserializableControl *control);
protected:
Structure(StringArray const & fieldNames, FieldConstPtrArray const & fields, String const & id = DEFAULT_ID);
Structure(StringArray const & fieldNames, FieldConstPtrArray const & fields, std::string const & id = DEFAULT_ID);
private:
void toStringCommon(StringBuilder buf,int indentLevel) const;
StringArray fieldNames;
FieldConstPtrArray fields;
String id;
friend class FieldCreate;
friend class Union;
std::string id;
virtual void dumpFields(std::ostream& o) const;
friend class FieldCreate;
friend class Union;
};
/**
@@ -546,12 +728,12 @@ public:
/**
* Default union ID.
*/
static epics::pvData::String DEFAULT_ID;
static std::string DEFAULT_ID;
/**
* Default variant union ID.
*/
static epics::pvData::String ANY_ID;
static std::string ANY_ID;
/**
* Destructor.
@@ -571,7 +753,7 @@ public:
* @return The introspection interface.
* This will hold a null pointer if the field is not in the union.
*/
FieldConstPtr getField(String const &fieldName) const;
FieldConstPtr getField(std::string const &fieldName) const;
/**
* Get the field for the specified fieldName.
* @param fieldName The index of the field to get;
@@ -584,7 +766,7 @@ public:
* @return The introspection interface.
* This will be -1 if the field is not in the union.
*/
std::size_t getFieldIndex(String const &fieldName) const;
std::size_t getFieldIndex(std::string const &fieldName) const;
/**
* Get the fields in the union.
* @return The array of fields.
@@ -595,51 +777,39 @@ public:
* @return The array of fieldNames.
*/
StringArray const & getFieldNames() const {return fieldNames;}
void renameField(std::size_t fieldIndex,String const & newName)
{fieldNames[fieldIndex] = newName;}
/**
* Get the name of the field with the specified index;
* @param fieldIndex The index of the desired field.
* @return The fieldName.
*/
String getFieldName(std::size_t fieldIndex) const {return fieldNames[fieldIndex];}
std::string getFieldName(std::size_t fieldIndex) const {return fieldNames[fieldIndex];}
/**
* Check if this union is variant union (aka any type).
* @return <code>true</code> if this union is variant union, otherwise <code>false</code>.
*/
bool isVariant() const {return (fieldNames.size() == 0);}
/**
* Convert the union to a string and add it to builder.
* @param builder The string builder.
*/
virtual void toString(StringBuilder buf) const{toString(buf,0);}
/**
* Convert the union to a string and add it to builder.
* @param builder The string builder.
* @param indentLevel The number of blanks at the beginning of new lines.
*/
virtual void toString(StringBuilder buf,int indentLevel) const;
virtual String getID() const;
virtual std::string getID() const;
virtual std::ostream& dump(std::ostream& o) const;
virtual void serialize(ByteBuffer *buffer, SerializableControl *control) const;
virtual void deserialize(ByteBuffer *buffer, DeserializableControl *control);
protected:
Union();
Union(StringArray const & fieldNames, FieldConstPtrArray const & fields, String const & id = DEFAULT_ID);
Union(StringArray const & fieldNames, FieldConstPtrArray const & fields, std::string const & id = DEFAULT_ID);
private:
void toStringCommon(StringBuilder buf,int indentLevel) const;
StringArray fieldNames;
FieldConstPtrArray fields;
String id;
StringArray fieldNames;
FieldConstPtrArray fields;
std::string id;
virtual void dumpFields(std::ostream& o) const;
friend class FieldCreate;
friend class Structure;
};
/**
* This is a singlton class for creating introspection interfaces.
*/
class FieldCreate;
typedef std::tr1::shared_ptr<FieldCreate> FieldCreatePtr;
@@ -671,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.
@@ -680,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.
@@ -751,8 +947,8 @@ public:
/**
* Complete the creation of a nested object.
* @see #addNestedStructure(String)
* @see #addNestedUnion(String)
* @see #addNestedStructure(std::string)
* @see #addNestedUnion(std::string)
* @return a previous (parent) {@code FieldBuilder}.
*/
FieldBuilderPtr endNested();
@@ -784,6 +980,9 @@ private:
};
/**
* This is a singleton class for creating introspection interfaces.
*/
class epicsShareClass FieldCreate {
public:
static FieldCreatePtr getFieldCreate();
@@ -800,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
@@ -812,6 +1032,11 @@ public:
* @return An {@code Array} Interface for the newly created object.
*/
StructureArrayConstPtr createStructureArray(StructureConstPtr const & structure) const;
/**
* Create a {@code Structure} field.
* @return a {@code Structure} interface for the newly created object.
*/
StructureConstPtr createStructure () const;
/**
* Create a {@code Structure} field.
* @param fieldNames The array of {@code fieldNames} for the structure.
@@ -829,7 +1054,7 @@ public:
* @return a {@code Structure} interface for the newly created object.
*/
StructureConstPtr createStructure (
String const & id,
std::string const & id,
StringArray const & fieldNames,
FieldConstPtrArray const & fields) const;
/**
@@ -866,7 +1091,7 @@ public:
* @return a {@code Union} interface for the newly created object.
*/
UnionConstPtr createUnion (
String const & id,
std::string const & id,
StringArray const & fieldNames,
FieldConstPtrArray const & fields) const;
/**
@@ -878,7 +1103,7 @@ public:
*/
StructureConstPtr appendField(
StructureConstPtr const & structure,
String const & fieldName, FieldConstPtr const & field) const;
std::string const & fieldName, FieldConstPtr const & field) const;
/**
* Append fields to a structure.
* @param structure The structure to which the fields appended.
@@ -924,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.
@@ -951,8 +1176,27 @@ OP(pvUInt, uint32)
OP(pvULong, uint64)
OP(pvFloat, float)
OP(pvDouble, double)
OP(pvString, String)
OP(pvString, std::string)
#undef OP
struct ScalarHashFunction {
size_t operator() (const Scalar& scalar) const { return scalar.getScalarType(); }
};
struct ScalarArrayHashFunction {
size_t operator() (const ScalarArray& scalarArray) const { return 0x10 | scalarArray.getElementType(); }
};
struct StructureHashFunction {
size_t operator() (const Structure& /*structure*/) const { return 0; }
// TODO hash
// final int PRIME = 31;
// return PRIME * Arrays.hashCode(fieldNames) + Arrays.hashCode(fields);
};
struct StructureArrayHashFunction {
size_t operator() (const StructureArray& structureArray) const { StructureHashFunction shf; return (0x10 | shf(*(structureArray.getStructure()))); }
};
}}
#endif /* PVINTROSPECT_H */

View File

@@ -17,68 +17,104 @@
namespace epics { namespace pvData {
/** @brief Copy a subarray from one PVValueArray to another.
* @warning The two PVValueArrays must both the same type
* @param from The source
* @param fromOffset The offset in the source
* @param to The destination
* @param toOffset The offset in the destination
* @param len The total number of elements to copy
/** @brief Copy a subarray from one scalar array to another.
* @warning The two scalar arrays must both be PVValueArrays of the same type.
* @param pvFrom The source array.
* @param fromOffset The offset in the source.
* @param fromStride The interval between elements in pvFrom.
* @param pvTo The destination array.
* @param toOffset The offset in the destination.
* @param toStride The interval between elements in pvTo.
* @param count The total number of elements to copy from pvFrom to pvTo.
*/
template<typename T>
void copy(
epicsShareExtern void copy(
PVValueArray<T> & pvFrom,
size_t fromOffset,
size_t fromStride,
PVValueArray<T> & pvTo,
size_t toOffset,
size_t len);
size_t toStride,
size_t count);
/** @brief Copy a subarray from one scalar array to another.
* @warning The two scalar arrays must both be PVValueArrays of the same type
* @param from The source
* @param fromOffset The offset in the source
* @param to The destination
* @param toOffset The offset in the destination
* @param len The total number of elements to copy
* @warning The two scalar arrays must both be PVValueArrays of the same type.
* @param pvFrom The source array.
* @param fromOffset The offset in the source.
* @param fromStride The interval between elements in pvFrom.
* @param pvTo The destination array.
* @param toOffset The offset in the destination.
* @param toStride The interval between elements in pvTo.
* @param count The total number of elements to copy from pvFrom to pvTo.
*/
epicsShareExtern void copy(
PVScalarArray & from,
PVScalarArray & pvFrom,
size_t fromOffset,
PVScalarArray & to,
size_t fromStride,
PVScalarArray & pvTo,
size_t toOffset,
size_t len);
size_t toStride,
size_t count);
/** @brief Copy a subarray from one structure array to another.
* @warning The two structure arrays must have the same
* structure introspection interface.
* @param from The source
* @param fromOffset The offset in the source
* @param to The destination
* @param toOffset The offset in the destination
* @param len The total number of elements to copy
* @param pvFrom The source array.
* @param fromOffset The offset in the source.
* @param fromStride The interval between elements in pvFrom.
* @param pvTo The destination array.
* @param toOffset The offset in the destination.
* @param toStride The interval between elements in pvTo.
* @param count The total number of elements to copy from pvFrom to pvTo.
*/
epicsShareExtern void copy(
PVStructureArray & from,
PVStructureArray & pvFrom,
size_t fromOffset,
PVStructureArray & to,
size_t fromStride,
PVStructureArray & pvToo,
size_t toOffset,
size_t len);
size_t toStride,
size_t count);
/** @brief Copy a subarray from one array to another.
* @warning The two arrays must have the same
* introspection interface.
* @param from The source
* @param fromOffset The offset in the source
* @param to The destination
* @param toOffset The offset in the destination
* @param len The total number of elements to copy
* @param pvFrom The source array.
* @param fromOffset The offset in the source.
* @param fromStride The interval between elements in pvFrom.
* @param pvTo The destination array.
* @param toOffset The offset in the destination.
* @param toStride The interval between elements in pvTo.
* @param count The total number of elements to copy from pvFrom to pvTo.
*/
epicsShareExtern void copy(
PVArray & from,
PVArray & pvFrom,
size_t fromOffset,
PVArray & to,
size_t fromStride,
PVArray & pvToo,
size_t toOffset,
size_t len);
size_t toStride,
size_t count);
/** @brief Copy a subarray from one array to another.
* @warning The two arrays must have the same
* introspection interface.
* @param pvFrom The source array.
* @param fromOffset The offset in the source.
* @param fromStride The interval between elements in pvFrom.
* @param pvTo The destination array.
* @param toOffset The offset in the destination.
* @param toStride The interval between elements in pvTo.
* @param count The total number of elements to copy from pvFrom to pvTo.
*/
epicsShareExtern void copy(
PVArray::shared_pointer const & pvFrom,
size_t fromOffset,
size_t fromStride,
PVArray::shared_pointer & pvToo,
size_t toOffset,
size_t toStride,
size_t count);
}}

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>
@@ -93,358 +93,24 @@ typedef uint64_t uint64;
// float and double are types
/**
* A string
*/
typedef std::string String;
/**
* A boolean array.
*/
typedef std::vector<uint8> BooleanArray;
typedef std::tr1::shared_ptr<BooleanArray> BooleanArrayPtr;
/* get is same is ubyte*/
typedef std::vector<uint8>::iterator BooleanArray_iterator;
typedef std::vector<uint8>::const_iterator BooleanArray_const_iterator;
/**
* A byte array.
*/
typedef std::vector<int8> ByteArray;
typedef std::tr1::shared_ptr<ByteArray> ByteArrayPtr;
inline int8 * get(ByteArray &value)
{
return &value[0];
}
inline int8 const * get(ByteArray const &value)
{
return static_cast<int8 const *>(&value[0]);
}
inline int8 * get(ByteArrayPtr &value)
{
return get(*value.get());
}
inline int8 const * get(ByteArrayPtr const &value)
{
return get(*value.get());
}
inline ByteArray & getVector(ByteArrayPtr &value)
{
return *value.get();
}
inline ByteArray const & getVector(ByteArrayPtr const &value)
{
return *value.get();
}
typedef std::vector<int8>::iterator ByteArray_iterator;
typedef std::vector<int8>::const_iterator ByteArray_const_iterator;
/**
* A short array.
*/
typedef std::vector<int16> ShortArray;
typedef std::tr1::shared_ptr<ShortArray> ShortArrayPtr;
inline int16 * get(ShortArray &value)
{
return &value[0];
}
inline int16 const * get(ShortArray const &value)
{
return static_cast<int16 const *>(&value[0]);
}
inline int16 * get(ShortArrayPtr &value)
{
return get(*value.get());
}
inline int16 const * get(ShortArrayPtr const &value)
{
return get(*value.get());
}
inline ShortArray & getVector(ShortArrayPtr &value)
{
return *value.get();
}
inline ShortArray const & getVector(ShortArrayPtr const &value)
{
return *value.get();
}
typedef std::vector<int16>::iterator ShortArray_iterator;
typedef std::vector<int16>::const_iterator ShortArray_const_iterator;
/**
* A int array.
*/
typedef std::vector<int32> IntArray;
typedef std::tr1::shared_ptr<IntArray> IntArrayPtr;
inline int32 * get(IntArray &value)
{
return &value[0];
}
inline int32 const * get(IntArray const &value)
{
return static_cast<int32 const *>(&value[0]);
}
inline int32 * get(IntArrayPtr &value)
{
return get(*value.get());
}
inline int32 const * get(IntArrayPtr const &value)
{
return get(*value.get());
}
inline IntArray & getVector(IntArrayPtr &value)
{
return *value.get();
}
inline IntArray const & getVector(IntArrayPtr const &value)
{
return *value.get();
}
typedef std::vector<int32>::iterator IntArray_iterator;
typedef std::vector<int32>::const_iterator IntArray_const_iterator;
/**
* A long array.
*/
typedef std::vector<int64> LongArray;
typedef std::tr1::shared_ptr<LongArray> LongArrayPtr;
inline int64 * get(LongArray &value)
{
return &value[0];
}
inline int64 const * get(LongArray const &value)
{
return static_cast<int64 const *>(&value[0]);
}
inline int64 * get(LongArrayPtr &value)
{
return get(*value.get());
}
inline int64 const * get(LongArrayPtr const &value)
{
return get(*value.get());
}
inline LongArray & getVector(LongArrayPtr &value)
{
return *value.get();
}
inline LongArray const & getVector(LongArrayPtr const &value)
{
return *value.get();
}
typedef std::vector<int64>::iterator LongArray_iterator;
typedef std::vector<int64>::const_iterator LongArray_const_iterator;
/**
* An unsigned byte array.
*/
typedef std::vector<uint8> UByteArray;
typedef std::tr1::shared_ptr<UByteArray> UByteArrayPtr;
inline uint8 * get(UByteArray &value)
{
return &value[0];
}
inline uint8 const * get(UByteArray const &value)
{
return static_cast<uint8 const *>(&value[0]);
}
inline uint8 * get(UByteArrayPtr &value)
{
return get(*value.get());
}
inline uint8 const * get(UByteArrayPtr const &value)
{
return get(*value.get());
}
inline UByteArray & getVector(UByteArrayPtr &value)
{
return *value.get();
}
inline UByteArray const & getVector(UByteArrayPtr const &value)
{
return *value.get();
}
typedef std::vector<uint8>::iterator UByteArray_iterator;
typedef std::vector<uint8>::const_iterator UByteArray_const_iterator;
/**
* An unsigned short array.
*/
typedef std::vector<uint16> UShortArray;
typedef std::tr1::shared_ptr<UShortArray> UShortArrayPtr;
inline uint16 * get(UShortArray &value)
{
return &value[0];
}
inline uint16 const * get(UShortArray const &value)
{
return static_cast<uint16 const *>(&value[0]);
}
inline uint16 * get(UShortArrayPtr &value)
{
return get(*value.get());
}
inline uint16 const * get(UShortArrayPtr const &value)
{
return get(*value.get());
}
inline UShortArray & getVector(UShortArrayPtr &value)
{
return *value.get();
}
inline UShortArray const & getVector(UShortArrayPtr const &value)
{
return *value.get();
}
typedef std::vector<uint16>::iterator UShortArray_iterator;
typedef std::vector<uint16>::const_iterator UShortArray_const_iterator;
/**
* An unsigned int array.
*/
typedef std::vector<uint32> UIntArray;
typedef std::tr1::shared_ptr<UIntArray> UIntArrayPtr;
inline uint32 * get(UIntArray &value)
{
return &value[0];
}
inline uint32 const * get(UIntArray const &value)
{
return static_cast<uint32 const *>(&value[0]);
}
inline uint32 * get(UIntArrayPtr &value)
{
return get(*value.get());
}
inline uint32 const * get(UIntArrayPtr const &value)
{
return get(*value.get());
}
inline UIntArray & getVector(UIntArrayPtr &value)
{
return *value.get();
}
inline UIntArray const & getVector(UIntArrayPtr const &value)
{
return *value.get();
}
typedef std::vector<uint32>::iterator UIntArray_iterator;
typedef std::vector<uint32>::const_iterator UIntArray_const_iterator;
/**
* An unsigned long array.
*/
typedef std::vector<uint64> ULongArray;
typedef std::tr1::shared_ptr<ULongArray> ULongArrayPtr;
inline uint64 * get(ULongArray &value)
{
return &value[0];
}
inline uint64 const * get(ULongArray const &value)
{
return static_cast<uint64 const *>(&value[0]);
}
inline uint64 * get(ULongArrayPtr &value)
{
return get(*value.get());
}
inline uint64 const * get(ULongArrayPtr const &value)
{
return get(*value.get());
}
inline ULongArray & getVector(ULongArrayPtr &value)
{
return *value.get();
}
inline ULongArray const & getVector(ULongArrayPtr const &value)
{
return *value.get();
}
typedef std::vector<uint64>::iterator ULongArray_iterator;
typedef std::vector<uint64>::const_iterator ULongArray_const_iterator;
/**
* A float array.
*/
typedef std::vector<float> FloatArray;
typedef std::tr1::shared_ptr<FloatArray> FloatArrayPtr;
inline float * get(FloatArray &value)
{
return &value[0];
}
inline float const * get(FloatArray const &value)
{
return static_cast<float const *>(&value[0]);
}
inline float * get(FloatArrayPtr &value)
{
return get(*value.get());
}
inline float const * get(FloatArrayPtr const &value)
{
return get(*value.get());
}
inline FloatArray & getVector(FloatArrayPtr &value)
{
return *value.get();
}
inline FloatArray const & getVector(FloatArrayPtr const &value)
{
return *value.get();
}
typedef std::vector<float>::iterator FloatArray_iterator;
typedef std::vector<float>::const_iterator FloatArray_const_iterator;
/**
* A double array.
*/
typedef std::vector<double> DoubleArray;
typedef std::tr1::shared_ptr<DoubleArray> DoubleArrayPtr;
inline double * get(DoubleArray &value)
{
return &value[0];
}
inline double const * get(DoubleArray const &value)
{
return static_cast<double const *>(&value[0]);
}
inline double * get(DoubleArrayPtr &value)
{
return get(*value.get());
}
inline double const * get(DoubleArrayPtr const &value)
{
return get(*value.get());
}
inline DoubleArray & getVector(DoubleArrayPtr &value)
{
return *value.get();
}
inline DoubleArray const & getVector(DoubleArrayPtr const &value)
{
return *value.get();
}
typedef std::vector<double>::iterator DoubleArray_iterator;
typedef std::vector<double>::const_iterator DoubleArray_const_iterator;
/**
* A string array.
*/
typedef std::vector<String> StringArray;
typedef std::vector<std::string> StringArray;
typedef std::tr1::shared_ptr<StringArray> StringArrayPtr;
inline String * get(StringArray &value)
inline std::string * get(StringArray &value)
{
return &value[0];
}
inline String const * get(StringArray const &value)
inline std::string const * get(StringArray const &value)
{
return static_cast<String const *>(&value[0]);
return static_cast<std::string const *>(&value[0]);
}
inline String * get(StringArrayPtr &value)
inline std::string * get(StringArrayPtr &value)
{
return get(*value.get());
}
inline String const * get(StringArrayPtr const &value)
inline std::string const * get(StringArrayPtr const &value)
{
return get(*value.get());
}
@@ -456,13 +122,8 @@ inline StringArray const & getVector(StringArrayPtr const &value)
{
return *value.get();
}
typedef std::vector<String>::iterator StringArray_iterator;
typedef std::vector<String>::const_iterator StringArray_const_iterator;
/**
* A convenience definition for toString methods
*/
typedef String * StringBuilder;
typedef std::vector<std::string>::iterator StringArray_iterator;
typedef std::vector<std::string>::const_iterator StringArray_const_iterator;
}}
#endif /* PVTYPE_H */

View File

@@ -20,6 +20,10 @@
namespace epics { namespace pvData {
class StandardField;
typedef std::tr1::shared_ptr<StandardField> StandardFieldPtr;
/**
* Standard Fields is a class or creating or sharing Field objects for standard fields.
* For each type of standard object two methods are defined:s
@@ -34,9 +38,9 @@ namespace epics { namespace pvData {
* For example the call:
* {@code
StructureConstPtr example = standardField->scalar(
String("value"),
std::string("value"),
pvDouble,
String("value,alarm,timeStamp"));
std::string("value,alarm,timeStamp"));
* }
* Will result in a Field definition that has the form: {@code
structure example
@@ -47,7 +51,7 @@ namespace epics { namespace pvData {
string message
structure timeStamp
long secondsPastEpoch
int nanoSeconds
int nanoseconds
int userTag
* }
* In addition there are methods that create each of the property structures,
@@ -57,42 +61,161 @@ namespace epics { namespace pvData {
StandardField *standardField = getStandardField();
* }
*/
class StandardField;
typedef std::tr1::shared_ptr<StandardField> StandardFieldPtr;
class epicsShareClass StandardField {
public:
/**
* getStandardField returns the singleton.
* @return Shared pointer to StandardField.
*/
static StandardFieldPtr getStandardField();
~StandardField();
StructureConstPtr scalar(ScalarType type,String const & properties);
StructureConstPtr scalarArray(ScalarType elementType, String const & properties);
StructureConstPtr structureArray(StructureConstPtr const & structure,String const & properties);
/** Create a structure that has a scalar value field.
* @param type The type.
* @param properties A comma separated list of properties.
* This is some combination of "alarm,timeStamp,display,control,valueAlarm".
* @return The const shared pointer to the structure.
*/
StructureConstPtr scalar(ScalarType type,std::string const & properties);
/** Create a structure that has a union value field.
* @param punion The interface for value field.
* @param properties A comma separated list of properties.
* This is some combination of "alarm,timeStamp,display,control,valueAlarm".
* @return The const shared pointer to the structure.
*/
StructureConstPtr regUnion(
UnionConstPtr const & punion,
std::string const & properties);
/** Create a structure that has a varient union value field.
* @param properties A comma separated list of properties.
* This is some combination of "alarm,timeStamp,display,control,valueAlarm".
* @return The const shared pointer to the structure.
*/
StructureConstPtr variantUnion(std::string const & properties);
/** Create a structure that has a scalarArray value field.
* @param type The type.
* @param properties A comma separated list of properties.
* This is some combination of "alarm,timeStamp,display,control,valueAlarm".
* @return The const shared pointer to the structure.
*/
StructureConstPtr scalarArray(ScalarType elementType, std::string const & properties);
/** Create a structure that has a structureArray value field.
* @param type The type.
* @param properties A comma separated list of properties.
* This is some combination of "alarm,timeStamp,display,control,valueAlarm".
* @return The const shared pointer to the structure.
*/
StructureConstPtr structureArray(
StructureConstPtr const & structure,
std::string const & properties);
/** Create a structure that has a unionArray value field.
* @param type The type.
* @param properties A comma separated list of properties.
* This is some combination of "alarm,timeStamp,display,control".
* @return The const shared pointer to the structure.
*/
StructureConstPtr unionArray(
UnionConstPtr const & punion,
std::string const & properties);
/** Create a structure that has an enumerated structure value field.
* The id for the structure is "enum-t".
* @return The const shared pointer to the structure.
*/
StructureConstPtr enumerated();
StructureConstPtr enumerated(String const & properties);
/** Create a structure that has an enumerated structure value field
* 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.
*/
StructureConstPtr enumerated(std::string const & properties);
/**
* create an alarm structure
* @return The const shared pointer to the structure.
*/
StructureConstPtr alarm();
/**
* create a timeStamp structure
* @return The const shared pointer to the structure.
*/
StructureConstPtr timeStamp();
/**
* create a display structure
* @return The const shared pointer to the structure.
*/
StructureConstPtr display();
/**
* create a control structure
* @return The const shared pointer to the structure.
*/
StructureConstPtr control();
/**
* create a boolean alarm structure
* @return The const shared pointer to the structure.
*/
StructureConstPtr booleanAlarm();
/**
* create a byte alarm structure
* @return The const shared pointer to the structure.
*/
StructureConstPtr byteAlarm();
/**
* create a unsigned byte alarm structure
* @return The const shared pointer to the structure.
*/
StructureConstPtr ubyteAlarm();
/**
* create a short alarm structure
* @return The const shared pointer to the structure.
*/
StructureConstPtr shortAlarm();
/**
* create a unsigned short alarm structure
* @return The const shared pointer to the structure.
*/
StructureConstPtr ushortAlarm();
/**
* create an int alarm structure
* @return The const shared pointer to the structure.
*/
StructureConstPtr intAlarm();
/**
* create a unsigned int alarm structure
* @return The const shared pointer to the structure.
*/
StructureConstPtr uintAlarm();
/**
* create a long alarm structure
* @return The const shared pointer to the structure.
*/
StructureConstPtr longAlarm();
/**
* create a unsigned long alarm structure
* @return The const shared pointer to the structure.
*/
StructureConstPtr ulongAlarm();
/**
* create a float alarm structure
* @return The const shared pointer to the structure.
*/
StructureConstPtr floatAlarm();
/**
* create a double alarm structure
* @return The const shared pointer to the structure.
*/
StructureConstPtr doubleAlarm();
/**
* create an enumerated alarm structure
* @return The const shared pointer to the structure.
*/
StructureConstPtr enumeratedAlarm();
private:
StandardField();
void init();
StructureConstPtr createProperties(String id,FieldConstPtr field,String properties);
StructureConstPtr createProperties(
std::string id,FieldConstPtr field,std::string properties);
FieldCreatePtr fieldCreate;
String notImplemented;
String valueFieldName;
std::string notImplemented;
std::string valueFieldName;
StructureConstPtr alarmField;
StructureConstPtr timeStampField;
StructureConstPtr displayField;

View File

@@ -20,6 +20,10 @@
#include <shareLib.h>
namespace epics { namespace pvData {
class StandardPVField;
typedef std::tr1::shared_ptr<StandardPVField> StandardPVFieldPtr;
/**
* StandardPVField is a class or creating standard data fields.
* Like class StandardField it has two forms of the methods which create a fields:
@@ -31,25 +35,67 @@ namespace epics { namespace pvData {
StandardPVField *standardPVField = getStandardPVField();
* }
*/
class StandardPVField;
typedef std::tr1::shared_ptr<StandardPVField> StandardPVFieldPtr;
class epicsShareClass StandardPVField : private NoDefaultMethods {
public:
/**
* getStandardPVField returns the singleton.
* @return Shared pointer to StandardPVField.
*/
static StandardPVFieldPtr getStandardPVField();
~StandardPVField();
PVStructurePtr scalar(ScalarType type,String const & properties);
PVStructurePtr scalarArray(ScalarType elementType, String const & properties);
PVStructurePtr structureArray(StructureConstPtr const &structure,String const & properties);
/**
* Create a structure that has a scalar value field.
* @param type The type.
* @param properties A comma separated list of properties.
* This is some combination of "alarm,timeStamp,display,control,valueAlarm".
* @return The const shared pointer to the structure.
*/
PVStructurePtr scalar(ScalarType type,std::string const & properties);
/**
* Create a structure that has a scalar array value field.
* @param type The type.
* @param properties A comma separated list of properties.
* This is some combination of "alarm,timeStamp,display,control,valueAlarm".
* @return The const shared pointer to the structure.
*/
PVStructurePtr scalarArray(ScalarType elementType, std::string const & properties);
/**
* Create a structure that has a structure array value field.
* @param type The type.
* @param properties A comma separated list of properties.
* This is some combination of "alarm,timeStamp,display,control,valueAlarm".
* @return The const shared pointer to the structure.
*/
PVStructurePtr structureArray(StructureConstPtr const &structure,std::string const & properties);
/**
* Create a structure that has a union array value field.
* @param type The type.
* @param properties A comma separated list of properties.
* This is some combination of "alarm,timeStamp,display,control,valueAlarm".
* @return The const shared pointer to the structure.
*/
PVStructurePtr unionArray(UnionConstPtr const &punion,std::string const & properties);
/**
* Create a structure that has an enumerated structure value field.
* The id for the structure is "enum_t".
* @param choices This is a StringArray of choices.
* @return The const shared pointer to the structure.
*/
PVStructurePtr enumerated(StringArray const &choices);
PVStructurePtr enumerated(StringArray const &choices, String const & properties);
/**
* Create a structure that has an enumerated structure value field.
* 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.
*/
PVStructurePtr enumerated(StringArray const &choices, std::string const & properties);
private:
StandardPVField();
StandardFieldPtr standardField;
FieldCreatePtr fieldCreate;
PVDataCreatePtr pvDataCreate;
String notImplemented;
std::string notImplemented;
};
epicsShareExtern StandardPVFieldPtr getStandardPVField();

View File

@@ -1,7 +1,31 @@
# Makefile for the pvData tests
TOP = ..
include $(TOP)/configure/CONFIG
DIRS += misc
DIRS += pv
DIRS += property
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

13
testApp/copy/Makefile Normal file
View File

@@ -0,0 +1,13 @@
# This is a Makefile fragment, see ../Makefile
SRC_DIRS += $(PVDATA_TEST)/copy
TESTPROD_HOST += testCreateRequest
testCreateRequest_SRCS = testCreateRequest.cpp
testHarness_SRCS += testCreateRequest.cpp
TESTS += testCreateRequest
TESTPROD_HOST += testPVCopy
testPVCopy_SRCS += testPVCopy.cpp
testHarness_SRCS += testPVCopy.cpp
TESTS += testPVCopy

View File

@@ -0,0 +1,322 @@
/* testCreateRequest.cpp */
/* Author: Matej Sekoranja Date: 2010.12.27 */
#include <stddef.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <stdio.h>
#include <iostream>
#include <epicsUnitTest.h>
#include <testMain.h>
#include <pv/createRequest.h>
using namespace epics::pvData;
using std::string;
using std::cout;
using std::endl;
static bool debug = false;
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(!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)";
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);
pvString = pvRequest->getSubField<PVString>("record._options.a");
sval = pvString->get();
testOk(sval.compare("b")==0,"record.a = b");
pvString = pvRequest->getSubField<PVString>("record._options.x");
sval = pvString->get();
testOk(sval.compare("y")==0,"record.x = y");
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])";
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);
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})";
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.a.b.c.d").get()!=NULL);
testPass("request %s",request.c_str());
request = "field(a.b[x=y]{c.d})";
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);
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").get()!=NULL);
testPass("request %s",request.c_str());
request = "field(a.b[x=y]{c.d[x=y]})";
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);
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");
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})";
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);
pvString = pvRequest->getSubField<PVString>("field.a.a._options.a");
sval = pvString->get();
testOk(sval.compare("b")==0,"field.a.a._options.a = b");
pvString = pvRequest->getSubField<PVString>("field.a.a.a.a._options.a");
sval = pvString->get();
testOk(sval.compare("b")==0,"field.a.a.a.a._options.a = b");
pvString = pvRequest->getSubField<PVString>("field.b.a._options.a");
sval = pvString->get();
testOk(sval.compare("b")==0,"field.b.a._options.a = b");
testOk1(pvRequest->getSubField("field.b.a.a").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(!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(!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._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(!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._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").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(!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._options.int = 2");
pvString = pvRequest->getSubField<PVString>("record._options.float");
sval = pvString->get();
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").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(!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(!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]")
+ "putField(power.value)"
+ "getField(alarm,timeStamp,power{value,alarm},"
+ "current{value,alarm},voltage{value,alarm},"
+ "ps0{alarm,timeStamp,power{value,alarm},current{value,alarm},voltage{value,alarm}},"
+ "ps1{alarm,timeStamp,power{value,alarm},current{value,alarm},voltage{value,alarm}}"
+ ")";
if(debug) { cout << "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("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(!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]")
+ "putField(power.value)"
+ "getField(alarm,timeStamp,power{value,alarm},"
+ "current{value,alarm},voltage{value,alarm},"
+ "ps0{alarm,timeStamp,power{value,alarm},current{value,alarm},voltage{value,alarm}},"
+ "ps1{alarm,timeStamp,power{value,alarm},current{value,alarm},voltage{value,alarm}"
+ ")";
if(debug) { cout << "request " << request <<endl;}
cout << endl << "Error Expected for next call!!" << endl;
pvRequest = createRequest->createRequest(request);
cout << "reason " << createRequest->getMessage() << endl;
testPass("request %s",request.c_str());
request = "record[process=true,power.value";
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());
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(119);
testCreateRequestInternal();
return testDone();
}

361
testApp/copy/testPVCopy.cpp Normal file
View File

@@ -0,0 +1,361 @@
/*testPVCopyMain.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvData is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
/**
* @author mrk
*/
/* Author: Marty Kraimer */
#include <cstddef>
#include <cstdlib>
#include <cstddef>
#include <string>
#include <cstdio>
#include <memory>
#include <iostream>
#include <epicsUnitTest.h>
#include <testMain.h>
#include <pv/standardField.h>
#include <pv/standardPVField.h>
#include <pv/convert.h>
#include <pv/pvCopy.h>
#include <pv/createRequest.h>
using namespace std;
using std::tr1::static_pointer_cast;
using namespace epics::pvData;
static bool debug = true;
static void testPVScalar(
string const & valueNameMaster,
string const & valueNameCopy,
PVStructurePtr const & pvMaster,
PVCopyPtr const & pvCopy)
{
PVStructurePtr pvStructureCopy;
PVFieldPtr pvField;
PVScalarPtr pvValueMaster;
PVScalarPtr pvValueCopy;
BitSetPtr bitSet;
size_t offset;
ConvertPtr convert = getConvert();
pvField = pvMaster->getSubField(valueNameMaster);
pvValueMaster = static_pointer_cast<PVScalar>(pvField);
convert->fromDouble(pvValueMaster,.04);
StructureConstPtr structure = pvCopy->getStructure();
if(debug) { cout << "structure from copy" << endl << *structure << endl; }
pvStructureCopy = pvCopy->createPVStructure();
pvField = pvStructureCopy->getSubField(valueNameCopy);
pvValueCopy = static_pointer_cast<PVScalar>(pvField);
bitSet = BitSetPtr(new BitSet(pvStructureCopy->getNumberFields()));
pvCopy->initCopy(pvStructureCopy, bitSet);
if(debug) { cout << "after initCopy pvValueCopy " << convert->toDouble(pvValueCopy); }
if(debug) { cout << endl; }
convert->fromDouble(pvValueMaster,.06);
testOk1(convert->toDouble(pvValueCopy)==.04);
pvCopy->updateCopySetBitSet(pvStructureCopy,bitSet);
testOk1(convert->toDouble(pvValueCopy)==.06);
testOk1(bitSet->get(pvValueCopy->getFieldOffset()));
if(debug) { cout << "after put(.06) pvValueCopy " << convert->toDouble(pvValueCopy); }
if(debug) { cout << " bitSet " << *bitSet; }
if(debug) { cout << endl; }
offset = pvCopy->getCopyOffset(pvValueMaster);
if(debug) { cout << "getCopyOffset() " << offset; }
if(debug) { cout << " pvValueCopy->getOffset() " << pvValueCopy->getFieldOffset(); }
if(debug) { cout << " pvValueMaster->getOffset() " << pvValueMaster->getFieldOffset(); }
if(debug) { cout << " bitSet " << *bitSet; }
if(debug) { cout << endl; }
bitSet->clear();
convert->fromDouble(pvValueMaster,1.0);
if(debug) { cout << "before updateCopyFromBitSet"; }
if(debug) { cout << " masterValue " << convert->toDouble(pvValueMaster); }
if(debug) { cout << " copyValue " << convert->toDouble(pvValueCopy); }
if(debug) { cout << " bitSet " << *bitSet; }
if(debug) { cout << endl; }
bitSet->set(0);
testOk1(convert->toDouble(pvValueCopy)==0.06);
pvCopy->updateCopyFromBitSet(pvStructureCopy,bitSet);
testOk1(convert->toDouble(pvValueCopy)==1.0);
if(debug) { cout << "after updateCopyFromBitSet"; }
if(debug) { cout << " masterValue " << convert->toDouble(pvValueMaster); }
if(debug) { cout << " copyValue " << convert->toDouble(pvValueCopy); }
if(debug) { cout << " bitSet " << *bitSet; }
if(debug) { cout << endl; }
convert->fromDouble(pvValueCopy,2.0);
bitSet->set(0);
if(debug) { cout << "before updateMaster"; }
if(debug) { cout << " masterValue " << convert->toDouble(pvValueMaster); }
if(debug) { cout << " copyValue " << convert->toDouble(pvValueCopy); }
if(debug) { cout << " bitSet " << *bitSet; }
if(debug) { cout << endl; }
testOk1(convert->toDouble(pvValueMaster)==1.0);
pvCopy->updateMaster(pvStructureCopy,bitSet);
testOk1(convert->toDouble(pvValueMaster)==2.0);
if(debug) { cout << "after updateMaster"; }
if(debug) { cout << " masterValue " << convert->toDouble(pvValueMaster); }
if(debug) { cout << " copyValue " << convert->toDouble(pvValueCopy); }
if(debug) { cout << " bitSet " << *bitSet; }
if(debug) { cout << endl; }
}
static void testPVScalarArray(
ScalarType scalarType,
string const & valueNameMaster,
string const & valueNameCopy,
PVStructurePtr const & pvMaster,
PVCopyPtr const & pvCopy)
{
PVStructurePtr pvStructureCopy;
PVScalarArrayPtr pvValueMaster;
PVScalarArrayPtr pvValueCopy;
BitSetPtr bitSet;
size_t offset;
size_t n = 5;
shared_vector<double> values(n);
shared_vector<const double> cvalues;
pvValueMaster = pvMaster->getScalarArrayField(valueNameMaster,scalarType);
for(size_t i=0; i<n; i++) values[i] = i;
const shared_vector<const double> xxx(freeze(values));
pvValueMaster->putFrom(xxx);
StructureConstPtr structure = pvCopy->getStructure();
if(debug) { cout << "structure from copy" << endl << *structure << endl;}
pvStructureCopy = pvCopy->createPVStructure();
pvValueCopy = pvStructureCopy->getScalarArrayField(valueNameCopy,scalarType);
bitSet = BitSetPtr(new BitSet(pvStructureCopy->getNumberFields()));
pvCopy->initCopy(pvStructureCopy, bitSet);
if(debug) { cout << "after initCopy pvValueCopy " << *pvValueCopy << endl; }
if(debug) { cout << endl; }
values.resize(n);
for(size_t i=0; i<n; i++) values[i] = i + .06;
const shared_vector<const double> yyy(freeze(values));
pvValueMaster->putFrom(yyy);
pvValueCopy->getAs(cvalues);
testOk1(cvalues[0]==0.0);
pvCopy->updateCopySetBitSet(pvStructureCopy,bitSet);
pvValueCopy->getAs(cvalues);
testOk1(cvalues[0]==0.06);
if(debug) { cout << "after put(i+ .06) pvValueCopy " << *pvValueCopy << endl; }
if(debug) { cout << " bitSet " << *bitSet; }
if(debug) { cout << endl; }
offset = pvCopy->getCopyOffset(pvValueMaster);
if(debug) { cout << "getCopyOffset() " << offset; }
if(debug) { cout << " pvValueCopy->getOffset() " << pvValueCopy->getFieldOffset(); }
if(debug) { cout << " pvValueMaster->getOffset() " << pvValueMaster->getFieldOffset(); }
if(debug) { cout << " bitSet " << *bitSet; }
if(debug) { cout << endl; }
bitSet->clear();
values.resize(n);
for(size_t i=0; i<n; i++) values[i] = i + 1.0;
const shared_vector<const double> zzz(freeze(values));
pvValueMaster->putFrom(zzz);
if(debug) { cout << "before updateCopyFromBitSet"; }
if(debug) { cout << " masterValue " << *pvValueMaster << endl; }
if(debug) { cout << " copyValue " << *pvValueCopy << endl; }
if(debug) { cout << " bitSet " << *bitSet; }
if(debug) { cout << endl; }
bitSet->set(0);
pvValueCopy->getAs(cvalues);
testOk1(cvalues[0]==0.06);
pvCopy->updateCopyFromBitSet(pvStructureCopy,bitSet);
pvValueCopy->getAs(cvalues);
testOk1(cvalues[0]==1.0);
if(debug) { cout << "after updateCopyFromBitSet"; }
if(debug) { cout << " masterValue " << *pvValueMaster << endl; }
if(debug) { cout << " copyValue " << *pvValueCopy << endl; }
if(debug) { cout << " bitSet " << *bitSet; }
if(debug) { cout << endl; }
values.resize(n);
for(size_t i=0; i<n; i++) values[i] = i + 2.0;
const shared_vector<const double> ttt(freeze(values));
pvValueMaster->putFrom(ttt);
bitSet->set(0);
if(debug) { cout << "before updateMaster"; }
if(debug) { cout << " masterValue " << *pvValueMaster << endl; }
if(debug) { cout << " copyValue " << *pvValueCopy << endl; }
if(debug) { cout << " bitSet " << *bitSet; }
if(debug) { cout << endl; }
pvValueMaster->getAs(cvalues);
testOk1(cvalues[0]==2.0);
pvCopy->updateMaster(pvStructureCopy,bitSet);
pvValueMaster->getAs(cvalues);
testOk1(cvalues[0]==1.0);
if(debug) { cout << "before updateMaster"; }
if(debug) { cout << " masterValue " << *pvValueMaster << endl; }
if(debug) { cout << " copyValue " << *pvValueCopy << endl; }
if(debug) { cout << " bitSet " << *bitSet; }
if(debug) { cout << endl; }
}
static void scalarTest()
{
if(debug) { cout << endl << endl << "****scalarTest****" << endl; }
PVStructurePtr pvMaster;
string request;
PVStructurePtr pvRequest;
PVFieldPtr pvMasterField;
PVCopyPtr pvCopy;
string valueNameMaster;
string valueNameCopy;
StandardPVFieldPtr standardPVField = getStandardPVField();
pvMaster = standardPVField->scalar(pvDouble,"alarm,timeStamp,display");
valueNameMaster = request = "value";
CreateRequest::shared_pointer createRequest = CreateRequest::create();
pvRequest = createRequest->createRequest(request);
if(debug) { cout << "request " << request << endl; }
if(debug) { cout << "pvRequest\n" << *pvRequest << endl; }
pvCopy = PVCopy::create(pvMaster,pvRequest,"");
valueNameCopy = "value";
testPVScalar(valueNameMaster,valueNameCopy,pvMaster,pvCopy);
request = "";
valueNameMaster = "value";
pvRequest = createRequest->createRequest(request);
if(debug) { cout << "request " << request << endl; }
if(debug) { cout << "pvRequest\n" << *pvRequest << endl; }
pvCopy = PVCopy::create(pvMaster,pvRequest,"");
valueNameCopy = "value";
testPVScalar(valueNameMaster,valueNameCopy,pvMaster,pvCopy);
request = "alarm,timeStamp,value";
valueNameMaster = "value";
pvRequest = createRequest->createRequest(request);
if(debug) { cout << "request " << request << endl; }
if(debug) { cout << "pvRequest\n" << *pvRequest << endl; }
pvCopy = PVCopy::create(pvMaster,pvRequest,"");
valueNameCopy = "value";
testPVScalar(valueNameMaster,valueNameCopy,pvMaster,pvCopy);
}
static void arrayTest()
{
if(debug) { cout << endl << endl << "****arrayTest****" << endl; }
PVStructurePtr pvMaster;
string request;
PVStructurePtr pvRequest;
PVFieldPtr pvMasterField;
PVCopyPtr pvCopy;
string valueNameMaster;
string valueNameCopy;
CreateRequest::shared_pointer createRequest = CreateRequest::create();
StandardPVFieldPtr standardPVField = getStandardPVField();
pvMaster = standardPVField->scalarArray(pvDouble,"alarm,timeStamp");
valueNameMaster = request = "value";
pvRequest = createRequest->createRequest(request);
if(debug) { cout << "request " << request << endl; }
if(debug) { cout << "pvRequest\n" << *pvRequest << endl; }
pvCopy = PVCopy::create(pvMaster,pvRequest,"");
valueNameCopy = "value";
testPVScalarArray(pvDouble,valueNameMaster,valueNameCopy,pvMaster,pvCopy);
request = "";
valueNameMaster = "value";
pvRequest = createRequest->createRequest(request);
if(debug) { cout << "request " << request << endl; }
if(debug) { cout << "pvRequest\n" << *pvRequest << endl; }
pvCopy = PVCopy::create(pvMaster,pvRequest,"");
valueNameCopy = "value";
testPVScalarArray(pvDouble,valueNameMaster,valueNameCopy,pvMaster,pvCopy);
request = "alarm,timeStamp,value";
valueNameMaster = "value";
pvRequest = createRequest->createRequest(request);
if(debug) { cout << "request " << request << endl; }
if(debug) { cout << "pvRequest\n" << *pvRequest << endl; }
pvCopy = PVCopy::create(pvMaster,pvRequest,"");
valueNameCopy = "value";
testPVScalarArray(pvDouble,valueNameMaster,valueNameCopy,pvMaster,pvCopy);
}
static PVStructurePtr createPowerSupply()
{
FieldCreatePtr fieldCreate = getFieldCreate();
StandardFieldPtr standardField = getStandardField();
PVDataCreatePtr pvDataCreate = getPVDataCreate();
size_t nfields = 5;
StringArray names;
names.reserve(nfields);
FieldConstPtrArray powerSupply;
powerSupply.reserve(nfields);
names.push_back("alarm");
powerSupply.push_back(standardField->alarm());
names.push_back("timeStamp");
powerSupply.push_back(standardField->timeStamp());
string properties("alarm,display");
names.push_back("voltage");
powerSupply.push_back(standardField->scalar(pvDouble,properties));
names.push_back("power");
powerSupply.push_back(standardField->scalar(pvDouble,properties));
names.push_back("current");
powerSupply.push_back(standardField->scalar(pvDouble,properties));
return pvDataCreate->createPVStructure(
fieldCreate->createStructure(names,powerSupply));
}
static void powerSupplyTest()
{
if(debug) { cout << endl << endl << "****powerSupplyTest****" << endl; }
PVStructurePtr pvMaster;
string request;
PVStructurePtr pvRequest;
PVFieldPtr pvMasterField;
PVCopyPtr pvCopy;
string builder;
string valueNameMaster;
string valueNameCopy;
CreateRequest::shared_pointer createRequest = CreateRequest::create();
pvMaster = createPowerSupply();
valueNameMaster = request = "power.value";
pvRequest = createRequest->createRequest(request);
if(debug) { cout << "request " << request << endl; }
if(debug) { cout << "pvRequest\n" << *pvRequest << endl; }
pvCopy = PVCopy::create(pvMaster,pvRequest,"");
valueNameCopy = "power.value";
testPVScalar(valueNameMaster,valueNameCopy,pvMaster,pvCopy);
request = "";
valueNameMaster = "power.value";
pvRequest = createRequest->createRequest(request);
if(debug) { cout << "request " << request << endl; }
if(debug) { cout << "pvRequest\n" << *pvRequest << endl; }
pvCopy = PVCopy::create(pvMaster,pvRequest,"");
valueNameCopy = "power.value";
testPVScalar(valueNameMaster,valueNameCopy,pvMaster,pvCopy);
request = "alarm,timeStamp,voltage.value,power.value,current.value";
valueNameMaster = "power.value";
pvRequest = createRequest->createRequest(request);
if(debug) { cout << "request " << request << endl; }
if(debug) { cout << "pvRequest\n" << *pvRequest << endl; }
pvCopy = PVCopy::create(pvMaster,pvRequest,"");
valueNameCopy = "power.value";
testPVScalar(valueNameMaster,valueNameCopy,pvMaster,pvCopy);
request = "alarm,timeStamp,voltage{value,alarm},power{value,alarm,display},current.value";
valueNameMaster = "power.value";
pvRequest = createRequest->createRequest(request);
if(debug) { cout << "request " << request << endl; }
if(debug) { cout << "pvRequest\n" << *pvRequest << endl; }
pvCopy = PVCopy::create(pvMaster,pvRequest,"");
valueNameCopy = "power.value";
testPVScalar(valueNameMaster,valueNameCopy,pvMaster,pvCopy);
}
MAIN(testPVCopy)
{
testPlan(67);
scalarTest();
arrayTest();
powerSupplyTest();
return testDone();
}

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

Some files were not shown because too many files have changed in this diff Show More