154 Commits
3.1.0 ... 5.0.2

Author SHA1 Message Date
Dave Hickin
7fc3f50ae9 Merge branch 'master' into release/5.0 2015-10-15 10:37:46 +01:00
Dave Hickin
05d41f81e4 Minor correction to README 2015-10-15 10:37:12 +01:00
Dave Hickin
d400e8eaf5 Merge branch 'master' into release/5.0 2015-10-15 09:39:53 +01:00
Dave Hickin
fdc289d888 Add new README
Replace out of date HTML README with a new markdown one
2015-10-15 09:16:20 +01:00
Dave Hickin
0a2243e033 Update TODO 2015-10-15 07:46:40 +01:00
Dave Hickin
9d877d764f Doxgen fixes and enhancements
Change &param to @param. Add missing parameter.
Add more doxygen comments in SerializeHelper.
2015-10-15 07:12:42 +01:00
Dave Hickin
f5df29cf34 Doxygen: remove @code when code block not wanted
@code produces a separate code block, rather than just displaying
contents as code.

Mostly replaced use with @c tag when block not wanted.
2015-10-15 06:50:26 +01:00
Dave Hickin
8008823ea5 Fix doxygen warnings 2015-10-14 23:01:28 +01:00
Dave Hickin
6515de4bc0 Add release notes for 5.0 2015-10-08 15:24:14 +01:00
Ralph Lange
8c5f535b79 jenkins: fix CloudBees doc job 2015-09-28 15:29:39 +02:00
Ralph Lange
de2fac122c jenkins: fix CloudBees doc job 2015-09-28 15:29:17 +02:00
Ralph Lange
7707da0b45 jenkins: adapt doc script to new CloudBees jenkins job 2015-09-14 16:48:33 +02:00
Ralph Lange
036186fc12 jenkins: adapt doc script to new CloudBees jenkins job 2015-09-14 16:48:15 +02:00
Dave Hickin
d3853bd4e9 Ignore target-specific RELEASE and CONFIG_SITE in git
Tell gir to ignore configuration files such as RELEASE.win32-x86.Common
or CONFIG_SITE.linux-x86_64.Common.
2015-09-02 16:36:26 +01:00
Dave Hickin
7253bac48a Updated copyright notice and license
Updated copyright notice using the one in normativeTypesCPP. Added
Diamond and BNL. Added legal discalimers for Diamond and BNL to license.
Added dates to copyright notice. "All rights reserved" added to
copyright.
2015-09-02 14:04:29 +01:00
dhickin
973fbeeba5 Merge pull request #8 from dhickin/move_getSubFieldT_def_from_class_body
Move getSubFieldT definitions out of class body
2015-09-01 17:03:14 +01:00
dhickin
f22cefba97 Merge pull request #11 from anjohnson/fix-mac-build
Fix build problem on Mac
2015-09-01 17:00:58 +01:00
Ralph Lange
a5abc37b17 Add QtCreator pattern to .gitignore 2015-08-18 16:11:33 +02:00
Ralph Lange
b95fa7be56 jenkins: remove hgweb job; split doc and build jobs; update EPICS Base version 2015-08-18 16:11:05 +02:00
Andrew Johnson
f6cf87a52d Fix build problem on Mac
../../testApp/pv/testPVData.cpp:549:14: error: use of overloaded operator '!='
      is ambiguous (with operand types 'PVIntPtr' (aka 'shared_ptr<PVInt>') and
      'long')
    testOk1(a!=NULL);
            ~^ ~~~~
2015-08-12 15:06:46 -05:00
dhickin
51f36b2281 Merge pull request #10 from dhickin/remove_deprecated_getDerivedTypeField
Remove deprecated PVStructure::get*Field Functions
2015-07-29 12:29:08 +01:00
Dave Hickin
ddebd494c6 Remove deprecated PVStructure::get*Field Functions
Remove the deprecated functions such as getIntField in PVStructure,
whose usage has been replaced by that of the template getSubField
function and which are now no longer called anywhere.
2015-07-28 17:45:26 +01:00
dhickin
d0a8d2b1cd Merge pull request #9 from dhickin/replace_calls_getScalarArrayField
Replace calls of deprecated PVStructure::getScalarArrayField
2015-07-28 17:07:50 +01:00
Dave Hickin
1731a0daf6 USAGE_DEPRECATED macro used for getScalarArrayField 2015-07-24 16:56:49 +01:00
Dave Hickin
3487b3ee9e Remove unused argument in testPVScalarArray 2015-07-24 11:22:50 +01:00
Dave Hickin
5834efb709 Remove calls of deprecated getScalarArrayField 2015-07-24 11:21:58 +01:00
Dave Hickin
52bc6d060d Move getSubFieldT definitions out of class body
Move definitions of 2 getSubFieldT overloads:
shared_ptr<PVT> PVStructure::getSubFieldT(const char *name) const
shared_ptr<PVT> PVStructure::getSubFieldT(size_t fieldOffset) const
out of class body so not implicitly inlined.
2015-07-15 11:34:44 +01:00
dhickin
35ca5f3aed Merge pull request #7 from dhickin/getSubFieldT
GetSubFieldT
2015-07-14 16:19:38 +01:00
Dave Hickin
ac2b6ea8db Make getSubFieldT return shared pointer
Signed-off-by: Dave Hickin <david.hickin@diamond.ac.uk>
2015-07-13 12:48:05 +01:00
Dave Hickin
9827caa3e3 Make overloads of getSubField and getSubFieldT match
For each getSubField overload a throwing getSubFieldT has been added and
vice versa. These have been documented in doxygen and in the module
documentation.

Signed-off-by: Dave Hickin <david.hickin@diamond.ac.uk>
2015-07-13 12:41:47 +01:00
Dave Hickin
ebe2d6196c Rename getAs getSubFieldT
Signed-off-by: Dave Hickin <david.hickin@diamond.ac.uk>
2015-07-13 12:34:15 +01:00
Dave Hickin
e4689dd3f8 Added unit tests for functions for getting subfields
Signed-off-by: Dave Hickin <david.hickin@diamond.ac.uk>
2015-07-13 12:07:54 +01:00
Dave Hickin
1dba611b8e Improve exception messages when getting PVStructure subfield
Signed-off-by: Dave Hickin <david.hickin@diamond.ac.uk>
2015-07-13 11:47:21 +01:00
Dave Hickin
97cbea6f4d Implement getSubField functions without using exceptions
Implementation of getSubField (and getScalarArrayField) introduced in
the getAs pull request throws an exception then catches it to return a
null pointer. Implement without throwing.

Signed-off-by: Dave Hickin <david.hickin@diamond.ac.uk>
2015-07-13 02:16:08 +01:00
Dave Hickin
d9963b0631 Add test for getAs when mid-field not structure
Signed-off-by: Dave Hickin <david.hickin@diamond.ac.uk>
2015-07-09 13:22:42 +01:00
Dave Hickin
8418303ce2 Fix bug in new PVStructure::getAs function
Fix seg fault when getAs is called with a string of the form x.y (or
x_1. ... x_n.y) where x or (x1. ... .x_i) is not a structure field.

Signed-off-by: Dave Hickin <david.hickin@diamond.ac.uk>
2015-07-09 13:21:45 +01:00
Dave Hickin
40952df965 Corrected spelling in test and exception messages
Signed-off-by: Dave Hickin <david.hickin@diamond.ac.uk>
2015-07-08 18:19:53 +01:00
Dave Hickin
4f2c51c480 Correct spelling and typos in doxygen and comments
Signed-off-by: Dave Hickin <david.hickin@diamond.ac.uk>
2015-07-08 18:18:37 +01:00
Marty Kraimer
fd31a0d6b0 Merge pull request #6 from mdavidsaver/dropprinter
remove unused PrinterPlain
2015-06-27 07:00:15 -04:00
Michael Davidsaver
9ad725a272 remove unused PrinterPlain 2015-06-25 16:51:04 -04:00
Marty Kraimer
2b6172ba63 Merge pull request #5 from mrkraimer/master
document new PVStructure::getAs method
2015-06-23 10:12:10 -04:00
Marty Kraimer
c521f9299d document new PVStructure::getAs method 2015-06-23 08:24:54 -04:00
Marty Kraimer
1e646f8df1 Merge pull request #4 from mdavidsaver/getasfield
Add PVStructure::getAs<>()
2015-06-23 07:24:30 -04:00
Marty Kraimer
b5a436c1b7 Merge pull request #3 from mdavidsaver/getdeprecate
Deprecated PVStructure::get*Field methods trigger a warning
2015-06-23 07:17:38 -04:00
Michael Davidsaver
4f25c7a3ea remove findSubField 2015-06-22 18:14:23 -04:00
Michael Davidsaver
eadb8ff65b add PVStructure::getAs<>() for field access w/o NULL 2015-06-22 18:14:23 -04:00
Michael Davidsaver
6a80e941a0 replace use of depercated methods 2015-06-22 14:36:27 -04:00
Michael Davidsaver
7fc9b42b3a PVStructure: compiler warning when deprecated methods are used 2015-06-22 14:27:44 -04:00
Dave Hickin
0d857999bf Make default type ID strings const.
Signed-off-by: Dave Hickin <david.hickin@diamond.ac.uk>
2015-06-17 14:51:07 +01:00
Marty Kraimer
8ba71b048e Merge pull request #1 from mdavidsaver/errmsg
Friendlier exception messages w/ stack trace during Field creation
2015-06-15 06:41:34 -04:00
Michael Davidsaver
e07f6c1703 Friendlier exception messages w/ stack trace during Field creation 2015-06-12 13:54:03 -04:00
Marty Kraimer
e4f38121d2 remove qtcreator file 2015-06-10 10:31:08 -04:00
Marty Kraimer
255ee3f151 clean up conversion from hg to got; remove qtcreator files 2015-06-09 08:43:41 -04:00
dhickin
e72dbaabe1 Add some doxygen 2015-06-08 10:06:06 +01:00
dhickin
b39662450f Fix for windows static build static initialisation errors. 2015-06-08 04:58:04 +01:00
dhickin
98da0c0bec Add template getField member functions which return specific field types to Structure and Union. 2015-03-30 09:05:59 +01:00
dhickin
45dde325fd Change the printing of structure array and union array fields of structure introspection objects. Removes superfluous information and brings it in line with pvData meta language. 2015-03-20 17:23:32 +00:00
dhickin
2967a8f798 Declare the one argument constructors of PVField and its derived classes explicit. 2015-03-06 21:05:50 +00:00
Matej Sekoranja
d4bdc73948 documentation/RELEASE_NOTES.md updated 2015-02-18 14:26:19 +01:00
Matej Sekoranja
37c2f6bb17 merge 2015-02-18 10:11:15 +01:00
Matej Sekoranja
a8e4d749e3 flow: Merged <feature> 'copy_refactoring' to <develop> ('default'). 2015-02-18 10:02:17 +01:00
Matej Sekoranja
3df16ee449 flow: Closed <feature> 'copy_refactoring'. 2015-02-18 10:02:17 +01:00
Matej Sekoranja
332c2f959b added copy() method back to convert, since it is usually used by external modules; marked as DEPRECATED 2015-02-17 22:36:28 +01:00
Matej Sekoranja
a1b89c9a3b PVScalar::copy made public; copy tests 2015-02-17 21:54:35 +01:00
Matej Sekoranja
d6921fdac0 removal of some methods from convert 2015-02-17 20:22:37 +01:00
Matej Sekoranja
4cb3c22221 update code to the new method, removed copy from convert 2015-02-17 18:56:56 +01:00
Matej Sekoranja
cc1536b6e1 moved operators to pvData/pvIntrospect, added copy/copyUnchecked methods 2015-02-17 13:59:15 +01:00
Matej Sekoranja
92a178cbf9 flow: Created branch 'feature/copy_refactoring'. 2015-02-17 09:36:44 +01:00
dhickin
fbebce0a49 Make sure postPut is called precisely once and after put in Convert::copyUnion. 2015-02-11 22:17:45 +00:00
Matej Sekoranja
b13bb9819a updated testPlan(0) to actual value 2015-02-11 20:56:38 +01:00
Matej Sekoranja
bb505b8ed9 win32: new operators were missing exports 2015-02-11 15:41:12 +01:00
dhickin
cf030bc711 Call postPut() in Convert::copyUnion(). 2015-02-11 14:04:15 +00:00
Marty Kraimer
6cb95c5cfc fixed possible SEGFAULT in ceateRequest; new stream operator for Field and PVField 2015-02-11 07:26:04 -05:00
Matej Sekoranja
a277a4fdd5 copy schematic 2015-02-11 11:30:39 +01:00
Matej Sekoranja
388799d39d monitors: minor monitor API doc update 2015-02-01 00:46:55 +01:00
Matej Sekoranja
4acf7edf95 non-copy (by reference) retrival of getFields()/getPVFields()/getFieldNames() 2015-01-30 11:35:43 +01:00
Matej Sekoranja
e39346d51e missing swap templates for unsigned types 2015-01-21 20:19:23 +01:00
Ralph Lange
5ae6de4f1d jenkins: fix cloudbees script (commands must return 0) 2014-12-19 14:01:13 +01:00
Ralph Lange
e0f1427af7 jenkins: create and update documentation in only one build configuration 2014-12-19 13:18:52 +01:00
Ralph Lange
69297bdb58 jenkins: make EPICS base a parameter in jenkins job 2014-12-12 09:49:01 +01:00
Marty Kraimer
0fa2f2c2ff merge branch release/4.0 2014-12-11 14:11:54 -05:00
Marty Kraimer
9efce46fff work on doxygen 2014-12-11 09:47:20 -05:00
dhickin
c356ecb402 make local RELEASE.local files take precedence over those in TOP/.. 2014-12-09 13:45:56 +00:00
dhickin
4c6887e7ec Added tag 4.0.3 for changeset 8543734dbf6e 2014-12-05 11:30:03 +00:00
Marty Kraimer
6d338cab15 merge branch release/4.0 2014-12-04 08:30:26 -05:00
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
Matej Sekoranja
f2b43b704c rtems compilation warnings (int32 != int) 2014-11-26 14:12:09 +01:00
Matej Sekoranja
de1478d7ba Event test added 2014-11-25 10:43:07 +01: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
Matej Sekoranja
2e4a8b2e23 Structure/Union: bound check access for getFieldName(int)/getField(int) 2014-11-13 18:32:50 +01: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
135 changed files with 29410 additions and 7328 deletions

15
.gitignore vendored Normal file
View File

@@ -0,0 +1,15 @@
bin/
lib/
doc/
include/
db/
dbd/
documentation/html
documentation/*.tag
envPaths
configure/*.local
configure/RELEASE.*
configure/CONFIG_SITE.*
!configure/ExampleRELEASE.local
**/O.*
QtC-*

View File

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

View File

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

12
.hgtags
View File

@@ -1,12 +0,0 @@
459f10877e5628241704f31437b4cbd342df0798 test1
6e8a22d01e824702088195c08bf50bfb6f293de5 1.0-BETA
d29d84f4c3f389f2accd497185b106c8541f95c9 1.1-SNAPSHOT
a29729ca0ecd60b66f2d997031d97911377e44a7 marchtest
9c59737f56e71aef641b70d0f72aa768fd7f8414 1.0.1-BETA
4559c3de0cb4e3420e26272817f58bab005063ec 1.1-BETA
d70c5ad29163306f50979a95b5aebbe9a93cfe76 2.0-BETA
4cecd4b200f88ab57bbb81978c45df2a67bbece1 3.0-pre1
4cecd4b200f88ab57bbb81978c45df2a67bbece1 3.0.0
2a289ff41e2ed3a0247877306c2db7b266f3b6b8 3.0.1
58092712d092ee521d1e1c8fa596a67f7d113ee9 3.0.2
40b681ffc5cd609320e3f8ffc8eb6aa3bfdfbf19 before_merge_changesAfter3_0_2

View File

@@ -1,12 +1,31 @@
/****************************************************
Copyright (c) 2008 All rights reserved
Copyright (c) 2008 Martin R. Kraimer
Copyright (c) 2006 The University of Chicago, as Operator of Argonne
National Laboratory.
This software is in part copyrighted by the various organizations and
individuals listed below. Permission to use it is set out in the file
LICENSE that accompanies the software.
In no event shall any copyright holder be liable to any party for
direct, indirect, special, incidental, or consequential damages arising
out of the use of this software, its documentation, or any derivatives
thereof, even if they have been advised of the possibility of such
damage.
The copyright holders specifically disclaim any warranties, including,
but not limited to, the implied warranties of merchantability, fitness
for a particular purpose, and non-infringement. This software is
provided on an "as is" basis, and the copyright holders have no
obligation either collectively or individually to provide maintenance,
support, updates, enhancements, or modifications.
Copyright (c) 2006 - 2015 All rights reserved
Martin R. Kraimer
The University of Chicago, as Operator of Argonne National Laboratory.
Deutsches Elektronen-Synchroton, Member of the Helmholtz Association,
(DESY), HAMBURG, GERMANY,
BERLINER SPEICHERRING GESELLSCHAFT FUER SYNCHROTRONSTRAHLUNG M.B.H.
(BESSY), BERLIN, GERMANY.
COSYLAB (Control System Laboratory)
(Cosylab) Ljubljana Slovenia
*************************************************** */
COSYLAB (Control System Laboratory), Ljubljana, Slovenia.
Brookhaven Science Associates, as Operator of Brookhaven
National Laboratory.
Diamond Light Source Ltd., Didcot, United Kingdom.

2343
Doxyfile

File diff suppressed because it is too large Load Diff

44
LICENSE
View File

@@ -1,12 +1,15 @@
Copyright (c) 2008 Martin R. Kraimer
Copyright (c) 2006-2015 Martin R. Kraimer
Copyright (c) 2006 The University of Chicago, as Operator of Argonne
National Laboratory.
Copyright (c) 2006 Deutsches Elektronen-Synchroton,
Copyright (c) 2006 Deutsches Elektronen-Synchrotron,
Member of the Helmholtz Association, (DESY), HAMBURG, GERMANY.
Copyright (c) 2007 Control System Laboratory,
Copyright (c) 2007-2015 Control System Laboratory,
(COSYLAB) Ljubljana Slovenia
Copyright (c) 2010-2015 Brookhaven Science Associates, as Operator of Brookhaven
National Laboratory
Copyright (c) 2011-2015 Diamond Light Source Limited,
(DLS) Didcot, United Kingdom
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
@@ -75,4 +78,37 @@ to, the implied warranties of merchantability, fitness for a particular
purpose, and non-infringement. This software is provided on an "as is"
basis, and DESY has no obligation to provide maintenance, support,
updates, enhancements, or modifications.
______________________________________________________________________
This software is in part copyrighted by the Brookhaven
National Laboratory (BNL).
In no event shall BNL be liable to any party for direct, indirect,
special, incidental, or consequential damages arising out of the use of
this software, its documentation, or any derivatives thereof, even if
BNL has been advised of the possibility of such damage.
BNL specifically disclaims any warranties, including, but not limited
to, the implied warranties of merchantability, fitness for a particular
purpose, and non-infringement. This software is provided on an "as is"
basis, and BNL has no obligation to provide maintenance, support,
updates, enhancements, or modifications.
________________________________________________________________________
This software is in part copyrighted by Diamond Light Source Limited (DLS)
In no event shall DLS be liable to any party for direct, indirect,
special, incidental, or consequential damages arising out of the use of
this software, its documentation, or any derivatives thereof, even if
DLS has been advised of the possibility of such damage.
DLS specifically disclaims any warranties, including, but not limited
to, the implied warranties of merchantability, fitness for a particular
purpose, and non-infringement. This software is provided on an "as is"
basis, and DLS has no obligation to provide maintenance, support,
updates, enhancements, or modifications.
________________________________________________________________________

View File

@@ -1,82 +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 pvData C++</title>
</head>
<body>
<h1 style="text-align: center">EPICS pvData C++<br />
Overview<br />
2010.08.10</h1>
CONTENTS
<hr />
<h2 style="text-align: center">Introduction</h2>
<hr />
<p>This project has the begining of the C++ implementation of pvData. The
following is done:</p>
<dl>
<dt>introspection interfaces</dt>
<dd>The introspection interfaces for clients are described.</dd>
<dt>introspection implementation</dt>
<dd>The following have been implemented: Type, ScalarType, Field,
Scalar</dd>
<dt>test</dt>
<dd>A test of Scalar.</dd>
<dt>As mentioned below there are problems with the current
implementation.</dt>
</dl>
<hr />
<h2 style="text-align: center">Building</h2>
<hr />
<p>The project is structured as an epics base client application. Edit
configure/RELEASE so that it references your EPICS base and then just
type:</p>
<pre> make</pre>
<p>At the top. Then execute the test in the bin directory.</p>
<p>pvDataApp has the following sub directories:</p>
<dl>
<dt>pv</dt>
<dd>pvData.h has the interface descriptions for client code.</dd>
<dt>factory</dt>
<dd>FieldCreateFactory.cpp has the current implementation</dd>
<dt>test</dt>
<dd>Has a test for the current implementation.</dd>
</dl>
<hr />
<h2 style="text-align: center">Questions about Classes</h2>
<hr />
<p>The pure virtual classes defined in pvData.h now work. But there are still
some things that are not so nice. Amoung these are:</p>
<ul>
<li>In FieldCreateFactory.cpp look for "WHY DO I". It asks why the derived
class must also define methods defined in the base class. If it does not
then a compilation error occurs. WHY??? </li>
<li>The toString methods have an argument of "std::string &amp;buf" instead
of "std::string *". Does this seem correct?</li>
<li>Can arguments and return descriptions be defined better?</li>
<li>Is const present everywhere it should be? Remember that introspection
classes are immutable.</li>
<li>The code is NOT thread safe. When we decide for sure what thread/lock
support to choose I will fix this.</li>
</ul>
<p>HELP WILL BE GREATLY APPRECIATED. because I am still coming up to speed
with c++</p>
<hr />
<h2 style="text-align: center">Garbage Collection</h2>
<hr />
<p>Not yet implemented. Lets get class structure correct first.</p>
</body>
</html>

57
README.md Normal file
View File

@@ -0,0 +1,57 @@
pvaDataCPP
==========
pvDataCPP is a set of data types and utilities that form part of the EPICS V4 project.
Further Info
------------
Consult the documents in the documentation directory, in particular
* pvDataCPP.html
* RELEASE_NOTES.md
Also see the [EPICS Version 4 website](http://epics-pvdata.sourceforge.net)
Prerequisites
-------------
The pvDataCPP requires recent versions of the following software:
1. EPICS Base (v3.14.12.3 or later)
2. EPICS4 pvCommonCPP (4.1.0 or later)
(pvCommonCPP may not be needed depending on host/compiler.)
Building
--------
Building uses the make utility and the EPICS base build system.
The build system needs the location of the prerequisites, e.g. by placing the
lines of the form
PVCOMMON = /home/install/epicsV4/pvCommonCPP
EPICS_BASE = /home/install/epics/base
pointing to the locations in a file called RELEASE.local
in the configure directory or the parent directory of pvDataCPP.
With this in place, to build type make
make
To perform a clean build type
make clean uninstall
To run the unit tests type
make runtests
For more information on the EPICS build system consult the
[Application Development guide](http://www.aps.anl.gov/epics/base/R3-14/12-docs/AppDevGuide.pdf).

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

@@ -21,5 +21,5 @@
# PVCOMMON = /home/install/epicsV4/pvCommonCPP
# EPICS_BASE = /home/install/epics/base
-include $(TOP)/configure/RELEASE.local
-include $(TOP)/../RELEASE.local
-include $(TOP)/configure/RELEASE.local

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,218 @@
<h1>Release 5.0</h1>
<p>The main changes since release 4.0 are:</p>
<ul>
<li>Deprecated getXXXField() methods have been removed from PVStructure</li>
<li>Convert copy methods and equals operators (re)moved</li>
<li>Convert::copyUnion now always copies between subfields.</li>
<li>New method getSubFieldT, like getSubField except it throws an exception</li>
<li>findSubField method removed from PVStructure</li>
<li>New stream operators for Field and PVField are provided</li>
<li>New template versions of Structure::getField</li>
<li>Fixes for static initialisation order issues</li>
<li>CreateRequest prevents a possible SEGFAULT</li>
</ul>
<h2>Deprecated getXXXField methods have been removed from PVStructure</h2>
<p>The following methods have been removed from PVStructure</p>
<ul>
<li>getBooleanField</li>
<li>getByteField, getShortField, getIntField, getLongField</li>
<li>getUByteField, getUShortField, getUIntField, getULongField</li>
<li>getStringField</li>
<li>getStructureField, getUnionField</li>
<li>getScalarArrayField, getStructureArrayField, getUnionArrayField</li>
</ul>
<p>Use template getSubField instead, e.g. use</p>
<pre><code>getSubField&lt; PVInt &gt;(fieldName)
</code></pre>
<p>in place of</p>
<pre><code>getIntField(fieldName)
</code></pre>
<h2>Convert copy methods and equals operators</h2>
<p>Convert copy methods where moved and replaced with methods
on PVField classes, i.e.</p>
<pre><code>PVField::copy(const PVField&amp; from)
</code></pre>
<p>Methods</p>
<pre><code>PVField::copyUnchecked(const PVField&amp; from)
</code></pre>
<p>were added to allow unchecked copies, to gain performance
where checked are not needed (anymore).</p>
<p>In addition:
- isCompatibleXXX methods were removed in favour of Field::operator==.
- equals methods were remove in favour of PVField::operator==.
- operator== methods where moved to pvIntrospect.h and pvData.h</p>
<h2>Convert::copyUnion</h2>
<p>Before this method, depending on types for to and from,
sometimes did a shallow copy, i.e. just made to shared_ptr for to
share the same data as from.
Now it always copies between the subfield of to and from.</p>
<h2>New method getSubFieldT, like getSubField except it throws an exception</h2>
<p>PVStructure has a new template member</p>
<pre><code>getSubFieldT(std::string const &amp;fieldName)
</code></pre>
<p>that is like <b>getSubField</b> except that it throws a runtime_error
instead of returning null.</p>
<h2>findSubField method removed from PVStructure</h2>
<p>This was mainly used in the implementation of getSubField. With a change to
the latter, findSubField was removed.</p>
<h2>New stream operators</h2>
<p>New steam operators are available for Field and PVField.
Before to print a Field (or any extension) or a PVField (or any extension)
it was necessary to have code like:</p>
<pre><code> void print(StructureConstPtr struc, PVStructurePtr pv)
{
if(struc) {
cout &lt;&lt; *struc &lt;&lt; endl;
} else {
cout &lt;&lt; "nullptr\n"
}
if(pv) {
cout &lt;&lt; *.struc &lt;&lt; endl;
} else {
cout &lt;&lt; "nullptr\n"
}
}
</code></pre>
<p>Now it can be done as follows:</p>
<pre><code> void print(StructureConstPtr struc, PVStructurePtr pv)
{
cout &lt;&lt; struc &lt;&lt; endl;
cout &lt;&lt; pv &lt;&lt; endl;
}
</code></pre>
<h2>New template version of Structure::getField</h2>
<p>A new template getField method has been added to Structure</p>
<p>template<typename FT >
std::tr1::shared_ptr&lt; const FT > getField(std::string const &amp;fieldName) const </p>
<p>Can be used, for example, as follows:</p>
<pre><code>StructurePtr tsStruc = struc-&gt;getField&lt;Structure&gt;("timeStamp");
</code></pre>
<h2>Fixes for static initialisation order issues</h2>
<p>Certain static builds (in particular Windows builds) of applications using
pvData had issues due to PVStructure::DEFAULT_ID being used before being initialised. This has been fixed.</p>
<h2>CreateRequest change</h2>
<p>createRequest could cause a SEGFAULT if passed a bad argument.
This has been changed so the it returns a null pvStructure
and provides an error.</p>
<h1>Release 4.0</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<em>vector facility.
This allows multiple instances of array data to use the shared raw data.
COW is implemented via shared</em>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 hysteresis 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>variant union</b> The field can have any type.</li>
<li><b>union</b> The field can any of specified set of types.</li>
</ul>
<p>The field type can be dynamically changed.</p>
<h2>copy </h2>
<p>This consists of createRequest and pvCopy.
createRequest was moved from pvAccess to here.
pvCopy is moved from pvDatabaseCPP and now depends
only on pvData, i.e. it no longer has any knowledge of PVRecord.</p>
<h2>monitorPlugin</h2>
<p>This is for is for use by code that implements pvAccess monitors.
This is prototype and is subject to debate.</p>
<h1>Release 3.0.2</h1>
<p>This was the starting point for RELEASE_NOTES</p>

View File

@@ -1,9 +1,155 @@
Release release/3.1 IN DEVELOPMENT
Release 5.0
===========
The main changes since release 4.0 are:
* Deprecated getXXXField() methods have been removed from PVStructure
* Convert copy methods and equals operators (re)moved
* Convert::copyUnion now always copies between subfields.
* New method getSubFieldT, like getSubField except it throws an exception
* findSubField method removed from PVStructure
* New stream operators for Field and PVField are provided
* New template versions of Structure::getField
* Fixes for static initialisation order issues
* CreateRequest prevents a possible SEGFAULT
Deprecated getXXXField methods have been removed from PVStructure
-------------------------------------------------------------------
The following methods have been removed from PVStructure
* getBooleanField
* getByteField, getShortField, getIntField, getLongField
* getUByteField, getUShortField, getUIntField, getULongField
* getStringField
* getStructureField, getUnionField
* getScalarArrayField, getStructureArrayField, getUnionArrayField
Use template getSubField instead, e.g. use
getSubField< PVInt >(fieldName)
in place of
getIntField(fieldName)
Convert copy methods and equals operators
-----------------------------------------
Convert copy methods where moved and replaced with methods
on PVField classes, i.e.
PVField::copy(const PVField& from)
Methods
PVField::copyUnchecked(const PVField& from)
were added to allow unchecked copies, to gain performance
where checked are not needed (anymore).
In addition:
- isCompatibleXXX methods were removed in favour of Field::operator==.
- equals methods were remove in favour of PVField::operator==.
- operator== methods where moved to pvIntrospect.h and pvData.h
Convert::copyUnion
-----------------
Before this method, depending on types for to and from,
sometimes did a shallow copy, i.e. just made to shared_ptr for to
share the same data as from.
Now it always copies between the subfield of to and from.
New method getSubFieldT, like getSubField except it throws an exception
--------------------
PVStructure has a new template member
getSubFieldT(std::string const &fieldName)
that is like <b>getSubField</b> except that it throws a runtime_error
instead of returning null.
findSubField method removed from PVStructure
--------------------------------------------
This was mainly used in the implementation of getSubField. With a change to
the latter, findSubField was removed.
New stream operators
--------------------
New steam operators are available for Field and PVField.
Before to print a Field (or any extension) or a PVField (or any extension)
it was necessary to have code like:
void print(StructureConstPtr struc, PVStructurePtr pv)
{
if(struc) {
cout << *struc << endl;
} else {
cout << "nullptr\n"
}
if(pv) {
cout << *.struc << endl;
} else {
cout << "nullptr\n"
}
}
Now it can be done as follows:
void print(StructureConstPtr struc, PVStructurePtr pv)
{
cout << struc << endl;
cout << pv << endl;
}
New template version of Structure::getField
--------------------------------------------
A new template getField method has been added to Structure
template<typename FT >
std::tr1::shared_ptr< const FT > getField(std::string const &fieldName) const
Can be used, for example, as follows:
StructurePtr tsStruc = struc->getField<Structure>("timeStamp");
Fixes for static initialisation order issues
--------------------------------------------
Certain static builds (in particular Windows builds) of applications using
pvData had issues due to PVStructure::DEFAULT_ID being used before being initialised. This has been fixed.
CreateRequest change
--------------------
createRequest could cause a SEGFAULT if passed a bad argument.
This has been changed so the it returns a null pvStructure
and provides an error.
Release 4.0
===========
The main changes since release 3.0.2 are:
* array semantics now enforce Copy On Write.
* String no longer defined.
* timeStamp and valueAlarm name changes
* toString replaced by stream I/O
* union is new type.
* copy is new.
* monitorPlugin is new.
@@ -16,6 +162,44 @@ In order to limit memory usage the storage for raw data is managed via a new sha
This allows multiple instances of array data to use the shared raw data.
COW is implemented via shared_vectors of const data, i. e. data that can not be modified.
String no longer defined
---------
This is replaced by std::string.
timeStamp and valueAlarm name changes
--------------
In timeStamp nanoSeconds is changed to nanoseconds.
In valueAlarm hysteresis 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.
------------
@@ -24,7 +208,7 @@ 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>variant 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.
@@ -35,12 +219,13 @@ 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.
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
==========

View File

@@ -1,54 +1,20 @@
TODO
===========
toString, dumpValue, printer, and streams
------------
The way to print introspection and data instances is not consistent.
This needs work.
Some items that need work are:
* Introspection has no support for streams. Only for toString.
* data has problems. toString is implemented by calling Convert::getString.
It look like this was intended to use printer but that did nor properly indent fields of structures.
The current implementation is:
void Convert::getString(StringBuilder buf,PVField const *pvField,int /*indentLevel*/)
{
// TODO indextLevel ignored
std::ostringstream strm;
strm << pvField->dumpValue(strm) << std::endl;
// PrinterPlain p;
// p.setStream(strm);
// p.print(*pvField);
strm.str().swap(*buf);
}
Thus it just uses dumpValue.
What should it do?
If printer is used it must do proper indentation.
doxygen
-------
There is a lot of public code that does not have doxygen tags.
valueAlarm
---------
normativeTypes.html describes valueAlarm only for a value field that has type
double.
The implementation also supports all the numeric scalar types.
monitorPlugin
-------------
A debate is on-going about what semantics should be.
PVFieldConstPtr etc
-------------------
In pvDataCPP.html look at the monoitorPlugin example.
It has a discussion of a possible need for shared pointers that can not be used to modify data.
This in addition to PVFieldPtr should PVFieldConstPtr exist.
But this means that all methods defined in pvDataCPP must be checked.
This is a BIG job.
Release 3.0.2
==========
This was the starting point for RELEASE_NOTES

View File

@@ -52,7 +52,7 @@ provides a language independent overview of <b>copy</b> and <b>monitor</b>.
</p>
<p>
<b>NOTE:pvRequest.html</b> must be updated since it is based on an earlier version of pvCopy that
had knowlege of PVRecord. The C++ version was implemented in pvDatabaseCPP
had knowledge of PVRecord. The C++ version was implemented in pvDatabaseCPP
and the Java version on pvIOCJava.
At present only the C++ version of the new API for pvCopy is implemented.
</p>
@@ -65,13 +65,13 @@ At present only the C++ version of the new API for pvCopy is implemented.
Given an ascii string createRequest creates a PVStructure that provides
a pvData representation of the information from the ascii string.
It is this structure that can be passed to the channel create methods.<br />
The information in a pvRequest selects an arbitrarary subset of the
The information in a pvRequest selects an arbitrary subset of the
fields in a top level structure that resides in the server.
In addition options can be specified. Both global and field specific
options can be specified.
</dd>
<dt>pvCopy</dt>
<dd>This is a faculity used by channel providers.
<dd>This is a facility used by channel providers.
It provides client specific code that manages a copy of an arbitrary
subset of the fields in a top level structure that resides in the
provider. It also allows provider access to options specified
@@ -185,7 +185,7 @@ where
This is the method for creating a PVCopy instance.<br/>
<dl>
<dt>pvMaster</dt>
<dd>the top level sructure managed by the server.</dd>
<dd>the top level structure managed by the server.</dd>
<dt>pvRequest</dt>
<dd>selects the set of subfields desired
and options for each field.</dd>
@@ -241,12 +241,12 @@ where
<dt>updateCopyFromBitSet</dt>
<dd>
For each set bit in bitSet set the field in copyPVStructure to the value
of the corrseponding field in pvMaster.
of the corresponding field in pvMaster.
</dd>
<dt>updateMaster</dt>
<dd>
For each set bit in bitSet set the field in pvMaster to the value
of the corrseponding field in copyPVStructure.
of the corresponding field in copyPVStructure.
</dd>
<dt>getOptions</dt>
@@ -266,7 +266,7 @@ where
<p>This consists of two components:
<dl>
<dt>monitor</dt>
<dd>Used by code that implements pvAccess montors.</dd>
<dd>Used by code that implements pvAccess monitors.</dd>
<dt>monitorPlugin</dt>
<dd>Code that provides special semantics for monitors.</dd>
</dl>
@@ -346,7 +346,7 @@ Note that each client has it's own queue that is not shared with other client.
<dt>start</dt>
<dd>
Start monitoring.
This will result in a an inital monitor that has the current value
This will result in a an initial monitor that has the current value
of all fields.
</dd>
<dt>stop</dt>
@@ -356,11 +356,11 @@ Note that each client has it's own queue that is not shared with other client.
<dt>poll</dt>
<dd>
Called to get a monitor element.
If no new elemants are available then a null pointer is returned.
If no new elements are available then a null pointer is returned.
</dd>
<dt>release</dt>
<dd>
Release the monotor element.
Release the monitor element.
The caller owns the monitor element between the calls to poll and release.
</dd>
<dl>
@@ -488,7 +488,7 @@ It has methods:</p>
<dd>
MonitorPluginManager is a singleton.
The first call to get will create the single instance.
Further calls will rerurn the single instance.
Further calls will return the single instance.
</dd>
<dt>addPlugin</dt>
<dd>
@@ -496,18 +496,18 @@ It has methods:</p>
</dd>
<dt>findPlugin</dt>
<dd>
Find a plugin. A NULL shared pointer is reurned if it has not been added.
Find a plugin. A NULL shared pointer is returned if it has not been added.
</dd>
<dt>showNames</dt>
<dd>
Show the names of all puugins that have been added.
Show the names of all plugins that have been added.
</dd>
</dl>
<p><b>NOTE:</b>
Should the method <b>causeMonitor</b>
have arguments <b>pvField</b> and <b>pvTop</b>
be defined so that they can not be modfied.
This would be posssible if the following was defined:
be defined so that they can not be modified.
This would be possible if the following was defined:
<pre>
typedef std::tr1::shared_ptr&lt;const PVField&gt; PVFieldConstPtr;
typedef std::tr1::shared_ptr&lt;const PVStructure&gt; PVStructureConstPtr;
@@ -519,7 +519,7 @@ virtual bool causeMonitor(
PVStructureConstPtr const &amp;pvTop,
MonitorElementPtr const &amp;monitorElement) = 0;
</pre>
But just adding these definitions is not sufficent.
But just adding these definitions is not sufficient.
In addition all methods defined in pvDataCPP must be checked.
In particular many of the methods in <b>Convert</b> must have
their arguments modified.
@@ -545,15 +545,15 @@ structure powerSupply
structure power
double value
structure alarm
struvture display
structure display
structure voltage
double value
structure alarm
struvture display
structure display
structure current
double value
structure alarm
struvture display
structure display
</pre>
<p>A pvAccess client wants to create a monitor on the powerSupply as follows:
The client wants a top level structure that looks like:
@@ -578,7 +578,7 @@ client wants. It can be attached to any field via the following options:
[plugin=onChange,raiseMonitor=value]
</pre>
This plugin will trigger a monitor for the field only if the field changes
value. In addition <b>value</b> equals <b>false</b> means do not raise a monotor
value. In addition <b>value</b> equals <b>false</b> means do not raise a monitor
for changes to this field.
But if a change to another field does cause a monitor the change to this field
will be passed to the client.

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -4,10 +4,19 @@
# Jenkins invokes scripts with the "-ex" option. So the build is considered a failure
# if any of the commands exits with a non-zero exit code.
#
# Author: Ralph Lange <Ralph.Lange@gmx.de>
# Author: Ralph Lange <ralph.lange@gmx.de>
# Copyright (C) 2013 Helmholtz-Zentrum Berlin für Materialien und Energie GmbH
# Copyright (C) 2014-2015 ITER Organization.
# All rights reserved. Use is subject to license terms.
###########################################
# Determine EPICS Base version
DEFAULT_BASE=3.14.12.5
BASE=${1:-${DEFAULT_BASE}}
USE_MB=${2:-"MB_NO"}
###########################################
# Fetch and unpack dependencies
@@ -17,10 +26,8 @@ rm -fr ${STUFF}
mkdir -p ${STUFF}
cd ${STUFF}
wget -nv https://openepics.ci.cloudbees.com/job/Base-3.14.12.3_Build/lastSuccessfulBuild/artifact/baseR3.14.12.3.CB-dist.tar.gz
wget -nv https://openepics.ci.cloudbees.com/job/Doxygen-1.8.3_Build/lastSuccessfulBuild/artifact/doxygen-1.8.3.CB-dist.tar.gz
tar -xzf baseR3.14.12.3.CB-dist.tar.gz
tar -xzf doxygen-1.8.3.CB-dist.tar.gz
wget -nv https://openepics.ci.cloudbees.com/job/Base-${BASE}_Build/lastSuccessfulBuild/artifact/base-${BASE}.CB-dist.tar.gz
tar -xzf base-${BASE}.CB-dist.tar.gz
###########################################
# Build
@@ -37,20 +44,13 @@ EPICS_BASE=${EPICS_BASE}
EOF
make distclean all
doxygen
###########################################
# Test
# EPICS Test Harness tests
make runtests
###########################################
# Create distribution
tar czf pvData.CB-dist.tar.gz lib include COPYRIGHT LICENSE
###########################################
# Publish documentation
rsync -aP --delete -e ssh documentation epics-jenkins@web.sourceforge.net:/home/project-web/epics-pvdata/htdocs/docbuild/pvDataCPP/tip

51
jenkins/cloudbees_doc Normal file
View File

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

View File

@@ -1,20 +0,0 @@
# pvData C++ implementation
# Jenkins @ Cloudbees hgweb sync script
#
# Jenkins invokes scripts with the "-ex" option. So the build is considered a failure
# if any of the commands exits with a non-zero exit code.
#
# Author: Ralph Lange <Ralph.Lange@gmx.de>
# Copyright (C) 2013 Helmholtz-Zentrum Berlin für Materialien und Energie GmbH
# All rights reserved. Use is subject to license terms.
###########################################
# Fetch complete repo
rm -fr hgweb
hg clone -U http://hg.code.sf.net/p/epics-pvdata/pvDataCPP hgweb
###########################################
# Sync into SF webspace
rsync -aqP --delete --exclude=\.hg/hgrc -e ssh hgweb/.hg epics-jenkins@web.sourceforge.net:/home/project-web/epics-pvdata/repos/pvDataCPP

View File

@@ -1 +0,0 @@
// ADD PREDEFINED MACROS HERE!

View File

@@ -1 +0,0 @@
[General]

View File

@@ -1,211 +0,0 @@
configure/CONFIG
configure/CONFIG_SITE
configure/RELEASE
configure/RELEASE.local
configure/RULES
configure/RULES.ioc
configure/RULES_DIRS
configure/RULES_TOP
documentation/pvDataCPP.html
documentation/pvDataCPP_20120927.html
documentation/pvDataCPP_20121001.html
documentation/pvDataCPP_20121026.html
documentation/pvDataCPP_20121212.html
jenkins/cloudbees_build
pvDataApp/factory/Compare.cpp
pvDataApp/factory/Convert.cpp
pvDataApp/factory/factory.h
pvDataApp/factory/FieldCreateFactory.cpp
pvDataApp/factory/PVArray.cpp
pvDataApp/factory/PVAuxInfoImpl.cpp
pvDataApp/factory/PVDataCreateFactory.cpp
pvDataApp/factory/PVDataCreateFactory.cpp.orig
pvDataApp/factory/PVField.cpp
pvDataApp/factory/PVScalar.cpp
pvDataApp/factory/PVScalarArray.cpp
pvDataApp/factory/PVStructure.cpp
pvDataApp/factory/PVStructureArray.cpp
pvDataApp/factory/StandardField.cpp
pvDataApp/factory/StandardPVField.cpp
pvDataApp/factory/TypeFunc.cpp
pvDataApp/misc/bitSet.cpp
pvDataApp/misc/bitSet.h
pvDataApp/misc/byteBuffer.cpp
pvDataApp/misc/byteBuffer.h
pvDataApp/misc/destroyable.h
pvDataApp/misc/epicsException.cpp
pvDataApp/misc/epicsException.h
pvDataApp/misc/event.cpp
pvDataApp/misc/event.h
pvDataApp/misc/executor.cpp
pvDataApp/misc/executor.h
pvDataApp/misc/localStaticLock.cpp
pvDataApp/misc/localStaticLock.h
pvDataApp/misc/localStaticLock.h.orig
pvDataApp/misc/lock.h
pvDataApp/misc/messageQueue.cpp
pvDataApp/misc/messageQueue.h
pvDataApp/misc/noDefaultMethods.h
pvDataApp/misc/queue.h
pvDataApp/misc/requester.cpp
pvDataApp/misc/requester.h
pvDataApp/misc/requester.h.orig
pvDataApp/misc/serialize.h
pvDataApp/misc/serializeHelper.cpp
pvDataApp/misc/serializeHelper.h
pvDataApp/misc/sharedPtr.h
pvDataApp/misc/status.cpp
pvDataApp/misc/status.h
pvDataApp/misc/thread.h
pvDataApp/misc/timeFunction.cpp
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
pvDataApp/property/control.h
pvDataApp/property/display.h
pvDataApp/property/pvAlarm.cpp
pvDataApp/property/pvAlarm.h
pvDataApp/property/pvControl.cpp
pvDataApp/property/pvControl.h
pvDataApp/property/pvDisplay.cpp
pvDataApp/property/pvDisplay.h
pvDataApp/property/pvEnumerated.cpp
pvDataApp/property/pvEnumerated.h
pvDataApp/property/pvTimeStamp.cpp
pvDataApp/property/pvTimeStamp.h
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
testApp/misc/testByteOrder.cpp
testApp/misc/testMessageQueue.cpp
testApp/misc/testQueue.cpp
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
testApp/pv/testPVAppend.cpp
testApp/pv/testPVAuxInfo.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
COPYRIGHT
Doxyfile
LICENSE
README.html

View File

@@ -1,6 +0,0 @@
/home/msekoranja/epicsV4/pvDataCPP/pvDataApp/factory
/home/msekoranja/epicsV4/pvDataCPP/pvDataApp/misc
/home/msekoranja/epicsV4/pvDataCPP/pvDataApp/monitor
/home/msekoranja/epicsV4/pvDataCPP/pvDataApp/property
/home/msekoranja/epicsV4/pvDataCPP/pvDataApp/pv
/home/msekoranja/epicsV4/pvDataCPP/pvDataApp/pvMisc

View File

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

View File

@@ -18,7 +18,12 @@
namespace epics { namespace pvData {
/**
* Class to create pvRequest structures to pass to pvAccess Channel methods.
* @brief Create pvRequest structure for Channel methods.
*
* Many methods of the Channel class of pvAccess have an
* argument <b>PVStructurePtr const * pvRequest</b>.
* This class provides a method that creates a valid pvRequest.
*
*/
class epicsShareClass CreateRequest {
public:
@@ -33,7 +38,6 @@ class epicsShareClass 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.

View File

@@ -18,7 +18,6 @@
#include <pv/thread.h>
#include <pv/pvCopy.h>
#include <pv/convert.h>
using std::tr1::static_pointer_cast;
using std::tr1::dynamic_pointer_cast;
@@ -29,6 +28,18 @@ using std::endl;
namespace epics { namespace pvData {
/**
* Convenience method for implementing dump.
* It generates a newline and inserts blanks at the beginning of the newline.
* @param builder The std::string * being constructed.
* @param indentLevel Indent level, Each level is four spaces.
*/
static void newLine(string *buffer, int indentLevel)
{
*buffer += "\n";
*buffer += string(indentLevel*4, ' ');
}
static PVCopyPtr NULLPVCopy;
static FieldConstPtr NULLField;
static StructureConstPtr NULLStructure;
@@ -67,11 +78,11 @@ PVCopyPtr PVCopy::create(
PVStructurePtr pvStructure(pvRequest);
if(structureName.size()>0) {
if(pvRequest->getStructure()->getNumberFields()>0) {
pvStructure = pvRequest->getStructureField(structureName);
if(pvStructure.get()==NULL) return NULLPVCopy;
pvStructure = pvRequest->getSubField<PVStructure>(structureName);
if(!pvStructure) return NULLPVCopy;
}
} else if(pvStructure->getSubField("field")!=NULL) {
pvStructure = pvRequest->getStructureField("field");
} else if(pvStructure->getSubField("field")) {
pvStructure = pvRequest->getSubField<PVStructure>("field");
}
PVCopyPtr pvCopy = PVCopyPtr(new PVCopy(pvMaster));
bool result = pvCopy->init(pvStructure);
@@ -118,7 +129,7 @@ StructureConstPtr PVCopy::getStructure()
PVStructurePtr PVCopy::createPVStructure()
{
if(cacheInitStructure.get()!=NULL) {
if(cacheInitStructure) {
PVStructurePtr save = cacheInitStructure;
cacheInitStructure.reset();
return save;
@@ -174,7 +185,7 @@ size_t PVCopy::getCopyOffset(PVFieldPtr const &masterPVField)
}
CopyStructureNodePtr node = static_pointer_cast<CopyStructureNode>(headNode);
CopyMasterNodePtr masterNode = getCopyOffset(node,masterPVField);
if(masterNode.get()!=NULL) return masterNode->structureOffset;
if(masterNode) return masterNode->structureOffset;
return string::npos;
}
@@ -190,7 +201,7 @@ size_t PVCopy::getCopyOffset(
CopyStructureNodePtr node = static_pointer_cast<CopyStructureNode>(headNode);
masterNode = getCopyOffset(node,masterPVField);
}
if(masterNode.get()==NULL) return string::npos;
if(!masterNode) return string::npos;
size_t diff = masterPVField->getFieldOffset()
- masterPVStructure->getFieldOffset();
return masterNode->structureOffset + diff;
@@ -205,7 +216,7 @@ PVFieldPtr PVCopy::getMasterPVField(size_t structureOffset)
CopyStructureNodePtr node = static_pointer_cast<CopyStructureNode>(headNode);
masterNode = getMasterNode(node,structureOffset);
}
if(masterNode.get()==NULL) {
if(!masterNode) {
throw std::invalid_argument(
"PVCopy::getMasterPVField: setstructureOffset not valid");
}
@@ -243,10 +254,9 @@ void PVCopy::updateCopySetBitSet(
updateSubFieldSetBitSet(copyPVField,pvMasterField,bitSet);
return;
}
ConvertPtr convert = getConvert();
bool isEqual = convert->equals(copyPVField,pvField);
bool isEqual = (*copyPVField == *pvField);
if(!isEqual) {
convert->copy(pvField, copyPVField);
copyPVField->copyUnchecked(*pvField);
bitSet->set(copyPVField->getFieldOffset());
}
}
@@ -292,22 +302,22 @@ string PVCopy::dump()
void PVCopy::dump(string *builder,CopyNodePtr const &node,int indentLevel)
{
getConvert()->newLine(builder,indentLevel);
newLine(builder,indentLevel);
std::stringstream ss;
ss << (node->isStructure ? "structureNode" : "masterNode");
ss << " structureOffset " << node->structureOffset;
ss << " nfields " << node->nfields;
*builder += ss.str();
PVStructurePtr options = node->options;
if(options.get()!=NULL) {
getConvert()->newLine(builder,indentLevel +1);
if(options) {
newLine(builder,indentLevel +1);
// TODO !!! ugly
std::ostringstream oss;
oss << *options;
*builder += oss.str();
getConvert()->newLine(builder,indentLevel);
newLine(builder,indentLevel);
}
if(!node->isStructure) {
CopyMasterNodePtr masterNode = static_pointer_cast<CopyMasterNode>(node);
@@ -320,7 +330,7 @@ void PVCopy::dump(string *builder,CopyNodePtr const &node,int indentLevel)
CopyNodePtrArrayPtr nodes = structureNode->nodes;
for(size_t i=0; i<nodes->size(); ++i) {
if((*nodes)[i].get()==NULL) {
getConvert()->newLine(builder,indentLevel +1);
newLine(builder,indentLevel +1);
ss.str("");
ss << "node[" << i << "] is null";
*builder += ss.str();
@@ -338,8 +348,8 @@ bool PVCopy::init(epics::pvData::PVStructurePtr const &pvRequest)
if(len==string::npos) entireMaster = true;
if(len==0) entireMaster = true;
PVStructurePtr pvOptions;
if(len==1 && pvRequest->getSubField("_options")!=NULL) {
pvOptions = pvRequest->getStructureField("_options");
if(len==1 && pvRequest->getSubField("_options")) {
pvOptions = pvRequest->getSubField<PVStructure>("_options");
}
if(entireMaster) {
structure = pvMasterStructure->getStructure();
@@ -353,7 +363,7 @@ bool PVCopy::init(epics::pvData::PVStructurePtr const &pvRequest)
return true;
}
structure = createStructure(pvMasterStructure,pvRequest);
if(structure==NULL) return false;
if(!structure) return false;
cacheInitStructure = createPVStructure();
headNode = createStructureNodes(
pvMaster,
@@ -387,7 +397,7 @@ StructureConstPtr PVCopy::createStructure(
for(size_t i=0; i<length; ++i) {
string const &fieldName = fromRequestFieldNames[i];
PVFieldPtr pvMasterField = pvMaster->getSubField(fieldName);
if(pvMasterField==NULL) continue;
if(!pvMasterField) continue;
FieldConstPtr field = pvMasterField->getField();
if(field->getType()==epics::pvData::structure) {
PVStructurePtr pvRequestStructure = static_pointer_cast<PVStructure>(
@@ -423,7 +433,7 @@ CopyNodePtr PVCopy::createStructureNodes(
PVFieldPtrArray const & copyPVFields = pvFromCopy->getPVFields();
PVStructurePtr pvOptions;
PVFieldPtr pvField = pvFromRequest->getSubField("_options");
if(pvField!=NULL) pvOptions = static_pointer_cast<PVStructure>(pvField);
if(pvField) pvOptions = static_pointer_cast<PVStructure>(pvField);
size_t number = copyPVFields.size();
CopyNodePtrArrayPtr nodes(new CopyNodePtrArray());
nodes->reserve(number);
@@ -435,7 +445,7 @@ CopyNodePtr PVCopy::createStructureNodes(
pvFromRequest->getSubField(fieldName));
PVStructurePtr pvSubFieldOptions;
PVFieldPtr pvField = requestPVStructure->getSubField("_options");
if(pvField!=NULL) pvSubFieldOptions = static_pointer_cast<PVStructure>(pvField);
if(pvField) pvSubFieldOptions = static_pointer_cast<PVStructure>(pvField);
PVFieldPtr pvMasterField;
PVFieldPtrArray const & pvMasterFields = pvMasterStructure->getPVFields();
for(size_t j=0; i<pvMasterFields.size(); j++ ) {
@@ -445,7 +455,7 @@ CopyNodePtr PVCopy::createStructureNodes(
}
}
size_t numberRequest = requestPVStructure->getPVFields().size();
if(pvSubFieldOptions!=NULL) numberRequest--;
if(pvSubFieldOptions) numberRequest--;
if(numberRequest>0) {
nodes->push_back(createStructureNodes(
static_pointer_cast<PVStructure>(pvMasterField),
@@ -499,17 +509,16 @@ void PVCopy::updateSubFieldSetBitSet(
FieldConstPtr field = pvCopy->getField();
Type type = field->getType();
if(type!=epics::pvData::structure) {
ConvertPtr convert = getConvert();
bool isEqual = convert->equals(pvCopy,pvMaster);
bool isEqual = (*pvCopy == *pvMaster);
if(isEqual) {
if(type==structureArray) {
// always act as though a change occurred.
// Note that array elements are shared.
bitSet->set(pvCopy->getFieldOffset());
bitSet->set(pvCopy->getFieldOffset());
}
}
if(isEqual) return;
convert->copy(pvMaster, pvCopy);
pvCopy->copyUnchecked(*pvMaster);
bitSet->set(pvCopy->getFieldOffset());
return;
}
@@ -574,7 +583,6 @@ void PVCopy::updateSubFieldFromBitSet(
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);
@@ -595,9 +603,9 @@ void PVCopy::updateSubFieldFromBitSet(
}
} else {
if(toCopy) {
convert->copy(pvMasterField, pvCopy);
pvCopy->copyUnchecked(*pvMasterField);
} else {
convert->copy(pvCopy, pvMasterField);
pvMasterField->copyUnchecked(*pvCopy);
}
}
}
@@ -621,7 +629,7 @@ CopyMasterNodePtr PVCopy::getCopyOffset(
static_pointer_cast<CopyStructureNode>(node);
CopyMasterNodePtr masterNode =
getCopyOffset(subNode,masterPVField);
if(masterNode.get()!=NULL) return masterNode;
if(masterNode) return masterNode;
}
}
return NULLCopyMasterNode;

View File

@@ -25,7 +25,8 @@ class PVCopyTraverseMasterCallback;
typedef std::tr1::shared_ptr<PVCopyTraverseMasterCallback> PVCopyTraverseMasterCallbackPtr;
/**
* Callback for traversing master structure
* @brief Callback for traversing master structure
*
* Must be implemented by code that creates pvCopy.
*/
class epicsShareClass PVCopyTraverseMasterCallback
@@ -53,6 +54,8 @@ typedef std::tr1::shared_ptr<CopyStructureNode> CopyStructureNodePtr;
/**
* @brief Support for subset of fields in a pvStructure.
*
* Class that manages one or more PVStructures that holds an arbitrary subset of the fields
* in another PVStructure called master.
*/
@@ -63,8 +66,8 @@ 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 pvMaster The top-level structure for which a copy of
* an arbitrary 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.
*/
@@ -75,8 +78,8 @@ public:
virtual ~PVCopy(){}
virtual void destroy();
/**
* Get the top level structure of master
* @returns The master top level structure.
* Get the top-level structure of master
* @returns The master top-level structure.
* This should not be modified.
*/
PVStructurePtr getPVMaster();
@@ -94,7 +97,7 @@ public:
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.
* Since each element needs a PVStructure, multiple top-level structures will be created.
*/
PVStructurePtr createPVStructure();
/**
@@ -113,15 +116,15 @@ public:
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.
* Given an offset in the copy get the corresponding field in pvMaster.
* @param structureOffset 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 copyPVStructure A copy top-level structure.
* @param bitSet A bitSet for copyPVStructure.
*/
void initCopy(
@@ -130,7 +133,7 @@ public:
/**
* 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 copyPVStructure A copy top-level structure.
* @param bitSet A bitSet for copyPVStructure.
*/
void updateCopySetBitSet(
@@ -138,8 +141,8 @@ public:
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.
* set the field in copyPVStructure to the value of the corresponding field in pvMaster.
* @param copyPVStructure A copy top-level structure.
* @param bitSet A bitSet for copyPVStructure.
*/
void updateCopyFromBitSet(
@@ -147,8 +150,8 @@ public:
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.
* set the field in pvMaster to the value of the corresponding field in copyPVStructure
* @param copyPVStructure A copy top-level structure.
* @param bitSet A bitSet for copyPVStructure.
*/
void updateMaster(
@@ -156,7 +159,7 @@ public:
BitSetPtr const &bitSet);
/**
* Get the options for the field at the specified offset.
* @param offset the offset in copy.
* @param fieldOffset 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

View File

@@ -12,13 +12,13 @@
#include <sstream>
#define epicsExportSharedSymbols
#include <pv/convert.h>
#include <pv/pvData.h>
using std::string;
namespace epics { namespace pvData {
// Introspection object comparision
// Introspection object comparison
/** Field equality conditions:
* 1) same instance
@@ -62,7 +62,7 @@ bool operator==(const Field& a, const Field& b)
return A==B;
}
default:
throw std::logic_error("Invalid Field type in comparision");
throw std::logic_error("Invalid Field type in comparison");
}
}
@@ -91,14 +91,14 @@ bool operator==(const Structure& a, const Structure& b)
return false;
// std::equals does not work, since FieldConstPtrArray is an array of shared_pointers
FieldConstPtrArray af = a.getFields();
FieldConstPtrArray bf = b.getFields();
FieldConstPtrArray const & af = a.getFields();
FieldConstPtrArray const & bf = b.getFields();
for (size_t i = 0; i < nflds; i++)
if (*(af[i].get()) != *(bf[i].get()))
return false;
StringArray an = a.getFieldNames();
StringArray bn = b.getFieldNames();
StringArray const & an = a.getFieldNames();
StringArray const & bn = b.getFieldNames();
return std::equal( an.begin(), an.end(), bn.begin() );
}
@@ -118,14 +118,14 @@ bool operator==(const Union& a, const Union& b)
return false;
// std::equals does not work, since FieldConstPtrArray is an array of shared_pointers
FieldConstPtrArray af = a.getFields();
FieldConstPtrArray bf = b.getFields();
FieldConstPtrArray const & af = a.getFields();
FieldConstPtrArray const & bf = b.getFields();
for (size_t i = 0; i < nflds; i++)
if (*(af[i].get()) != *(bf[i].get()))
return false;
StringArray an = a.getFieldNames();
StringArray bn = b.getFieldNames();
StringArray const & an = a.getFieldNames();
StringArray const & bn = b.getFieldNames();
return std::equal( an.begin(), an.end(), bn.begin() );
}
@@ -134,6 +134,13 @@ bool operator==(const UnionArray& a, const UnionArray& b)
return *(a.getUnion().get())==*(b.getUnion().get());
}
bool operator==(const BoundedString& a, const BoundedString& b)
{
if(&a==&b)
return true;
return a.getMaximumLength()==b.getMaximumLength();
}
// PVXXX object comparison
namespace {
@@ -244,7 +251,13 @@ bool compareField(const PVStructureArray* left, const PVStructureArray* right)
lit!=lend;
++lit, ++rit)
{
if(**lit != **rit)
// element can be null
if (!(*lit) || !(*rit))
{
if (*lit || *rit)
return false;
}
else if (**lit != **rit)
return false;
}
return true;
@@ -297,7 +310,13 @@ bool compareField(const PVUnionArray* left, const PVUnionArray* right)
lit!=lend;
++lit, ++rit)
{
if(**lit != **rit)
// element can be null
if (!(*lit) || !(*rit))
{
if (*lit || *rit)
return false;
}
else if (**lit != **rit)
return false;
}
return true;

View File

@@ -18,7 +18,6 @@
#include <pv/pvIntrospect.h>
#include <pv/pvData.h>
#include <pv/convert.h>
#include <pv/printer.h>
using std::tr1::static_pointer_cast;
using std::size_t;
@@ -51,10 +50,8 @@ void Convert::getString(string *buf,PVField const *pvField,int /*indentLevel*/)
{
// TODO indextLevel ignored
std::ostringstream strm;
strm << pvField->dumpValue(strm) << std::endl;
// PrinterPlain p;
// p.setStream(strm);
// p.print(*pvField);
pvField->dumpValue(strm);
strm << std::endl;
strm.str().swap(*buf);
}
@@ -152,374 +149,6 @@ size_t Convert::toStringArray(PVScalarArrayPtr const & pv,
return data.size();
}
bool Convert::isCopyCompatible(FieldConstPtr const &from, FieldConstPtr const &to)
{
if(from->getType()!=to->getType()) return false;
switch(from->getType()) {
case scalar:
{
ScalarConstPtr xxx = static_pointer_cast<const Scalar>(from);
ScalarConstPtr yyy = static_pointer_cast<const Scalar>(to);
return isCopyScalarCompatible(xxx,yyy);
}
case scalarArray:
{
ScalarArrayConstPtr xxx = static_pointer_cast<const ScalarArray>(from);
ScalarArrayConstPtr yyy = static_pointer_cast<const ScalarArray>(to);
return isCopyScalarArrayCompatible(xxx,yyy);
}
case structure:
{
StructureConstPtr xxx = static_pointer_cast<const Structure>(from);
StructureConstPtr yyy = static_pointer_cast<const Structure>(to);
return isCopyStructureCompatible(xxx,yyy);
}
case structureArray:
{
StructureArrayConstPtr xxx = static_pointer_cast<const StructureArray>(from);
StructureArrayConstPtr yyy = static_pointer_cast<const StructureArray>(to);
return isCopyStructureArrayCompatible(xxx,yyy);
}
case union_:
{
UnionConstPtr xxx = static_pointer_cast<const Union>(from);
UnionConstPtr yyy = static_pointer_cast<const Union>(to);
return isCopyUnionCompatible(xxx,yyy);
}
case unionArray:
{
UnionArrayConstPtr xxx = static_pointer_cast<const UnionArray>(from);
UnionArrayConstPtr yyy = static_pointer_cast<const UnionArray>(to);
return isCopyUnionArrayCompatible(xxx,yyy);
}
}
string message("Convert::isCopyCompatible should never get here");
throw std::logic_error(message);
}
void Convert::copy(PVFieldPtr const & from, PVFieldPtr const & to)
{
switch(from->getField()->getType()) {
case scalar:
{
PVScalarPtr xxx = static_pointer_cast<PVScalar>(from);
PVScalarPtr yyy = static_pointer_cast<PVScalar>(to);
copyScalar(xxx,yyy);
return;
}
case scalarArray:
{
PVScalarArrayPtr fromArray = static_pointer_cast<PVScalarArray>(from);
PVScalarArrayPtr toArray = static_pointer_cast<PVScalarArray>(to);
toArray->assign(*fromArray.get());
return;
}
case structure:
{
PVStructurePtr xxx = static_pointer_cast<PVStructure>(from);
PVStructurePtr yyy = static_pointer_cast<PVStructure>(to);
copyStructure(xxx,yyy);
return;
}
case structureArray: {
PVStructureArrayPtr fromArray = static_pointer_cast<PVStructureArray>(from);
PVStructureArrayPtr toArray = static_pointer_cast<PVStructureArray>(to);
copyStructureArray(fromArray,toArray);
return;
}
case union_:
{
PVUnionPtr xxx = static_pointer_cast<PVUnion>(from);
PVUnionPtr yyy = static_pointer_cast<PVUnion>(to);
copyUnion(xxx,yyy);
return;
}
case unionArray: {
PVUnionArrayPtr fromArray = static_pointer_cast<PVUnionArray>(from);
PVUnionArrayPtr toArray = static_pointer_cast<PVUnionArray>(to);
copyUnionArray(fromArray,toArray);
return;
}
}
}
bool Convert::isCopyScalarCompatible(
ScalarConstPtr const & fromField, ScalarConstPtr const & toField)
{
ScalarType fromScalarType = fromField->getScalarType();
ScalarType toScalarType = toField->getScalarType();
if(fromScalarType==toScalarType) return true;
if(ScalarTypeFunc::isNumeric(fromScalarType)
&& ScalarTypeFunc::isNumeric(toScalarType)) return true;
if(fromScalarType==pvString) return true;
if(toScalarType==pvString) return true;
return false;
}
void Convert::copyScalar(PVScalarPtr const & from, PVScalarPtr const & to)
{
if(to->isImmutable()) {
if(from==to) return;
string message("Convert.copyScalar destination is immutable");
throw std::invalid_argument(message);
}
to->assign(*from.get());
}
bool Convert::isCopyScalarArrayCompatible(ScalarArrayConstPtr const &fromArray,
ScalarArrayConstPtr const &toArray)
{
ScalarType fromType = fromArray->getElementType();
ScalarType toType = toArray->getElementType();
if(fromType==toType) return true;
if(ScalarTypeFunc::isNumeric(fromType)
&& ScalarTypeFunc::isNumeric(toType)) return true;
if(toType==pvString) return true;
if(fromType==pvString) return true;
return false;
}
bool Convert::isCopyStructureCompatible(
StructureConstPtr const &fromStruct, StructureConstPtr const &toStruct)
{
FieldConstPtrArray fromFields = fromStruct->getFields();
FieldConstPtrArray toFields = toStruct->getFields();
size_t length = fromStruct->getNumberFields();
if(length!=toStruct->getNumberFields()) return false;
for(size_t i=0; i<length; i++) {
FieldConstPtr from = fromFields[i];
FieldConstPtr to = toFields[i];
Type fromType = from->getType();
Type toType = to->getType();
if(fromType!=toType) return false;
switch(fromType) {
case scalar:
{
ScalarConstPtr xxx = static_pointer_cast<const Scalar>(from);
ScalarConstPtr yyy = static_pointer_cast<const Scalar>(to);
if(!isCopyScalarCompatible(xxx,yyy)) return false;
}
break;
case scalarArray:
{
ScalarArrayConstPtr xxx = static_pointer_cast<const ScalarArray>(from);
ScalarArrayConstPtr yyy = static_pointer_cast<const ScalarArray>(to);
if(!isCopyScalarArrayCompatible(xxx,yyy)) return false;
}
break;
case structure:
{
StructureConstPtr xxx = static_pointer_cast<const Structure>(from);
StructureConstPtr yyy = static_pointer_cast<const Structure>(to);
if(!isCopyStructureCompatible(xxx,yyy)) return false;
}
break;
case structureArray:
{
StructureArrayConstPtr xxx = static_pointer_cast<const StructureArray>(from);
StructureArrayConstPtr yyy = static_pointer_cast<const StructureArray>(to);
if(!isCopyStructureArrayCompatible(xxx,yyy)) return false;
}
case union_:
{
UnionConstPtr xxx = static_pointer_cast<const Union>(from);
UnionConstPtr yyy = static_pointer_cast<const Union>(to);
if(!isCopyUnionCompatible(xxx,yyy)) return false;
}
break;
case unionArray:
{
UnionArrayConstPtr xxx = static_pointer_cast<const UnionArray>(from);
UnionArrayConstPtr yyy = static_pointer_cast<const UnionArray>(to);
if(!isCopyUnionArrayCompatible(xxx,yyy)) return false;
}
break;
}
}
return true;
}
void Convert::copyStructure(PVStructurePtr const & from, PVStructurePtr const & to)
{
if(to->isImmutable()) {
if(from==to) return;
throw std::invalid_argument("Convert.copyStructure destination is immutable");
}
if(from==to) return;
PVFieldPtrArray const & fromDatas = from->getPVFields();
PVFieldPtrArray const & toDatas = to->getPVFields();
if(from->getStructure()->getNumberFields()
!= to->getStructure()->getNumberFields()) {
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();
// look for enumerated structure and copy choices first
if(name0.compare("index")==0 && name1.compare("choices")==0) {
FieldConstPtr fieldIndex = fromDatas[0]->getField();
FieldConstPtr fieldChoices = fromDatas[1]->getField();
if(fieldIndex->getType()==scalar
&& fieldChoices->getType()==scalarArray) {
PVScalarPtr pvScalar = static_pointer_cast<PVScalar>(fromDatas[0]);
PVScalarArrayPtr pvArray =
static_pointer_cast<PVScalarArray>(fromDatas[1]);
if((pvScalar->getScalar()->getScalarType()==pvInt)
&& (pvArray->getScalarArray()->getElementType()==pvString)) {
PVScalarArrayPtr toArray =
static_pointer_cast<PVScalarArray>(toDatas[1]);
toArray->assign(*pvArray.get());
PVScalarPtr toScalar = static_pointer_cast<PVScalar>(toDatas[0]);
copyScalar(pvScalar,toScalar);
return;
}
}
}
}
for(size_t i=0; i < numberFields; i++) {
PVFieldPtr fromData = fromDatas[i];
PVFieldPtr toData = toDatas[i];
Type fromType = fromData->getField()->getType();
Type toType = toData->getField()->getType();
if(fromType!=toType) {
string message("Convert.copyStructure Illegal copyStructure");
throw std::invalid_argument(message);
}
if(toData->isImmutable()) {
if(fromData==toData) return;
throw std::invalid_argument("Convert.copyStructure destination is immutable");
}
switch(fromType) {
case scalar:
{
PVScalarPtr xxx = static_pointer_cast<PVScalar>(fromData);
PVScalarPtr yyy = static_pointer_cast<PVScalar>(toData);
copyScalar(xxx,yyy);
break;
}
case scalarArray:
{
PVScalarArrayPtr fromArray = static_pointer_cast<PVScalarArray>(fromData);
PVScalarArrayPtr toArray = static_pointer_cast<PVScalarArray>(toData);
toArray->assign(*fromArray.get());
break;
}
case structure:
{
PVStructurePtr xxx = static_pointer_cast<PVStructure>(fromData);
PVStructurePtr yyy = static_pointer_cast<PVStructure>(toData);
copyStructure(xxx,yyy);
break;
}
case structureArray:
{
PVStructureArrayPtr fromArray =
static_pointer_cast<PVStructureArray>(fromData);
PVStructureArrayPtr toArray =
static_pointer_cast<PVStructureArray>(toData);
copyStructureArray(fromArray,toArray);
break;
}
case union_:
{
PVUnionPtr xxx = static_pointer_cast<PVUnion>(fromData);
PVUnionPtr yyy = static_pointer_cast<PVUnion>(toData);
copyUnion(xxx,yyy);
break;
}
case unionArray:
{
PVUnionArrayPtr fromArray =
static_pointer_cast<PVUnionArray>(fromData);
PVUnionArrayPtr toArray =
static_pointer_cast<PVUnionArray>(toData);
copyUnionArray(fromArray,toArray);
break;
}
}
}
}
bool Convert::isCopyUnionCompatible(
UnionConstPtr const &from, UnionConstPtr const &to)
{
return *(from.get()) == *(to.get());
}
void Convert::copyUnion(PVUnionPtr const & from, PVUnionPtr const & to)
{
if(to->isImmutable()) {
if(from==to) return;
throw std::invalid_argument("Convert.copyUnion destination is immutable");
}
if(from==to) return;
if(!isCopyUnionCompatible(from->getUnion(), to->getUnion())) {
throw std::invalid_argument("Illegal copyUnion");
}
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()
}
else
{
if (fromValue.get() == 0)
to->select(PVUnion::UNDEFINED_INDEX);
else
to->set(from->getSelectedFieldName(),from->get());
}
}
bool Convert::isCopyStructureArrayCompatible(
StructureArrayConstPtr const &from, StructureArrayConstPtr const &to)
{
StructureConstPtr xxx = from->getStructure();
StructureConstPtr yyy = to->getStructure();
return isCopyStructureCompatible(xxx,yyy);
}
void Convert::copyStructureArray(
PVStructureArrayPtr const & from, PVStructureArrayPtr const & to)
{
if(from==to) {
return;
} else if(to->isImmutable()) {
throw std::invalid_argument("Convert.copyStructureArray destination is immutable");
}
to->replace(from->view());
}
bool Convert::isCopyUnionArrayCompatible(
UnionArrayConstPtr const &from, UnionArrayConstPtr const &to)
{
UnionConstPtr xxx = from->getUnion();
UnionConstPtr yyy = to->getUnion();
return isCopyUnionCompatible(xxx,yyy);
}
void Convert::copyUnionArray(
PVUnionArrayPtr const & from, PVUnionArrayPtr const & to)
{
if(from==to) {
return;
} else if(to->isImmutable()) {
throw std::invalid_argument("Convert.copyUnionArray destination is immutable");
}
to->replace(from->view());
}
void Convert::newLine(string *buffer, int indentLevel)
{
*buffer += "\n";
*buffer += string(indentLevel*4, ' ');
}
ConvertPtr Convert::getConvert()
{
static ConvertPtr convert;

View File

@@ -17,11 +17,11 @@
#include <string>
#include <cstdio>
#include <stdexcept>
#include <sstream>
#define epicsExportSharedSymbols
#include <pv/lock.h>
#include <pv/pvIntrospect.h>
#include <pv/convert.h>
#include <pv/factory.h>
#include <pv/serializeHelper.h>
@@ -51,7 +51,7 @@ Scalar::Scalar(ScalarType scalarType)
: Field(scalar),scalarType(scalarType)
{
if(scalarType<0 || scalarType>MAX_SCALAR_TYPE)
throw std::invalid_argument("Can't construct Scalar from invalid ScalarType");
THROW_EXCEPTION2(std::invalid_argument, "Can't construct Scalar from invalid ScalarType");
}
Scalar::~Scalar(){}
@@ -80,7 +80,7 @@ string Scalar::getID() const
return idScalarLUT[scalarType];
}
int8 Scalar::getTypeCodeLUT() const
int8 Scalar::getTypeCodeLUT(ScalarType scalarType)
{
static const int8 typeCodeLUT[] = {
0x00, // pvBoolean
@@ -88,10 +88,10 @@ int8 Scalar::getTypeCodeLUT() const
0x21, // pvShort
0x22, // pvInt
0x23, // pvLong
0x28, // pvUByte
0x29, // pvUShort
0x2A, // pvUInt
0x2B, // pvULong
0x24, // pvUByte
0x25, // pvUShort
0x26, // pvUInt
0x27, // pvULong
0x42, // pvFloat
0x43, // pvDouble
0x60 // pvString
@@ -102,7 +102,7 @@ int8 Scalar::getTypeCodeLUT() const
void Scalar::serialize(ByteBuffer *buffer, SerializableControl *control) const {
control->ensureBuffer(1);
buffer->putByte(getTypeCodeLUT());
buffer->putByte(getTypeCodeLUT(scalarType));
}
void Scalar::deserialize(ByteBuffer* /*buffer*/, DeserializableControl* /*control*/) {
@@ -110,6 +110,38 @@ void Scalar::deserialize(ByteBuffer* /*buffer*/, DeserializableControl* /*contro
throw std::runtime_error("not valid operation, use FieldCreate::deserialize instead");
}
std::string BoundedString::getID() const
{
std::ostringstream id;
id << Scalar::getID() << '(' << maxLength << ')';
return id.str();
}
void BoundedString::serialize(ByteBuffer *buffer, SerializableControl *control) const
{
control->ensureBuffer(1);
buffer->putByte(0x83);
SerializeHelper::writeSize(maxLength, buffer, control);
}
std::size_t BoundedString::getMaximumLength() const
{
return maxLength;
}
BoundedString::BoundedString(std::size_t maxStringLength) :
Scalar(pvString), maxLength(maxStringLength)
{
if (maxLength == 0)
THROW_EXCEPTION2(std::invalid_argument, "maxLength == 0");
}
BoundedString::~BoundedString() {}
static string emptyStringtring;
static void serializeStructureField(const Structure* structure, ByteBuffer* buffer, SerializableControl* control)
@@ -198,7 +230,8 @@ Array::Array(Type type)
Array::~Array() {}
ScalarArray::ScalarArray(ScalarType elementType)
: Array(scalarArray),elementType(elementType)
: Array(scalarArray),
elementType(elementType)
{
if(elementType<0 || elementType>MAX_SCALAR_TYPE)
throw std::invalid_argument("Can't construct ScalarArray from invalid ScalarType");
@@ -206,31 +239,12 @@ ScalarArray::ScalarArray(ScalarType elementType)
ScalarArray::~ScalarArray() {}
int8 ScalarArray::getTypeCodeLUT() const
{
static const int8 typeCodeLUT[] = {
0x00, // pvBoolean
0x20, // pvByte
0x21, // pvShort
0x22, // pvInt
0x23, // pvLong
0x28, // pvUByte
0x29, // pvUShort
0x2A, // pvUInt
0x2B, // pvULong
0x42, // pvFloat
0x43, // pvDouble
0x60 // pvString
};
return typeCodeLUT[elementType];
}
const string ScalarArray::getIDScalarArrayLUT() const
{
static const string idScalarArrayLUT[] = {
"boolean[]", // pvBoolean
"byte[]", // pvByte
"short[]", // pvShort
"boolean[]", // pvBoolean
"byte[]", // pvByte
"short[]", // pvShort
"int[]", // pvInt
"long[]", // pvLong
"ubyte[]", // pvUByte
@@ -256,13 +270,59 @@ std::ostream& ScalarArray::dump(std::ostream& o) const
void ScalarArray::serialize(ByteBuffer *buffer, SerializableControl *control) const {
control->ensureBuffer(1);
buffer->putByte((int8)0x10 | getTypeCodeLUT());
buffer->putByte((int8)0x08 | Scalar::getTypeCodeLUT(elementType));
}
void ScalarArray::deserialize(ByteBuffer* /*buffer*/, DeserializableControl* /*control*/) {
throw std::runtime_error("not valid operation, use FieldCreate::deserialize instead");
}
BoundedScalarArray::~BoundedScalarArray() {}
BoundedScalarArray::BoundedScalarArray(ScalarType elementType, size_t size)
: ScalarArray(elementType),
size(size)
{
}
string BoundedScalarArray::getID() const
{
char buffer[32];
sprintf(buffer, "%s<%zu>", ScalarTypeFunc::name(getElementType()), size);
return string(buffer);
}
void BoundedScalarArray::serialize(ByteBuffer *buffer, SerializableControl *control) const {
control->ensureBuffer(1);
buffer->putByte((int8)0x10 | Scalar::getTypeCodeLUT(getElementType()));
SerializeHelper::writeSize(size, buffer, control);
}
FixedScalarArray::~FixedScalarArray() {}
FixedScalarArray::FixedScalarArray(ScalarType elementType, size_t size)
: ScalarArray(elementType),
size(size)
{
}
string FixedScalarArray::getID() const
{
char buffer[32];
sprintf(buffer, "%s[%zu]", ScalarTypeFunc::name(getElementType()), size);
return string(buffer);
}
void FixedScalarArray::serialize(ByteBuffer *buffer, SerializableControl *control) const {
control->ensureBuffer(1);
buffer->putByte((int8)0x18 | Scalar::getTypeCodeLUT(getElementType()));
SerializeHelper::writeSize(size, buffer, control);
}
StructureArray::StructureArray(StructureConstPtr const & structure)
: Array(structureArray),pstructure(structure)
{
@@ -289,7 +349,7 @@ std::ostream& StructureArray::dump(std::ostream& o) const
void StructureArray::serialize(ByteBuffer *buffer, SerializableControl *control) const {
control->ensureBuffer(1);
buffer->putByte((int8)0x90);
buffer->putByte((int8)0x88);
control->cachedSerialize(pstructure, buffer);
}
@@ -326,11 +386,11 @@ void UnionArray::serialize(ByteBuffer *buffer, SerializableControl *control) con
if (punion->isVariant())
{
// unrestricted/variant union
buffer->putByte((int8)0x92);
buffer->putByte((int8)0x8A);
}
else
{
buffer->putByte((int8)0x91);
buffer->putByte((int8)0x89);
control->cachedSerialize(punion, buffer);
}
}
@@ -339,7 +399,13 @@ void UnionArray::deserialize(ByteBuffer* /*buffer*/, DeserializableControl* /*co
throw std::runtime_error("not valid operation, use FieldCreate::deserialize instead");
}
string Structure::DEFAULT_ID = "structure";
const string Structure::DEFAULT_ID = Structure::defaultId();
const string & Structure::defaultId()
{
static const string id = "structure";
return id;
}
Structure::Structure (
StringArray const & fieldNames,
@@ -351,27 +417,27 @@ Structure::Structure (
id(inid)
{
if(inid.empty()) {
throw std::invalid_argument("id is empty");
THROW_EXCEPTION2(std::invalid_argument, "Can't construct Structure, id is empty string");
}
if(fieldNames.size()!=fields.size()) {
throw std::invalid_argument("fieldNames.size()!=fields.size()");
THROW_EXCEPTION2(std::invalid_argument, "Can't construct Structure, fieldNames.size()!=fields.size()");
}
size_t number = fields.size();
for(size_t i=0; i<number; i++) {
const string& name = fieldNames[i];
if(name.empty()) {
throw std::invalid_argument("fieldNames has a zero length string");
THROW_EXCEPTION2(std::invalid_argument, "Can't construct Structure, empty string in fieldNames");
}
if(fields[i].get()==NULL)
throw std::invalid_argument("Can't construct Structure with NULL Field");
THROW_EXCEPTION2(std::invalid_argument, "Can't construct Structure, NULL in fields");
// look for duplicates
for(size_t j=i+1; j<number; j++) {
string otherName = fieldNames[j];
int result = name.compare(otherName);
if(result==0) {
string message("duplicate fieldName ");
string message("Can't construct Structure, duplicate fieldName ");
message += name;
throw std::invalid_argument(message);
THROW_EXCEPTION2(std::invalid_argument, message);
}
}
}
@@ -436,7 +502,9 @@ void Structure::dumpFields(std::ostream& o) const
case structureArray:
{
format::indent_scope s(o);
o << *pfield;
Field const *xxx = pfield.get();
StructureArray const *pstructureArray = static_cast<StructureArray const*>(xxx);
o << *pstructureArray->getStructure();
break;
}
case union_:
@@ -450,7 +518,9 @@ void Structure::dumpFields(std::ostream& o) const
case unionArray:
{
format::indent_scope s(o);
o << *pfield;
Field const *xxx = pfield.get();
UnionArray const *punionArray = static_cast<UnionArray const*>(xxx);
o << *punionArray->getUnion();
break;
}
}
@@ -467,20 +537,30 @@ void Structure::deserialize(ByteBuffer* /*buffer*/, DeserializableControl* /*con
throw std::runtime_error("not valid operation, use FieldCreate::deserialize instead");
}
string Union::DEFAULT_ID = "union";
const string Union::DEFAULT_ID = Union::defaultId();
#define UNION_ANY_ID "any"
string Union::ANY_ID = UNION_ANY_ID;
const string & Union::defaultId()
{
static const string id = "union";
return id;
}
const string Union::ANY_ID = Union::anyId();
const string & Union::anyId()
{
static const string id = "any";
return id;
}
Union::Union ()
: Field(union_),
fieldNames(),
fields(),
id(UNION_ANY_ID)
id(anyId())
{
}
#undef UNION_ANY_ID
Union::Union (
StringArray const & fieldNames,
@@ -492,31 +572,31 @@ Union::Union (
id(inid)
{
if(inid.empty()) {
throw std::invalid_argument("id is empty");
THROW_EXCEPTION2(std::invalid_argument, "Can't construct Union, id is empty string");
}
if(fieldNames.size()!=fields.size()) {
throw std::invalid_argument("fieldNames.size()!=fields.size()");
THROW_EXCEPTION2(std::invalid_argument, "Can't construct Union, fieldNames.size()!=fields.size()");
}
if(fields.size()==0 && inid!=ANY_ID) {
throw std::invalid_argument("no fields but id is different than " + ANY_ID);
THROW_EXCEPTION2(std::invalid_argument, "Can't construct Union, no fields only allowed when id = " + ANY_ID);
}
size_t number = fields.size();
for(size_t i=0; i<number; i++) {
const string& name = fieldNames[i];
if(name.empty()) {
throw std::invalid_argument("fieldNames has a zero length string");
THROW_EXCEPTION2(std::invalid_argument, "Can't construct Union, empty string in fieldNames");
}
if(fields[i].get()==NULL)
throw std::invalid_argument("Can't construct Union with NULL Field");
THROW_EXCEPTION2(std::invalid_argument, "Can't construct Union, NULL in fields");
// look for duplicates
for(size_t j=i+1; j<number; j++) {
string otherName = fieldNames[j];
int result = name.compare(otherName);
if(result==0) {
string message("duplicate fieldName ");
string message("Can't construct Union, duplicate fieldName ");
message += name;
throw std::invalid_argument(message);
THROW_EXCEPTION2(std::invalid_argument, message);
}
}
}
@@ -552,7 +632,7 @@ size_t Union::getFieldIndex(string const &fieldName) const {
std::ostream& Union::dump(std::ostream& o) const
{
o << getID() << std::endl;
o << format::indent() << getID() << std::endl;
{
format::indent_scope s(o);
dumpFields(o);
@@ -655,6 +735,12 @@ FieldBuilderPtr FieldBuilder::add(string const & name, ScalarType scalarType)
return shared_from_this();
}
FieldBuilderPtr FieldBuilder::addBoundedString(std::string const & name, std::size_t maxLength)
{
fields.push_back(fieldCreate->createBoundedString(maxLength)); fieldNames.push_back(name);
return shared_from_this();
}
FieldBuilderPtr FieldBuilder::add(string const & name, FieldConstPtr const & field)
{
fields.push_back(field); fieldNames.push_back(name);
@@ -667,6 +753,18 @@ FieldBuilderPtr FieldBuilder::addArray(string const & name, ScalarType scalarTyp
return shared_from_this();
}
FieldBuilderPtr FieldBuilder::addFixedArray(string const & name, ScalarType scalarType, size_t size)
{
fields.push_back(fieldCreate->createFixedScalarArray(scalarType, size)); fieldNames.push_back(name);
return shared_from_this();
}
FieldBuilderPtr FieldBuilder::addBoundedArray(string const & name, ScalarType scalarType, size_t size)
{
fields.push_back(fieldCreate->createBoundedScalarArray(scalarType, size)); fieldNames.push_back(name);
return shared_from_this();
}
FieldBuilderPtr FieldBuilder::addArray(string const & name, FieldConstPtr const & element)
{
switch (element->getType())
@@ -678,10 +776,17 @@ FieldBuilderPtr FieldBuilder::addArray(string const & name, FieldConstPtr const
fields.push_back(fieldCreate->createUnionArray(static_pointer_cast<const Union>(element)));
break;
case scalar:
if (std::tr1::dynamic_pointer_cast<const BoundedString>(element).get())
THROW_EXCEPTION2(std::invalid_argument, "bounded string arrays are not supported");
fields.push_back(fieldCreate->createScalarArray(static_pointer_cast<const Scalar>(element)->getScalarType()));
break;
// scalarArray?
default:
throw std::invalid_argument("unsupported array element type:" + element->getType());
std::ostringstream msg("unsupported array element type: ");
msg << element->getType();
THROW_EXCEPTION2(std::invalid_argument, msg.str());
}
fieldNames.push_back(name);
@@ -707,14 +812,18 @@ FieldConstPtr FieldBuilder::createFieldInternal(Type type)
fieldCreate->createUnion(fieldNames, fields);
}
else
throw std::invalid_argument("unsupported type: " + type);
{
std::ostringstream msg("unsupported type: ");
msg << type;
THROW_EXCEPTION2(std::invalid_argument, msg.str());
}
}
StructureConstPtr FieldBuilder::createStructure()
{
if (parentBuilder.get())
throw std::runtime_error("createStructure() called in nested FieldBuilder");
THROW_EXCEPTION2(std::runtime_error, "createStructure() called in nested FieldBuilder");
StructureConstPtr field(static_pointer_cast<const Structure>(createFieldInternal(structure)));
reset();
@@ -724,7 +833,7 @@ StructureConstPtr FieldBuilder::createStructure()
UnionConstPtr FieldBuilder::createUnion()
{
if (parentBuilder.get())
throw std::runtime_error("createUnion() called in nested FieldBuilder");
THROW_EXCEPTION2(std::runtime_error, "createUnion() called in nested FieldBuilder");
UnionConstPtr field(static_pointer_cast<const Union>(createFieldInternal(union_)));
reset();
@@ -756,7 +865,7 @@ FieldBuilderPtr FieldBuilder::addNestedUnionArray(string const & name)
FieldBuilderPtr FieldBuilder::endNested()
{
if (!parentBuilder.get())
throw std::runtime_error("this method can only be called to create nested fields");
THROW_EXCEPTION2(std::runtime_error, "this method can only be called to create nested fields");
FieldConstPtr nestedField = createFieldInternal(nestedClassToBuild);
if (nestedArray)
@@ -775,20 +884,62 @@ FieldBuilderPtr FieldCreate::createFieldBuilder() const
ScalarConstPtr FieldCreate::createScalar(ScalarType scalarType) const
{
if(scalarType<0 || scalarType>MAX_SCALAR_TYPE)
throw std::invalid_argument("Can't construct Scalar from invalid ScalarType");
if(scalarType<0 || scalarType>MAX_SCALAR_TYPE) {
std::ostringstream strm("Can't construct Scalar from invalid ScalarType ");
strm << scalarType;
THROW_EXCEPTION2(std::invalid_argument, strm.str());
}
return scalars[scalarType];
}
BoundedStringConstPtr FieldCreate::createBoundedString(std::size_t maxLength) const
{
// TODO use std::make_shared
std::tr1::shared_ptr<BoundedString> s(new BoundedString(maxLength), Field::Deleter());
BoundedStringConstPtr sa = s;
return sa;
}
ScalarArrayConstPtr FieldCreate::createScalarArray(ScalarType elementType) const
{
if(elementType<0 || elementType>MAX_SCALAR_TYPE)
throw std::invalid_argument("Can't construct ScalarArray from invalid ScalarType");
if(elementType<0 || elementType>MAX_SCALAR_TYPE) {
std::ostringstream strm("Can't construct ScalarArray from invalid ScalarType ");
strm << elementType;
THROW_EXCEPTION2(std::invalid_argument, strm.str());
}
return scalarArrays[elementType];
}
ScalarArrayConstPtr FieldCreate::createFixedScalarArray(ScalarType elementType, size_t size) const
{
if(elementType<0 || elementType>MAX_SCALAR_TYPE) {
std::ostringstream strm("Can't construct fixed ScalarArray from invalid ScalarType ");
strm << elementType;
THROW_EXCEPTION2(std::invalid_argument, strm.str());
}
// TODO use std::make_shared
std::tr1::shared_ptr<ScalarArray> s(new FixedScalarArray(elementType, size), Field::Deleter());
ScalarArrayConstPtr sa = s;
return sa;
}
ScalarArrayConstPtr FieldCreate::createBoundedScalarArray(ScalarType elementType, size_t size) const
{
if(elementType<0 || elementType>MAX_SCALAR_TYPE) {
std::ostringstream strm("Can't construct bounded ScalarArray from invalid ScalarType ");
strm << elementType;
THROW_EXCEPTION2(std::invalid_argument, strm.str());
}
// TODO use std::make_shared
std::tr1::shared_ptr<ScalarArray> s(new BoundedScalarArray(elementType, size), Field::Deleter());
ScalarArrayConstPtr sa = s;
return sa;
}
StructureConstPtr FieldCreate::createStructure () const
{
StringArray fieldNames;
@@ -799,8 +950,9 @@ StructureConstPtr FieldCreate::createStructure () const
StructureConstPtr FieldCreate::createStructure (
StringArray const & fieldNames,FieldConstPtrArray const & fields) const
{
StructureConstPtr structure(
new Structure(fieldNames,fields), Field::Deleter());
// TODO use std::make_shared
std::tr1::shared_ptr<Structure> sp(new Structure(fieldNames,fields), Field::Deleter());
StructureConstPtr structure = sp;
return structure;
}
@@ -809,24 +961,27 @@ StructureConstPtr FieldCreate::createStructure (
StringArray const & fieldNames,
FieldConstPtrArray const & fields) const
{
StructureConstPtr structure(
new Structure(fieldNames,fields,id), Field::Deleter());
// TODO use std::make_shared
std::tr1::shared_ptr<Structure> sp(new Structure(fieldNames,fields,id), Field::Deleter());
StructureConstPtr structure = sp;
return structure;
}
StructureArrayConstPtr FieldCreate::createStructureArray(
StructureConstPtr const & structure) const
{
StructureArrayConstPtr structureArray(
new StructureArray(structure), Field::Deleter());
// TODO use std::make_shared
std::tr1::shared_ptr<StructureArray> sp(new StructureArray(structure), Field::Deleter());
StructureArrayConstPtr structureArray = sp;
return structureArray;
}
UnionConstPtr FieldCreate::createUnion (
StringArray const & fieldNames,FieldConstPtrArray const & fields) const
{
UnionConstPtr punion(
new Union(fieldNames,fields), Field::Deleter());
// TODO use std::make_shared
std::tr1::shared_ptr<Union> sp(new Union(fieldNames,fields), Field::Deleter());
UnionConstPtr punion = sp;
return punion;
}
@@ -835,8 +990,9 @@ UnionConstPtr FieldCreate::createUnion (
StringArray const & fieldNames,
FieldConstPtrArray const & fields) const
{
UnionConstPtr punion(
new Union(fieldNames,fields,id), Field::Deleter());
// TODO use std::make_shared
std::tr1::shared_ptr<Union> sp(new Union(fieldNames,fields,id), Field::Deleter());
UnionConstPtr punion = sp;
return punion;
}
@@ -848,8 +1004,9 @@ UnionConstPtr FieldCreate::createVariantUnion () const
UnionArrayConstPtr FieldCreate::createUnionArray(
UnionConstPtr const & punion) const
{
UnionArrayConstPtr unionArray(
new UnionArray(punion), Field::Deleter());
// TODO use std::make_shared
std::tr1::shared_ptr<UnionArray> sp(new UnionArray(punion), Field::Deleter());
UnionArrayConstPtr unionArray = sp;
return unionArray;
}
@@ -863,8 +1020,8 @@ StructureConstPtr FieldCreate::appendField(
string const & fieldName,
FieldConstPtr const & field) const
{
StringArray oldNames = structure->getFieldNames();
FieldConstPtrArray oldFields = structure->getFields();
StringArray const & oldNames = structure->getFieldNames();
FieldConstPtrArray const & oldFields = structure->getFields();
size_t oldLen = oldNames.size();
StringArray newNames(oldLen+1);
FieldConstPtrArray newFields(oldLen+1);
@@ -882,8 +1039,8 @@ StructureConstPtr FieldCreate::appendFields(
StringArray const & fieldNames,
FieldConstPtrArray const & fields) const
{
StringArray oldNames = structure->getFieldNames();
FieldConstPtrArray oldFields = structure->getFields();
StringArray const & oldNames = structure->getFieldNames();
FieldConstPtrArray const & oldFields = structure->getFields();
size_t oldLen = oldNames.size();
size_t extra = fieldNames.size();
StringArray newNames(oldLen+extra);
@@ -904,22 +1061,14 @@ static int decodeScalar(int8 code)
{
static const int integerLUT[] =
{
pvByte, // 8-bits
pvShort, // 16-bits
pvInt, // 32-bits
pvLong, // 64-bits
-1,
-1,
-1,
-1,
pvByte, // 8-bits
pvShort, // 16-bits
pvInt, // 32-bits
pvLong, // 64-bits
pvUByte, // unsigned 8-bits
pvUShort, // unsigned 16-bits
pvUInt, // unsigned 32-bits
pvULong, // unsigned 64-bits
-1,
-1,
-1,
-1
pvULong // unsigned 64-bits
};
static const int floatLUT[] =
@@ -931,22 +1080,14 @@ static int decodeScalar(int8 code)
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1
};
// bits 7-5
switch (code >> 5)
{
case 0: return pvBoolean;
case 1: return integerLUT[code & 0x0F];
case 2: return floatLUT[code & 0x0F];
case 1: return integerLUT[code & 0x07];
case 2: return floatLUT[code & 0x07];
case 3: return pvString;
default: return -1;
}
@@ -959,8 +1100,9 @@ FieldConstPtr FieldCreate::deserialize(ByteBuffer* buffer, DeserializableControl
if (code == -1)
return FieldConstPtr();
int typeCode = code & 0xEF;
bool notArray = ((code & 0x10) == 0);
int typeCode = code & 0xE7;
int scalarOrArray = code & 0x18;
bool notArray = (scalarOrArray == 0);
if (notArray)
{
if (typeCode < 0x80)
@@ -986,33 +1128,90 @@ FieldConstPtr FieldCreate::deserialize(ByteBuffer* buffer, DeserializableControl
// Type type = Type.union; variant union (aka any type)
return variantUnion;
}
else if (typeCode == 0x83)
{
// TODO cache?
// bounded string
size_t size = SerializeHelper::readSize(buffer, control);
// TODO use std::make_shared
std::tr1::shared_ptr<Field> sp(
new BoundedString(size),
Field::Deleter());
FieldConstPtr p = sp;
return p;
}
else
throw std::invalid_argument("invalid type encoding");
}
else // array
{
bool isVariable = (scalarOrArray == 0x08);
// bounded == 0x10;
bool isFixed = (scalarOrArray == 0x18);
size_t size = (isVariable ? 0 : SerializeHelper::readSize(buffer, control));
if (typeCode < 0x80)
{
// Type type = Type.scalarArray;
int scalarType = decodeScalar(code);
if (scalarType == -1)
throw std::invalid_argument("invalid scalarArray type encoding");
return scalarArrays[scalarType];
if (isVariable)
return scalarArrays[scalarType];
else if (isFixed)
{
// TODO use std::make_shared
std::tr1::shared_ptr<Field> sp(
new FixedScalarArray(static_cast<epics::pvData::ScalarType>(scalarType), size),
Field::Deleter());
FieldConstPtr p = sp;
return p;
}
else
{
// TODO use std::make_shared
std::tr1::shared_ptr<Field> sp(
new BoundedScalarArray(static_cast<epics::pvData::ScalarType>(scalarType), size),
Field::Deleter());
FieldConstPtr p = sp;
return p;
}
}
else if (typeCode == 0x80)
{
// TODO fixed and bounded array support
if (!isVariable)
throw std::invalid_argument("fixed and bounded structure array not supported");
// Type type = Type.structureArray;
StructureConstPtr elementStructure = std::tr1::static_pointer_cast<const Structure>(control->cachedDeserialize(buffer));
return FieldConstPtr(new StructureArray(elementStructure), Field::Deleter());
// TODO use std::make_shared
std::tr1::shared_ptr<Field> sp(new StructureArray(elementStructure), Field::Deleter());
FieldConstPtr p = sp;
return p;
}
else if (typeCode == 0x81)
{
// TODO fixed and bounded array support
if (!isVariable)
throw std::invalid_argument("fixed and bounded structure array not supported");
// Type type = Type.unionArray;
UnionConstPtr elementUnion = std::tr1::static_pointer_cast<const Union>(control->cachedDeserialize(buffer));
return FieldConstPtr(new UnionArray(elementUnion), Field::Deleter());
// TODO use std::make_shared
std::tr1::shared_ptr<Field> sp(new UnionArray(elementUnion), Field::Deleter());
FieldConstPtr p = sp;
return p;
}
else if (typeCode == 0x82)
{
// TODO fixed and bounded array support
if (!isVariable)
throw std::invalid_argument("fixed and bounded structure array not supported");
// Type type = Type.unionArray; variant union (aka any type)
return variantUnionArray;
}
@@ -1037,11 +1236,24 @@ FieldCreate::FieldCreate()
{
for (int i = 0; i <= MAX_SCALAR_TYPE; i++)
{
scalars.push_back(ScalarConstPtr(new Scalar(static_cast<ScalarType>(i)), Field::Deleter()));
scalarArrays.push_back(ScalarArrayConstPtr(new ScalarArray(static_cast<ScalarType>(i)), Field::Deleter()));
// TODO use std::make_shared
std::tr1::shared_ptr<Scalar> sp(new Scalar(static_cast<ScalarType>(i)), Field::Deleter());
ScalarConstPtr p = sp;
scalars.push_back(p);
// TODO use std::make_shared
std::tr1::shared_ptr<ScalarArray> spa(new ScalarArray(static_cast<ScalarType>(i)), Field::Deleter());
ScalarArrayConstPtr pa = spa;
scalarArrays.push_back(spa);
}
variantUnion = UnionConstPtr(new Union(), Field::Deleter());
variantUnionArray = UnionArrayConstPtr(new UnionArray(variantUnion), Field::Deleter());
// TODO use std::make_shared
std::tr1::shared_ptr<Union> su(new Union(), Field::Deleter());
variantUnion = su;
// TODO use std::make_shared
std::tr1::shared_ptr<UnionArray> sua(new UnionArray(variantUnion), Field::Deleter());
variantUnionArray = sua;
}
FieldCreatePtr getFieldCreate() {
@@ -1049,3 +1261,12 @@ FieldCreatePtr getFieldCreate() {
}
}}
namespace std{
std::ostream& operator<<(std::ostream& o, const epics::pvData::Field *ptr)
{
if(ptr) return o << *ptr;
return o << "nullptr";
}
}

View File

@@ -21,7 +21,6 @@
#include <pv/lock.h>
#include <pv/pvIntrospect.h>
#include <pv/pvData.h>
#include <pv/convert.h>
#include <pv/factory.h>
#include <pv/serializeHelper.h>
@@ -145,11 +144,18 @@ public:
SerializableControl *pflusher, size_t offset, size_t count) const;
private:
string value;
std::size_t maxLength;
};
BasePVString::BasePVString(ScalarConstPtr const & scalar)
: PVString(scalar),value()
{}
{
BoundedStringConstPtr boundedString = std::tr1::dynamic_pointer_cast<const BoundedString>(scalar);
if (boundedString.get())
maxLength = boundedString->getMaximumLength();
else
maxLength = 0;
}
BasePVString::~BasePVString() {}
@@ -157,6 +163,9 @@ string BasePVString::get() const { return value;}
void BasePVString::put(string val)
{
if (maxLength > 0 && val.length() > maxLength)
throw std::overflow_error("string too long");
value = val;
postPut();
}
@@ -190,6 +199,19 @@ void BasePVString::serialize(ByteBuffer *pbuffer,
SerializeHelper::serializeSubstring(value, offset, count, pbuffer, pflusher);
}
void PVArray::checkLength(size_t len)
{
Array::ArraySizeType type = getArray()->getArraySizeType();
if (type != Array::variable)
{
size_t size = getArray()->getMaximumCapacity();
if (type == Array::fixed && len != size)
throw std::invalid_argument("invalid length for a fixed size array");
else if (type == Array::bounded && len > size)
throw std::invalid_argument("new array capacity too large for a bounded size array");
}
}
/** Default storage for arrays
*/
template<typename T>
@@ -231,7 +253,14 @@ DefaultPVArray<T>::DefaultPVArray(ScalarArrayConstPtr const & scalarArray)
: PVValueArray<T>(scalarArray),
value()
{ }
{
ArrayConstPtr array = this->getArray();
if (array->getArraySizeType() == Array::fixed)
{
// this->setLength(array->getMaximumCapacity());
this->setCapacityMutable(false);
}
}
template<typename T>
DefaultPVArray<T>::~DefaultPVArray()
@@ -240,18 +269,25 @@ template<typename T>
void DefaultPVArray<T>::setCapacity(size_t capacity)
{
if(this->isCapacityMutable()) {
this->checkLength(capacity);
value.reserve(capacity);
}
else
THROW_EXCEPTION2(std::logic_error, "capacity immutable");
}
template<typename T>
void DefaultPVArray<T>::setLength(size_t length)
{
if(this->isImmutable())
THROW_EXCEPTION2(std::logic_error,"Immutable");
if(length == value.size())
THROW_EXCEPTION2(std::logic_error, "immutable");
if (length == value.size())
return;
else if(length < value.size())
this->checkLength(length);
if (length < value.size())
value.slice(0, length);
else
value.resize(length);
@@ -260,6 +296,8 @@ void DefaultPVArray<T>::setLength(size_t length)
template<typename T>
void DefaultPVArray<T>::replace(const const_svector& next)
{
this->checkLength(next.size());
value = next;
this->postPut();
}
@@ -267,8 +305,10 @@ void DefaultPVArray<T>::replace(const const_svector& next)
template<typename T>
void DefaultPVArray<T>::swap(const_svector &other)
{
if(this->isImmutable())
THROW_EXCEPTION2(std::logic_error,"Immutable");
if (this->isImmutable())
THROW_EXCEPTION2(std::logic_error, "immutable");
// no checkLength call here
value.swap(other);
}
@@ -283,7 +323,10 @@ void DefaultPVArray<T>::serialize(ByteBuffer *pbuffer,
template<typename T>
void DefaultPVArray<T>::deserialize(ByteBuffer *pbuffer,
DeserializableControl *pcontrol) {
size_t size = SerializeHelper::readSize(pbuffer, pcontrol);
size_t size = this->getArray()->getArraySizeType() == Array::fixed ?
this->getArray()->getMaximumCapacity() :
SerializeHelper::readSize(pbuffer, pcontrol);
svector nextvalue(thaw(value));
nextvalue.resize(size); // TODO: avoid copy of stuff we will then overwrite
@@ -321,6 +364,7 @@ void DefaultPVArray<T>::deserialize(ByteBuffer *pbuffer,
remaining -= n2read;
}
value = freeze(nextvalue);
// TODO !!!
// inform about the change?
PVField::postPut();
}
@@ -334,7 +378,11 @@ void DefaultPVArray<T>::serialize(ByteBuffer *pbuffer,
temp.slice(offset, count);
count = temp.size();
SerializeHelper::writeSize(temp.size(), pbuffer, pflusher);
ArrayConstPtr array = this->getArray();
if (array->getArraySizeType() != Array::fixed)
SerializeHelper::writeSize(count, pbuffer, pflusher);
else if (count != array->getMaximumCapacity())
throw std::length_error("fixed array cannot be partially serialized");
const T* cur = temp.data();
@@ -368,7 +416,10 @@ void DefaultPVArray<T>::serialize(ByteBuffer *pbuffer,
template<>
void DefaultPVArray<string>::deserialize(ByteBuffer *pbuffer,
DeserializableControl *pcontrol) {
size_t size = SerializeHelper::readSize(pbuffer, pcontrol);
size_t size = this->getArray()->getArraySizeType() == Array::fixed ?
this->getArray()->getMaximumCapacity() :
SerializeHelper::readSize(pbuffer, pcontrol);
svector nextvalue(thaw(value));
@@ -396,7 +447,9 @@ void DefaultPVArray<string>::serialize(ByteBuffer *pbuffer,
const_svector temp(value);
temp.slice(offset, count);
SerializeHelper::writeSize(temp.size(), pbuffer, pflusher);
// TODO if fixed count == getArray()->getMaximumCapacity()
if (this->getArray()->getArraySizeType() != Array::fixed)
SerializeHelper::writeSize(temp.size(), pbuffer, pflusher);
const string * pvalue = temp.data();
for(size_t i = 0; i<temp.size(); i++) {
@@ -473,7 +526,7 @@ PVFieldPtr PVDataCreate::createPVField(PVFieldPtr const & fieldToClone)
PVStructurePtr pvStructure
= static_pointer_cast<PVStructure>(fieldToClone);
StringArray const & fieldNames = pvStructure->getStructure()->getFieldNames();
PVFieldPtrArray pvFieldPtrArray = pvStructure->getPVFields();
PVFieldPtrArray const & pvFieldPtrArray = pvStructure->getPVFields();
return createPVStructure(fieldNames,pvFieldPtrArray);
}
case structureArray:
@@ -483,7 +536,7 @@ PVFieldPtr PVDataCreate::createPVField(PVFieldPtr const & fieldToClone)
StructureArrayConstPtr structureArray = from->getStructureArray();
PVStructureArrayPtr to = createPVStructureArray(
structureArray);
getConvert()->copyStructureArray(from, to);
to->copyUnchecked(*from);
return to;
}
case union_:
@@ -498,7 +551,7 @@ PVFieldPtr PVDataCreate::createPVField(PVFieldPtr const & fieldToClone)
= static_pointer_cast<PVUnionArray>(fieldToClone);
UnionArrayConstPtr unionArray = from->getUnionArray();
PVUnionArrayPtr to = createPVUnionArray(unionArray);
getConvert()->copyUnionArray(from, to);
to->copyUnchecked(*from);
return to;
}
}
@@ -548,7 +601,7 @@ PVScalarPtr PVDataCreate::createPVScalar(PVScalarPtr const & scalarToClone)
{
ScalarType scalarType = scalarToClone->getScalar()->getScalarType();
PVScalarPtr pvScalar = createPVScalar(scalarType);
getConvert()->copyScalar(scalarToClone, pvScalar);
pvScalar->copyUnchecked(*scalarToClone);
return pvScalar;
}
@@ -649,7 +702,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);
@@ -658,7 +711,7 @@ PVStructurePtr PVDataCreate::createPVStructure(PVStructurePtr const & structToCl
}
StructureConstPtr structure = structToClone->getStructure();
PVStructurePtr pvStructure(new PVStructure(structure));
getConvert()->copyStructure(structToClone,pvStructure);
pvStructure->copyUnchecked(*structToClone);
return pvStructure;
}
@@ -687,3 +740,12 @@ PVDataCreatePtr getPVDataCreate() {
}
}}
namespace std{
std::ostream& operator<<(std::ostream& o, const epics::pvData::PVField *ptr)
{
if(ptr) return o << *ptr;
return o << "nullptr";
}
}

View File

@@ -16,7 +16,6 @@
#include <pv/lock.h>
#include <pv/pvData.h>
#include <pv/factory.h>
#include <pv/convert.h>
using std::tr1::const_pointer_cast;
using std::size_t;
@@ -121,7 +120,7 @@ void PVField::computeOffset(const PVField * pvField) {
}
size_t offset = 0;
size_t nextOffset = 1;
PVFieldPtrArray pvFields = pvTop->getPVFields();
const PVFieldPtrArray & pvFields = pvTop->getPVFields();
for(size_t i=0; i < pvTop->getStructure()->getNumberFields(); i++) {
offset = nextOffset;
PVField *pvField = pvFields[i].get();
@@ -153,7 +152,7 @@ void PVField::computeOffset(const PVField * pvField,size_t offset) {
size_t beginOffset = offset;
size_t nextOffset = offset + 1;
const PVStructure *pvStructure = static_cast<const PVStructure *>(pvField);
const PVFieldPtrArray pvFields = pvStructure->getPVFields();
const PVFieldPtrArray & pvFields = pvStructure->getPVFields();
for(size_t i=0; i < pvStructure->getStructure()->getNumberFields(); i++) {
offset = nextOffset;
PVField *pvSubField = pvFields[i].get();
@@ -180,4 +179,117 @@ void PVField::computeOffset(const PVField * pvField,size_t offset) {
xxx->nextFieldOffset = nextOffset;
}
void PVField::copy(const PVField& from)
{
if(isImmutable())
throw std::invalid_argument("destination is immutable");
if (getField()->getType() != from.getField()->getType())
throw std::invalid_argument("field types do not match");
switch(getField()->getType())
{
case scalar:
{
const PVScalar* fromS = static_cast<const PVScalar*>(&from);
PVScalar* toS = static_cast<PVScalar*>(this);
toS->copy(*fromS);
break;
}
case scalarArray:
{
const PVScalarArray* fromS = static_cast<const PVScalarArray*>(&from);
PVScalarArray* toS = static_cast<PVScalarArray*>(this);
toS->copy(*fromS);
break;
}
case structure:
{
const PVStructure* fromS = static_cast<const PVStructure*>(&from);
PVStructure* toS = static_cast<PVStructure*>(this);
toS->copy(*fromS);
break;
}
case structureArray:
{
const PVStructureArray* fromS = static_cast<const PVStructureArray*>(&from);
PVStructureArray* toS = static_cast<PVStructureArray*>(this);
toS->copy(*fromS);
break;
}
case union_:
{
const PVUnion* fromS = static_cast<const PVUnion*>(&from);
PVUnion* toS = static_cast<PVUnion*>(this);
toS->copy(*fromS);
break;
}
case unionArray:
{
const PVUnionArray* fromS = static_cast<const PVUnionArray*>(&from);
PVUnionArray* toS = static_cast<PVUnionArray*>(this);
toS->copy(*fromS);
break;
}
default:
{
throw std::logic_error("PVField::copy unknown type");
}
}
}
void PVField::copyUnchecked(const PVField& from)
{
switch(getField()->getType())
{
case scalar:
{
const PVScalar* fromS = static_cast<const PVScalar*>(&from);
PVScalar* toS = static_cast<PVScalar*>(this);
toS->copyUnchecked(*fromS);
break;
}
case scalarArray:
{
const PVScalarArray* fromS = static_cast<const PVScalarArray*>(&from);
PVScalarArray* toS = static_cast<PVScalarArray*>(this);
toS->copyUnchecked(*fromS);
break;
}
case structure:
{
const PVStructure* fromS = static_cast<const PVStructure*>(&from);
PVStructure* toS = static_cast<PVStructure*>(this);
toS->copyUnchecked(*fromS);
break;
}
case structureArray:
{
const PVStructureArray* fromS = static_cast<const PVStructureArray*>(&from);
PVStructureArray* toS = static_cast<PVStructureArray*>(this);
toS->copyUnchecked(*fromS);
break;
}
case union_:
{
const PVUnion* fromS = static_cast<const PVUnion*>(&from);
PVUnion* toS = static_cast<PVUnion*>(this);
toS->copyUnchecked(*fromS);
break;
}
case unionArray:
{
const PVUnionArray* fromS = static_cast<const PVUnionArray*>(&from);
PVUnionArray* toS = static_cast<PVUnionArray*>(this);
toS->copyUnchecked(*fromS);
break;
}
default:
{
throw std::logic_error("PVField::copy unknown type");
}
}
}
}}

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

@@ -16,7 +16,6 @@
#define epicsExportSharedSymbols
#include <pv/pvData.h>
#include <pv/pvIntrospect.h>
#include <pv/convert.h>
#include <pv/factory.h>
#include <pv/bitSet.h>
@@ -45,18 +44,14 @@ PVUnionPtr PVStructure::nullPVUnion;
PVUnionArrayPtr PVStructure::nullPVUnionArray;
PVScalarArrayPtr PVStructure::nullPVScalarArray;
static PVFieldPtr findSubField(
string const &fieldName,
const PVStructure *pvStructure);
PVStructure::PVStructure(StructureConstPtr const & structurePtr)
: PVField(structurePtr),
structurePtr(structurePtr),
extendsStructureName("")
{
size_t numberFields = structurePtr->getNumberFields();
FieldConstPtrArray fields = structurePtr->getFields();
StringArray fieldNames = structurePtr->getFieldNames();
FieldConstPtrArray const & fields = structurePtr->getFields();
StringArray const & fieldNames = structurePtr->getFieldNames();
// PVFieldPtrArray * xxx = const_cast<PVFieldPtrArray *>(&pvFields);
pvFields.reserve(numberFields);
PVDataCreatePtr pvDataCreate = getPVDataCreate();
@@ -76,7 +71,7 @@ PVStructure::PVStructure(StructureConstPtr const & structurePtr,
extendsStructureName("")
{
size_t numberFields = structurePtr->getNumberFields();
StringArray fieldNames = structurePtr->getFieldNames();
StringArray const & fieldNames = structurePtr->getFieldNames();
pvFields.reserve(numberFields);
for(size_t i=0; i<numberFields; i++) {
pvFields.push_back(pvs[i]);
@@ -112,7 +107,11 @@ const PVFieldPtrArray & PVStructure::getPVFields() const
PVFieldPtr PVStructure::getSubField(string const &fieldName) const
{
return findSubField(fieldName,this);
PVField * field = getSubFieldImpl(fieldName.c_str(), false);
if (field)
return field->shared_from_this();
else
return PVFieldPtr();
}
@@ -135,107 +134,111 @@ PVFieldPtr PVStructure::getSubField(size_t fieldOffset) const
throw std::logic_error("PVStructure.getSubField: Logic error");
}
PVBooleanPtr PVStructure::getBooleanField(string const &fieldName)
PVFieldPtr PVStructure::getSubFieldT(std::size_t fieldOffset) const
{
return getSubField<PVBoolean>(fieldName);
}
PVBytePtr PVStructure::getByteField(string const &fieldName)
{
return getSubField<PVByte>(fieldName);
}
PVShortPtr PVStructure::getShortField(string const &fieldName)
{
return getSubField<PVShort>(fieldName);
}
PVIntPtr PVStructure::getIntField(string const &fieldName)
{
return getSubField<PVInt>(fieldName);
}
PVLongPtr PVStructure::getLongField(string const &fieldName)
{
return getSubField<PVLong>(fieldName);
}
PVUBytePtr PVStructure::getUByteField(string const &fieldName)
{
return getSubField<PVUByte>(fieldName);
}
PVUShortPtr PVStructure::getUShortField(string const &fieldName)
{
return getSubField<PVUShort>(fieldName);
}
PVUIntPtr PVStructure::getUIntField(string const &fieldName)
{
return getSubField<PVUInt>(fieldName);
}
PVULongPtr PVStructure::getULongField(string const &fieldName)
{
return getSubField<PVULong>(fieldName);
}
PVFloatPtr PVStructure::getFloatField(string const &fieldName)
{
return getSubField<PVFloat>(fieldName);
}
PVDoublePtr PVStructure::getDoubleField(string const &fieldName)
{
return getSubField<PVDouble>(fieldName);
}
PVStringPtr PVStructure::getStringField(string const &fieldName)
{
return getSubField<PVString>(fieldName);
}
PVStructurePtr PVStructure::getStructureField(string const &fieldName)
{
return getSubField<PVStructure>(fieldName);
}
PVUnionPtr PVStructure::getUnionField(string const &fieldName)
{
return getSubField<PVUnion>(fieldName);
}
PVScalarArrayPtr PVStructure::getScalarArrayField(
string const &fieldName,ScalarType elementType)
{
PVFieldPtr pvField = findSubField(fieldName,this);
if(pvField.get()==NULL) {
return nullPVScalarArray;
PVFieldPtr pvField = getSubField(fieldOffset);
if (pvField.get())
return pvField;
else
{
std::stringstream ss;
ss << "Failed to get field with offset "
<< fieldOffset << "(Invalid offset)" ;
throw std::runtime_error(ss.str());
}
FieldConstPtr field = pvField->getField();
Type type = field->getType();
if(type!=scalarArray) {
return nullPVScalarArray;
}
ScalarArrayConstPtr pscalarArray
= static_pointer_cast<const ScalarArray>(pvField->getField());
if(pscalarArray->getElementType()!=elementType) {
return nullPVScalarArray;
}
return std::tr1::static_pointer_cast<PVScalarArray>(pvField);
}
PVStructureArrayPtr PVStructure::getStructureArrayField(
string const &fieldName)
PVField* PVStructure::getSubFieldImpl(const char *name, bool throws) const
{
return getSubField<PVStructureArray>(fieldName);
}
const PVStructure *parent = this;
if(!name)
{
if (throws)
throw std::invalid_argument("Failed to get field: (Field name is NULL string)");
else
return NULL;
}
const char *fullName = name;
while(true) {
const char *sep=name;
while(*sep!='\0' && *sep!='.' && *sep!=' ') sep++;
if(*sep==' ')
{
if (throws)
{
std::stringstream ss;
ss << "Failed to get field: " << fullName
<< " (No spaces allowed in field name)";
throw std::runtime_error(ss.str());
}
else
return NULL;
}
size_t N = sep-name;
if(N==0)
{
if (throws)
{
std::stringstream ss;
ss << "Failed to get field: " << fullName
<< " (Zero-length field name encountered)";
throw std::runtime_error(ss.str());
}
else
return NULL;
}
PVUnionArrayPtr PVStructure::getUnionArrayField(
string const &fieldName)
{
return getSubField<PVUnionArray>(fieldName);
const PVFieldPtrArray& pvFields = parent->getPVFields();
PVField *child = NULL;
for(size_t i=0, n=pvFields.size(); i!=n; i++) {
const PVFieldPtr& fld = pvFields[i];
const std::string& fname = fld->getFieldName();
if(fname.size()==N && memcmp(name, fname.c_str(), N)==0) {
child = fld.get();
break;
}
}
if(!child)
{
if (throws)
{
std::stringstream ss;
ss << "Failed to get field: " << fullName << " ("
<< std::string(fullName, sep) << " not found)";
throw std::runtime_error(ss.str());
}
else
return NULL;
}
if(*sep) {
// this is not the requested leaf
parent = dynamic_cast<PVStructure*>(child);
if(!parent)
{
if (throws)
{
std::stringstream ss;
ss << "Failed to get field: " << fullName
<< " (" << std::string(fullName, sep)
<< " is not a structure)";
throw std::runtime_error(ss.str());
}
else
return NULL;
}
child = NULL;
name = sep+1; // skip past '.'
// loop around to new parent
} else {
return child;
}
}
}
@@ -328,37 +331,6 @@ void PVStructure::deserialize(ByteBuffer *pbuffer,
}
}
static PVFieldPtr findSubField(
string const & fieldName,
PVStructure const *pvStructure)
{
if( fieldName.length()<1) return PVFieldPtr();
string::size_type index = fieldName.find('.');
string name = fieldName;
string restOfName = string();
if(index>0) {
name = fieldName.substr(0, index);
if(fieldName.length()>index) {
restOfName = fieldName.substr(index+1);
}
}
PVFieldPtrArray pvFields = pvStructure->getPVFields();
PVFieldPtr pvField;
size_t numFields = pvStructure->getStructure()->getNumberFields();
for(size_t i=0; i<numFields; i++) {
pvField = pvFields[i];
size_t result = pvField->getFieldName().compare(name);
if(result==0) {
if(restOfName.length()==0) return pvFields[i];
if(pvField->getField()->getType()!=structure) return PVFieldPtr();
PVStructurePtr pvStructure =
std::tr1::static_pointer_cast<PVStructure>(pvField);
return findSubField(restOfName,pvStructure.get());
}
}
return PVFieldPtr();
}
std::ostream& PVStructure::dumpValue(std::ostream& o) const
{
o << format::indent() << getStructure()->getID() << ' ' << getFieldName();
@@ -382,4 +354,79 @@ std::ostream& PVStructure::dumpValue(std::ostream& o) const
return o;
}
void PVStructure::copy(const PVStructure& from)
{
if(isImmutable())
throw std::invalid_argument("destination is immutable");
if(*getStructure() != *from.getStructure())
throw std::invalid_argument("structure definitions do not match");
copyUnchecked(from);
}
void PVStructure::copyUnchecked(const PVStructure& from)
{
if (this == &from)
return;
PVFieldPtrArray const & fromPVFields = from.getPVFields();
PVFieldPtrArray const & toPVFields = getPVFields();
size_t fieldsSize = fromPVFields.size();
for(size_t i = 0; i<fieldsSize; i++) {
toPVFields[i]->copyUnchecked(*fromPVFields[i]);
}
}
void PVStructure::copyUnchecked(const PVStructure& from, const BitSet& maskBitSet, bool inverse)
{
if (this == &from)
return;
size_t numberFields = from.getNumberFields();
size_t offset = from.getFieldOffset();
int32 next = inverse ?
maskBitSet.nextClearBit(static_cast<uint32>(offset)) :
maskBitSet.nextSetBit(static_cast<uint32>(offset));
// no more changes or no changes in this structure
if(next<0||next>=static_cast<int32>(offset+numberFields)) return;
// entire structure
if(static_cast<int32>(offset)==next) {
copyUnchecked(from);
return;
}
PVFieldPtrArray const & fromPVFields = from.getPVFields();
PVFieldPtrArray const & toPVFields = getPVFields();
size_t fieldsSize = fromPVFields.size();
for(size_t i = 0; i<fieldsSize; i++) {
PVFieldPtr pvField = fromPVFields[i];
offset = pvField->getFieldOffset();
int32 inumberFields = static_cast<int32>(pvField->getNumberFields());
next = inverse ?
maskBitSet.nextClearBit(static_cast<uint32>(offset)) :
maskBitSet.nextSetBit(static_cast<uint32>(offset));
// no more changes
if(next<0) return;
// no change in this pvField
if(next>=static_cast<int32>(offset+inumberFields)) continue;
// serialize field or fields
if(inumberFields==1) {
toPVFields[i]->copyUnchecked(*pvField);
} else {
PVStructure::shared_pointer fromPVStructure = std::tr1::static_pointer_cast<PVStructure>(pvField);
PVStructure::shared_pointer toPVStructure = std::tr1::static_pointer_cast<PVStructure>(toPVFields[i]);
toPVStructure->copyUnchecked(*fromPVStructure, maskBitSet, inverse);
}
}
}
}}

View File

@@ -14,7 +14,6 @@
#define epicsExportSharedSymbols
#include <pv/pvData.h>
#include <pv/convert.h>
#include <pv/factory.h>
#include <pv/serializeHelper.h>
@@ -25,6 +24,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 +45,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 +68,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 +105,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 +116,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 +144,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 +161,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();
@@ -160,7 +178,7 @@ void PVStructureArray::deserialize(ByteBuffer *pbuffer,
data[i].reset();
}
else {
if(data[i].get()==NULL) {
if(data[i].get()==NULL || !data[i].unique()) {
data[i] = pvDataCreate->createPVStructure(structure);
}
data[i]->deserialize(pbuffer, pcontrol);
@@ -175,7 +193,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,9 +231,33 @@ 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;
}
void PVStructureArray::copy(const PVStructureArray& from)
{
if(isImmutable())
throw std::invalid_argument("destination is immutable");
if(*getStructureArray() != *from.getStructureArray())
throw std::invalid_argument("structureArray definitions do not match");
copyUnchecked(from);
}
void PVStructureArray::copyUnchecked(const PVStructureArray& from)
{
if (this == &from)
return;
replace(from.view());
}
}}

View File

@@ -16,7 +16,6 @@
#define epicsExportSharedSymbols
#include <pv/pvData.h>
#include <pv/pvIntrospect.h>
#include <pv/convert.h>
#include <pv/factory.h>
#include <pv/serializeHelper.h>
@@ -29,6 +28,8 @@ namespace epics { namespace pvData {
#define PVUNION_UNDEFINED_INDEX -1
int32 PVUnion::UNDEFINED_INDEX = PVUNION_UNDEFINED_INDEX;
PVDataCreatePtr PVUnion::pvDataCreate(getPVDataCreate());
PVUnion::PVUnion(UnionConstPtr const & unionPtr)
: PVField(unionPtr),
unionPtr(unionPtr),
@@ -87,7 +88,7 @@ PVFieldPtr PVUnion::select(int32 index)
FieldConstPtr field = unionPtr->getField(index);
selector = index;
value = getPVDataCreate()->createPVField(field);
value = pvDataCreate->createPVField(field);
return value;
}
@@ -169,7 +170,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 = pvDataCreate->createPVField(field);
value->deserialize(pbuffer, pcontrol);
}
else
@@ -177,11 +180,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 = pvDataCreate->createPVField(field);
}
value->deserialize(pbuffer, pcontrol);
}
else
@@ -209,4 +218,57 @@ std::ostream& PVUnion::dumpValue(std::ostream& o) const
return o;
}
void PVUnion::copy(const PVUnion& from)
{
if(isImmutable())
throw std::invalid_argument("destination is immutable");
if(*getUnion() != *from.getUnion())
throw std::invalid_argument("union definitions do not match");
copyUnchecked(from);
}
void PVUnion::copyUnchecked(const PVUnion& from)
{
PVFieldPtr fromValue = from.get();
if (from.getUnion()->isVariant())
{
if (fromValue.get() == 0)
{
set(PVField::shared_pointer());
}
else
{
PVFieldPtr toValue = get();
if (toValue.get() == 0 || *toValue->getField() != *fromValue->getField())
{
toValue = pvDataCreate->createPVField(fromValue->getField());
toValue->copyUnchecked(*fromValue);
set(toValue);
}
else
{
toValue->copyUnchecked(*fromValue);
postPut();
}
}
}
else
{
if (fromValue.get() == 0)
{
select(PVUnion::UNDEFINED_INDEX);
}
else
{
select(from.getSelectedIndex())->copyUnchecked(*fromValue);
}
postPut();
}
}
}}

View File

@@ -14,7 +14,6 @@
#define epicsExportSharedSymbols
#include <pv/pvData.h>
#include <pv/convert.h>
#include <pv/factory.h>
#include <pv/serializeHelper.h>
@@ -25,6 +24,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 +45,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 +68,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 +106,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 +116,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 +146,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 +160,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();
@@ -160,7 +177,7 @@ void PVUnionArray::deserialize(ByteBuffer *pbuffer,
data[i].reset();
}
else {
if(data[i].get()==NULL) {
if(data[i].get()==NULL || !data[i].unique()) {
data[i] = pvDataCreate->createPVUnion(punion);
}
data[i]->deserialize(pbuffer, pcontrol);
@@ -175,7 +192,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,9 +230,34 @@ 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;
}
void PVUnionArray::copy(const PVUnionArray& from)
{
if(isImmutable())
throw std::invalid_argument("destination is immutable");
if(*getUnionArray() != *from.getUnionArray())
throw std::invalid_argument("unionArray definitions do not match");
copyUnchecked(from);
}
void PVUnionArray::copyUnchecked(const PVUnionArray& from)
{
if (this == &from)
return;
replace(from.view());
}
}}

View File

@@ -89,9 +89,9 @@ StructureConstPtr StandardField::createProperties(string id,FieldConstPtr field,
}
if(type==structure) {
StructureConstPtr structurePtr = static_pointer_cast<const Structure>(field);
StringArray names = structurePtr->getFieldNames();
StringArray const & names = structurePtr->getFieldNames();
if(names.size()==2) {
FieldConstPtrArray fields = structurePtr->getFields();
FieldConstPtrArray const & fields = structurePtr->getFields();
FieldConstPtr first = fields[0];
FieldConstPtr second = fields[1];
string nameFirst = names[0];
@@ -162,7 +162,7 @@ void StandardField::createTimeStamp() {
FieldConstPtrArray fields(num);
StringArray names(num);
names[0] = "secondsPastEpoch";
names[1] = "nanoSeconds";
names[1] = "nanoseconds";
names[2] = "userTag";
fields[0] = fieldCreate->createScalar(pvLong);
fields[1] = fieldCreate->createScalar(pvInt);
@@ -228,7 +228,7 @@ void StandardField::createByteAlarm() {
names[6] = "lowWarningSeverity";
names[7] = "highWarningSeverity";
names[8] = "highAlarmSeverity";
names[9] = "hystersis";
names[9] = "hysteresis";
fields[0] = fieldCreate->createScalar(pvBoolean);
fields[1] = fieldCreate->createScalar(pvByte);
fields[2] = fieldCreate->createScalar(pvByte);
@@ -255,7 +255,7 @@ void StandardField::createShortAlarm() {
names[6] = "lowWarningSeverity";
names[7] = "highWarningSeverity";
names[8] = "highAlarmSeverity";
names[9] = "hystersis";
names[9] = "hysteresis";
fields[0] = fieldCreate->createScalar(pvBoolean);
fields[1] = fieldCreate->createScalar(pvShort);
fields[2] = fieldCreate->createScalar(pvShort);
@@ -282,7 +282,7 @@ void StandardField::createIntAlarm() {
names[6] = "lowWarningSeverity";
names[7] = "highWarningSeverity";
names[8] = "highAlarmSeverity";
names[9] = "hystersis";
names[9] = "hysteresis";
fields[0] = fieldCreate->createScalar(pvBoolean);
fields[1] = fieldCreate->createScalar(pvInt);
fields[2] = fieldCreate->createScalar(pvInt);
@@ -309,7 +309,7 @@ void StandardField::createLongAlarm() {
names[6] = "lowWarningSeverity";
names[7] = "highWarningSeverity";
names[8] = "highAlarmSeverity";
names[9] = "hystersis";
names[9] = "hysteresis";
fields[0] = fieldCreate->createScalar(pvBoolean);
fields[1] = fieldCreate->createScalar(pvLong);
fields[2] = fieldCreate->createScalar(pvLong);
@@ -336,7 +336,7 @@ void StandardField::createUByteAlarm() {
names[6] = "lowWarningSeverity";
names[7] = "highWarningSeverity";
names[8] = "highAlarmSeverity";
names[9] = "hystersis";
names[9] = "hysteresis";
fields[0] = fieldCreate->createScalar(pvBoolean);
fields[1] = fieldCreate->createScalar(pvUByte);
fields[2] = fieldCreate->createScalar(pvUByte);
@@ -363,7 +363,7 @@ void StandardField::createUShortAlarm() {
names[6] = "lowWarningSeverity";
names[7] = "highWarningSeverity";
names[8] = "highAlarmSeverity";
names[9] = "hystersis";
names[9] = "hysteresis";
fields[0] = fieldCreate->createScalar(pvBoolean);
fields[1] = fieldCreate->createScalar(pvUShort);
fields[2] = fieldCreate->createScalar(pvUShort);
@@ -390,7 +390,7 @@ void StandardField::createUIntAlarm() {
names[6] = "lowWarningSeverity";
names[7] = "highWarningSeverity";
names[8] = "highAlarmSeverity";
names[9] = "hystersis";
names[9] = "hysteresis";
fields[0] = fieldCreate->createScalar(pvBoolean);
fields[1] = fieldCreate->createScalar(pvUInt);
fields[2] = fieldCreate->createScalar(pvUInt);
@@ -417,7 +417,7 @@ void StandardField::createULongAlarm() {
names[6] = "lowWarningSeverity";
names[7] = "highWarningSeverity";
names[8] = "highAlarmSeverity";
names[9] = "hystersis";
names[9] = "hysteresis";
fields[0] = fieldCreate->createScalar(pvBoolean);
fields[1] = fieldCreate->createScalar(pvULong);
fields[2] = fieldCreate->createScalar(pvULong);
@@ -444,7 +444,7 @@ void StandardField::createFloatAlarm() {
names[6] = "lowWarningSeverity";
names[7] = "highWarningSeverity";
names[8] = "highAlarmSeverity";
names[9] = "hystersis";
names[9] = "hysteresis";
fields[0] = fieldCreate->createScalar(pvBoolean);
fields[1] = fieldCreate->createScalar(pvFloat);
fields[2] = fieldCreate->createScalar(pvFloat);
@@ -471,7 +471,7 @@ void StandardField::createDoubleAlarm() {
names[6] = "lowWarningSeverity";
names[7] = "highWarningSeverity";
names[8] = "highAlarmSeverity";
names[9] = "hystersis";
names[9] = "hysteresis";
fields[0] = fieldCreate->createScalar(pvBoolean);
fields[1] = fieldCreate->createScalar(pvDouble);
fields[2] = fieldCreate->createScalar(pvDouble);
@@ -503,28 +503,28 @@ StructureConstPtr StandardField::scalar(
ScalarType type,string const &properties)
{
ScalarConstPtr field = fieldCreate->createScalar(type); // scalar_t
return createProperties("uri:ev4:nt/2012/pwd:NTScalar",field,properties);
return createProperties("epics:nt/NTScalar:1.0",field,properties);
}
StructureConstPtr StandardField::regUnion(
UnionConstPtr const &field,
string const & properties)
{
return createProperties("uri:ev4:nt/2012/pwd:NTUnion",field,properties);
return createProperties("epics:nt/NTUnion:1.0",field,properties);
}
StructureConstPtr StandardField::variantUnion(
string const & properties)
{
UnionConstPtr field = fieldCreate->createVariantUnion();
return createProperties("uri:ev4:nt/2012/pwd:NTUnion",field,properties);
return createProperties("epics:nt/NTUnion:1.0",field,properties);
}
StructureConstPtr StandardField::scalarArray(
ScalarType elementType, string const &properties)
{
ScalarArrayConstPtr field = fieldCreate->createScalarArray(elementType); // scalar_t[]
return createProperties("uri:ev4:nt/2012/pwd:NTScalarArray",field,properties);
return createProperties("epics:nt/NTScalarArray:1.0",field,properties);
}
@@ -533,7 +533,7 @@ StructureConstPtr StandardField::structureArray(
{
StructureArrayConstPtr field = fieldCreate->createStructureArray(
structure);
return createProperties("uri:ev4:nt/2012/pwd:NTStructureArray",field,properties);
return createProperties("epics:nt/NTStructureArray:1.0",field,properties);
}
StructureConstPtr StandardField::unionArray(
@@ -541,7 +541,7 @@ StructureConstPtr StandardField::unionArray(
{
UnionArrayConstPtr field = fieldCreate->createUnionArray(
punion);
return createProperties("uri:ev4:nt/2012/pwd:NTUnionArray",field,properties);
return createProperties("epics:nt/NTUnionArray:1.0",field,properties);
}
StructureConstPtr StandardField::enumerated()
@@ -554,13 +554,13 @@ StructureConstPtr StandardField::enumerated()
fields[0] = fieldCreate->createScalar(pvInt);
fields[1] = fieldCreate->createScalarArray(pvString);
return fieldCreate->createStructure("enum_t",names,fields);
// NOTE: if this method is used to get NTEnum wihtout properties the ID will be wrong!
// NOTE: if this method is used to get NTEnum without properties the ID will be wrong!
}
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

@@ -14,7 +14,6 @@
#include <pv/lock.h>
#include <pv/pvIntrospect.h>
#include <pv/pvData.h>
#include <pv/convert.h>
#include <pv/standardField.h>
#include <pv/standardPVField.h>
@@ -67,11 +66,9 @@ PVStructurePtr StandardPVField::enumerated(StringArray const &choices)
{
StructureConstPtr field = standardField->enumerated();
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(field);
PVScalarArrayPtr pvScalarArray = pvStructure->getScalarArrayField(
"choices",pvString);
PVStringArray::svector cdata(choices.size());
std::copy(choices.begin(), choices.end(), cdata.begin());
static_cast<PVStringArray&>(*pvScalarArray).replace(freeze(cdata));
pvStructure->getSubField<PVStringArray>("choices")->replace(freeze(cdata));
return pvStructure;
}
@@ -80,11 +77,9 @@ PVStructurePtr StandardPVField::enumerated(
{
StructureConstPtr field = standardField->enumerated(properties);
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(field);
PVScalarArrayPtr pvScalarArray = pvStructure->getScalarArrayField(
"value.choices",pvString);
PVStringArray::svector cdata(choices.size());
std::copy(choices.begin(), choices.end(), cdata.begin());
static_cast<PVStringArray&>(*pvScalarArray).replace(freeze(cdata));
pvStructure->getSubField<PVStringArray>("value.choices")->replace(freeze(cdata));
return pvStructure;
}

View File

@@ -8,25 +8,22 @@
#include <deque>
#define epicsExportSharedSymbols
#include <pv/printer.h>
#include <pv/pvIntrospect.h>
using std::string;
namespace {
void indentN(std::ostream& strm, size_t N)
{
while(N--)
strm.put(' ');
}
}
namespace epics { namespace pvData {
namespace format
{
std::ostream& operator<<(std::ostream& os, indent_level const& indent)
static int indent_index = std::ios_base::xalloc();
long& indent_value(std::ios_base& ios)
{
return ios.iword(indent_index);
}
std::ostream& operator<<(std::ostream& os, indent_level const& indent)
{
indent_value(os) = indent.level;
return os;
@@ -45,246 +42,4 @@ namespace format
}
};
PrinterBase::PrinterBase()
:strm(NULL)
{}
PrinterBase::~PrinterBase() {}
void PrinterBase::setStream(std::ostream& s)
{
strm = &s;
}
void PrinterBase::clearStream()
{
strm = NULL;
}
void PrinterBase::print(const PVField& pv)
{
if(!strm)
throw std::runtime_error("No stream set for PV Printer");
impl_print(pv);
}
void PrinterBase::beginStructure(const PVStructure&) {}
void PrinterBase::endStructure(const PVStructure&) {}
void PrinterBase::beginStructureArray(const PVStructureArray&) {}
void PrinterBase::endStructureArray(const PVStructureArray&) {}
void PrinterBase::beginUnion(const PVUnion&) {}
void PrinterBase::endUnion(const PVUnion&) {}
void PrinterBase::beginUnionArray(const PVUnionArray&) {}
void PrinterBase::endUnionArray(const PVUnionArray&) {}
void PrinterBase::encodeScalar(const PVScalar&) {}
void PrinterBase::encodeArray(const PVScalarArray&) {}
void PrinterBase::encodeNull() {}
void PrinterBase::impl_print(const PVField& pv)
{
static const PVField* marker = (const PVField*)&marker;
/* Depth first recursive iteration.
* Each PV to be printed is appended to the todo queue.
* The last child of a structure is followed by a NULL.
* As the tree is walked structures and structarrays
* are appended to the inprog queue.
*/
std::deque<const PVField*> todo, inprog;
todo.push_back(&pv);
while(!todo.empty()) {
const PVField *next = todo.front();
todo.pop_front();
if(next==marker) {
// finished with a structure or structarray,
// now we fall back to its parent.
assert(!inprog.empty());
switch(inprog.back()->getField()->getType()) {
case structure:
endStructure(*static_cast<const PVStructure *>(inprog.back()));
break;
case structureArray:
endStructureArray(*static_cast<const PVStructureArray *>(inprog.back()));
break;
case union_:
endUnion(*static_cast<const PVUnion *>(inprog.back()));
break;
case unionArray:
endUnionArray(*static_cast<const PVUnionArray *>(inprog.back()));
break;
default:
assert(false); // oops!
return;
}
inprog.pop_back();
} else {
// real field
if(!next) {
// NULL entry in a structure array
encodeNull();
continue;
}
switch(next->getField()->getType()) {
case scalar:
encodeScalar(*static_cast<const PVScalar*>(next));
break;
case scalarArray:
encodeArray(*static_cast<const PVScalarArray*>(next));
break;
case structure: {
const PVStructure &fld = *static_cast<const PVStructure*>(next);
const PVFieldPtrArray& vals = fld.getPVFields();
inprog.push_back(next);
beginStructure(fld);
for(size_t i=0, nfld=fld.getStructure()->getNumberFields(); i<nfld; i++)
todo.push_back(vals[i].get());
todo.push_back(marker);
break;
}
case structureArray: {
const PVStructureArray &fld = *static_cast<const PVStructureArray*>(next);
PVStructureArray::const_svector vals(fld.view());
inprog.push_back(next);
beginStructureArray(fld);
for(PVStructureArray::const_svector::const_iterator it=vals.begin();
it!=vals.end(); ++it)
{
todo.push_back(it->get());
}
todo.push_back(marker);
break;
}
case union_: {
const PVUnion &fld = *static_cast<const PVUnion*>(next);
inprog.push_back(next);
beginUnion(fld);
PVFieldPtr val = fld.get();
if (val.get()) // TODO print "(none)" ?
todo.push_back(val.get());
todo.push_back(marker);
break;
}
case unionArray: {
const PVUnionArray &fld = *static_cast<const PVUnionArray*>(next);
PVUnionArray::const_svector vals(fld.view());
inprog.push_back(next);
beginUnionArray(fld);
for(PVUnionArray::const_svector::const_iterator it=vals.begin();
it!=vals.end(); ++it)
{
todo.push_back(it->get());
}
todo.push_back(marker);
break;
}
}
}
}
}
PrinterPlain::PrinterPlain()
:PrinterBase()
,ilvl(0)
{}
PrinterPlain::~PrinterPlain() {}
void PrinterPlain::beginStructure(const PVStructure& pv)
{
indentN(S(), ilvl);
S() << pv.getStructure()->getID() << " " << pv.getFieldName();
S() << std::endl;
ilvl++;
}
void PrinterPlain::endStructure(const PVStructure&) {ilvl--;}
void PrinterPlain::beginStructureArray(const PVStructureArray& pv)
{
indentN(S(), ilvl);
S() << pv.getStructureArray()->getID() << " "
<< pv.getFieldName() << "[] ";
ilvl++;
}
void PrinterPlain::endStructureArray(const PVStructureArray&) {ilvl--;}
void PrinterPlain::beginUnion(const PVUnion& pv)
{
indentN(S(), ilvl);
S() << pv.getUnion()->getID() << " " << pv.getFieldName() << std::endl;
ilvl++;
}
void PrinterPlain::endUnion(const PVUnion&) {ilvl--;}
void PrinterPlain::beginUnionArray(const PVUnionArray& pv)
{
indentN(S(), ilvl);
S() << pv.getUnionArray()->getID() << " "
<< pv.getFieldName() << "[] ";
ilvl++;
}
void PrinterPlain::endUnionArray(const PVUnionArray&) {ilvl--;}
void PrinterPlain::encodeScalar(const PVScalar& pv)
{
indentN(S(), ilvl);
S() << pv.getScalar()->getID() << " "
<< pv.getFieldName() << " "
<< pv.getAs<string>() << std::endl;
}
void PrinterPlain::encodeArray(const PVScalarArray& pv)
{
indentN(S(), ilvl);
shared_vector<const string> temp;
pv.getAs<string>(temp);
S() << pv.getScalarArray()->getID() << " "
<< pv.getFieldName() << " [";
for(size_t i=0, len=pv.getLength(); i<len; i++) {
S() << temp[i];
if(i!=len-1)
S().put(',');
}
S() << "]" << std::endl;
}
void PrinterPlain::encodeNull()
{
indentN(S(), ilvl);
S() << "NULL" << std::endl;
}
}}

View File

@@ -22,7 +22,6 @@ INC += status.h
INC += sharedPtr.h
INC += localStaticLock.h
INC += typeCast.h
INC += printer.h
INC += sharedVector.h
INC += templateMeta.h
INC += current_function.h

View File

@@ -24,16 +24,18 @@ namespace epics { namespace pvData {
typedef std::tr1::shared_ptr<BitSet> BitSetPtr;
/**
* @brief A vector of bits.
*
* This class implements a vector of bits that grows as needed. Each
* component of the bit set has a {@code bool} value. The
* bits of a {@code BitSet} are indexed by nonnegative integers.
* Individual indexed bits can be examined, set, or cleared. One
* {@code BitSet} may be used to modify the contents of another
* {@code BitSet} through logical AND, logical inclusive OR, and
* logical exclusive OR operations.
* component of the bit set has a @c bool value. The bits of a
* @c BitSet are indexed by nonnegative integers. Individual
* indexed bits can be examined, set, or cleared. One @c BitSet may
* be used to modify the contents of another @c BitSet through
* logical AND, logical inclusive OR, and logical exclusive OR
* operations.
*
* <p>By default, all bits in the set initially have the value
* {@code false}.
* @c false.
*
* <p>Every bit set has a current size, which is the number of bits
* of space currently in use by the bit set. Note that the size is
@@ -41,8 +43,8 @@ namespace epics { namespace pvData {
* implementation. The length of a bit set relates to logical length
* of a bit set and is defined independently of implementation.
*
* <p>A {@code BitSet} is not safe for multithreaded use without
* external synchronization.
* <p>A @c BitSet is not safe for multithreaded use without external
* synchronization.
*
* Based on Java implementation.
*/
@@ -51,14 +53,14 @@ namespace epics { namespace pvData {
POINTER_DEFINITIONS(BitSet);
static BitSetPtr create(uint32 nbits);
/**
* Creates a new bit set. All bits are initially {@code false}.
* Creates a new bit set. All bits are initially @c false.
*/
BitSet();
/**
* Creates a bit set whose initial size is large enough to explicitly
* represent bits with indices in the range {@code 0} through
* {@code nbits-1}. All bits are initially {@code false}.
* represent bits with indices in the range @c 0 through
* @c nbits-1. All bits are initially @c false.
*
* @param nbits the initial size of the bit set
*/
@@ -78,14 +80,14 @@ namespace epics { namespace pvData {
void flip(uint32 bitIndex);
/**
* Sets the bit at the specified index to {@code true}.
* Sets the bit at the specified index to @c true.
*
* @param bitIndex a bit index
*/
void set(uint32 bitIndex);
/**
* Sets the bit specified by the index to {@code false}.
* Sets the bit specified by the index to @c false.
*
* @param bitIndex the index of the bit to be cleared
*/
@@ -101,9 +103,8 @@ namespace epics { namespace pvData {
/**
* Returns the value of the bit with the specified index. The value
* is {@code true} if the bit with the index {@code bitIndex}
* is currently set in this {@code BitSet}; otherwise, the result
* is {@code false}.
* is @c true if the bit with the index @c bitIndex is currently
* set in this @c BitSet; otherwise, the result is @c false.
*
* @param bitIndex the bit index
* @return the value of the bit with the specified index
@@ -111,16 +112,16 @@ namespace epics { namespace pvData {
bool get(uint32 bitIndex) const;
/**
* Sets all of the bits in this BitSet to {@code false}.
* Sets all of the bits in this BitSet to @c false.
*/
void clear();
/**
* Returns the index of the first bit that is set to {@code true}
* that occurs on or after the specified starting index. If no such
* bit exists then {@code -1} is returned.
* Returns the index of the first bit that is set to @c true that
* occurs on or after the specified starting index. If no such bit
* exists then @c -1 is returned.
*
* <p>To iterate over the {@code true} bits in a {@code BitSet},
* <p>To iterate over the @c true bits in a @c BitSet,
* use the following loop:
*
* <pre> {@code
@@ -129,13 +130,13 @@ namespace epics { namespace pvData {
* }}</pre>
*
* @param fromIndex the index to start checking from (inclusive)
* @return the index of the next set bit, or {@code -1} if there
* @return the index of the next set bit, or @c -1 if there
* is no such bit
*/
int32 nextSetBit(uint32 fromIndex) const;
/**
* Returns the index of the first bit that is set to {@code false}
* Returns the index of the first bit that is set to @c false
* that occurs on or after the specified starting index.
*
* @param fromIndex the index to start checking from (inclusive)
@@ -144,23 +145,23 @@ namespace epics { namespace pvData {
int32 nextClearBit(uint32 fromIndex) const;
/**
* Returns true if this {@code BitSet} contains no bits that are set
* to {@code true}.
* Returns true if this @c BitSet contains no bits that are set
* to @c true.
*
* @return indicating whether this {@code BitSet} is empty
* @return indicating whether this @c BitSet is empty
*/
bool isEmpty() const;
/**
* Returns the number of bits set to {@code true} in this {@code BitSet}.
* Returns the number of bits set to @c true in this @c BitSet.
*
* @return the number of bits set to {@code true} in this {@code BitSet}
* @return the number of bits set to @c true in this @c BitSet
*/
uint32 cardinality() const;
/**
* Returns the number of bits of space actually in use by this
* {@code BitSet} to represent bit values.
* @c BitSet to represent bit values.
* The maximum element in the set is the size - 1st element.
*
* @return the number of bits currently in this bit set
@@ -170,9 +171,9 @@ namespace epics { namespace pvData {
/**
* Performs a logical <b>AND</b> of this target bit set with the
* argument bit set. This bit set is modified so that each bit in it
* has the value {@code true} if and only if it both initially
* had the value {@code true} and the corresponding bit in the
* bit set argument also had the value {@code true}.
* has the value @c true if and only if it both initially
* had the value @c true and the corresponding bit in the
* bit set argument also had the value @c true.
*
* @param set a bit set
*/
@@ -181,9 +182,9 @@ namespace epics { namespace pvData {
/**
* Performs a logical <b>OR</b> of this bit set with the bit set
* argument. This bit set is modified so that a bit in it has the
* value {@code true} if and only if it either already had the
* value {@code true} or the corresponding bit in the bit set
* argument has the value {@code true}.
* value @c true if and only if it either already had the
* value @c true or the corresponding bit in the bit set
* argument has the value @c true.
*
* @param set a bit set
*/
@@ -192,13 +193,13 @@ namespace epics { namespace pvData {
/**
* Performs a logical <b>XOR</b> of this bit set with the bit set
* argument. This bit set is modified so that a bit in it has the
* value {@code true} if and only if one of the following
* value @c true if and only if one of the following
* statements holds:
* <ul>
* <li>The bit initially has the value {@code true}, and the
* corresponding bit in the argument has the value {@code false}.
* <li>The bit initially has the value {@code false}, and the
* corresponding bit in the argument has the value {@code true}.
* <li>The bit initially has the value @c true, and the
* corresponding bit in the argument has the value @c false.
* <li>The bit initially has the value @c false, and the
* corresponding bit in the argument has the value @c true.
* </ul>
*
* @param set a bit set
@@ -206,7 +207,7 @@ namespace epics { namespace pvData {
BitSet& operator^=(const BitSet& set);
/**
* Assigment operator.
* Assignment operator.
*/
BitSet& operator=(const BitSet &set);

View File

@@ -144,6 +144,24 @@ inline int64 swap(int64 val)
return swap64(val);
}
template<>
inline uint16 swap(uint16 val)
{
return swap16(val);
}
template<>
inline uint32 swap(uint32 val)
{
return swap32(val);
}
template<>
inline uint64 swap(uint64 val)
{
return swap64(val);
}
template<>
inline float swap(float val)
{
@@ -188,8 +206,9 @@ inline double swap(double val)
#endif
/**
* This class implements {@code Bytebuffer} that is like the {@code java.nio.ByteBuffer}.
* <p>A {@code BitSet} is not safe for multithreaded use without
* @brief This class implements a Bytebuffer that is like the java.nio.ByteBuffer.
*
* <p>A @c BitSet is not safe for multithreaded use without
* external synchronization.
*
* Based on Java implementation.
@@ -354,7 +373,7 @@ public:
template<typename T>
inline void put(std::size_t index, T value);
/**
* Get the new object from the byte buffer. The item MUST have type {@code T}.
* Get the new object from the byte buffer. The item MUST have type @c T.
* The position is adjusted based on the type.
*
* @return The object.
@@ -368,7 +387,7 @@ public:
#endif
/**
* Get the new object from the byte buffer at the specified index.
* The item MUST have type {@code T}.
* The item MUST have type @c T.
* The position is adjusted based on the type.
*
* @param index The location in the byte buffer.
@@ -380,9 +399,9 @@ public:
* Put a sub-array of bytes into the byte buffer.
* The position is increased by the count.
*
* @param src The source array.
* @param offset The starting position within src.
* @param count The number of bytes to put into the byte buffer,
* @param src The source array.
* @param src_offset The starting position within src.
* @param count The number of bytes to put into the byte buffer,
*/
inline void put(const char* src, std::size_t src_offset, std::size_t count) {
//if(count>getRemaining()) THROW_BASE_EXCEPTION("buffer overflow");
@@ -393,9 +412,9 @@ public:
* Get a sub-array of bytes from the byte buffer.
* The position is increased by the count.
*
* @param dest The destination array.
* @param offset The starting position within src.
* @param count The number of bytes to put into the byte buffer,
* @param dest The destination array.
* @param dest_offset The starting position within src.
* @param count The number of bytes to put into the byte buffer.
*/
inline void get(char* dest, std::size_t dest_offset, std::size_t count) {
//if(count>getRemaining()) THROW_BASE_EXCEPTION("buffer overflow");
@@ -403,7 +422,7 @@ public:
_position += count;
}
/**
* Put an array of type {@code T} into the byte buffer.
* Put an array of type @c T into the byte buffer.
* The position is adjusted.
*
* @param values The input array.
@@ -412,7 +431,7 @@ public:
template<typename T>
inline void putArray(const T* values, std::size_t count);
/**
* Get an array of type {@code T} from the byte buffer.
* Get an array of type @c T from the byte buffer.
* The position is adjusted.
*
* @param values The destination array.
@@ -618,7 +637,7 @@ public:
/**
* Get a boolean value from the byte buffer at the specified index.
*
* @param double The offset in the byte buffer.
* @param index The offset in the byte buffer.
* @return The value.
*/
inline double getDouble (std::size_t index) { return get<double>(index); }
@@ -695,7 +714,7 @@ private:
}
else
{
// NOTE: this check and branching does not always payoff
// NOTE: this check and branching does not always pay off
if (ADAPTIVE_ACCESS && is_aligned(_position, sizeof(T)))
{
*((T*)_position) = value;
@@ -738,12 +757,12 @@ private:
if (UNALIGNED_ACCESS)
{
// NOTE: some CPU handle unaligned access preety good (e.g. x86)
// NOTE: some CPU handle unaligned access pretty good (e.g. x86)
*((T*)(_buffer + index)) = value;
}
else
{
// NOTE: this check and branching does not always payoff
// NOTE: this check and branching does not always pay off
if (ADAPTIVE_ACCESS && is_aligned(_position, sizeof(T)))
{
*((T*)(_buffer + index)) = value;
@@ -786,13 +805,13 @@ private:
if (UNALIGNED_ACCESS)
{
// NOTE: some CPU handle unaligned access preety good (e.g. x86)
// NOTE: some CPU handle unaligned access pretty good (e.g. x86)
value = *((T*)_position);
_position += sizeof(T);
}
else
{
// NOTE: this check and branching does not always payoff
// NOTE: this check and branching does not always pay off
if (ADAPTIVE_ACCESS && is_aligned(_position, sizeof(T)))
{
value = *((T*)_position);
@@ -838,12 +857,12 @@ private:
if (UNALIGNED_ACCESS)
{
// NOTE: some CPU handle unaligned access preety good (e.g. x86)
// NOTE: some CPU handle unaligned access pretty good (e.g. x86)
value = *((T*)(_buffer + index));
}
else
{
// NOTE: this check and branching does not always payoff
// NOTE: this check and branching does not always pay off
if (ADAPTIVE_ACCESS && is_aligned(_position, sizeof(T)))
{
value = *((T*)(_buffer + index));
@@ -890,7 +909,7 @@ private:
memcpy(_position, values, n);
_position += n;
// ... so that we can be fast changing endianess
// ... so that we can be fast changing endianness
if (ENDIANESS_SUPPORT && reverse<T>())
{
for (std::size_t i = 0; i < count; i++)
@@ -918,7 +937,7 @@ private:
memcpy(values, _position, n);
_position += n;
// ... so that we can be fast changing endianess
// ... so that we can be fast changing endianness
if (ENDIANESS_SUPPORT && reverse<T>())
{
for (std::size_t i = 0; i < count; i++)

View File

@@ -18,7 +18,8 @@ namespace epics { namespace pvData {
/**
* Instance declaring destroy method.
* @brief Instance declaring destroy method.
*
* @author mse
*/
class epicsShareClass Destroyable {

View File

@@ -202,13 +202,26 @@ do { \
#define THROW_EXCEPTION2(E,A) do{throw (E)(A);}while(0)
#endif // THROW_EXCEPTION_COMPAT
/**
* @brief Base for pvData exceptions.
*
*/
class epicsShareClass BaseException : public std::logic_error {
public:
/**
* Constructor.
*/
explicit BaseException(const std::string msg) : std::logic_error(msg) {}
/**
* Destructor.
*/
virtual ~BaseException() throw(){};
/**
*
* Reason for excepton.
*/
virtual const char* what() const throw();
private:

View File

@@ -38,8 +38,7 @@ Event::~Event() {
Event::Event(bool full)
: id(epicsEventCreate(full?epicsEventFull : epicsEventEmpty)),
alreadyOn("already on list")
: id(epicsEventCreate(full?epicsEventFull : epicsEventEmpty))
{
}

View File

@@ -35,18 +35,44 @@ namespace epics { namespace pvData {
class Event;
typedef std::tr1::shared_ptr<Event> EventPtr;
/**
* @brief C++ wrapper for epicsEvent from EPICS base.
*
*/
class epicsShareClass Event {
public:
POINTER_DEFINITIONS(Event);
/**
* Constructor
*/
explicit Event(bool = false);
/**
* Destructor.
*/
~Event();
/**
* Signal the event i.e. ensures that the next or current call to wait completes.
*/
void signal();
/**
* wait
* @return (false,true) if (some error, event signaled).
* The next wait or tryWait will clear signal.
*/
bool wait (); /* blocks until full */
/**
* wait for up to timeOut seconds.
* @param timeOut max number of seconds to wait
* @return (false, true) if (timeout or error, event signaled).
*/
bool wait ( double timeOut ); /* false if empty at time out */
/**
* See if a signal has been called.
* @return (false, true) if (timeout or error, event signaled).
*/
bool tryWait (); /* false if empty */
private:
epicsEventId id;
std::string alreadyOn;
};
}}

View File

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

View File

@@ -27,22 +27,56 @@ class Executor;
typedef std::tr1::shared_ptr<Command> CommandPtr;
typedef std::tr1::shared_ptr<Executor> ExecutorPtr;
/**
* @brief A command to be called by Executor
*
*/
class epicsShareClass Command {
public:
POINTER_DEFINITIONS(Command);
/**
*
* Destructor
*/
virtual ~Command(){}
/**
*
* The command that is executed.
*/
virtual void command() = 0;
private:
CommandPtr next;
friend class Executor;
};
/**
* @brief A class that executes commands.
*
*/
class epicsShareClass Executor : public Runnable{
public:
POINTER_DEFINITIONS(Executor);
/**
* Constructor
*
* @param threadName name for the executor thread.
* @param priority The thread priority.
*/
Executor(std::string const & threadName,ThreadPriority priority);
/**
* Destructor
*/
~Executor();
void execute(CommandPtr const &node);
/**
*
* Request to execute a command.
* @param command A shared pointer to the command instance.
*/
void execute(CommandPtr const &command);
/**
*
* The thread run method.
*/
virtual void run();
private:
CommandPtr head;

View File

@@ -38,12 +38,30 @@ namespace epics { namespace pvData {
typedef epicsMutex Mutex;
/**
* @brief A lock for multithreading
*
* This is based on item 14 of
* * Effective C++, Third Edition, Scott Meyers
*/
class epicsShareClass Lock : private NoDefaultMethods {
public:
/**
* Constructor
* @param m The mutex for the facility being locked.
*/
explicit Lock(Mutex &m)
: mutexPtr(m), locked(true)
{ mutexPtr.lock();}
/**
* Destructor
* Note that destructor does an automatic unlock.
*/
~Lock(){unlock();}
/**
* Take the lock
* Recursive locks are supported but each lock must be matched with an unlock.
*/
void lock()
{
if(!locked)
@@ -52,6 +70,9 @@ public:
locked = true;
}
}
/**
* release the lock.
*/
void unlock()
{
if(locked)
@@ -60,6 +81,10 @@ public:
locked=false;
}
}
/**
* If lock is not held take the lock.
* @return (false,true) if caller (does not have, has) the lock.
*/
bool tryLock()
{
if(locked) return true;
@@ -69,6 +94,10 @@ public:
}
return false;
}
/**
* See if caller has the lock,
* @return (false,true) if caller (does not have, has) the lock.
*/
bool ownsLock() const{return locked;}
private:
Mutex &mutexPtr;

View File

@@ -28,10 +28,26 @@ typedef std::tr1::shared_ptr<MessageNode> MessageNodePtr;
typedef std::vector<MessageNodePtr> MessageNodePtrArray;
typedef std::tr1::shared_ptr<MessageQueue> MessageQueuePtr;
/**
* @brief A node that can be put on a MessageQueue.
*
*/
class epicsShareClass MessageNode {
public:
/**
* Constructor
*/
MessageNode();
/**
*
* Get the message value.
* @return The message value.
*/
std::string getMessage() const;
/**
* Get the message type.
* @return The message type which is defined in Requester.
*/
MessageType getMessageType() const;
private:
std::string message;
@@ -39,19 +55,65 @@ private:
friend class MessageQueue;
};
/**
* @brief A bounded queue for messages.
*
*
*/
class epicsShareClass MessageQueue : public Queue<MessageNode> {
public:
POINTER_DEFINITIONS(MessageQueue);
/**
* Factory method to create a MessageQueue.
* @param size The number of MessageNodes in the queue.
* @return shared_ptr to MessageQueue.
*/
static MessageQueuePtr create(int size);
/**
* Constructor
* @param nodeArray an array of shared_ptr to MessageNodes,
*/
MessageQueue(MessageNodePtrArray &nodeArray);
/**
* Destructor
*/
virtual ~MessageQueue();
/**
* get the next MessageNode of the queue.
* @return A shared_ptr to the MessageNode.
* This will be a null pointer if queue is empty.
* If get is successful then release for this MessageNode
* must be called before another get can be issued.
*/
MessageNodePtr &get();
// must call release before next get
/**
* Release the MessageNode that was returned by the previous call to get.
*/
void release();
// return (false,true) if message (was not, was) put into queue
/**
*
* put a message into the message queue
* @param message The message string.
* @param messageType The message type as defined in Requester,
* @param replaceLast If true and queue is full then replace.
* @return (false,true) if a message (was not, was) put in queiue.
*/
bool put(std::string message,MessageType messageType,bool replaceLast);
/**
* Is queue empty?
* @return (false,true) if (is not, is) empty.
*/
bool isEmpty() ;
/**
* Is queue full?
* @return (false,true) if (is not, is) full.
*/
bool isFull() ;
/**
*
* Clear number of times queue was overrun and return the number
* of times the queue was overrun.
*/
int getClearOverrun();
private:
MessageNodePtr nullNode;

View File

@@ -17,17 +17,26 @@ namespace epics { namespace pvData {
* Effective C++, Third Edition, Scott Meyers
*/
class epicsShareClass NoDefaultMethods {
protected:
// allow by derived objects
/**
* @brief Base class for not allowing default methods.
*
* Note that copy constructor a copy methods are declared private.
*/
class epicsShareClass NoDefaultMethods {
protected:
/**
* Constructor
*/
NoDefaultMethods(){};
/**
* Destructor
*/
~NoDefaultMethods(){}
private:
// do not implment
// do not implement
NoDefaultMethods(const NoDefaultMethods&);
NoDefaultMethods & operator=(const NoDefaultMethods &);
};
};
}}
#endif /* NO_DEFAULT_METHODS_H */

View File

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

View File

@@ -18,6 +18,12 @@
namespace epics { namespace pvData {
/**
* @brief Template class for a bounded queue.
*
* An instance can make a queueElement be any class desired
* but must create a std::vector of shared_ptr to queueElements.
*/
template <typename T>
class Queue
{
@@ -25,15 +31,58 @@ public:
POINTER_DEFINITIONS(Queue);
typedef std::tr1::shared_ptr<T> queueElementPtr;
typedef std::vector<queueElementPtr> queueElementPtrArray;
Queue(queueElementPtrArray &);
/**
* Constructor
* @param elementArray The vector of shared_ptr to queue elements.
*/
Queue(queueElementPtrArray & elementArray);
/**
* Destructor
*/
virtual ~Queue();
/**
* Clear the queue.
*/
void clear();
/**
* get the capacity of the queue, i. e. number of queue elements,
* @return The capacity.
*/
int capacity();
/**
* Get the number of free elements in the queue.
* @return The number.
*/
int getNumberFree();
/**
* Get the number of used elements in the queue.
* This is the number that have been setUsed but not released.
* @return The number.
*/
int getNumberUsed();
/**
* Get the next free element.
* @return a shared_ptr to the queue element.
* This is null if queue was full.
*/
queueElementPtr & getFree();
/**
* Set the element returned by getFree as used.
* Until this is called getUsed will not return it.
* @param element The element. It must be the element returned
* by the most recent call to getUsed.
*/
void setUsed(queueElementPtr const &element);
/**
* Get the oldest used element;
* @return a shared_ptr to the queue element.
* This is null if no used element is available.`
*/
queueElementPtr & getUsed();
/**
* Release the element obtained by the most recent call to getUsed.
* @param element The element.
*/
void releaseUsed(queueElementPtr const &element);
private:
queueElementPtr nullElement;

View File

@@ -28,11 +28,43 @@ enum MessageType {
epicsShareExtern std::string getMessageTypeName(MessageType messageType);
/**
* @brief Callback class for passing messages to a requester.
*
* This is used by many other classes and also extended by other classes.
* The request is passed a message and a messageType.
* A message is just a string and a messageType is:
@code
enum MessageType {
infoMessage,warningMessage,errorMessage,fatalErrorMessage
};
@endcode
*
*/
class epicsShareClass Requester {
public:
POINTER_DEFINITIONS(Requester);
/**
* Destructor
*/
virtual ~Requester(){}
/**
* The requester must have a name.
* @return The requester's name.
*/
virtual std::string getRequesterName() = 0;
/**
*
* A message for the requester.
* @param message The message.
* @param messageType The type of message:
@code
enum MessageType {
infoMessage,warningMessage,errorMessage,fatalErrorMessage
};
@endcode
*/
virtual void message(std::string const & message,MessageType messageType) = 0;
};

View File

@@ -25,51 +25,184 @@ namespace epics { namespace pvData {
class BitSet;
class Field;
/**
* @brief Callback class for serialization.
*
* This must be provided by code that calls serialize.
*/
class epicsShareClass SerializableControl {
public:
/**
* Destructor.
*/
virtual ~SerializableControl(){}
/**
* Done with this buffer. Flush it.
*/
virtual void flushSerializeBuffer() =0;
/**
* Make sure buffer has at least size bytes remaining.
* If not flush existing buffer and provide a new one.
* @param size The number of bytes.
*/
virtual void ensureBuffer(std::size_t size) =0;
/**
* Add pad bytes to buffer.
* @param alignment alignment required.
*/
virtual void alignBuffer(std::size_t alignment) =0;
virtual bool directSerialize(ByteBuffer *existingBuffer, const char* toSerialize,
std::size_t elementCount, std::size_t elementSize) = 0;
virtual void cachedSerialize(std::tr1::shared_ptr<const Field> const & field, ByteBuffer* buffer) = 0;
/**
* method for serializing array data.
* This should only be used for arrays of primitive types.
* i. e. boolean,byte,...,double.
* It can not be called for string, structure, or union arrays.
* @param existingBuffer the existing buffer from the caller.
* @param toSerialize location of data to be put into buffer.
* @param elementCount number of elements.
* @param elementSize element size.
*/
virtual bool directSerialize(
ByteBuffer *existingBuffer,
const char* toSerialize,
std::size_t elementCount,
std::size_t elementSize) = 0;
/**
* serialize via cache
* @param field instance to be serialized
* @param buffer buffer to be serialized to
*/
virtual void cachedSerialize(
std::tr1::shared_ptr<const Field> const & field,
ByteBuffer* buffer) = 0;
};
/**
* @brief Callback class for deserialization.
*
* This must be provided by code that calls deserialize.
*/
class epicsShareClass DeserializableControl {
public:
/**
* Destructor.
*/
virtual ~DeserializableControl(){}
/**
* Helper method.
* Ensures specified size of bytes, provides it if necessary.
* @param size The number of bytes.
*/
virtual void ensureData(std::size_t size) =0;
/**
* Align buffer.
* Note that this takes care only current buffer alignment.
* If streaming protocol is used,
* care must be taken that entire stream is aligned.
* @param alignment size in bytes, must be power of two.
*/
virtual void alignData(std::size_t alignment) =0;
virtual bool directDeserialize(ByteBuffer *existingBuffer, char* deserializeTo,
std::size_t elementCount, std::size_t elementSize) = 0;
virtual std::tr1::shared_ptr<const Field> cachedDeserialize(ByteBuffer* buffer) = 0;
/**
* method for deserializing array data.
* This should only be used for arrays of primitive types.
* i. e. boolean,byte,...,double.
* It can not be called for string, structure, or union arrays.
* @param existingBuffer the existing buffer from the caller.
* @param deserializeTo location of data.
* @param elementCount number of elements.
* @param elementSize element size.
*/
virtual bool directDeserialize(
ByteBuffer *existingBuffer,
char* deserializeTo,
std::size_t elementCount,
std::size_t elementSize) = 0;
/**
* deserialize via cache
* @param buffer buffer to be deserialized from
*/
virtual std::tr1::shared_ptr<const Field> cachedDeserialize(
ByteBuffer* buffer) = 0;
};
/**
* @brief Base class for serialization.
*
*/
class epicsShareClass Serializable {
public:
/**
* Destructor.
*/
virtual ~Serializable(){}
/**
* Serialize field into given buffer.
* @param buffer serialization buffer.
* @param flusher flush interface.
*/
virtual void serialize(ByteBuffer *buffer,
SerializableControl *flusher) const = 0;
/**
* Deserialize buffer.
* @param buffer serialization buffer.
* @param flusher deserialization control.
*/
virtual void deserialize(ByteBuffer *buffer,
DeserializableControl *flusher) = 0;
};
/**
* @brief Class for serializing bitSets.
*
*/
class epicsShareClass BitSetSerializable {
public:
/**
* Destructor.
*/
virtual ~BitSetSerializable(){}
/**
* Serialize field into given buffer.
* @param buffer serialization buffer.
* @param flusher flush interface.
* @param bitSet The bitSet to serialize.
*/
virtual void serialize(ByteBuffer *buffer,
SerializableControl *flusher,BitSet *bitSet) const = 0;
/**
* Deserialize buffer.
* @param buffer serialization buffer.
* @param flusher deserialization control.
* @param bitSet The bitSet to deserialize.
*/
virtual void deserialize(ByteBuffer *buffer,
DeserializableControl *flusher,BitSet *bitSet) = 0;
};
class epicsShareClass SerializableArray : virtual public Serializable {
/**
* @brief Class for serializing arrays.
*
*/
class epicsShareClass SerializableArray : public virtual Serializable {
public:
/**
* Destructor.
*/
virtual ~SerializableArray(){}
virtual void serialize(ByteBuffer *buffer,
SerializableControl *flusher, std::size_t offset, std::size_t count) const = 0;
using Serializable::serialize;
/**
* Serialize field into given buffer.
* @param buffer serialization buffer.
* @param flusher flush interface.
* @param offset offset in elements.
* @param count number of elements
*/
virtual void serialize(
ByteBuffer *buffer,
SerializableControl *flusher,
std::size_t offset,
std::size_t count) const = 0;
};
}}

View File

@@ -7,7 +7,7 @@
* serializeHelper.cpp
*
* Created on: Oct 22, 2010
* Author: Miha vitorovic
* Author: Miha Vitorovic
*/
#include <algorithm>

View File

@@ -23,23 +23,33 @@
namespace epics {
namespace pvData {
/**
* @brief Serialization helper.
*
*/
class epicsShareClass SerializeHelper : public NoDefaultMethods {
public:
/**
* Serialize array size.
* Serialize the specified array size into the specified
* buffer, flushing when necessary.
* The specified SerializableControl manages any flushing
* required.
*
* @param[in] s size to encode
* @param[in] buffer serialization buffer
* @param[in] flusher flusher
* @param[in] flusher SerializableControl to manage the flushing
*/
static void writeSize(std::size_t s, ByteBuffer* buffer,
SerializableControl* flusher);
/**
* Deserialize array size.
* The specified DeserializableControl ensures
* sufficient bytes are available.
*
* @param[in] buffer deserialization buffer.
* @param[in] control the DeserializableControl.
* @returns array size.
*/
static std::size_t readSize(ByteBuffer* buffer,
@@ -59,7 +69,7 @@ namespace epics {
* std::string serialization helper method.
*
* @param[in] value std::string to serialize
* @param[in] offset start of the substring in {@code value}
* @param[in] offset start of the substring in value
* @param[in] count the number of characters to write
* @param[in] buffer serialization buffer
* @param[in] flusher flusher

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

@@ -230,7 +230,7 @@ namespace detail {
};
}
/** @brief A holder for a contigious piece of memory.
/** @brief A holder for a contiguous piece of memory.
*
* Data is shared, but offset and length are not.
* This allows one vector to have access to only a
@@ -427,7 +427,7 @@ public:
* owner of the data array.
*
* If a copy is needed, memory is allocated with new[]. If this is
* not desireable then do something like the following.
* not desirable then do something like the following.
@code
shared_vector<E> original(...);
@@ -527,9 +527,12 @@ public:
};
//! Specialization for storing untyped pointers
//! Does not allow access or iteration of contents
//! other than as void* or const void*
/**
* @brief Specialization for storing untyped pointers.
*
* Does not allow access or iteration of contents
* other than as void* or const void*
*/
template<typename E>
class shared_vector<E, typename meta::is_void<E>::type >
: public detail::shared_vector_base<E>
@@ -861,7 +864,7 @@ std::ostream& operator<<(std::ostream& strm, const epics::pvData::shared_vector<
* The copy constructor and assignment operator allow implicit
* casting from type 'shared_vector<T>' to 'shared_vector<const T>'.
*
* To faciliate safe modification the methods unique() and
* To facilitate safe modification the methods unique() and
* make_unique() are provided.
*
* The slice() method selects a sub-set of the shared_vector.

View File

@@ -21,7 +21,9 @@
namespace epics { namespace pvData {
/**
* Status.
* @brief Status.
*
* This is a class for returning status to clients.
* @author mse
*/
class epicsShareClass Status : public epics::pvData::Serializable {

View File

@@ -47,9 +47,28 @@ typedef std::tr1::shared_ptr<epicsThread> EpicsThreadPtr;
typedef epicsThreadRunable Runnable;
/**
* @brief C++ wrapper for epicsThread from EPICS base.
*
*/
class epicsShareClass Thread : public epicsThread, private NoDefaultMethods {
public:
/**
*
* Constructor
* @param name thread name.
* @param priority priority is one of:
@code
enum ThreadPriority {
lowestPriority, lowerPriority, lowPriority,
middlePriority,
highPriority, higherPriority, highestPriority
};
@endcode
* @param runnable this is a c function
* @param stkcls stack size as specified by epicsThreadStackSizeClass
*/
Thread(std::string name,
ThreadPriority priority,
Runnable *runnable,
@@ -62,6 +81,21 @@ public:
this->start();
}
/**
*
* Constructor
* @param runnable this is a c function
* @name thread name.
* @param stkcls stack size as specified by epicsThreadStackSizeClass
* @param priority priority is one of:
@code
enum ThreadPriority {
lowestPriority, lowerPriority, lowPriority,
middlePriority,
highPriority, higherPriority, highestPriority
};
@endcode
*/
Thread(Runnable &runnable,
std::string name,
unsigned int stksize,
@@ -74,6 +108,9 @@ public:
this->start();
}
/**
* Destructor
*/
~Thread()
{
this->exitWait();

View File

@@ -21,19 +21,46 @@ class TimeFunction;
typedef std::tr1::shared_ptr<TimeFunctionRequester> TimeFunctionRequesterPtr;
typedef std::tr1::shared_ptr<TimeFunction> TimeFunctionPtr;
/**
* @brief Class that must be implemented by timeFunction requester.
*
*/
class epicsShareClass TimeFunctionRequester {
public:
POINTER_DEFINITIONS(TimeFunctionRequester);
/**
* Destructor
*/
virtual ~TimeFunctionRequester(){}
/**
* function to be timed.
* It will get called multiple times.
*/
virtual void function() = 0;
};
/**
* @brief Class for measuring time it takes to execute a function.
*
*/
class epicsShareClass TimeFunction {
public:
POINTER_DEFINITIONS(TimeFunction);
/**
* Constructor
* @param requester The class that has a function method.
*/
TimeFunction(TimeFunctionRequesterPtr const & requester);
/**
* Destructor
*/
~TimeFunction();
/**
* Time the function.
* @return the time in seconds to execute the function.
* Note that the function may be called many times.
*/
double timeCall();
private:
TimeFunctionRequesterPtr requester;

View File

@@ -14,9 +14,9 @@
#include <stdexcept>
#include <string>
#include <iostream>
#define epicsExportSharedSymbols
#include <pv/convert.h>
#include <pv/timer.h>
using std::string;

View File

@@ -32,12 +32,28 @@ class Timer;
typedef std::tr1::shared_ptr<TimerCallback> TimerCallbackPtr;
typedef std::tr1::shared_ptr<Timer> TimerPtr;
/**
* @brief Class that must be implemented by code that makes Timer requests.
*
*/
class epicsShareClass TimerCallback {
public:
POINTER_DEFINITIONS(TimerCallback);
/**
* Constructor
*/
TimerCallback();
/**
* Destructor
*/
virtual ~TimerCallback(){}
/**
* The method that is called when a timer expires.
*/
virtual void callback() = 0;
/**
* The timer has stopped.
*/
virtual void timerStopped() = 0;
private:
TimerCallbackPtr next;
@@ -47,22 +63,60 @@ private:
friend class Timer;
};
/**
* @brief Support for delayed or periodic callback execution.
*
*/
class epicsShareClass Timer : public Runnable {
public:
POINTER_DEFINITIONS(Timer);
/**
* Constructor
* @param threadName name for the timer thread.
* @param priority thread priority
*/
Timer(std::string threadName, ThreadPriority priority);
/**
* Destructor
*/
virtual ~Timer();
/**
* The thread run method. This is called automatically.
*/
virtual void run();
/**
* schedule a callback after a delay.
* @param timerCallback the timerCallback instance.
* @param delay number of seconds before calling callback.
*/
void scheduleAfterDelay(
TimerCallbackPtr const &timerCallback,
double delay);
/**
* schedule a periodic callback.`
* @param timerCallback the timerCallback instance.
* @param delay number of seconds before first callback.
* @param period time in seconds between each callback.
*/
void schedulePeriodic(
TimerCallbackPtr const &timerCallback,
double delay,
double period);
/**
* cancel a callback.
* @param timerCallback the timerCallback to cancel.
*/
void cancel(TimerCallbackPtr const &timerCallback);
/**
* Is the callback scheduled to be called?
* @param timerCallback the timerCallback.
* @return (false,true) if (not, is) scheduled.
*/
bool isScheduled(TimerCallbackPtr const &timerCallback);
/**
* show the elements in the timer queue.
* @param o The output stream for the output
*/
void dump(std::ostream& o);
private:

View File

@@ -59,7 +59,7 @@ namespace detail {
typedef T return_t;
static FORCE_INLINE return_t op(const T& i) { return i; }
};
// trick std::ostream into treating char's as numbers
// trick std::ostream into treating chars as numbers
// by promoting char to int
template<>
struct print_convolute<int8> {
@@ -142,7 +142,7 @@ namespace detail {
* - float -> double
*
* Conversions where out of range inputs always produce
* a defined result, but may not be reversable.
* a defined result, but may not be reversible.
*
* - double -> float. When abs(value) is outside the range
* [FLT_MIN, FLT_MAX] the value is clipped to FLT_MIN or FLT_MAX

View File

@@ -30,6 +30,8 @@ typedef std::tr1::shared_ptr<Monitor> MonitorPtr;
/**
* @brief An element for a monitorQueue.
*
* Class instance representing monitor element.
* @author mrk
*/
@@ -48,7 +50,9 @@ class epicsShareClass MonitorElement {
};
/**
* Interface for Monitor.
* @brief Monitor changes to fields of a pvStructure.
*
* This is used by pvAccess to implement monitors.
* @author mrk
*/
class epicsShareClass Monitor : public Destroyable{
@@ -73,6 +77,7 @@ class epicsShareClass Monitor : public Destroyable{
virtual MonitorElementPtr poll() = 0;
/**
* Release a MonitorElement that was returned by poll.
* A poll() must be called after the release() to check the presence of any modified data.
* @param monitorElement
*/
virtual void release(MonitorElementPtr const & monitorElement) = 0;
@@ -80,6 +85,8 @@ class epicsShareClass Monitor : public Destroyable{
/**
* @brief Callback implemented by monitor clients.
*
* Requester for ChannelMonitor.
* @author mrk
*/

View File

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

View File

@@ -20,32 +20,25 @@
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;
/**
* @brief 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
* A monitor is assumed to be associated with a field of a top-level
* structure.
*/
class epicsShareClass MonitorPlugin
@@ -60,8 +53,8 @@ public:
/**
* 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.
* @param pvTop The top-level structure 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
@@ -73,9 +66,6 @@ public:
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.
*/
@@ -100,7 +90,9 @@ public:
virtual void endGroupPut() {};
};
/** A class that creates a plugin.
/**
* @brief A class that creates a plugin.
*
* Normlly a plugin is created for a single client.
*/
class epicsShareClass MonitorPluginCreator
@@ -110,7 +102,7 @@ public:
/**
* Create a monitor plugin.
* @param field The introspection interface for the field monitored.
* @param top The introspsction interface for the client structure.
* @param top The introspection 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.
@@ -130,6 +122,8 @@ public:
/**
* @brief Manager for plugins.
*
* This manages a set of monitor plugins.
* @author mrk
*/

View File

@@ -18,37 +18,129 @@
namespace epics { namespace pvData {
/** @brief enum definition of AlarmSeverity
*
* AlarmSeverity is:
@code
enum AlarmSeverity {
noAlarm,minorAlarm,majorAlarm,invalidAlarm,undefinedAlarm
};
@endcode
*
*/
enum AlarmSeverity {
noAlarm,minorAlarm,majorAlarm,invalidAlarm,undefinedAlarm
};
/** @brief enum definition of AlarmStatus
*
* AlarmStatus is:
@code
enum AlarmStatus {
noStatus,deviceStatus,driverStatus,recordStatus,
dbStatus,confStatus,undefinedStatus,clientStatus
};
@endcode
*
*/
enum AlarmStatus {
noStatus,deviceStatus,driverStatus,recordStatus,
dbStatus,confStatus,undefinedStatus,clientStatus
};
/** @brief methods for AlarmSeverity
*
*/
class epicsShareClass AlarmSeverityFunc {
public:
/**
* Get the severity.
* @param value Get the alarm severity corresponding to the integer value.
* @return The severity.
* @throw if severity value is out of range.
*/
static AlarmSeverity getSeverity(int value);
/**
* Get the array of severity names.
* @return The array of severity names.
*/
static StringArrayPtr getSeverityNames();
};
/** @brief methods for AlarmStatus
*
*/
class epicsShareClass AlarmStatusFunc {
public:
/**
* Get the status.
* @param value Get the alarm status corresponding to the integer value.
* @return The status.
* @throw if status value is out of range.
*/
static AlarmStatus getStatus(int value);
/**
* Get the array of status names.
* @return The array of status names.
*/
static StringArrayPtr getStatusNames();
};
/** @brief Methods for manipulating alarm.
*
* An alarm structure has the following fields:
@code
structure
int severity
int status
string message
@endcode
* This is a class that holds values corresponding to the fields in
* an alarm structure.
* It is meant to be used together with pvAlarm
* which allows values to be copied between an alarm structure
* and this class.
* This class should not be extended.
*/
class epicsShareClass Alarm {
public:
/**
* Constructor
*/
Alarm() : severity(0),status(0), message(std::string("")) {}
//default constructors and destructor are OK
/**
* get the current message.
* @return The message.
*/
std::string getMessage() const {return message;}
/**
* set the current message.
* @param value The new message value.
*/
void setMessage(std::string const &value) {message = value;}
/**
* get the current severity.
* @return The severity.
*/
AlarmSeverity getSeverity() const;
/**
* set the current severity.
* @param value The new severity.
* @throw if severity value is out of range.
*/
void setSeverity(AlarmSeverity value) {severity = value;}
/**
* get the current status.
* @return The status.
*/
AlarmStatus getStatus() const;
/**
* set the current status.
* @param value The new status.
* @throw if status value is out of range.
*/
void setStatus(AlarmStatus value) { status = value;}
private:
int32 severity;

View File

@@ -14,15 +14,58 @@
namespace epics { namespace pvData {
/** @brief Methods for a control structure.
*
* An control structure has the following fields:
@code
structure
double limitLow
double limitHigh
double minStep
@endcode
* This is a class that holds values corresponding to the fields in
* a control structure.
* It is meant to be used together with pvControl
* which allows values to be copied between an control structure
* and this class.
* This class should not be extended.
*/
class epicsShareClass Control {
public:
Control() : low(0.0), high(0.0) {}
/**
* Constructor
*/
Control() : low(0.0), high(0.0), minStep(0.0) {}
//default constructors and destructor are OK
/**
* get limitLow
* @return the current value.
*/
double getLow() const {return low;}
/**
* get limitHigh
* @return the current value.
*/
double getHigh() const {return high;}
/**
* get minStep
* @return the current value.
*/
double getMinStep() const {return minStep;}
/**
* set limitLow
* @param value The new value.
*/
void setLow(double value) {low = value;}
/**
* set limitHigh
* @param value The new value.
*/
void setHigh(double value) {high = value;}
/**
* set minStep
* @param value The new value.
*/
void setMinStep(double value) {minStep = value;}
private:
double low;

View File

@@ -19,21 +19,83 @@
namespace epics { namespace pvData {
/** @brief Methods for a display structure.
*
* An display structure has the following fields:
@code
structure
double limitLow
double limitHigh
string description
string format
string units
@endcode
* This is a class that holds values corresponding to the fields in
* a display structure.
* It is meant to be used together with pvDisplay
* which allows values to be copied between an display structure
* and this class.
* This class should not be extended.
*/
class epicsShareClass Display {
public:
/**
* Constructor
*/
Display()
: description(std::string("")),format(std::string("")),units(std::string("")),
low(0.0),high(0.0) {}
//default constructors and destructor are OK
/**
* Get the current value of limitLow.
* @return The current value.
*/
double getLow() const {return low;}
/**
* Get the current value of limitHigh.
* @return The current value.
*/
double getHigh() const{ return high;}
/**
* Set limitLow to a new value.
* @param value The value.
*/
void setLow(double value){low = value;}
/**
* Set limitHigh to a new value.
* @param value The value.
*/
void setHigh(double value){high = value;}
/**
* Get the current value of description.
* @return The current value.
*/
std::string getDescription() const {return description;}
/**
* Set description to a new value.
* @param value The value.
*/
void setDescription(std::string const & value) {description = value;}
/**
* Get the current value of format.
* @return The current value.
*/
std::string getFormat() const {return format;}
/**
* Set format to a new value.
* @param value The value.
* The rules for a valid syntax has not been specified.
*/
void setFormat(std::string const & value) {format = value;}
/**
* Get the current value of units.
* @return The current value.
*/
std::string getUnits() const {return units;}
/**
* Set units to a new value.
* @param value The value.
*/
void setUnits(std::string const & value) {units = value;}
private:
std::string description;

View File

@@ -28,14 +28,14 @@ bool PVAlarm::attach(PVFieldPtr const & pvField)
{
if(pvField->getField()->getType()!=structure) return false;
PVStructurePtr pvStructure = static_pointer_cast<PVStructure>(pvField);
pvSeverity = pvStructure->getIntField("severity");
pvSeverity = pvStructure->getSubField<PVInt>("severity");
if(pvSeverity.get()==NULL) return false;
pvStatus = pvStructure->getIntField("status");
pvStatus = pvStructure->getSubField<PVInt>("status");
if(pvStatus.get()==NULL) {
pvSeverity.reset();
return false;
}
pvMessage = pvStructure->getStringField("message");
pvMessage = pvStructure->getSubField<PVString>("message");
if(pvMessage.get()==NULL) {
pvSeverity.reset();
pvStatus.reset();

View File

@@ -20,18 +20,65 @@
namespace epics { namespace pvData {
/** @brief Methods for accessing an alarm structure.
*
* An alarm structure has the following fields:
@code
structure
int severity
int status
string message
@endcode
* This class can be attached to an alarm structure field of any
* PVData object.
* The methods provide access to the fields in the attached structure,
* via an instance of class Alarm.
* This class should not be extended.
*/
class epicsShareClass PVAlarm {
public:
/**
*
* Constructor
*/
PVAlarm() {}
//default constructors and destructor are OK
//returns (false,true) if pvField(isNot, is valid enumerated structure
//returns (false,true) if pvField(is not, is) a valid alarm structure
//An automatic detach is issued if already attached.
/*
* Attach to a field of a PVData object.
* @param pvField The pvField.
* @return (false,true) if the pvField (is not, is) an alarm structure.
*/
/*
* Attach to a field of a PVData object.
* @param pvField The pvField.
* @return (false,true) if the pvField (is not, is) an alarm structure.
*/
bool attach(PVFieldPtr const & pvField);
/**
* Detach for pvField.
*/
void detach();
/**
* Is the PVAlarm attached to a pvField?
* @return (false,true) (is not,is) attached to a pvField.
*/
bool isAttached();
// each of the following throws logic_error is not attached to PVField
// set returns false if field is immutable
/**
* copy the alarm structure values to Alarm
* @param alarm An instance of class Alarm
* @throw If not attached to a pvField.
*/
void get(Alarm & alarm) const;
/**
* copy the values from Alarm to the alarm structure.
* @param alarm An instance of class Alarm
* @return (false,true) if pvField (immutable, mutable)
* @throw If not attached to a pvField.
*/
bool set(Alarm const & alarm);
private:
PVIntPtr pvSeverity;

View File

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

View File

@@ -17,22 +17,65 @@
namespace epics { namespace pvData {
/** @brief Methods for accessing an control structure.
*
* An control structure has the following fields:
@code
structure
double limitLow
double limitHigh
double minStep
@endcode
* This class can be attached to an control structure field of any
* PVData object.
* The methods provide access to the fields in the attached structure,
* via an instance of class Control.
* This class should not be extended.
*/
class epicsShareClass PVControl {
public:
/**
*
* Constructor
*/
PVControl(){}
//default constructors and destructor are OK
//returns (false,true) if pvField(isNot, is valid enumerated structure
//returns (false,true) if pvField(is not, is) a valid control structure
//An automatic detach is issued if already attached.
/*
* Attach to a field of a PVData object.
* @param pvField The pvField.
* @return (false,true) if the pvField (is not, is) an control structure.
*/
bool attach(PVFieldPtr const & pvField);
/**
* Detach for pvField.
*/
void detach();
/**
* Is the PVControl attached to a pvField?
* @return (false,true) (is not,is) attached to a pvField.
*/
bool isAttached();
// each of the following throws logic_error is not attached to PVField
// each of the following throws logic_error if not attached to PVField
// set returns false if field is immutable
void get(Control &) const;
/**
* copy the control structure values to Control
* @param control An instance of class Control
* @throw If not attached to a pvField.
*/
void get(Control & control) const;
/**
* copy the values from Control to the control structure.
* @param control An instance of class Control
* @return (false,true) if pvField (immutable, mutable)
* @throw If not attached to a pvField.
*/
bool set(Control const & control);
private:
PVDoublePtr pvLow;
PVDoublePtr pvHigh;
PVDoublePtr pvMinStep;
static std::string noControlFound;
static std::string notAttached;
};

View File

@@ -28,24 +28,24 @@ bool PVDisplay::attach(PVFieldPtr const & pvField)
{
if(pvField->getField()->getType()!=structure) return false;
PVStructurePtr pvStructure = static_pointer_cast<PVStructure>(pvField);
pvDescription = pvStructure->getStringField("description");
pvDescription = pvStructure->getSubField<PVString>("description");
if(pvDescription.get()==NULL) return false;
pvFormat = pvStructure->getStringField("format");
pvFormat = pvStructure->getSubField<PVString>("format");
if(pvFormat.get()==NULL) {
detach();
return false;
}
pvUnits = pvStructure->getStringField("units");
pvUnits = pvStructure->getSubField<PVString>("units");
if(pvUnits.get()==NULL) {
detach();
return false;
}
pvLow = pvStructure->getDoubleField(string("limitLow"));
pvLow = pvStructure->getSubField<PVDouble>(string("limitLow"));
if(pvLow.get()==NULL) {
detach();
return false;
}
pvHigh = pvStructure->getDoubleField(string("limitHigh"));
pvHigh = pvStructure->getSubField<PVDouble>(string("limitHigh"));
if(pvHigh.get()==NULL) {
detach();
return false;

View File

@@ -20,17 +20,61 @@
namespace epics { namespace pvData {
/** @brief Methods for accessing an display structure.
*
* A display structure has the following fields:
@code
structure
double limitLow
double limitHigh
string description
string format
string units
@endcode
* This class can be attached to a display structure field of any
* PVData object.
* The methods provide access to the fields in the attached structure,
* via an instance of class Display.
* This class should not be extended.
*/
class epicsShareClass PVDisplay {
public:
/**
*
* Constructor
*/
PVDisplay() {}
//default constructors and destructor are OK
//An automatic detach is issued if already attached.
/*
* Attach to a field of a PVData object.
* @param pvField The pvField.
* @return (false,true) if the pvField (is not, is) an display structure.
*/
bool attach(PVFieldPtr const & pvField);
/**
* Detach for pvField.
*/
void detach();
/**
* Is the PVDisplay attached to a pvField?
* @return (false,true) (is not,is) attached to a pvField.
*/
bool isAttached();
// each of the following throws logic_error is not attached to PVField
// each of the following throws logic_error if not attached to PVField
// a set returns false if field is immutable
void get(Display &) const;
/**
* copy the display structure values to Display
* @param display An instance of class Display
* @throw If not attached to a pvField.
*/
void get(Display & display) const;
/**
* copy the values from Display to the display structure.
* @param display An instance of class Display
* @return (false,true) if pvField (immutable, mutable)
* @throw If not attached to a pvField.
*/
bool set(Display const & display);
private:
static std::string noDisplayFound;

View File

@@ -28,15 +28,14 @@ bool PVEnumerated::attach(PVFieldPtr const & pvField)
{
if(pvField->getField()->getType()!=structure) return false;
PVStructurePtr pvStructure = static_pointer_cast<PVStructure>(pvField);
pvIndex = pvStructure->getIntField("index");
pvIndex = pvStructure->getSubField<PVInt>("index");
if(pvIndex.get()==NULL) return false;
PVScalarArrayPtr pvScalarArray = pvStructure->getScalarArrayField(
"choices",pvString);
if(pvScalarArray.get()==NULL) {
PVStringArrayPtr pvStringArray = pvStructure->getSubField<PVStringArray>("choices");
if(pvStringArray.get()==NULL) {
pvIndex.reset();
return false;
}
pvChoices = static_pointer_cast<PVStringArray>(pvScalarArray);
pvChoices = pvStringArray;
return true;
}
@@ -74,8 +73,12 @@ string PVEnumerated::getChoice()
if(pvIndex.get()==NULL ) {
throw std::logic_error(notAttached);
}
int index = pvIndex->get();
size_t index = pvIndex->get();
const PVStringArray::const_svector& data(pvChoices->view());
if(/*index<0 ||*/ index>=data.size()) {
string nullString;
return nullString;
}
return data[index];
}

View File

@@ -19,24 +19,89 @@
namespace epics { namespace pvData {
/** @brief Methods for accessing an enumerated structure.
*
* An enumerated structure has the following fields:
@code
structure
int index
string[] choices
@endcode
* This class can be attached to an enumerated structure field of any
* PVData object.
* The methods provide access to the fields in the attached structure.
* This class should not be extended.
*/
class epicsShareClass PVEnumerated {
public:
/*
* Constructor.
*/
PVEnumerated() {}
//default constructors and destructor are OK
//This class should not be extended
//returns (false,true) if pvField(isNot, is valid enumerated structure
//returns (false,true) if pvField(is not, is) a valid enumerated structure
//An automatic detach is issued if already attached.
/*
* Attach to a field of a PVData object.
* @param pvField The pvField.
* @return (false,true) if the pvField (is not, is) an enumerated structure.
*/
bool attach(PVFieldPtr const & pvField);
/**
* Detach for pvField.
*/
void detach();
/**
* Is the PVEnumerated attached to a pvField?
* @return (false,true) (is not,is) attached to a pvField.
*/
bool isAttached();
// each of the following throws logic_error is not attached to PVField
// a set returns false if field is immutable
/**
* Set the index.
* @param index The new index.
* @throw if not attached.
* The index will be changed even if it is out of range of size of choices.
*/
bool setIndex(int32 index);
/**
* Get the index.
* @return The current index.
* @throw if not attached.
*/
int32 getIndex();
/**
* Get the choice corresponding to current index.
* @return The choice. If index is out of range a null string is returned.
* @throw if not attached.
*/
std::string getChoice();
/**
* Can choices be changed?
* @return (false,true) if choices (can not, can) be changed.
* @throw if not attached.
*/
bool choicesMutable();
/**
* Get the choices.
* @return The current index.
* @throw if not attached.
*/
inline PVStringArray::const_svector getChoices(){return pvChoices->view();}
/**
* Get the size of the choices array.
* @return The size.
* @throw if not attached.
*/
int32 getNumberChoices();
/**
* Get the choices.
* @param choices The new value for choices.`
* @return (false,true) if choices (was not was) replaced.
* @throw if not attached.
*/
bool setChoices(const StringArray & choices);
private:
static std::string notFound;

View File

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

View File

@@ -21,19 +21,61 @@
namespace epics { namespace pvData {
/** @brief Methods for accessing a timeStamp structure.
*
* A timeStamp structure has the following fields:
@code
structure
long secondsPastEpoch
int nanoseconds
int userTag
@endcode
* This class can be attached to a timeStamp structure field of any
* PVData object.
* The methods provide access to the fields in the attached structure,
* via an instance of class TimeStamp.
* This class should not be extended.
*/
class epicsShareClass PVTimeStamp {
public:
/**
*
* Constructor
*/
PVTimeStamp(){}
//default constructors and destructor are OK
//This class should not be extended
//returns (false,true) if pvField(isNot, is valid timeStamp structure
//returns (false,true) if pvField(is not, is) a valid timeStamp structure
/*
* Attach to a field of a PVData object.
* @param pvField The pvField.
* @return (false,true) if the pvField (is not, is) an timeStamp structure.
*/
bool attach(PVFieldPtr const & pvField);
/**
* Detach for pvField.
*/
void detach();
/**
* Is the PVTimeStamp attached to a pvField?
* @return (false,true) (is not,is) attached to a pvField.
*/
bool isAttached();
// following throw logic_error is not attached to PVField
// a set returns false if field is immutable
void get(TimeStamp &) const;
// following throw logic_error if not attached to PVField
// set returns false if field is immutable
/**
* copy the timeStamp structure values to TimeStamp
* @param timeStamp An instance of class TimeStamp
* @throw If not attached to a pvField.
*/
void get(TimeStamp & timeStamp) const;
/**
* copy the values from TimeStamp to the timeStamp structure.
* @param timeStamp An instance of class TimeStamp
* @return (false,true) if pvField (immutable, mutable)
* @throw If not attached to a pvField.
*/
bool set(TimeStamp const & timeStamp);
private:
static std::string noTimeStamp;

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

@@ -35,47 +35,162 @@ epicsShareExtern int32 microSecPerSec;
epicsShareExtern int32 nanoSecPerSec;
epicsShareExtern int64 posixEpochAtEpicsEpoch;
/** @brief Methods for manipulating timeStamp.
*
* A timeStamp structure has the following fields:
@code
structure
long secondsPastEpoch
int nanoseconds
int userTag
@endcode
* This is a class that holds values corresponding to the fields in
* a timeStamp structure.
* It is meant to be used together with pvTimeStamp
* which allows values to be copied between an timeStamp structure
* and this class.
* This class should not be extended.
*/
class epicsShareClass TimeStamp {
public:
/**
* Default constructor
*/
TimeStamp()
:secondsPastEpoch(0), nanoSeconds(0), userTag(0) {}
TimeStamp(int64 secondsPastEpoch,int32 nanoSeconds = 0,int32 userTag = 0);
:secondsPastEpoch(0), nanoseconds(0), userTag(0) {}
/**
* Constructor
* @param secondsPastEpoch seconds since 1970 UTC
* @param nanoseconds nanoseconds since secondsPastEpoch
* @param userTag application specific
*/
TimeStamp(int64 secondsPastEpoch,int32 nanoseconds = 0,int32 userTag = 0);
//default constructors and destructor are OK
//This class should not be extended
/**
* adjust secondsPastEpoch and nanoseconds so that
* 0 <= nanoseconds < nanoSecPerSec
*/
void normalize();
void fromTime_t(const time_t &);
void toTime_t(time_t &) const;
/**
* Set timeStamp from standard C time
* @param time time as returned by std::time
*/
void fromTime_t(const time_t & time);
/**
* Set time from timeStamp
* @param time time as defined by std::time
*/
void toTime_t(time_t &time) const;
/**
* Get secondsPastEpoch.
* @return The secondsPastEpoch.
*/
int64 getSecondsPastEpoch() const {return secondsPastEpoch;}
/**
* Get secondsPastEpoch for EPICS V3.
* This is seconds since 1990 UTC.
* @return The epics V3 secondsPastEpoch.
*/
int64 getEpicsSecondsPastEpoch() const {
return secondsPastEpoch - posixEpochAtEpicsEpoch;
}
int32 getNanoSeconds() const {return nanoSeconds;}
/**
* Get nanoseconds.
* @return nanoseconds within timeStamp.
*/
int32 getNanoseconds() const {return nanoseconds;}
/**
* Get userTag.
* @return userTag.
*/
int32 getUserTag() const {return userTag;}
/**
* Set userTag.
* @param userTag application specific.
*/
void setUserTag(int userTag) {this->userTag = userTag;}
void put(int64 secondsPastEpoch,int32 nanoSeconds = 0) {
/**
* Set time fields in timeStamp.
* Result will be normalized.
* @param secondsPastEpoch seconds part of timeStamp.
* @param nanoseconds nanoseconds part of timeStamp.
*/
void put(int64 secondsPastEpoch,int32 nanoseconds = 0) {
this->secondsPastEpoch = secondsPastEpoch;
this->nanoSeconds = nanoSeconds;
this->nanoseconds = nanoseconds;
normalize();
}
/**
* Set time fields in timeStamp.
* @param milliseconds The number of milliseconds since the epoch.
*/
void put(int64 milliseconds);
/**
* Set the timeStamp to the current time.
*/
void getCurrent();
/**
* Convert the timeStamp to a double value that is seconds past epoch.
* @return seconds past 1970 UTC
*/
double toSeconds() const ;
/**
* Standard C++ operator.
*/
bool operator==(TimeStamp const &) const;
/**
* Standard C++ operator.
*/
bool operator!=(TimeStamp const &) const;
/**
* Standard C++ operator.
*/
bool operator<=(TimeStamp const &) const;
/**
* Standard C++ operator.
*/
bool operator< (TimeStamp const &) const;
/**
* Standard C++ operator.
*/
bool operator>=(TimeStamp const &) const;
/**
* Standard C++ operator.
*/
bool operator> (TimeStamp const &) const;
/**
* Return a-b as a double value with units of seconds.
* @param a first timeStamp
* @param b second timeStamp
* @return time difference in seconds.
*/
static double diff(TimeStamp const & a,TimeStamp const & b);
/**
* Standard C++ operator.
*/
TimeStamp & operator+=(int64 seconds);
/**
* Standard C++ operator.
*/
TimeStamp & operator-=(int64 seconds);
/**
* Standard C++ operator.
*/
TimeStamp & operator+=(double seconds);
/**
* Standard C++ operator.
*/
TimeStamp & operator-=(double seconds);
int64 getMilliseconds(); // milliseconds since epoch
/**
* Get number of milliseconds past epoch.
* @return milliseconds past epoch.
*/
int64 getMilliseconds();
private:
static int64 diffInt(TimeStamp const &left,TimeStamp const &right );
int64 secondsPastEpoch;
int32 nanoSeconds;
int32 nanoseconds;
int32 userTag;
};

View File

@@ -22,37 +22,12 @@
namespace epics { namespace pvData {
bool epicsShareExtern operator==(const PVField&, const PVField&);
static inline bool operator!=(const PVField& a, const PVField& b)
{return !(a==b);}
bool epicsShareExtern operator==(const Field&, const Field&);
bool epicsShareExtern operator==(const Scalar&, const Scalar&);
bool epicsShareExtern operator==(const ScalarArray&, const ScalarArray&);
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&);
static inline bool operator!=(const Field& a, const Field& b)
{return !(a==b);}
static inline bool operator!=(const Scalar& a, const Scalar& b)
{return !(a==b);}
static inline bool operator!=(const ScalarArray& a, const ScalarArray& b)
{return !(a==b);}
static inline bool operator!=(const Structure& a, const Structure& b)
{return !(a==b);}
static inline bool operator!=(const StructureArray& a, const StructureArray& b)
{return !(a==b);}
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);}
class Convert;
typedef std::tr1::shared_ptr<Convert> ConvertPtr;
/**
* @brief Conversion and Copy facility for pvData.
*
* Convert between numeric types, convert any field to a string,
* or convert from a string to a scalar field.
* <p>Numeric conversions are between scalar numeric types or between arrays of
@@ -63,9 +38,7 @@ static inline bool operator!=(const UnionArray& a, const UnionArray& b)
* pvUByte, pvUShort, pvUInt, pvULong,
* pvFloat, or pvDouble.</p>
*
* <p>getString converts any supported type to a std::string.
* Code that implements a PVField interface should implement
* method toString by calling this method.</p>
* <p>getString converts any supported type to a std::string.</p>
*
* <p>fromString converts a std::string to a scalar.
* fromStringArray converts an array of std::strings
@@ -73,85 +46,45 @@ static inline bool operator!=(const UnionArray& a, const UnionArray& b)
* 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>
*/
class Convert;
typedef std::tr1::shared_ptr<Convert> ConvertPtr;
class epicsShareClass Convert {
public:
static ConvertPtr getConvert();
/**
* Get the full fieldName for the pvField.
* @param builder The builder that will have the result.
* @param pvField The pvField.
*/
void getFullName(std::string *buf,PVFieldPtr const & pvField)
{
*buf = pvField->getFullName();
}
/**
* Do fields have the same definition.
*
* @param First field
* @param Second field
* @return (false, true) if the fields (are not, are) the same.
* Copy from a PVField to another PVField.
* This calls one on copyScalar, copyArray, copyStructure.
* The two arguments must be compatible.
* @param from The source.
* @param to The destination
* @throws std::invalid_argument if the arguments are not compatible.
* @deprecated use "to->copy[Unchecked](*from)" instead
*/
inline bool equals(PVFieldPtr const &a,PVFieldPtr const &b)
{
return *a==*b;
}
/**
* Do fields have the same definition.
*
* @param First field
* @param Second field
* @return (false, true) if the fields (are not, are) the same.
*/
inline bool equals(PVField &a,PVField &b)
{
return a==b;
void copy(PVFieldPtr const & from, PVFieldPtr const & to) {
to->copy(*from);
}
/**
* Convert a PVField to a string.
* @param buf buffer for the result
* @param pv a PVField to convert to a string.
* If a PVField is a structure or array be prepared for a very long string.
* @param indentLevel indentation level
*/
inline void getString(std::string *buf,PVFieldPtr const & pvField,int indentLevel)
{getString(buf, pvField.get(), 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.
* @param buf string that will hold pvField converted to a string,
* @param pvField The PVField to convert to a string.
*/
inline void getString(std::string * buf,PVFieldPtr const & pvField)
{getString(buf, pvField.get(), 0);}
/**
* Convert a PVField to a string.
* @param buf buffer for the result
* @param pv a PVField to convert to a string.
* If a PVField is a structure or array be prepared for a very long string.
* @param buf string that will hold pvField converted to a string,
* @param pvField The PVField to convert to a string.
* @param indentLevel indentation level
*/
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(std::string * buf,PVField const * pvField)
{getString(buf, pvField, 0);}
/**
* Convert from an array of std::string to a PVScalar
* Convert from an array of std::string to a PVStructure
* @param pv The 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.
* @return The total number of fields that have been changed.
* @throws std::logic_error if the array of std::string does not have a valid values.
*/
std::size_t fromString(
@@ -211,129 +144,7 @@ public:
StringArray & to,
std::size_t toOffset);
/**
* Are from and to valid arguments to copy.
* This first checks of both arguments have the same Type.
* Then calls one of isCopyScalarCompatible,
* isCopyArrayCompatible, or isCopyStructureCompatible.
* @param from The source.
* @param to The destination.
* @return (false,true) is the arguments (are not, are) compatible.
*/
bool isCopyCompatible(FieldConstPtr const & from, FieldConstPtr const & to);
/**
* Copy from a PVField to another PVField.
* This calls one on copyScalar, copyArray, copyStructure.
* The two arguments must be compatible.
* @param from The source.
* @param to The destination
* @throws std::invalid_argument if the arguments are not compatible.
*/
void copy(PVFieldPtr const & from, PVFieldPtr const & to);
/**
* Are from and to valid arguments to copyScalar.
* false will be returned if either argument is not a scalar as defined by Type.isScalar().
* If both are scalars the return value is true if any of the following are true.
* <ul>
* <li>Both arguments are numeric.</li>
* <li>Both arguments have the same type.</li>
* <li>Either argument is a string.</li>
* </ul>
* @param from The introspection interface for the from data.
* @param to The introspection interface for the to data..
* @return (false,true) If the arguments (are not, are) compatible.
*/
bool isCopyScalarCompatible(
ScalarConstPtr const & from,
ScalarConstPtr const & to);
/**
* Copy from a scalar pv to another scalar pv.
* @param from the source.
* @param to the destination.
* @throws std::invalid_argument if the arguments are not compatible.
*/
void copyScalar(PVScalarPtr const & from, PVScalarPtr const & to);
/**
* Are from and to valid arguments to copyArray.
* The results are like isCopyScalarCompatible except that the tests are made on the elementType.
* @param from The from array.
* @param to The to array.
* @return (false,true) If the arguments (are not, are) compatible.
*/
bool isCopyScalarArrayCompatible(
ScalarArrayConstPtr const & from,
ScalarArrayConstPtr const & to);
/**
* Are from and to valid arguments for copyStructure.
* They are only compatible if they have the same Structure description.
* @param from from structure.
* @param to structure.
* @return (false,true) If the arguments (are not, are) compatible.
*/
bool isCopyStructureCompatible(
StructureConstPtr const & from, StructureConstPtr const & to);
/**
* Copy from a structure pv to another structure pv.
* NOTE: Only compatible nodes are copied. This means:
* <ul>
* <li>For scalar nodes this means that isCopyScalarCompatible is true.</li>
* <li>For array nodes this means that isCopyArrayCompatible is true.</li>
* <li>For structure nodes this means that isCopyStructureCompatible is true.</li>
* <li>Link nodes are not copied.</li>
* </ul>
* @param from The source.
* @param to The destination.
* @throws std::invalid_argument if the arguments are not compatible.
*/
void copyStructure(PVStructurePtr const & from, PVStructurePtr const & to);
/**
* Are from and to valid for copyStructureArray.
* @param from The from StructureArray.
* @param to The to StructureArray.
* @return (false,true) If the arguments (are not, are) compatible.
*/
bool isCopyStructureArrayCompatible(
StructureArrayConstPtr const & from, StructureArrayConstPtr const & to);
/**
* Copy from a structure array to another structure array.
* @param from The source array.
* @param to The destination array.
*/
void copyStructureArray(
PVStructureArrayPtr const & from, PVStructureArrayPtr const & to);
/**
* Are from and to valid arguments for copyUnion.
* They are only compatible if they have the same Union description.
* @param from from union.
* @param to union.
* @return (false,true) If the arguments (are not, are) compatible.
*/
bool isCopyUnionCompatible(
UnionConstPtr const & from, UnionConstPtr const & to);
/**
* Copy from a union pv to another union pv.
* NOTE: Only compatible nodes are copied.
* @param from The source.
* @param to The destination.
* @throws std::invalid_argument if the arguments are not compatible.
*/
void copyUnion(PVUnionPtr const & from, PVUnionPtr const & to);
/**
* Are from and to valid for copyUnionArray.
* @param from The from UnionArray.
* @param to The to UnionArray.
* @return (false,true) If the arguments (are not, are) compatible.
*/
bool isCopyUnionArrayCompatible(
UnionArrayConstPtr const & from, UnionArrayConstPtr const & to);
/**
* Copy from a union array to another union array.
* @param from The source array.
* @param to The destination array.
*/
void copyUnionArray(
PVUnionArrayPtr const & from, PVUnionArrayPtr const & to);
/**
* Convert a PV to a <byte>.
* Convert a PV to a byte.
* @param pv a PV
* @return converted value
*/
@@ -477,13 +288,6 @@ public:
*/
inline void fromDouble(PVScalarPtr const & pv, double from) { pv->putFrom<double>(from); }
/**
* Convenience method for implementing toString.
* It generates a newline and inserts blanks at the beginning of the newline.
* @param builder The std::string * being constructed.
* @param indentLevel Indent level, Each level is four spaces.
*/
void newLine(std::string * buf, int indentLevel);
};
static inline ConvertPtr getConvert() { return Convert::getConvert(); }

View File

@@ -1,73 +0,0 @@
#ifndef PRINTER_H
#define PRINTER_H
#include <ostream>
#include <shareLib.h>
#include "pvData.h"
namespace epics { namespace pvData {
class PrinterBase
{
public:
virtual void setStream(std::ostream&);
virtual void clearStream();
virtual void print(const PVField&);
protected:
PrinterBase();
virtual ~PrinterBase()=0;
virtual void beginStructure(const PVStructure&);
virtual void endStructure(const PVStructure&);
virtual void beginStructureArray(const PVStructureArray&);
virtual void endStructureArray(const PVStructureArray&);
virtual void beginUnion(const PVUnion&);
virtual void endUnion(const PVUnion&);
virtual void beginUnionArray(const PVUnionArray&);
virtual void endUnionArray(const PVUnionArray&);
virtual void encodeScalar(const PVScalar&);
virtual void encodeArray(const PVScalarArray&);
virtual void encodeNull();
inline std::ostream& S() { return *strm; }
void impl_print(const PVField&);
private:
std::ostream *strm;
};
class PrinterPlain : public PrinterBase
{
size_t ilvl;
protected:
virtual void beginStructure(const PVStructure&);
virtual void endStructure(const PVStructure&);
virtual void beginStructureArray(const PVStructureArray&);
virtual void endStructureArray(const PVStructureArray&);
virtual void beginUnion(const PVUnion&);
virtual void endUnion(const PVUnion&);
virtual void beginUnionArray(const PVUnionArray&);
virtual void endUnionArray(const PVUnionArray&);
virtual void encodeScalar(const PVScalar&);
virtual void encodeArray(const PVScalarArray&);
virtual void encodeNull();
public:
PrinterPlain();
virtual ~PrinterPlain();
};
}}
#endif // PRINTER_H

View File

@@ -33,6 +33,14 @@
typedef class std::ios std::ios_base;
#endif
#if defined(__GNUC__) && !(defined(__vxworks) && !defined(_WRS_VXWORKS_MAJOR))
#define USAGE_DEPRECATED __attribute__((deprecated))
#define USAGE_ERROR(MSG) __attribute__((error(MSG)))
#else
#define USAGE_DEPRECATED
#define USAGE_ERROR(MSG) { throw std::runtime_error(MSG); }
#endif
namespace epics { namespace pvData {
class PostHandler;
@@ -122,7 +130,8 @@ class PVDataCreate;
typedef std::tr1::shared_ptr<PVDataCreate> PVDataCreatePtr;
/**
* This class is implemented by code that calls setPostHander
* @brief This class is implemented by code that calls setPostHander
*
*/
class epicsShareClass PostHandler
{
@@ -133,13 +142,14 @@ public:
*/
virtual ~PostHandler(){}
/**
* This is called evertime postPut is called for this field.
* This is called every time postPut is called for this field.
*/
virtual void postPut() = 0;
};
/**
* PVField is the base class for each PVData field.
* @brief PVField is the base class for each PVData field.
*
* Each PVData field has an interface that extends PVField.
*/
class epicsShareClass PVField
@@ -158,19 +168,19 @@ public:
virtual ~PVField();
/**
* Get the fieldName for this field.
* @return The name or empty string if top level field.
* @return The name or empty string if top-level field.
*/
inline const std::string& getFieldName() const {return fieldName;}
/**
* Fully expand the name of this field using the
* names of its parent fields with a dot '.' seperating
* names of its parent fields with a dot '.' separating
* each name.
*/
std::string getFullName() const;
/**
* Get offset of the PVField field within top level structure.
* Get offset of the PVField field within top-level structure.
* Every field within the PVStructure has a unique offset.
* The top level structure has an offset of 0.
* The top-level structure has an offset of 0.
* The first field within the structure has offset equal to 1.
* The other offsets are determined by recursively traversing each structure of the tree.
* @return The offset.
@@ -194,8 +204,8 @@ public:
*/
bool isImmutable() const;
/**
* Set the field to be immutable, i. e. it can no longer be modified.
* This is permanent, i.e. once done the field can onot be made mutable.
* Set the field to be immutable, i.e. it can no longer be modified.
* This is permanent, i.e. once done the field cannot be made mutable.
*/
virtual void setImmutable();
/**
@@ -231,12 +241,15 @@ public:
*/
virtual std::ostream& dumpValue(std::ostream& o) const = 0;
void copy(const PVField& from);
void copyUnchecked(const PVField& from);
protected:
PVField::shared_pointer getPtrSelf()
{
return shared_from_this();
}
PVField(FieldConstPtr field);
explicit PVField(FieldConstPtr field);
void setParentAndName(PVStructure *parent, std::string const & fieldName);
private:
static void computeOffset(const PVField *pvField);
@@ -256,7 +269,8 @@ private:
epicsShareExtern std::ostream& operator<<(std::ostream& o, const PVField& f);
/**
* PVScalar is the base class for each scalar field.
* @brief PVScalar is the base class for each scalar field.
*
*/
class epicsShareClass PVScalar : public PVField {
// friend our child class(s) so that it
@@ -317,12 +331,16 @@ public:
virtual void assign(const PVScalar&) = 0;
virtual void copy(const PVScalar& from) = 0;
virtual void copyUnchecked(const PVScalar& from) = 0;
protected:
PVScalar(ScalarConstPtr const & scalar);
explicit PVScalar(ScalarConstPtr const & scalar);
};
/**
* Class that holds the data for each posssible scalar type.
* @brief Class that holds the data for each possible scalar type.
*
*/
template<typename T>
class epicsShareClass PVScalarValue : public PVScalar {
@@ -345,7 +363,7 @@ public:
virtual T get() const = 0;
/**
* Put a new value into the PVScalar.
* @param The value.
* @param value The value.
*/
virtual void put(T value) = 0;
@@ -381,8 +399,27 @@ public:
put(castUnsafe<T,T1>(val));
}
virtual void assign(const PVScalar& scalar)
{
if(isImmutable())
throw std::invalid_argument("destination is immutable");
copyUnchecked(scalar);
}
virtual void copy(const PVScalar& from)
{
assign(from);
}
virtual void copyUnchecked(const PVScalar& from)
{
if(this==&from)
return;
T result;
from.getAs((void*)&result, typeCode);
put(result);
}
protected:
PVScalarValue(ScalarConstPtr const & scalar)
explicit PVScalarValue(ScalarConstPtr const & scalar)
: PVScalar(scalar) {}
virtual void getAs(void * result, ScalarType rtype) const
{
@@ -395,16 +432,6 @@ protected:
castUnsafeV(1, typeCode, (void*)&result, stype, src);
put(result);
}
virtual void assign(const PVScalar& scalar)
{
if(this==&scalar)
return;
if(isImmutable())
throw std::invalid_argument("Destination is immutable");
T result;
scalar.getAs((void*)&result, typeCode);
put(result);
}
private:
friend class PVDataCreate;
@@ -437,7 +464,8 @@ typedef std::tr1::shared_ptr<PVFloat> PVFloatPtr;
typedef std::tr1::shared_ptr<PVDouble> PVDoublePtr;
/**
* PVString is special case, since it implements SerializableArray
* @brief PVString is special case, since it implements SerializableArray
*
*/
class epicsShareClass PVString : public PVScalarValue<std::string>, SerializableArray {
public:
@@ -446,14 +474,18 @@ public:
*/
virtual ~PVString() {}
protected:
PVString(ScalarConstPtr const & scalar)
explicit PVString(ScalarConstPtr const & scalar)
: PVScalarValue<std::string>(scalar) {}
};
typedef std::tr1::shared_ptr<PVString> PVStringPtr;
/**
* PVArray is the base class for all array types, i.e. the scalarArray types and structureArray.
* @brief PVArray is the base class for all array types.
*
* The array types are unionArray, strucrtureArray and scalarArray.
* There is a scalarArray type for each scalarType.
*
*/
class epicsShareClass PVArray : public PVField, public SerializableArray {
public:
@@ -472,8 +504,8 @@ public:
*/
virtual ArrayConstPtr getArray() const = 0;
/**
* Set the field to be immutable, i. e. it can no longer be modified.
* This is permanent, i.e. once done the field can onot be made mutable.
* Set the field to be immutable, i.e. it can no longer be modified.
* This is permanent, i.e. once done the field cannot be made mutable.
*/
virtual void setImmutable();
/**
@@ -483,7 +515,7 @@ public:
virtual std::size_t getLength() const = 0;
/**
* Set the array length.
* @param The length.
* @param length The length.
*/
virtual void setLength(std::size_t length) = 0;
/**
@@ -503,14 +535,16 @@ public:
void setCapacityMutable(bool isMutable);
/**
* Set the array capacity.
* @param The capacity.
* @param capacity The capacity.
*/
virtual void setCapacity(std::size_t capacity) = 0;
using PVField::dumpValue;
virtual std::ostream& dumpValue(std::ostream& o, std::size_t index) const = 0;
protected:
PVArray(FieldConstPtr const & field);
explicit PVArray(FieldConstPtr const & field);
void checkLength(size_t length);
private:
bool capacityMutable;
friend class PVDataCreate;
@@ -518,9 +552,9 @@ private:
epicsShareExtern std::ostream& operator<<(format::array_at_internal const& manip, const PVArray& array);
/**
* Base class for a scalarArray.
* @brief Base class for a scalarArray.
*
*/
class epicsShareClass PVScalarArray : public PVArray {
public:
@@ -568,7 +602,7 @@ public:
* A copy and element-wise conversion is performed unless
* the element type of the PVScalarArray matches the
* type of the provided data.
* If the types do match then a new refernce to the provided
* If the types do match then a new reference to the provided
* data is kept.
*
* Calls postPut()
@@ -586,22 +620,38 @@ public:
* A copy and element-wise conversion is performed unless
* the element type of the PVScalarArray matches the
* type of the provided data.
* If the types do match then a new refernce to the provided
* If the types do match then a new reference to the provided
* data is kept.
*/
void assign(PVScalarArray& pv) {
void assign(const PVScalarArray& pv) {
if (isImmutable())
throw std::invalid_argument("destination is immutable");
copyUnchecked(pv);
}
void copy(const PVScalarArray& from) {
assign(from);
}
void copyUnchecked(const PVScalarArray& from) {
if (this==&from)
return;
shared_vector<const void> temp;
pv._getAsVoid(temp);
from._getAsVoid(temp);
_putFromVoid(temp);
}
protected:
PVScalarArray(ScalarArrayConstPtr const & scalarArray);
explicit PVScalarArray(ScalarArrayConstPtr const & scalarArray);
private:
friend class PVDataCreate;
};
/**
* @brief Data interface for a structure,
*
*/
class epicsShareClass PVStructure : public PVField, public BitSetSerializable
{
public:
@@ -613,8 +663,8 @@ public:
typedef PVStructure & reference;
typedef const PVStructure & const_reference;
/**
* Set the field to be immutable, i. e. it can no longer be modified.
* This is permanent, i.e. once done the field can onot be made mutable.
* Set the field to be immutable, i.e. it can no longer be modified.
* This is permanent, i.e. once done the field cannot be made mutable.
*/
virtual void setImmutable();
/**
@@ -634,23 +684,42 @@ public:
*/
PVFieldPtr getSubField(std::string const &fieldName) const;
/**
* Get a subfield with the specified name.
* @param fieldName a '.' separated list of child field names (no whitespace allowed)
* @returns A pointer to the sub-field or null if field does not exist or has a different type
* @code
* PVIntPtr ptr = pvStruct->getSubField<PVInt>("substruct.leaffield");
* @endcode
*/
template<typename PVT>
std::tr1::shared_ptr<PVT> getSubField(std::string const &fieldName) const
FORCE_INLINE std::tr1::shared_ptr<PVT> getSubField(std::string const &fieldName) const
{
PVFieldPtr pvField = getSubField(fieldName);
if (pvField.get())
return std::tr1::dynamic_pointer_cast<PVT>(pvField);
return this->getSubField<PVT>(fieldName.c_str());
}
template<typename PVT>
std::tr1::shared_ptr<PVT> getSubField(const char *name) const
{
PVField *raw = getSubFieldImpl(name, false);
if (raw)
return std::tr1::dynamic_pointer_cast<PVT>(raw->shared_from_this());
else
return std::tr1::shared_ptr<PVT>();
}
/**
* Get the subfield with the specified offset.
* @param fieldOffset The offset.
* @return Pointer to the field or null if field does not exist.
*/
PVFieldPtr getSubField(std::size_t fieldOffset) const;
/**
* Get the subfield with the specified offset.
* @param fieldOffset The offset.
* @return Pointer to the field or null if field does not exist.
*/
template<typename PVT>
std::tr1::shared_ptr<PVT> getSubField(std::size_t fieldOffset) const
{
@@ -662,127 +731,51 @@ public:
}
/**
* Get a boolean field with the specified name.
* No longer needed. Use templete version of getSubField
* @param fieldName The name of the field to get.
* @return Pointer to the field of null if a field with that name and type does not exist.
* Get a subfield with the specified name.
* @param fieldName a '.' separated list of child field names (no whitespace allowed)
* @returns A reference to the sub-field (never NULL)
* @throws std::runtime_error if the requested sub-field doesn't exist, or has a different type
*/
PVBooleanPtr getBooleanField(std::string const &fieldName) ;
FORCE_INLINE PVFieldPtr getSubFieldT(std::string const &fieldName) const
{
return getSubFieldImpl(fieldName.c_str())->shared_from_this();
}
/**
* Get a byte field with the specified name.
* No longer needed. Use templete version of getSubField
* @param fieldName The name of the field to get.
* @return Pointer to the field of null if a field with that name and type does not exist.
* Get a subfield with the specified name.
* @param fieldName a '.' separated list of child field names (no whitespace allowed)
* @returns A reference to the sub-field (never NULL)
* @throws std::runtime_error if the requested sub-field doesn't exist, or has a different type
* @code
* PVIntPtr ptr = pvStruct->getSubFieldT<PVInt>("substruct.leaffield");
* @endcode
*/
PVBytePtr getByteField(std::string const &fieldName) ;
template<typename PVT>
FORCE_INLINE std::tr1::shared_ptr<PVT> getSubFieldT(std::string const &fieldName) const
{
return this->getSubFieldT<PVT>(fieldName.c_str());
}
template<typename PVT>
std::tr1::shared_ptr<PVT> getSubFieldT(const char *name) const;
/**
* Get a short field with the specified name.
* No longer needed. Use templete version of getSubField
* @param fieldName The name of the field to get.
* @return Pointer to the field of null if a field with that name and type does not exist.
* Get the subfield with the specified offset.
* @param fieldOffset The offset.
* @returns A reference to the sub-field (never NULL)
* @throws std::runtime_error if the requested sub-field doesn't exist
*/
PVShortPtr getShortField(std::string const &fieldName) ;
PVFieldPtr getSubFieldT(std::size_t fieldOffset) const;
/**
* Get a int field with the specified name.
* No longer needed. Use templete version of getSubField
* @param fieldName The name of the field to get.
* @return Pointer to the field of null if a field with that name and type does not exist.
* Get the subfield with the specified offset.
* @param fieldOffset The offset.
* @returns A reference to the sub-field (never NULL)
* @throws std::runtime_error if the requested sub-field doesn't exist, or has a different type
*/
PVIntPtr getIntField(std::string const &fieldName) ;
/**
* Get a long field with the specified name.
* No longer needed. Use templete version of getSubField
* @param fieldName The name of the field to get.
* @return Pointer to the field of null if a field with that name and type does not exist.
*/
PVLongPtr getLongField(std::string const &fieldName) ;
/**
* Get an unsigned byte field with the specified name.
* No longer needed. Use templete version of getSubField
* @param fieldName The name of the field to get.
* @return Pointer to the field of null if a field with that name and type does not exist.
*/
PVUBytePtr getUByteField(std::string const &fieldName) ;
/**
* Get an unsigned short field with the specified name.
* No longer needed. Use templete version of getSubField
* @param fieldName The name of the field to get.
* @return Pointer to the field of null if a field with that name and type does not exist.
*/
PVUShortPtr getUShortField(std::string const &fieldName) ;
/**
* Get an unsigned int field with the specified name.
* No longer needed. Use templete version of getSubField
* @param fieldName The name of the field to get.
* @return Pointer to the field of null if a field with that name and type does not exist.
*/
PVUIntPtr getUIntField(std::string const &fieldName) ;
/**
* Get an unsigned long field with the specified name.
* No longer needed. Use templete version of getSubField
* @param fieldName The name of the field to get.
* @return Pointer to the field of null if a field with that name and type does not exist.
*/
PVULongPtr getULongField(std::string const &fieldName) ;
/**
* Get a float field with the specified name.
* No longer needed. Use templete version of getSubField
* @param fieldName The name of the field to get.
* @return Pointer to the field of null if a field with that name and type does not exist.
*/
PVFloatPtr getFloatField(std::string const &fieldName) ;
/**
* Get a double field with the specified name.
* No longer needed. Use templete version of getSubField
* @param fieldName The name of the field to get.
* @return Pointer to the field of null if a field with that name and type does not exist.
*/
PVDoublePtr getDoubleField(std::string const &fieldName) ;
/**
* Get a string field with the specified name.
* No longer needed. Use templete version of getSubField
* @param fieldName The name of the field to get.
* @return Pointer to the field of null if a field with that name and type does not exist.
*/
PVStringPtr getStringField(std::string const &fieldName) ;
/**
* Get a structure field with the specified name.
* No longer needed. Use templete version of getSubField
* @param fieldName The name of the field to get.
* @return Pointer to the field of null if a field with that name and type does not exist.
*/
PVStructurePtr getStructureField(std::string const &fieldName) ;
/**
* Get a union field with the specified name.
* No longer needed. Use templete version of getSubField
* @param fieldName The name of the field to get.
* @return Pointer to the field of null if a field with that name and type does not exist.
*/
PVUnionPtr getUnionField(std::string const &fieldName) ;
/**
* Get a scalarArray field with the specified name.
* No longer needed. Use templete version of getSubField
* @param fieldName The name of the field to get.
* @param elementType The element type.
* @return Pointer to the field of null if a field with that name and type does not exist.
*/
PVScalarArrayPtr getScalarArrayField(
std::string const &fieldName,ScalarType elementType) ;
/**
* Get a structureArray field with the specified name.
* No longer needed. Use templete version of getSubField
* @param fieldName The name of the field to get.
* @return Pointer to the field of null if a field with that name and type does not exist.
*/
PVStructureArrayPtr getStructureArrayField(std::string const &fieldName) ;
/**
* Get a unionArray field with the specified name.
* No longer needed. Use templete version of getSubField
* @param fieldName The name of the field to get.
* @return Pointer to the field of null if a field with that name and type does not exist.
*/
PVUnionArrayPtr getUnionArrayField(std::string const &fieldName) ;
template<typename PVT>
std::tr1::shared_ptr<PVT> getSubFieldT(std::size_t fieldOffset) const;
/**
* Serialize.
* @param pbuffer The byte buffer.
@@ -817,7 +810,7 @@ public:
* Constructor
* @param structure The introspection interface.
*/
PVStructure(StructureConstPtr const & structure);
explicit PVStructure(StructureConstPtr const & structure);
/**
* Constructor
* @param structure The introspection interface.
@@ -827,7 +820,14 @@ public:
virtual std::ostream& dumpValue(std::ostream& o) const;
void copy(const PVStructure& from);
void copyUnchecked(const PVStructure& from);
void copyUnchecked(const PVStructure& from, const BitSet& maskBitSet, bool inverse = false);
private:
PVField *getSubFieldImpl(const char *name, bool throws = true) const;
static PVFieldPtr nullPVField;
static PVBooleanPtr nullPVBoolean;
static PVBytePtr nullPVByte;
@@ -854,8 +854,43 @@ private:
};
template<typename PVT>
std::tr1::shared_ptr<PVT> PVStructure::getSubFieldT(const char *name) const
{
std::tr1::shared_ptr<PVT> pvField = std::tr1::dynamic_pointer_cast<PVT>(
getSubFieldImpl(name)->shared_from_this());
if (pvField.get())
return pvField;
else
{
std::stringstream ss;
ss << "Failed to get field: " << name << " (Field has wrong type)";
throw std::runtime_error(ss.str());
}
}
template<typename PVT>
std::tr1::shared_ptr<PVT> PVStructure::getSubFieldT(std::size_t fieldOffset) const
{
std::tr1::shared_ptr<PVT> pvField = std::tr1::dynamic_pointer_cast<PVT>(
getSubFieldT(fieldOffset));
if (pvField.get())
return pvField;
else
{
std::stringstream ss;
ss << "Failed to get field with offset "
<< fieldOffset << " (Field has wrong type)";
throw std::runtime_error(ss.str());
}
}
/**
* PVUnion has a single subfield which has a type specified by a union introspection interface.
* @brief PVUnion has a single subfield.
*
* The type for the subfield is specified by a union introspection interface.
*
*/
class epicsShareClass PVUnion : public PVField
{
@@ -871,7 +906,7 @@ public:
/**
* Undefined index.
* Default value upon PVUnion construction. Can be set by the user.
* Corresponds to {@code null} value.
* Corresponds to @c null value.
*/
static int32 UNDEFINED_INDEX;
@@ -882,8 +917,8 @@ public:
UnionConstPtr getUnion() const;
/**
* Get the {@code PVField} value stored in the field.
* @return {@code PVField} value of field, {@code null} if {@code getSelectedIndex() == UNDEFINED_INDEX}.
* Get the @c PVField value stored in the field.
* @return @c PVField value of field, @c null if {@code getSelectedIndex() == UNDEFINED_INDEX}.
*/
PVFieldPtr get() const;
@@ -895,8 +930,8 @@ public:
/**
* Select field (set index) and get the field at the index.
* @param index index of the field to select.
* @return corresponding PVField (of undetermined value), {@code null} if {@code index == UNDEFINED_INDEX}.
* @throws {@code std::invalid_argument} if index is invalid (out of range).
* @return corresponding PVField (of undetermined value), @c null if {@code index == UNDEFINED_INDEX}.
* @throws std::invalid_argument if index is invalid (out of range).
*/
PVFieldPtr select(int32 index);
@@ -909,7 +944,7 @@ public:
* Select field (set index) and get the field by given name.
* @param fieldName the name of the field to select.
* @return corresponding PVField (of undetermined value).
* @throws {@code std::invalid_argument} if field does not exist.
* @throws std::invalid_argument if field does not exist.
*/
PVFieldPtr select(std::string const & fieldName);
@@ -931,27 +966,30 @@ public:
std::string getSelectedFieldName() const;
/**
* Set the {@code PVField} (by reference!) as selected field.
* If a value is not a valid union field an {@code std::invalid_argument} exception is thrown.
* Set the @c PVField (by reference!) as selected field.
* If a value is not a valid union field an @c std::invalid_argument
* exception is thrown.
* @param value the field to set.
*/
void set(PVFieldPtr const & value);
/**
* Set the {@code PVField} (by reference!) as field at given index.
* If a value is not a valid union field an {@code std::invalid_argument} exception is thrown.
* Use {@code select(int)} to put by value.
* Set the @c PVField (by reference!) as field at given index.
* If a value is not a valid union field an @c std::invalid_argument
* exception is thrown.
* Use @c select(int32) to put by value.
* @param index index of a field to put.
* @param value the field to set.
* @see #select(int)
* @see #select(int32)
*/
void set(int32 index, PVFieldPtr const & value);
/**
* Set the {@code PVField} (by reference!) as field by given name.
* If a value is not a valid union field an {@code std::invalid_argument} exception is thrown.
* Use {@code select(std::string)} to put by value.
* Set the @c PVField (by reference!) as field by given name.
* If a value is not a valid union field an @c std::invalid_argument
* exception is thrown.
* Use @c select(std::string const &) to put by value.
* @param fieldName Name of the field to put.
* @param value the field to set.
* @see #select(std::string)
* @see #select(std::string const &)
*/
void set(std::string const & fieldName, PVFieldPtr const & value);
@@ -973,13 +1011,17 @@ public:
* Constructor
* @param punion The introspection interface.
*/
PVUnion(UnionConstPtr const & punion);
explicit PVUnion(UnionConstPtr const & punion);
virtual std::ostream& dumpValue(std::ostream& o) const;
void copy(const PVUnion& from);
void copyUnchecked(const PVUnion& from);
private:
static PVDataCreatePtr pvDataCreate;
friend class PVDataCreate;
UnionConstPtr unionPtr;
int32 selector;
@@ -1017,11 +1059,11 @@ namespace detail {
PVVectorStorage() : Base() {}
template<typename A>
PVVectorStorage(A a) : Base(a) {}
explicit PVVectorStorage(A a) : Base(a) {}
public:
virtual ~PVVectorStorage(){};
// Primative array manipulations
// Primitive array manipulations
//! Fetch a read-only view of the current array data
virtual const_svector view() const = 0;
@@ -1063,6 +1105,13 @@ namespace detail {
};
} // namespace detail
/**
* @brief template class for all extensions of PVArray.
*
* The direct extensions are pvBooleanArray, pvByteArray, ..., pvStringArray.
* There are specializations for PVStringArray, PVStructureArray, and PVUnionArray.
*
*/
template<typename T>
class epicsShareClass PVValueArray : public detail::PVVectorStorage<T,PVScalarArray> {
typedef detail::PVVectorStorage<T,PVScalarArray> base_t;
@@ -1084,6 +1133,9 @@ public:
*/
virtual ~PVValueArray() {}
/**
* Get introspection interface.
*/
virtual ArrayConstPtr getArray() const
{
return std::tr1::static_pointer_cast<const Array>(this->getField());
@@ -1121,14 +1173,15 @@ protected:
this->replace(shared_vector_convert<const T>(in));
}
PVValueArray(ScalarArrayConstPtr const & scalar)
explicit PVValueArray(ScalarArrayConstPtr const & scalar)
: base_t(scalar) {}
friend class PVDataCreate;
};
/**
* Data class for a structureArray
* @brief Data class for a structureArray
*
*/
template<>
class epicsShareClass PVValueArray<PVStructurePtr> : public detail::PVVectorStorage<PVStructurePtr,PVArray>
@@ -1195,6 +1248,7 @@ public:
virtual const_svector view() const { return value; }
virtual void swap(const_svector &other);
virtual void replace(const const_svector &other) {
checkLength(other.size());
value = other;
PVField::postPut();
}
@@ -1209,8 +1263,11 @@ public:
virtual std::ostream& dumpValue(std::ostream& o) const;
virtual std::ostream& dumpValue(std::ostream& o, std::size_t index) const;
void copy(const PVStructureArray& from);
void copyUnchecked(const PVStructureArray& from);
protected:
PVValueArray(StructureArrayConstPtr const & structureArray)
explicit PVValueArray(StructureArrayConstPtr const & structureArray)
:base_t(structureArray)
,structureArray(structureArray)
{}
@@ -1223,7 +1280,8 @@ private:
/**
* Data class for a unionArray
* @brief Data class for a unionArray
*
*/
template<>
class epicsShareClass PVValueArray<PVUnionPtr> : public detail::PVVectorStorage<PVUnionPtr,PVArray>
@@ -1290,6 +1348,7 @@ public:
virtual const_svector view() const { return value; }
virtual void swap(const_svector &other);
virtual void replace(const const_svector &other) {
checkLength(other.size());
value = other;
PVField::postPut();
}
@@ -1304,8 +1363,11 @@ public:
virtual std::ostream& dumpValue(std::ostream& o) const;
virtual std::ostream& dumpValue(std::ostream& o, std::size_t index) const;
void copy(const PVUnionArray& from);
void copyUnchecked(const PVUnionArray& from);
protected:
PVValueArray(UnionArrayConstPtr const & unionArray)
explicit PVValueArray(UnionArrayConstPtr const & unionArray)
:base_t(unionArray)
,unionArray(unionArray)
{}
@@ -1356,7 +1418,8 @@ typedef PVValueArray<std::string> PVStringArray;
typedef std::tr1::shared_ptr<PVStringArray> PVStringArrayPtr;
/**
* This is a singlton class for creating data instances.
* @brief This is a singleton class for creating data instances.
*
*/
class epicsShareClass PVDataCreate {
public:
@@ -1387,7 +1450,7 @@ public:
PVScalarPtr createPVScalar(ScalarConstPtr const & scalar);
/**
* Create an implementation of a scalar field. A Scalar introspection interface is created.
* @param fieldType The field type.
* @param scalarType The scalar type.
* @return The PVScalar implementation.
*/
PVScalarPtr createPVScalar(ScalarType scalarType);
@@ -1400,7 +1463,7 @@ public:
PVScalarPtr createPVScalar(PVScalarPtr const & scalarToClone);
/**
* template version
* @param PVT must ve a valid pvType
* @tparam PVT must be a valid PVType
* @return The PVScalar implementation.
*/
template<typename PVT>
@@ -1432,7 +1495,7 @@ public:
/**
* Create implementation for PVUnion.
* @param union The introspection interface.
* @param punion The introspection interface.
* @return The PVUnion implementation
*/
PVUnionPtr createPVUnion(UnionConstPtr const & punion);
@@ -1450,13 +1513,12 @@ public:
/**
* Create an implementation of an array field reusing the Array introspection interface.
* @param array The introspection interface.
* @param scalarArray The introspection interface.
* @return The PVScalarArray implementation.
*/
PVScalarArrayPtr createPVScalarArray(ScalarArrayConstPtr const & scalarArray);
/**
* Create an implementation for an array field. An Array introspection interface is created.
* @param parent The parent interface.
* @param elementType The element type.
* @return The PVScalarArray implementation.
*/
@@ -1464,13 +1526,13 @@ public:
/**
* Create an implementation of an array field by cloning an existing PVArray.
* The new PVArray will have the same value and auxInfo as the original.
* @param arrayToClone The PVScalarArray to clone.
* @param scalarArrayToClone The PVScalarArray to clone.
* @return The PVScalarArray implementation.
*/
PVScalarArrayPtr createPVScalarArray(PVScalarArrayPtr const & scalarArrayToClone);
/**
* template version
* @param PVT must ve a valid pvType
* @tparam PVT must be a valid pvType
* @return The PVScalarArray implementation.
*/
template<typename PVAT>
@@ -1506,7 +1568,7 @@ public:
PVUnionArrayPtr createPVUnionArray(UnionArrayConstPtr const & unionArray);
/**
* Create an implementation of an array with union elements.
* @param punion The introspection interface tht is used to create UnionArrayConstPtr.
* @param punion The introspection interface that is used to create UnionArrayConstPtr.
* All elements share the same introspection interface.
* @return The PVUnionArray implementation.
*/
@@ -1526,11 +1588,32 @@ private:
};
/**
* Get the single class that implemnents PVDataCreate
* @param The PVDataCreate factory.
* Get the single class that implements PVDataCreate
* @return The PVDataCreate factory.
*/
epicsShareExtern PVDataCreatePtr getPVDataCreate();
bool epicsShareExtern operator==(const PVField&, const PVField&);
static inline bool operator!=(const PVField& a, const PVField& b)
{return !(a==b);}
}}
/**
* stream support for pvField
*/
namespace std{
epicsShareExtern std::ostream& operator<<(std::ostream& o, const epics::pvData::PVField *ptr);
}
#undef USAGE_DEPRECATED
#undef USAGE_ERROR
#endif /* PVDATA_H */
/** @page Overview Documentation
*
* <a href = "pvDataCPP.html">pvData.html</a>
*
*/

File diff suppressed because it is too large Load Diff

View File

@@ -71,7 +71,7 @@ epicsShareExtern void copy(
PVStructureArray & pvFrom,
size_t fromOffset,
size_t fromStride,
PVStructureArray & pvToo,
PVStructureArray & pvTo,
size_t toOffset,
size_t toStride,
size_t count);
@@ -91,7 +91,7 @@ epicsShareExtern void copy(
PVArray & pvFrom,
size_t fromOffset,
size_t fromStride,
PVArray & pvToo,
PVArray & pvTo,
size_t toOffset,
size_t toStride,
size_t count);
@@ -111,7 +111,7 @@ epicsShareExtern void copy(
PVArray::shared_pointer const & pvFrom,
size_t fromOffset,
size_t fromStride,
PVArray::shared_pointer & pvToo,
PVArray::shared_pointer & pvTo,
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>
@@ -49,11 +49,11 @@ namespace detail {
}
/**
* This is a set of typdefs used by pvData.
* This is a set of typedefs used by pvData.
*/
/**
* boolean, i.e. can only have the values {@code false} or {@code true}
* boolean, i.e. can only have the values @c false or @c true
*/
typedef detail::pick_type<int8_t, signed char,
detail::pick_type<uint8_t, char, unsigned char>::type

View File

@@ -25,7 +25,8 @@ class StandardField;
typedef std::tr1::shared_ptr<StandardField> StandardFieldPtr;
/**
* Standard Fields is a class or creating or sharing Field objects for standard fields.
* @brief 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
* one with no properties and with properties
* The property field is a comma separated string of property names of the following:
@@ -51,7 +52,7 @@ typedef std::tr1::shared_ptr<StandardField> StandardFieldPtr;
string message
structure timeStamp
long secondsPastEpoch
int nanoSeconds
int nanoseconds
int userTag
* }
* In addition there are methods that create each of the property structures,
@@ -85,21 +86,21 @@ public:
StructureConstPtr regUnion(
UnionConstPtr const & punion,
std::string const & properties);
/** Create a structure that has a varient union value field.
/** Create a structure that has a variant 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 elementType The element 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 structure The Structure introspection object for elements of the 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.
@@ -108,7 +109,7 @@ public:
StructureConstPtr const & structure,
std::string const & properties);
/** Create a structure that has a unionArray value field.
* @param type The type.
* @param punion The Union introspection object for elements of the value field.
* @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.
@@ -117,12 +118,12 @@ public:
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".
* The id for the structure is "enum_t".
* @return The const shared pointer to the structure.
*/
StructureConstPtr enumerated();
/** Create a structure that has an enumerated structure value field
* The id for the structure is "uri:ev4:nt/2012/pwd:NTEnum".
* 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.

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