393 Commits
test1 ... 4.0.3

Author SHA1 Message Date
dhickin
354fdd412f make "local" *.local files take precedence over those in TOP/.. 2014-12-03 16:55:27 +00:00
dhickin
f3f6141e6a include CONFIG_SITE.local instead of CONFIG.local at top-level. 2014-12-03 16:10:25 +00:00
Marty Kraimer
b9592eeb8c Added tag 4.0.2 for changeset af82285f71aa 2014-11-24 06:55:18 -05:00
Marty Kraimer
6a62f9c082 catch std::exception and return NULL PVStructurePtr 2014-11-24 06:54:28 -05:00
Marty Kraimer
c5112ffa11 Added tag 4.0.1 for changeset b0d39d12d743 2014-11-11 07:05:19 -05:00
Matej Sekoranja
7b9fda4e81 merge 2014-11-10 21:33:47 +01:00
Matej Sekoranja
278e531806 PVUnion copy allways shallow 2014-11-10 21:30:48 +01:00
Marty Kraimer
047de40642 change date, this version, and previous version 2014-11-10 09:06:35 -05:00
Matej Sekoranja
4e671a1c21 win32 indent problem: local static DLL saga 2014-11-06 22:18:58 +01:00
Matej Sekoranja
f36c8ce280 testByteOrder: use MAIN instead of main 2014-11-06 14:28:49 +01:00
Matej Sekoranja
e77f2c91d7 fixed undeterministic serialization test on clang 2014-11-06 13:03:59 +01:00
Matej Sekoranja
82b0d5ce5f merge 2014-11-06 12:50:04 +01:00
Matej Sekoranja
6117035863 null element handling for structure/union array 2014-11-06 12:48:57 +01:00
Matej Sekoranja
c86e31ad99 vxWorks: type cast fixes 2014-11-06 12:38:01 +01:00
Matej Sekoranja
f506fe1c0e int/int32 compilation fix; now all test spass on RTEMS-i386 2014-11-05 14:05:28 +01:00
Matej Sekoranja
554dc06eda ScalarTypeID mapping fixed in case 'int' == 'long', e.g. RTEMS-i386 2014-11-05 13:52:10 +01:00
Matej Sekoranja
80e1dfd142 removed forces NE2K card or non i386 builds 2014-11-03 13:51:21 +01:00
Matej Sekoranja
6db5cf60dc removing file should not have been commited 2014-11-03 12:41:09 +01:00
Matej Sekoranja
63d181a0ac RTEMS QEMU tests 2014-11-03 12:37:12 +01:00
Matej Sekoranja
73c4896cce tests: VxWorks tests are now ready to be run 2014-10-31 17:49:10 -04:00
Matej Sekoranja
5b1b5ab904 tests: refactored test building so that one test object can be created for VxWorks and RTEMS 2014-10-31 18:29:55 +01:00
Matej Sekoranja
80a537bc4c vxWork tests for all subtests; still need to combine them all to one 2014-10-31 07:57:20 -04:00
Matej Sekoranja
2a8a1d3736 tests: PROD_HOST to TESTPROD_HOST; VxWorks tests for testApp/pv PASSES 2014-10-31 06:42:52 -04:00
Matej Sekoranja
61fbfa0684 Added tag 4.0.0 for changeset f9f187685032 2014-10-29 12:59:39 +01:00
Matej Sekoranja
f06a6bfe7b merge to default branch 2014-10-28 19:37:34 +01:00
Matej Sekoranja
587f81f511 win32 in vs2013 compilation fix 2014-10-28 19:36:57 +01:00
Matej Sekoranja
435ca63d1b ev4 to epics URI 2014-10-28 18:53:11 +01:00
Marty Kraimer
64bb660f44 Added tag 4.0.0 for changeset 9c62aaa83b9d 2014-10-15 14:47:48 -04:00
Marty Kraimer
8bf24de0b3 removed pvArray.html and pvDataDiscussion.html; good ideas now implemented 2014-10-08 15:03:52 -04:00
Marty Kraimer
943ea633a4 more work on pvDataCPP.html; minor changes to examples 2014-10-08 14:48:30 -04:00
dhickin
b1d5f7d7e5 Corrected NTUnio to NTUnion 2014-10-07 15:32:26 +01:00
dhickin
188b94ce19 Corrected spelling of synchrotron in licence. 2014-10-04 02:45:53 +01:00
dhickin
515282abfe Spelling and typos. 2014-10-04 01:33:59 +01:00
dhickin
efbdb722e7 Made sub-field/subfield consistent by changing to subfield. 2014-10-04 01:28:19 +01:00
dhickin
e980823294 Corrected NTUnio->NTUnion. 2014-10-04 00:22:46 +01:00
dhickin
3692f4fb3c Correctly produce <> for templates in code samples for PVUnionArray in pvDataCPP.html. 2014-10-03 15:58:55 +01:00
dhickin
3e645f3c79 Corrected spelling in pvDataCPP.html. 2014-10-03 15:24:20 +01:00
Marty Kraimer
6127763302 Added tag 4.0.0 for changeset 1348c22b1258 2014-09-30 16:59:37 -04:00
Marty Kraimer
19a181b38f change ev4:nt: to 3v4:nt/ 2014-09-30 15:26:23 -04:00
Marty Kraimer
2818b0384c flow: Created branch 'release/4.0'. 2014-09-30 15:06:43 -04:00
Marty Kraimer
36faf8c2ea change URI naming 2014-09-30 15:05:18 -04:00
Marty Kraimer
a208171250 change uri:ev4:nt/2012 to uri:ev4:nt/2014 2014-09-23 14:34:21 -04:00
Marty Kraimer
b8a2b7cff6 get documantation ready for pre release 2014-09-03 09:01:15 -04:00
Marty Kraimer
2a08cbc1a0 add static 2014-08-25 08:09:28 -04:00
Matej Sekoranja
62bc6c1fb1 PVControl::minStep implemented 2014-08-22 22:22:38 +02:00
Matej Sekoranja
1098650421 clang fix 2014-08-20 21:42:29 +02:00
Marty Kraimer
15d85c2f87 fix misspelled field names: nanoSecond => nanosecond; hystersis=>hysteresis 2014-08-20 06:27:24 -04:00
Matej Sekoranja
16fb3f0339 clang fixes 2014-08-19 20:58:12 +02:00
Matej Sekoranja
37f6dff065 bounded string 2014-08-19 20:42:15 +02:00
Marty Kraimer
baf8832fc9 allow record[] field() getField() putField() 2014-08-19 09:15:06 -04:00
Marty Kraimer
b558e11ede major changes to CreateRequest; now compatible with Java version 2014-08-19 08:25:38 -04:00
Matej Sekoranja
103cdabff1 fixed clang std::tr1 import by adding include 2014-08-13 21:53:15 +02:00
Matej Sekoranja
57e33c8f7d clang porting 2014-08-13 09:36:37 +02:00
Matej Sekoranja
da0f65c2d3 fixed size array serialization test 2014-08-12 13:20:00 +02:00
Matej Sekoranja
6535c075f3 fixed sized arrays 2014-08-12 13:17:17 +02:00
Matej Sekoranja
f3c0b9544c dumpValue for boolean fix 2014-08-11 22:09:46 +02:00
Matej Sekoranja
3609fd4745 fixed testCreateRequest, still fails 2014-07-30 21:49:52 +02:00
Matej Sekoranja
622e140622 Fixed/bounded scalar array impl. 2014-07-30 21:41:08 +02:00
Marty Kraimer
a4954c3825 fixed bug in createRequest.cpp 2014-07-30 06:50:22 -04:00
Matej Sekoranja
b6e1b9c203 reuse existing PVField instance on PVUnion::deserialize 2014-07-28 23:23:01 +02:00
Matej Sekoranja
34a35c2658 fixed/bounded array introspection data serialization 2014-07-28 23:05:49 +02:00
Marty Kraimer
90b7c9a17c change in TODO.md; add RELEASE_NOTES.html and TODO.html 2014-07-22 08:49:02 -04:00
Marty Kraimer
c72297020b update documentation 2014-07-10 13:17:26 -04:00
Matej Sekoranja
f07b601dce merge 2014-07-07 20:55:49 +02:00
Matej Sekoranja
63c62a2aae Union::dump indentification fixed 2014-07-07 20:54:38 +02:00
Matej Sekoranja
6888a9d340 Added tag 3.1.0 for changeset 260f35b9c6ca 2014-07-02 00:09:01 +02:00
Matej Sekoranja
72bf9f76a3 forgot to remove friend operator<< 2014-06-19 21:56:56 +02:00
Matej Sekoranja
c0c6213c7c Win32: friend incosistent linkage 2014-06-19 21:24:14 +02:00
Matej Sekoranja
652ef4bc82 merge 2014-06-19 14:29:05 +02:00
Matej Sekoranja
c6eed12139 String -> std::string, toString methods removed 2014-06-19 14:27:48 +02:00
Marty Kraimer
1132e25072 fix bug related to stride 2014-06-13 09:52:30 -04:00
Marty Kraimer
879e3a2b67 support UnionArray 2014-06-12 15:26:31 -04:00
Matej Sekoranja
6ec207141f fixed missing dllimport/dllexport on new code 2014-06-11 11:56:04 +02:00
Matej Sekoranja
45c657ce79 added missing src/copy/Makefile 2014-06-10 13:50:04 +02:00
Matej Sekoranja
888dc11c03 Added tag before_merge_changesAfter3_0_2 for changeset 40b681ffc5cd 2014-06-10 13:39:41 +02:00
Matej Sekoranja
5e3159f800 completed merge 2014-06-09 23:15:57 +02:00
Matej Sekoranja
570ec97eda flow: Closed <feature> 'changesAfter3_0_2'. 2014-06-09 22:53:59 +02:00
Matej Sekoranja
09c75823e6 byteBuffer: wrap support 2014-06-09 08:28:00 +02:00
Marty Kraimer
50c8c3b0bd more work on stride 2014-06-06 11:24:12 -04:00
Marty Kraimer
3fb44312c7 add support for stride 2014-06-05 10:20:01 -04:00
Matej Sekoranja
67bdf2ab8b bitSet <<operator(ostream) 2014-06-01 20:54:07 +02:00
Marty Kraimer
a56ed44e74 fix bugs found by tests in pvIOCJava 2014-05-24 06:47:16 -04:00
Marty Kraimer
3c912c3812 put to union field did not call postPut. 2014-05-21 16:18:38 -04:00
Matej Sekoranja
0ceb87eee1 Array IF added 2014-05-13 00:18:30 +02:00
Marty Kraimer
6510c10884 major update to pvDataCPP.html; minor updates while working on documentation 2014-05-01 10:33:01 -04:00
Andrew Johnson
89da38cfa4 Jenkins fixes.
Remove aps_build script, no longer used.
Tests have all been converted to the EPICS harness,
so don't need running separately.
2014-04-29 12:10:35 -05:00
Andrew Johnson
82b5d0e50b flow: Merged <feature> 'housekeeping' to <develop> ('default'). 2014-04-29 10:43:05 -05:00
Andrew Johnson
bb8789a9ad flow: Closed <feature> 'housekeeping'. 2014-04-29 10:43:05 -05:00
Marty Kraimer
20345ab0dd forgot monitor.h 2014-04-23 09:16:28 -04:00
Marty Kraimer
d5dfb3de0c added monitorPlugin; fixed bug in PVField::getFullName(); 2014-04-23 09:10:37 -04:00
Andrew Johnson
88aabb41e7 Replace USAGE_DEPRECATED with EPICS_DEPRECATED
Also make USAGE_ERROR conditional on the GCC version,
to remove warnings from VxWorks 6.8 builds.
2014-04-21 11:11:09 -05:00
Andrew Johnson
897059303d Merged changes from default branch 2014-04-18 16:55:13 -05:00
Andrew Johnson
0b7607cf04 Merged change from default branch. 2014-04-16 16:08:08 -05:00
Matej Sekoranja
4a512f47de merge 2014-04-09 15:19:43 +02:00
Matej Sekoranja
76a54d38e4 byteBuffer: wrapped buffer support 2014-04-09 15:18:40 +02:00
Matej Sekoranja
b9b03940a2 DefaultArray deserialize fix 2014-04-08 13:27:24 +02:00
Andrew Johnson
8370a97866 Unify configure files with the other V4 modules
Move include/pv setting into src/Makefile
2014-04-03 16:57:14 -05:00
Andrew Johnson
b659c77dbb Fix instructions in RELEASE file 2014-04-02 15:19:14 -05:00
Andrew Johnson
e45b842a6c Enable CHECK_RELEASE warnings 2014-04-02 14:43:32 -05:00
Marty Kraimer
c2f22a4ad8 make testPVCopy.cpp a proper epicsUnitTest 2014-04-02 10:15:53 -04:00
Marty Kraimer
cb15a8676b remove PVData methods that change introspection interface
remove deprecated methods
move CreateRequest from pvAccessCPP to pvDataCPP
move pvCopy from pvDatabaseCPP to pvDataCPP
2014-04-01 09:35:29 -04:00
Andrew Johnson
32ba6d444b Cleaned up CONFIG_SITE file.
Introduced WITH_COVERAGE Make variable
to control build options.
2014-03-31 17:25:22 -05:00
Andrew Johnson
95b7a04041 Makefile fixups 2014-03-28 11:53:39 -05:00
Andrew Johnson
d81ef64799 Remove __rtems__, already defined by the compiler 2014-03-28 11:20:03 -05:00
Andrew Johnson
19269735ae Rename pvDataApp to src, adjust Makefiles. 2014-03-28 10:20:24 -05:00
Matej Sekoranja
f7957c8ea5 merge 2014-03-28 00:04:18 +01:00
Andrew Johnson
1e40797bc4 Split pvDataApp/Makefile into fragments. 2014-03-27 17:58:43 -05:00
Andrew Johnson
ad66f8af73 Tidy up top-level Makefile 2014-03-27 17:36:10 -05:00
Andrew Johnson
d436e61bdb sharedPtr.h: Remove trailing ; from macro expansion. 2014-03-27 17:35:05 -05:00
Andrew Johnson
c71e62746d ParseToPOD needs limits.h on some arch's 2014-03-27 17:34:02 -05:00
Andrew Johnson
d5b0ad5d80 flow: Created branch 'feature/housekeeping'. 2014-03-27 17:28:55 -05:00
Marty Kraimer
34f2d7bc9a created feature branch 2014-03-25 07:23:14 -04:00
Marty Kraimer
fb7f1b622b flow: Created branch 'feature/changesAfter3_0_2'. 2014-03-25 07:04:59 -04:00
Marty Kraimer
4a992e6e1c flow initialization: Added configuration file. 2014-03-25 07:04:47 -04:00
Matej Sekoranja
9593de8c0f DefaultPVArray: removed unnecessary flush at the end of serialization 2014-02-17 12:47:07 +01:00
Matej Sekoranja
8205be5220 #63: implemented PVStructure.get<type>Field() using template method, no more messages emitted 2014-02-14 15:10:18 +01:00
Matej Sekoranja
39c43c4c02 rtems build: testProperty _HOST was missing 2014-02-06 11:58:14 +01:00
Matej Sekoranja
8a9fa956e0 vxWorks (vx68 and later): m_data -> m_sdata; m_data is a macro efined by vxWorks 2014-02-05 22:28:54 +01:00
Matej Sekoranja
06e9c533e3 parseToPOD RTEMS 2014-01-31 11:53:51 +01:00
Matej Sekoranja
5bdcaf43db sharedVector: count > capacity bugfix (2) 2013-12-04 10:49:16 +01:00
Matej Sekoranja
df1d13a155 sharedVector: count > capacity bugfix 2013-12-04 10:01:50 +01:00
Matej Sekoranja
6e7b19b090 added current_function.h 2013-12-03 12:16:08 +01:00
Matej Sekoranja
279b73a477 win32 port : warnings removed 2013-11-28 21:31:02 +01:00
Matej Sekoranja
74239303b3 testPVScalarArray: cast to the right type 2013-11-27 01:45:40 +01:00
Matej Sekoranja
134f390a5f fixed SerializeHelper::writeSize back 2013-11-27 01:37:16 +01:00
Matej Sekoranja
8aa26b78bb win32 port: parseToPOD NEED_LONGLONG check, missing monitor.cpp 2013-11-27 01:15:35 +01:00
Matej Sekoranja
301038664e win32 port: visibility, warnings, templates 2013-11-27 01:11:12 +01:00
Matej Sekoranja
ccad38f2db added programmers cookbook raw draft 2013-11-26 14:46:36 +01:00
Matej Sekoranja
29dee42d34 FieldBuilder: typo addNested() -> endNested() 2013-11-26 13:45:30 +01:00
Matej Sekoranja
f9135c81de testSerialization: fixed warnings 2013-11-26 11:08:16 +01:00
Matej Sekoranja
9400635fd9 testBitSet: replaced printf with testDiag 2013-11-25 22:07:28 +01:00
Marty Kraimer
4102deceb3 convert all tests to use epicsUnitTest 2013-11-25 15:46:00 -05:00
Matej Sekoranja
86306740be typeCast.cpp: do not report index in exception message for scalars 2013-11-22 10:31:21 +01:00
Matej Sekoranja
8e63fc8b25 castVtyped: added index in exeption error message 2013-11-22 09:44:21 +01:00
Matej Sekoranja
3219bd0307 Win32 port: import/export headers 2013-11-20 14:49:40 +01:00
Matej Sekoranja
bdb4430bb6 Win32 port: fix and success compile and run using GCC -fvisibility=hidden 2013-11-20 13:40:07 +01:00
Matej Sekoranja
a574dbf89b start of Win32 port 2013-11-20 13:04:28 +01:00
Matej Sekoranja
47178370d5 FieldBuilder: better method names 2013-11-11 22:36:06 +01:00
dhickin
ac67fddbcb Fixed bug in outputting UnionArrays. 2013-11-11 12:02:35 +00:00
dhickin
e97fab3107 Simpler fix for bug in outputting StructureArrays. 2013-11-08 18:49:57 +00:00
dhickin
fee6f03ec2 Fixed bug in outputting StructureArrays. 2013-11-08 18:27:15 +00:00
Matej Sekoranja
1aff2ec112 tempalte helpers; static initialization order 2013-11-08 13:50:54 +01:00
Matej Sekoranja
57b3e9a8b2 run EPICS Harness Tests on CI 2013-11-08 00:01:24 +01:00
Matej Sekoranja
35dad272eb merge 2013-11-07 14:13:37 +01:00
Matej Sekoranja
d40c41048d PVUnion/PVUnionArray support and tests 2013-11-07 14:12:26 +01:00
Marty Kraimer
03f59c94b4 commit after merge 2013-11-06 07:42:03 -05:00
Marty Kraimer
87718f1c82 get rid of warnings 2013-11-06 07:41:16 -05:00
Matej Sekoranja
cbf7b69ef0 Union/UnionArray implemented, PVUnion/PVUnionArray not yet implemented; also implemented reuse of scalar/scalarArray instances in FieldCreate 2013-11-05 16:15:12 +01:00
Matej Sekoranja
c56c976a22 FieldBuilder (incl. tests) 2013-11-04 19:04:28 +01:00
Marty Kraimer
3579d17a05 moved pvSubArrayCopy from pvDatabaseCPP to pvDataCPP 2013-10-31 06:44:54 -04:00
Marty Kraimer
0f17bd23c7 make bitSet more comnpatible with Java implementation. 2013-10-31 06:03:51 -04:00
Marty Kraimer
db10bed951 update documentation; fix bug in executor; add typedefs to thread.h 2013-10-30 08:13:19 -04:00
Michael Davidsaver
071806f12b remove redundancy in print_cast 2013-10-29 18:06:42 -04:00
Michael Davidsaver
9cd7008efe typeCast String <-> boolean 2013-10-29 17:56:36 -04:00
Michael Davidsaver
14dc098761 no deperecated warning on old vxworks 2013-10-29 16:58:09 -04:00
Michael Davidsaver
8c6a895b19 disambiguate a template 2013-10-29 16:54:02 -04:00
Michael Davidsaver
01b8e69e4b remove illegal copy op
Can bypass freeze/thaw
2013-10-28 17:54:59 -04:00
Michael Davidsaver
11e91ac3fa Merge branch 'shared-vector' 2013-10-28 17:42:11 -04:00
Marty Kraimer
70380b9a43 Added tag 3.0.2 for changeset 58092712d092 2013-09-10 16:54:02 -04:00
Marty Kraimer
fa7a44f5b3 update links in .html files 2013-09-10 16:53:21 -04:00
Andrew Johnson
fb0329c0b5 APS Jenkins adjustment 2013-09-05 12:24:38 -05:00
Andrew Johnson
c3d04fdd08 Fix VxWorks builds 2013-09-05 10:26:56 -05:00
Marty Kraimer
ebb0c97c51 Added tag 3.0.1 for changeset 2a289ff41e2e 2013-09-03 08:37:28 -04:00
Marty Kraimer
aabe0f3594 update links on .html files 2013-09-03 08:37:08 -04:00
dhickin
7c21bf7aa1 Added tag 3.0.0 for changeset 4cecd4b200f8 2013-08-21 12:03:42 +01:00
Michael Davidsaver
de70d90603 shared_vector: simplify slice()
Correctly tracks capacity when user
over-slices.
2013-08-06 11:32:34 -04:00
Michael Davidsaver
31be738c10 minor 2013-08-06 10:43:47 -04:00
Michael Davidsaver
759d268af0 update testPVScalarArray 2013-07-29 15:10:04 -04:00
Michael Davidsaver
f21811eb6a Change enum to type in converters 2013-07-29 15:09:47 -04:00
Michael Davidsaver
c643509c7e PVField converters use type
Use type as template parameter instead of ScalarType
enum value.
2013-07-29 15:08:59 -04:00
Michael Davidsaver
0860f8e6f9 don't use deprecated PVValueArray<T>::get() 2013-07-29 11:44:53 -04:00
Michael Davidsaver
e96b447e37 add print_cast()
Cast value to "printable" type.
A no-op except for char types, which are cast to int
so that they are printed as numbers std::ostream operators.
2013-07-29 11:44:52 -04:00
Michael Davidsaver
0eecd3b1fe document freeze/thaw 2013-07-29 11:44:52 -04:00
Michael Davidsaver
b5b6ae100d update pvD array in tests 2013-07-25 17:30:33 -04:00
Michael Davidsaver
8fd9bf10e5 update pvD array implementation 2013-07-25 17:30:18 -04:00
Michael Davidsaver
9ac030169a update pvD array handling
Interface only uses shared_vector<const T>
storage also uses only const.
2013-07-25 17:22:16 -04:00
Michael Davidsaver
569bd3b681 update testSharedVector 2013-07-25 17:02:08 -04:00
Michael Davidsaver
45bb461c32 shared_vector require freeze/thaw
Remove the implicit cast from non-const to const.
Require the use of freeze/thaw when
changing between const and non-const.

Change argument of const_shared_vector_cast
to a non-const shared_vector reference
to allow it to be cleared by freeze/thaw.
2013-07-25 15:26:29 -04:00
Michael Davidsaver
105c3185f7 remove take(), copyIn(), and copyOut(). 2013-07-19 14:20:55 -04:00
Michael Davidsaver
5565e4e30c Convert don't use copyIn or copyOut 2013-07-19 14:18:04 -04:00
Michael Davidsaver
70ae281f45 test freeze/thaw 2013-07-16 18:59:04 -04:00
Marty Kraimer
b518efd196 Added tag 3.0-pre1 for changeset 4cecd4b200f8 2013-07-16 14:47:34 -04:00
Michael Davidsaver
6e3a344caa fix Convert::fromStringArray
destination should grow to fit
2013-07-16 10:48:01 -04:00
Michael Davidsaver
2e3cbed520 restart testConvert
start with fromStringArray
2013-07-16 10:47:11 -04:00
Michael Davidsaver
5e2e7c81a6 Merge remote branch 'md/master' into pvarr
* md/master:
  added
  minor changes
  comparison between implementations
  Proposed pvData.h interface
  added pvArray.html; made queue.h and bitSetUtil.* compatible with pvDataCPP.
2013-07-09 18:37:53 -04:00
Michael Davidsaver
cff59487ae shared_vector freeze and thaw 2013-07-09 18:24:51 -04:00
Michael Davidsaver
cdcbfe7378 update testPVScalarArray 2013-07-09 18:24:51 -04:00
Michael Davidsaver
0c4ef8f079 PV* use shared_vector_convert 2013-07-09 18:24:50 -04:00
Michael Davidsaver
c0e9dcff21 revise static_shared_vector_cast
Move the work into a special ctor
to allow full inline of casting wrapper

Prevent static_shared_vector_cast from
casting const <-> non-const
2013-07-09 18:24:41 -04:00
Michael Davidsaver
79eeb0fa2a update PVScalar and PVScalarValue<T>
hide the void* members for now.

Define PVScalarValue<T>::getAs and putFrom
to give a more efficient implementation.
2013-07-09 18:24:41 -04:00
Michael Davidsaver
46feb86a99 test shared_vector_convert 2013-07-09 18:24:41 -04:00
Michael Davidsaver
74f68c47d3 shared_vector_convert
Allow converting of shared_vector between types

Conversion utilizes castUnsafe<TO,FROM>().

Converting to/from void is supported.  Convert to void
is an alias for static_shared_vector_cast<void>().
Convert from void utilizes shared_vector<void>::original_type()
and throws std::runtime_error if this is not valid.

Casting now handles 'const void'
is most places where 'void' can be used.
2013-07-09 18:24:40 -04:00
Michael Davidsaver
3c7a738ffc shared_vector<void> tracks original type 2013-07-09 18:24:40 -04:00
Michael Davidsaver
22d4a53d65 create templateMeta.h
Home for common C++ template tricks
2013-07-09 18:24:40 -04:00
Michael Davidsaver
d319e2ed7b add ScalarTypeID template
Define a compile time mapping from
type to ScalarType enum value.
2013-07-09 11:19:46 -04:00
Michael Davidsaver
2cb07a8490 move parts of ScalarTypeFunc to sharedVector.h
Move the parts of ScalarTypeFunc which
deal with untyped shared_vector s
to sharedVector.h to allow sharedVector.h
to include pvIntrospect.h w/o creating
an include loop...
2013-07-09 10:36:48 -04:00
Michael Davidsaver
6900d4bbec make boolean type unambiguous
"char", "signed char", and "unsigned char"
are distinct types.  Define "boolean" to
be whichever is not "int8" or "uint8".
2013-07-08 09:58:37 -04:00
Michael Davidsaver
73450bdbc7 combine shared_vector<T> for void and const void 2013-07-03 14:23:17 -04:00
Marty Kraimer
776ff49ed2 added 2013-07-03 12:11:05 -04:00
Michael Davidsaver
00da6c88ae minor 2013-07-03 11:41:53 -04:00
Michael Davidsaver
986f036d20 replace accepts const_svector
Allows

PVValueArray<T> *a, *b;

a->replace(b->view());
2013-07-03 11:34:32 -04:00
Michael Davidsaver
5699c43b74 correct max_size
Take into account sizeof(E).
2013-07-02 17:42:46 -04:00
Marty Kraimer
b58b97a916 minor changes 2013-06-28 14:17:23 -04:00
Marty Kraimer
5f52f14094 comparison between implementations 2013-06-25 12:18:38 -04:00
Ralph Lange
5f8fa26bf3 jenkins: Fix CloudBees hgweb job 2013-06-19 18:11:04 +02:00
Ralph Lange
a5c835cfeb jenkins: add CloudBees hgweb job to sync repo to SF webspace 2013-06-19 10:59:29 +02:00
Marty Kraimer
ec6b67ffad Proposed pvData.h interface 2013-06-18 10:01:52 -04:00
Marty Kraimer
3de28e3cef added pvArray.html; made queue.h and bitSetUtil.* compatible with pvDataCPP. 2013-06-13 14:52:27 -04:00
Andrew Johnson
d2a649f5fa Fixed compiler warning, 2013-06-12 21:21:44 -05:00
Michael Davidsaver
23d5aab1e8 add Doxyfile 2013-06-11 17:42:31 -04:00
Michael Davidsaver
cf8c6718dd test PVStructureArray in testSerialization 2013-06-11 17:42:30 -04:00
Michael Davidsaver
b0c8249562 re-write testPVStructureArray 2013-06-11 17:42:30 -04:00
Michael Davidsaver
8cb0b1a7d6 use new PVStructureArray api 2013-06-11 17:42:30 -04:00
Michael Davidsaver
7f9745c8d1 Implement PVStructureArray with shared_vector
Combine as much as possible with scalar array handling.

PVStructureArray becomes PVValueArray<shared_ptr<PVStructure> >

Bulk of shared implementation moved the PVVectorStorage
which has a parametrized base to avoid using multiple inheritance.
2013-06-11 17:42:30 -04:00
Michael Davidsaver
4e749cc8be Improve shared_vector::push_back
push_back now allocates additional space
in powers of 2 up to 1k elements, then
in blocks of 1k elements.
2013-06-11 17:42:30 -04:00
Michael Davidsaver
70c9a7c18f simplify shared_vector ctors
Casting will be done through the copy constructor.
2013-06-11 14:39:40 -04:00
Michael Davidsaver
11e2ee19ea Fix Printer for structure arrays
Not handling NULL elements correctly.
2013-06-11 14:39:40 -04:00
Michael Davidsaver
a4cfab1242 Fix "optimize shared_vector for storing non-POD types"
Can't move references when the source array is
still referenced by other shared_vectors
2013-06-11 14:39:40 -04:00
Michael Davidsaver
be4738f59c remove weak_vector
It seems that shared_ptr::use_count() does
not include weak_ptr instances.  Therefore
shared_ptr::use_count()==1 (aka unique())
does *not* ensure exclusive ownership!

This breaks the assumption used by
shared_vector::make_unique() to avoid
allocating a new array in some cases.
2013-06-10 15:09:42 -04:00
Michael Davidsaver
b63c3da565 add const_pointer to shared_vector 2013-06-10 12:09:29 -04:00
Michael Davidsaver
0b89f08d09 explicit copy and assignment for shared_vector
Add explicit copy constructor and
assignment operator for shared_vector.
2013-06-10 12:09:29 -04:00
Michael Davidsaver
ac53153bea shared_vector: test reference and const_reference
Ensure that these typedefs are present and work
for 'T' and 'const T'.
2013-06-05 16:15:49 -04:00
Michael Davidsaver
bc3187a3f6 optimize shared_vector for storing non-POD types
pass values by reference where appropriate.
When reallocating arrays of shared_ptr
"move" with swap() instead of operator=
to avoid ref counter inc and dec for each
element.
2013-06-03 19:31:05 -04:00
Michael Davidsaver
4294710d9e make viewUnsafe protected
No longer part of the public API of PVValueArray
2013-06-03 19:31:05 -04:00
Matej Sekoranja
476f18332a valueAlarm for numeric scalar arrays support 2013-05-31 21:15:54 +02:00
Michael Davidsaver
82a33460cf pvData update doc comments 2013-05-31 09:58:52 -04:00
Michael Davidsaver
3b6268a4fc add const_iterator to shared_vector 2013-05-31 09:58:52 -04:00
Michael Davidsaver
41425b3fa1 more testIntrospect 2013-05-31 09:58:52 -04:00
Andrew Johnson
a964e3668d Added jenkins/aps_build script 2013-05-30 17:32:15 -05:00
Michael Davidsaver
57804494ef Misc fixes and error checking
fix argument type for getScalarType
mark getFieldName as const
Argument checking for Field construction
2013-05-24 18:28:54 -04:00
Michael Davidsaver
9039a10c9a update testIntrospect with epicsUnitTest 2013-05-24 18:28:54 -04:00
Michael Davidsaver
9e865bc37d Avoid unnecessary copying in copyIn
Only re-use the existing reference if
it is large enough to hold all the new data.
If it isn't then throw it away to avoid
copying its current contents during
the resize().
2013-05-23 18:19:35 -04:00
Michael Davidsaver
54ee8bf7a0 PVStructureArray: setLength before postPut
Ensure that the correct (new) length is seen.
2013-05-23 17:51:52 -04:00
Michael Davidsaver
629c8346d2 postPut in new array API
Call when appropriate (putFrom(), copyIn(), and replace()).
Not called by swap(), take(), reuse(), or shareData().
Users of the second set of methods are expected to call
one of the methods in the first set, or call postPut() directly.

Document when postPut is (not) called.
2013-05-23 17:51:52 -04:00
Michael Davidsaver
1bf2ff430a array resize respect immutability 2013-05-23 17:51:52 -04:00
Marty Kraimer
69be072a07 added test 2013-05-17 19:33:16 -04:00
Marty Kraimer
a2ca21a1a6 changes to queue and to bitSetUtil. 2013-05-16 09:04:42 -04:00
Michael Davidsaver
572c02bf6e update testOperators 2013-05-08 18:35:51 -04:00
Michael Davidsaver
80777b293f rewrite testPVScalarArray 2013-05-08 18:35:51 -04:00
Michael Davidsaver
3c08834377 update testSerialization 2013-05-08 18:35:51 -04:00
Michael Davidsaver
eeae12e3d4 Convert: remove to/from*Array 2013-05-08 18:35:51 -04:00
Michael Davidsaver
992ac73068 use new API
make copying explicit and replace some
use of PVValueArray<T>::put and get
2013-05-08 18:35:51 -04:00
Michael Davidsaver
e843779555 New array API for PVValueArray using shared_vector<T>
* In PVScalarArray

Add methods assign, getAs/putFrom, and copyOut/copyIn to allow get/put
with implicit convert.

assign() copys on PVScalarArray to another converting as necessary.
If the types do not match then an allocate and convert is done.

getAs/putFrom work with shared_vector<T> and can avoid a allocate
and convert operation if the types match.

copyOut/copyIn use plain C arrays will do either a copy if the types
match, and a convert otherwise.  No allocation is performed.

* In PVValueArray<T>

All array operations re-implemented in terms of
two virtual methods

  virtual const shared_vector<T>& viewUnsafe() const;
  virtual void swap(shared_vector<T>&);

Some convienence methods are also included:

  shared_vector<const T> view() const
  shared_vector<T> take()
  shared_vector<T> reuse()

Deprecate get(...), put(...), and shareData(...)

Remove getVector() and getSharedVector()

Adjust DefaultPVArray accordingly
2013-05-08 18:35:51 -04:00
Michael Davidsaver
5f4ca240b4 add ScalarTypeFunc::elementSize 2013-05-08 18:35:50 -04:00
Michael Davidsaver
79cd374f16 add ScalarTypeFunc::allocArray 2013-05-08 18:35:50 -04:00
Michael Davidsaver
b137b32fc6 test shared_vector<T>
use epicsUnitTest
test handling of void and const void instances
2013-05-08 18:35:50 -04:00
Michael Davidsaver
3cd2bfdef0 shared_vector implementation
Shared ownership of a single C array.

Tracks offset and length for each instance
allowing each owner to "view" a different
piece of the array.

Parts of shared_vector<T> which can work
for T=void are in shared_vector_base<T>.
Specializations shared_vector<void>
and shared_vector<const void> handle
un-typed arrays.

Allow casting to/from typed vector

Offsets and sizes of untyped vectors are tracked in
bytes.  Therefore casting to types where sizeof(T)>1
is undefined if the offset is not a multiple of
sizeof(T).
2013-05-08 18:21:34 -04:00
Michael Davidsaver
461dbdf0f8 remove Convert pointer from PVField
Allow inline construction of Convert
2013-05-08 17:46:31 -04:00
Michael Davidsaver
9e8a6b6304 fix const-ness in PVField compare 2013-05-08 17:46:31 -04:00
Michael Davidsaver
fd5ea89340 typo 2013-05-01 14:27:00 -04:00
Michael Davidsaver
1d1d2b31cd remove remaining state from Convert 2013-05-01 14:20:01 -04:00
Michael Davidsaver
d75656dad7 testTypeCast use epicsUnitTest 2013-05-01 12:41:19 -04:00
Michael Davidsaver
f0aa2fe0e0 fix printer
Don't overflow the stack for deep structures!
2013-05-01 12:18:21 -04:00
Michael Davidsaver
ae847aea2b allow putFrom to implicitly resize 2013-05-01 12:18:21 -04:00
Michael Davidsaver
00ac5bf64f PVStructure::getNumberFields != Structure::getNumberFields
Apparently PVStructure::getNumberFields is one indexed???
2013-05-01 12:18:21 -04:00
Michael Davidsaver
61e8024c65 fix mapping between int* and epicsInt* types 2013-04-30 18:14:05 -04:00
Michael Davidsaver
ee5a370c01 misc 2013-04-30 18:14:05 -04:00
Michael Davidsaver
659ce13e98 replace vector to/from in Convert 2013-04-30 18:14:04 -04:00
Michael Davidsaver
a7fde21300 replace scalar to/from in Convert 2013-04-30 18:14:04 -04:00
Michael Davidsaver
a6bfab2d74 replace copyScalarArray with PVScalarArray::assign 2013-04-30 18:14:04 -04:00
Michael Davidsaver
e948af1851 PVScalar::assign and PVScalarArray::assign 2013-04-30 18:14:04 -04:00
Michael Davidsaver
2062cc5d10 Convert::toStringArray with castUnsafe 2013-04-30 18:14:02 -04:00
Michael Davidsaver
e85d10c6d9 Convert::fromStringArray with castUnsafe 2013-04-30 18:14:02 -04:00
Michael Davidsaver
0e0ab66d45 add PVScalarArray::getAs and PVScalarArray::putFrom 2013-04-30 18:14:02 -04:00
Michael Davidsaver
f2635c7fdc Convert::fromString with castUnsafe 2013-04-30 18:14:02 -04:00
Michael Davidsaver
4d92bbe541 Use PrinterPlain in Convert 2013-04-30 18:14:01 -04:00
Michael Davidsaver
e6e1434fc1 Add PrinterPlain 2013-04-30 18:13:32 -04:00
Michael Davidsaver
5e689f94f4 add PVScalar::getAs and PVScalar::putFrom
Allow get/put to a scalar without knowledge of ScalarType

Currently won't work correctly for PVBoolean
2013-04-26 15:44:05 -04:00
Michael Davidsaver
c1b6d26b8e Convert::equals: move to operator==(PVField&,PVField&) 2013-04-22 16:12:03 -04:00
Michael Davidsaver
f72c5dba84 PVStructure compare typo 2013-04-22 15:47:51 -04:00
Michael Davidsaver
704007092c Convert::getFullName becomes PVField::getFullName
Compatibility wrapper using current Convert API
Allow PVField::getFieldName to be inline'd
Avoid multiple resize and copy operations
on result String.
2013-04-22 14:48:59 -04:00
Michael Davidsaver
2f8c434429 add castUnsafeV
non-template version of castUnsafe<TO>(FROM v)).
2013-04-22 11:59:20 -04:00
Michael Davidsaver
b0c57e7ae3 test castUnsafe w/ transform() 2013-04-22 11:59:20 -04:00
Michael Davidsaver
0e57391b4d vxWorks compatibility 2013-04-22 11:59:20 -04:00
Michael Davidsaver
7ff1a93e72 parseToPOD: fix 64-bit
Try again to detect if uint16_t is long or long long.
2013-04-18 13:54:04 -04:00
Michael Davidsaver
d7eada7216 type casting with castUnsafe<TO>(FROM val) 2013-04-15 14:39:42 -04:00
Michael Davidsaver
c435f71592 testOperators: avoid warning 2013-04-15 14:34:45 -04:00
Matej Sekoranja
0dd6f01ef6 direct, i.e. no-copy, de/serialization support 2013-04-12 21:54:11 +02:00
Matej Sekoranja
cd95b75563 gcc 4.7+ compiler warnings removed 2013-02-27 11:44:00 +01:00
Ralph Lange
4122e772c1 merge SF changes 2013-02-26 17:22:16 +01:00
Ralph Lange
2fbe99909c documentation: update Doxyfile 2013-02-26 17:21:28 +01:00
Ralph Lange
d4f3d6209c jenkins: fix URLs for dependencies 2013-02-26 17:20:52 +01:00
Ralph Lange
641a51aa4f Fix .hgignore to use patterns 2013-02-26 17:20:28 +01:00
Matej Sekoranja
67afe84593 mb moved to pvCommonCPP 2013-02-25 10:29:34 +01:00
Matej Sekoranja
66f7c90c51 merge 2013-02-22 21:30:01 +01:00
Matej Sekoranja
959117c391 mb portability, still to be ported to boost atomic 2013-02-22 21:27:26 +01:00
5e810c704f Missing library reference in Makefile 2013-02-21 15:50:57 +01:00
Matej Sekoranja
675243061d -Wextra compiler warnings fixed 2013-02-16 12:50:36 +01:00
Matej Sekoranja
246825d672 base 3.14 fix 2013-02-13 14:29:38 +01:00
Matej Sekoranja
aa1a67d6c1 added micro-benchmark 2013-02-13 14:18:42 +01:00
Matej Sekoranja
97b1848ba3 added array_at manip test 2013-02-11 10:30:30 +01:00
Matej Sekoranja
c4f6132aca added simple operators 'test', added <<= >>= operators to PVScalar 2013-02-08 22:45:04 +01:00
Matej Sekoranja
a0de4f126f operator<< for all PVField, indent and array_at manipulator 2013-02-07 22:52:16 +01:00
Ralph Lange
a8a96def97 jenkins: Publish documentation to .../tip in CloudBees build 2013-01-18 15:19:37 +01:00
Ralph Lange
eaddc30def Add doxygen to Cloudbees build (as local dependency) 2013-01-14 12:22:15 +01:00
Ralph Lange
aa17639e20 Comment out doxygen (which does not work on CloudBees) 2013-01-13 18:32:09 +01:00
Ralph Lange
58d7ad494b Add doxygen run to jenkins build job 2013-01-13 18:20:43 +01:00
Ralph Lange
2895f48bd6 Add build script for Jenkins on Cloudbees 2013-01-13 18:11:55 +01:00
Ralph Lange
8f6ea47501 configure: improved generic RELEASE file 2013-01-11 19:12:50 +01:00
Marty Kraimer
3eb6237343 missing '.' in "This version" and "Previous version" 2012-12-12 15:25:18 -05:00
Marty Kraimer
cb19940fa7 I forget to do an hg add on documentation/pvDataCPP_20121212.html 2012-12-12 15:17:44 -05:00
Marty Kraimer
4bc7e9c8fe several minor problems found while developing pvDatabaseCPP 2012-12-12 14:59:33 -05:00
dhickin
18ba24156c Added tag 2.0-BETA for changeset d70c5ad29163 2012-11-22 15:23:15 +00:00
Marty Kraimer
1d3c4d1762 get rid of unnecessary copies for StringArray 2012-10-29 13:32:34 -04:00
Marty Kraimer
51abc5032c make sure copy of vector is not made 2012-10-20 07:24:07 -04:00
Ralph Lange
69b3692841 Remove IDE configuration files (QtCreator) 2012-10-18 11:36:10 -04:00
Marty Kraimer
d627e08419 fix bug in PVStructure::appendPVField and PVStructure::appendPVFields 2012-10-11 06:19:08 -04:00
Matej Sekoranja
bd9f1d1949 StandardField IDs, dumpValue fix for (u)int8 2012-10-10 17:59:12 +02:00
Matej Sekoranja
04db13d00e default Structure id serialization opt. 2012-10-09 08:43:43 +02:00
Matej Sekoranja
f88f0b4a76 localStaticLock - static local thread-safety 2012-10-08 12:19:21 +02:00
Marty Kraimer
07f9a8c0f6 must include standardField or pvAccessCPP fails 2012-10-03 09:08:51 -04:00
Marty Kraimer
5ba0209f39 get rid of all static global objects 2012-10-03 08:59:23 -04:00
Marty Kraimer
ced439f4c4 fix for crash in pvDataCPP testV3Channel 2012-10-02 16:01:03 -04:00
Matej Sekoranja
cf44ec1191 scalar array (de)serialization fixed 2012-10-01 21:47:43 +02:00
Marty Kraimer
e7458fad01 change name to what it should be 2012-10-01 10:06:01 -04:00
Marty Kraimer
52dfdace88 fix some typos in pvDataCPP.html 2012-10-01 10:02:09 -04:00
Marty Kraimer
a23631a8ca fix bug related to PVStructurePtr createPVStructure(
StringArray const & fieldNames,PVFieldPtrArray const & pvFields);
The old implementation created a new version of each element of pvField.
The new version uses the version from pvFields.
There is a new shared pointer but the new shared pointer referenced the
same PVField as the original.
2012-09-28 06:33:39 -04:00
Unknown
6a378dae0d removed sprintf format warnings 2012-09-14 13:54:35 +02:00
Unknown
0b4a8550e5 type cast warnings removed 2012-09-13 17:50:38 +02:00
Matej Sekoranja
519601595c PVStructure de/serialization fixed 2012-09-12 11:30:58 +02:00
Matej Sekoranja
8dfd8ec02e merge 2012-09-10 08:59:36 +02:00
Matej Sekoranja
4cef1135a3 PVStructure serialization fixed 2012-09-10 08:56:11 +02:00
Unknown
a7bd52bd48 minimize preprocessor branching for vxWorks 2012-09-06 17:12:53 +02:00
Unknown
55df2e06e2 compatibility with vxWorks 2012-09-05 14:11:07 +02:00
Matej Sekoranja
cfc9ebefb0 merge 2012-09-03 23:46:06 +02:00
Matej Sekoranja
516518529c VxWorks ports from Dirk 2012-09-03 23:43:26 +02:00
Marty Kraimer
6b4eb1a1b0 StandardField: fix enumeratedAlarm ; testConvert fix uint64 integer constants 2012-08-28 13:09:37 -04:00
Marty Kraimer
5e3311a024 LICENSE, COPYRIGHT, file header 2012-08-22 14:39:19 -04:00
Matej Sekoranja
233a90e608 merge 2012-08-21 23:35:50 +02:00
Matej Sekoranja
4b26e1c442 dumpValue methods 2012-08-21 23:34:59 +02:00
Marty Kraimer
b216a62d1e changes for "String const&" 2012-08-20 14:51:09 -04:00
Matej Sekoranja
978cb937c4 String const & message 2012-08-20 19:09:01 +02:00
Matej Sekoranja
86adfc091b passing string by const ref 2012-08-20 16:37:26 +02:00
Marty Kraimer
8f3a1dde34 Use "String const &" in many more places 2012-08-20 09:16:43 -04:00
Marty Kraimer
9061e8f731 better implementation of setCapacity 2012-08-20 07:13:05 -04:00
Matej Sekoranja
05be6e6729 append/remove fields now preserves ID 2012-08-20 09:22:27 +02:00
Matej Sekoranja
156a05079e structure array deserialization fixed 2012-08-20 09:03:45 +02:00
Matej Sekoranja
0e48497cd4 array deserialization fixed 2012-08-20 09:01:51 +02:00
Marty Kraimer
fbfed5bab1 make tests more like regresion tests 2012-08-17 14:13:18 -04:00
Marty Kraimer
66fb300873 documentation updated; changes for Field::ID 2012-08-17 06:45:20 -04:00
Matej Sekoranja
6a86496385 added BitSet::size() 2012-07-31 11:47:42 +02:00
Matej Sekoranja
ac10b73e69 Field::getID() added 2012-07-31 10:30:50 +02:00
Matej Sekoranja
689d0875b7 null string check 2012-07-30 22:03:23 +02:00
Matej Sekoranja
d9465b0954 fixed due to monitor.h change 2012-07-24 21:28:37 +02:00
Matej Sekoranja
25b9e5fa5a monitor.h revised 2012-07-24 20:47:56 +02:00
Marty Kraimer
31922eac32 commit so that Matej can look at Monitor 2012-07-23 16:56:49 -04:00
Marty Kraimer
60d3467b1b commit after pull and merge 2012-07-23 07:06:41 -04:00
Marty Kraimer
ec1b5860fd more changes for unsigned 2012-07-23 07:04:25 -04:00
jrowlandls
00196cb7e2 merged 2012-07-20 10:25:34 +01:00
jrowlandls
92c68dfcbc pvData ctypes: added context handler and handle destructor to test example 2012-07-20 10:25:01 +01:00
Marty Kraimer
1db56f4b29 fix bug in unsigned standardField; missing const in pvIntrospect.h 2012-07-19 16:08:11 -04:00
jrowlandls
038567280b pvData: added C api test 2012-07-19 14:22:37 +01:00
Marty Kraimer
022e6304a3 call epicsExitCallAtExits() 2012-07-17 09:40:41 -04:00
Marty Kraimer
5dcd864c58 more shared_pointer everywhere 2012-07-17 09:23:53 -04:00
Marty Kraimer
32790674d6 changes for PVStructureArray 2012-07-08 12:51:46 -04:00
Marty Kraimer
5d6205cb44 changes to PVStructureArray 2012-07-08 08:38:57 -04:00
Marty Kraimer
27c4da5b73 working on PVStructureArray 2012-07-06 13:03:37 -04:00
Marty Kraimer
5d57e9bbcf remove monitorQueue 2012-07-03 14:52:30 -04:00
Marty Kraimer
9775fd4707 redo monotorQueue 2012-07-02 16:17:58 -04:00
Marty Kraimer
12d13bc2c0 fix bug in renameField; Add check for zero length fieldNames in Structure. 2012-06-22 14:04:05 -04:00
Matej Sekoranja
3991a51fd6 size_t changes 2012-06-07 14:15:12 +02:00
Matej Sekoranja
90960d370d added unsigned ints to the test 2012-05-23 08:08:00 +02:00
Marty Kraimer
126fe9c711 use const where appropriate 2012-05-22 11:51:53 -04:00
Matej Sekoranja
770e63b8da removed BitSetPtr due to possible 4.6.1 gcc problem 2012-05-21 21:11:20 +02:00
Marty Kraimer
e9b0dcd9f4 lots of work on Scalar Arrays 2012-05-21 10:06:28 -04:00
Matej Sekoranja
8040ad5fc7 serialization test, shared-ptr const 2012-05-18 11:42:57 +02:00
Marty Kraimer
24a08fe348 after merge 2012-05-17 16:06:15 -04:00
Marty Kraimer
198eb453be add testConvert 2012-05-17 16:04:49 -04:00
Marty Kraimer
e6a97e83ab fix more bugs 2012-05-17 09:15:19 -04:00
Matej Sekoranja
9ab2262e86 serialization/deserialization of Field-s 2012-05-16 22:11:17 +02:00
Marty Kraimer
29593a6eda get rid of unnecessary method in class StructureArray 2012-05-16 06:46:23 -04:00
Marty Kraimer
27ce426f46 return StringArray instead of StringArray & for choices 2012-05-15 16:06:33 -04:00
Marty Kraimer
ca195b44cf more debuging 2012-05-15 11:58:24 -04:00
Marty Kraimer
a396d8e6ac change the way PVField::getFieldName is implemented 2012-05-15 09:40:44 -04:00
Marty Kraimer
d320f00e96 fix messageType name 2012-05-10 06:28:27 -04:00
Marty Kraimer
7a60e02d5c make methods non inline 2012-05-09 15:38:19 -04:00
Marty Kraimer
fb453ea9e5 working on queue code 2012-05-09 14:06:17 -04:00
Marty Kraimer
87bff33c30 support unsigned; move fieldName; pvData use shared_pointer everywhere 2012-05-08 09:29:30 -04:00
Matej Sekoranja
2693201cfd OK -> Ok 2012-03-29 08:19:39 +02:00
Matej Sekoranja
2dba4aab2b Dirk's VxWorks porting 2012-03-28 20:40:49 +02:00
Matej Sekoranja
6caa725f5a Field serialization moved to pvData 2012-03-27 10:32:37 +02:00
msekoranja
198562c36c Added tag 1.1-BETA for changeset 4559c3de0cb4 2012-03-25 22:26:21 +02:00
jrowlandls
686a46f24c Added tag 1.0.1-BETA for changeset 9c59737f56e7 2012-03-14 16:27:36 +00:00
jrowlandls
c6debc3208 Added tag marchtest for changeset a29729ca0ecd 2012-03-07 16:03:20 +00:00
jrowlandls
7d3da0087a added local configs to hgignore 2012-01-03 15:19:28 +00:00
jrowlandls
f8e37ea18f updated RELEASE comments - need a default RELEASE for the build server 2011-12-22 11:11:20 +00:00
jrowlandls
b857c8f69c updated RELEASE comments 2011-12-22 11:08:27 +00:00
Marty Kraimer
b3cfd12487 update abstract 2011-12-20 09:23:43 -05:00
Marty Kraimer
04dc3a18ba change abstract 2011-12-20 08:22:28 -05:00
jrowlandls
1702f2aceb Added tag 1.1-SNAPSHOT for changeset d29d84f4c3f3 2011-12-19 18:25:45 +00:00
jrowlandls
5cfb66656d Added tag 1.0-BETA for changeset 6e8a22d01e82 2011-12-19 18:00:16 +00:00
Marty Kraimer
e8a3fbcf01 expand abstract 2011-12-19 07:20:11 -05:00
jrowlandls
793c8efb9c Added tag test1 for changeset 459f10877e56 2011-12-15 10:07:09 +00:00
304 changed files with 70878 additions and 21250 deletions

8
.hgflow Normal file
View File

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

View File

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

20
.hgtags Normal file
View File

@@ -0,0 +1,20 @@
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
260f35b9c6cad113f242c83c89be9cdac802f610 3.1.0
1348c22b125861ecb9da95b23f20314b167ee155 4.0.0
1348c22b125861ecb9da95b23f20314b167ee155 4.0.0
9c62aaa83b9db6ad69740a6bb46d6529e0e60b78 4.0.0
9c62aaa83b9db6ad69740a6bb46d6529e0e60b78 4.0.0
f9f187685032ebf4b108c759be196fda055c9e42 4.0.0
b0d39d12d743b82038066955db6bb957b1f2f767 4.0.1
af82285f71aae5d08fa8cf333b03772c5e689aff 4.0.2

12
COPYRIGHT Normal file
View File

@@ -0,0 +1,12 @@
/****************************************************
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.
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
*************************************************** */

1694
Doxyfile

File diff suppressed because it is too large Load Diff

78
LICENSE Normal file
View File

@@ -0,0 +1,78 @@
Copyright (c) 2008 Martin R. Kraimer
Copyright (c) 2006 The University of Chicago, as Operator of Argonne
National Laboratory.
Copyright (c) 2006 Deutsches Elektronen-Synchrotron,
Member of the Helmholtz Association, (DESY), HAMBURG, GERMANY.
Copyright (c) 2007 Control System Laboratory,
(COSYLAB) Ljubljana Slovenia
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
________________________________________________________________________
This software is in part copyrighted by the University of Chicago (UofC)
In no event shall UofC 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
UofC has been advised of the possibility of such damage.
UofC 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 UofC has no obligation to provide maintenance, support,
updates, enhancements, or modifications.
________________________________________________________________________
This software is in part copyrighted by the BERLINER SPEICHERRING
GESELLSCHAFT FUER SYNCHROTRONSTRAHLUNG M.B.H. (BESSY), BERLIN, GERMANY.
In no event shall BESSY 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
BESSY has been advised of the possibility of such damage.
BESSY 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 BESSY has no obligation to provide maintenance, support,
updates, enhancements, or modifications.
________________________________________________________________________
This software is in part copyrighted by the Deutsches Elektronen-Synchroton,
Member of the Helmholtz Association, (DESY), HAMBURG, GERMANY.
In no event shall DESY 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
DESY has been advised of the possibility of such damage.
DESY 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 DESY has no obligation to provide maintenance, support,
updates, enhancements, or modifications.
________________________________________________________________________

View File

@@ -1,12 +1,14 @@
#Makefile at top of application tree
# Makefile for the EPICS V4 pvData module
TOP = .
include $(TOP)/configure/CONFIG
DIRS += configure
DIRS += pvDataApp
pvDataApp_DEPEND_DIRS = configure
DIRS += src
src_DEPEND_DIRS = configure
DIRS += testApp
testApp_DEPEND_DIRS = pvDataApp
testApp_DEPEND_DIRS = src
include $(TOP)/configure/RULES_TOP

View File

@@ -1,66 +0,0 @@
<!DOCTYPE QtCreatorProject>
<qtcreator>
<data>
<variable>GenericProjectManager.GenericProject.Toolchain</variable>
<value type="int">0</value>
</data>
<data>
<variable>ProjectExplorer.Project.ActiveTarget</variable>
<value type="int">0</value>
</data>
<data>
<variable>ProjectExplorer.Project.EditorSettings</variable>
<valuemap type="QVariantMap">
<value key="EditorConfiguration.Codec" type="QByteArray">System</value>
</valuemap>
</data>
<data>
<variable>ProjectExplorer.Project.Target.0</variable>
<valuemap type="QVariantMap">
<value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Desktop</value>
<value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">GenericProjectManager.GenericTarget</value>
<value key="ProjectExplorer.Target.ActiveBuildConfiguration" type="int">0</value>
<value key="ProjectExplorer.Target.ActiveRunConfiguration" type="int">0</value>
<valuemap key="ProjectExplorer.Target.BuildConfiguration.0" type="QVariantMap">
<value key="GenericProjectManager.GenericBuildConfiguration.BuildDirectory" type="QString">/home/mrk/hgwork/pvDataCPP</value>
<valuemap key="ProjectExplorer.BuildConfiguration.BuildStep.0" type="QVariantMap">
<valuelist key="GenericProjectManager.GenericMakeStep.BuildTargets" type="QVariantList">
<value type="QString">all</value>
</valuelist>
<valuelist key="GenericProjectManager.GenericMakeStep.MakeArguments" type="QVariantList"/>
<value key="GenericProjectManager.GenericMakeStep.MakeCommand" type="QString"></value>
<value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Make</value>
<value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">GenericProjectManager.GenericMakeStep</value>
</valuemap>
<value key="ProjectExplorer.BuildConfiguration.BuildStepsCount" type="int">1</value>
<value key="ProjectExplorer.BuildConfiguration.CleanStepsCount" type="int">0</value>
<value key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment" type="bool">false</value>
<valuelist key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges" type="QVariantList"/>
<value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">all</value>
<value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">GenericProjectManager.GenericBuildConfiguration</value>
</valuemap>
<value key="ProjectExplorer.Target.BuildConfigurationCount" type="int">1</value>
<valuemap key="ProjectExplorer.Target.RunConfiguration.0" type="QVariantMap">
<valuelist key="ProjectExplorer.CustomExecutableRunConfiguration.Arguments" type="QVariantList"/>
<value key="ProjectExplorer.CustomExecutableRunConfiguration.BaseEnvironmentBase" type="int">2</value>
<value key="ProjectExplorer.CustomExecutableRunConfiguration.Executable" type="QString">/home/mrk/hgwork/pvDataCPP/bin/linux-x86/testIntrospect</value>
<value key="ProjectExplorer.CustomExecutableRunConfiguration.UseTerminal" type="bool">false</value>
<valuelist key="ProjectExplorer.CustomExecutableRunConfiguration.UserEnvironmentChanges" type="QVariantList"/>
<value key="ProjectExplorer.CustomExecutableRunConfiguration.UserName" type="QString">testIntrospect</value>
<value key="ProjectExplorer.CustomExecutableRunConfiguration.UserSetName" type="bool">true</value>
<value key="ProjectExplorer.CustomExecutableRunConfiguration.WorkingDirectory" type="QString">$BUILDDIR</value>
<value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">testIntrospect</value>
<value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">ProjectExplorer.CustomExecutableRunConfiguration</value>
</valuemap>
<value key="ProjectExplorer.Target.RunConfigurationCount" type="int">1</value>
</valuemap>
</data>
<data>
<variable>ProjectExplorer.Project.TargetCount</variable>
<value type="int">1</value>
</data>
<data>
<variable>ProjectExplorer.Project.Updater.FileVersion</variable>
<value type="int">4</value>
</data>
</qtcreator>

View File

@@ -1,85 +0,0 @@
include/AbstractPVArray.h
include/AbstractPVField.h
include/AbstractPVScalar.h
include/AbstractPVScalarArray.h
include/BasePVBoolean.h
include/BasePVBooleanArray.h
include/BasePVByte.h
include/BasePVByteArray.h
include/BasePVDouble.h
include/BasePVDoubleArray.h
include/BasePVFloat.h
include/BasePVFloatArray.h
include/BasePVInt.h
include/BasePVIntArray.h
include/BasePVLong.h
include/BasePVLongArray.h
include/BasePVShort.h
include/BasePVShortArray.h
include/BasePVString.h
include/BasePVStructure.h
include/BasePVStructureArray.h
include/bitSet.h
include/byteBuffer.h
include/convert.h
include/factory.h
include/lock.h
include/noDefaultMethods.h
include/pvData.h
include/pvIntrospect.h
include/requester.h
include/serialize.h
include/standardField.h
pvDataApp/factory/AbstractPVArray.h
pvDataApp/factory/AbstractPVField.h
pvDataApp/factory/AbstractPVScalar.h
pvDataApp/factory/AbstractPVScalarArray.h
pvDataApp/factory/BasePVBoolean.h
pvDataApp/factory/BasePVBooleanArray.h
pvDataApp/factory/BasePVByte.h
pvDataApp/factory/BasePVByteArray.h
pvDataApp/factory/BasePVDouble.h
pvDataApp/factory/BasePVDoubleArray.h
pvDataApp/factory/BasePVFloat.h
pvDataApp/factory/BasePVFloatArray.h
pvDataApp/factory/BasePVInt.h
pvDataApp/factory/BasePVIntArray.h
pvDataApp/factory/BasePVLong.h
pvDataApp/factory/BasePVLongArray.h
pvDataApp/factory/BasePVShort.h
pvDataApp/factory/BasePVShortArray.h
pvDataApp/factory/BasePVString.h
pvDataApp/factory/BasePVStringArray.h
pvDataApp/factory/BasePVStructure.h
pvDataApp/factory/BasePVStructureArray.h
pvDataApp/factory/Convert.cpp
pvDataApp/factory/factory.h
pvDataApp/factory/FieldCreateFactory.cpp
pvDataApp/factory/PVAuxInfoImpl.cpp
pvDataApp/factory/PVDataCreateFactory.cpp
pvDataApp/factory/StandardField.cpp
pvDataApp/factory/TypeFunc.cpp
pvDataApp/misc/bitSet.h
pvDataApp/misc/byteBuffer.h
pvDataApp/misc/lock.h
pvDataApp/misc/noDefaultMethods.h
pvDataApp/misc/requester.h
pvDataApp/misc/serialize.h
pvDataApp/pv/convert.h
pvDataApp/pv/pvData.h
pvDataApp/pv/pvIntrospect.h
pvDataApp/pv/standardField.h
pvDataApp/test/testIntrospect.cpp
pvDataApp/test/testPVAuxInfo.cpp
pvDataApp/test/testPVScalar.cpp
pvDataApp/test/testPVScalarArray.cpp
pvDataApp/test/testSimpleStructure.cpp
pvDataApp/misc/epicsException.h
pvDataApp/misc/byteBuffer.cpp
pvDataApp/misc/bitSet.cpp
pvDataApp/miscTest/testByteBuffer.cpp
pvDataApp/miscTest/testBitSet.cpp
pvDataApp/miscTest/testBaseException.cpp
pvDataApp/misc/serializeHelper.h
pvDataApp/misc/serializeHelper.cpp
pvDataApp/pvTest/testIntrospect.cpp

View File

@@ -1,4 +0,0 @@
include
pvDataApp/factory
pvDataApp/misc
pvDataApp/pv

View File

@@ -1,30 +1,29 @@
# CONFIG
# CONFIG - Load build configuration data
#
# Do not make changes to this file!
# You might want to change this to some shared set of rules, e.g.
# RULES=/path/to/epics/support/modules/rules/x-y
RULES=$(EPICS_BASE)
# Allow user to override where the build rules come from
RULES = $(EPICS_BASE)
# RELEASE files point to other application tops
include $(TOP)/configure/RELEASE
-include $(TOP)/configure/RELEASE.$(EPICS_HOST_ARCH)
-include $(TOP)/configure/RELEASE.$(EPICS_HOST_ARCH).Common
ifdef T_A
-include $(TOP)/configure/RELEASE.Common.$(T_A)
-include $(TOP)/configure/RELEASE.$(EPICS_HOST_ARCH).$(T_A)
endif
CONFIG=$(RULES)/configure
CONFIG = $(RULES)/configure
include $(CONFIG)/CONFIG
# Override for definition in base
# Override the Base definition:
INSTALL_LOCATION = $(TOP)
include $(TOP)/configure/CONFIG_SITE
-include $(TOP)/configure/CONFIG_SITE.$(EPICS_HOST_ARCH)
-include $(TOP)/configure/CONFIG_SITE.$(EPICS_HOST_ARCH).Common
# CONFIG_SITE files contain other build configuration settings
include $(TOP)/configure/CONFIG_SITE
-include $(TOP)/configure/CONFIG_SITE.$(EPICS_HOST_ARCH).Common
ifdef T_A
-include $(TOP)/configure/CONFIG_SITE.Common.$(T_A)
-include $(TOP)/configure/CONFIG_SITE.$(EPICS_HOST_ARCH).$(T_A)
-include $(TOP)/configure/O.$(T_A)/CONFIG_APP_INCLUDE
endif

View File

@@ -1,35 +1,30 @@
# CONFIG_SITE
# Make any application-specific changes to the EPICS build
# configuration variables in this file.
# configuration variables in this file.
#
# Host/target specific settings can be specified in files named
# CONFIG_SITE.$(EPICS_HOST_ARCH).Common
# CONFIG_SITE.Common.$(T_A)
# CONFIG_SITE.$(EPICS_HOST_ARCH).$(T_A)
# CONFIG_SITE.$(EPICS_HOST_ARCH).Common
# CONFIG_SITE.Common.$(T_A)
# CONFIG_SITE.$(EPICS_HOST_ARCH).$(T_A)
# Set this when you only want to compile this application
# for a subset of the cross-compiled target architectures
# that Base is built for.
#CROSS_COMPILER_TARGET_ARCHS = vxWorks-68040
# CHECK_RELEASE controls the consistency checking of the support
# applications pointed to by the RELEASE* files.
# Normally CHECK_RELEASE should be set to YES.
# Set CHECK_RELEASE to NO to disable checking completely.
# Set CHECK_RELEASE to WARN to perform consistency checking but
# continue building anyway if conflicts are found.
CHECK_RELEASE = YES
# Set this when your IOC and the host use different paths
# to access the application. This will be needed to boot
# from a Microsoft FTP server or with some NFS mounts.
# You must rebuild in the iocBoot directory for this to
# take effect.
#IOCS_APPL_TOP = <path to application top as seen by IOC>
# To install files into a location other than $(TOP) define
# INSTALL_LOCATION here.
#INSTALL_LOCATION=</path/name/to/install/top>
# If you don't want to install into $(TOP) then
# define INSTALL_LOCATION here
#INSTALL_LOCATION=<fullpathname>
-include $(TOP)/../CONFIG_SITE.local
-include $(TOP)/configure/CONFIG_SITE.local
ifeq ($(EPICS_TEST_COVERAGE),1)
ifdef WITH_COVERAGE
USR_CPPFLAGS += --coverage
USR_LDFLAGS += --coverage
endif
INSTALL_INCLUDE = $(INSTALL_LOCATION)/include/pv
USR_INCLUDES += -I $(INSTALL_LOCATION)/include
-include $(TOP)/configure/CONFIG_SITE.local

View File

@@ -2,14 +2,6 @@ TOP=..
include $(TOP)/configure/CONFIG
# CHECK_RELEASE controls the consistency checking of the support
# applications defined in the $(TOP)/configure/RELEASE* files.
# Normally CHECK_RELEASE should be set to YES.
# Set CHECK_RELEASE to NO to disable checking completely.
# Set CHECK_RELEASE to WARN to perform consistency checking,
# but continue the build even if conflicts are found.
CHECK_RELEASE = YES
TARGETS = $(CONFIG_TARGETS)
CONFIGS += $(subst ../,,$(wildcard $(CONFIG_INSTALLS)))

View File

@@ -1,33 +1,25 @@
#RELEASE Location of external products
# pvDataCPP RELEASE - Location of external support modules
#
# IF YOU MAKE ANY CHANGES to this file you MUST at least run
# "gnumake" in this directory afterwards; you usually need
# to run "gnumake rebuild" in the application's top level
# directory each time this file is changed.
# IF YOU CHANGE this file or any file it includes you must
# subsequently do a "gnumake rebuild" in the application's
# top level directory.
#
# NOTE: The build does not check dependencies against files
# that are outside this application, thus you should run
# "gnumake distclean install" in the top directory each time
# EPICS_BASE, SNCSEQ, or any other external module defined
# in the RELEASE file is rebuilt.
# The build process does not check dependencies against files
# that are outside this application, thus you should also do a
# "gnumake rebuild" in the top level directory after EPICS_BASE
# or any other external module pointed to below is rebuilt.
#
# Host/target specific settings can be specified in files named
# Host- or target-specific settings can be given in files named
# RELEASE.$(EPICS_HOST_ARCH).Common
# RELEASE.Common.$(T_A)
# RELEASE.$(EPICS_HOST_ARCH).$(T_A)
TEMPLATE_TOP=$(EPICS_BASE)/templates/makeBaseApp/top
#If using the sequencer, point SNCSEQ at its top directory:
#SNCSEQ=$(EPICS_BASE)/../modules/soft/seq
# EPICS_BASE usually appears last so other apps can override stuff:
#EPICS_BASE=/opt/epics/base
EPICS_BASE=/home/install/epics/base
#Capfast users may need the following definitions
#CAPFAST_TEMPLATES=
#SCH2EDIF_PATH=
# EPICS V4 Developers: Do not edit the locations in this file!
#
# Create a file RELEASE.local pointing to your PVCOMMON
# and EPICS_BASE build directories, e.g.
# PVCOMMON = /home/install/epicsV4/pvCommonCPP
# EPICS_BASE = /home/install/epics/base
-include $(TOP)/configure/RELEASE.local
-include $(TOP)/../RELEASE.local

1621
documentation/Doxyfile Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,58 @@
<h1>Release 4.0 IN DEVELOPMENT</h1>
<p>The main changes since release 3.0.2 are:</p>
<ul>
<li>array semantics now enforce Copy On Write.</li>
<li>String no longer defined.</li>
<li>timeStamp and valueAlarm name changes</li>
<li>toString replaced by stream I/O </li>
<li>union is new type.</li>
<li>copy is new.</li>
<li>monitorPlugin is new.</li>
</ul>
<h2>New Semantics for Arrays</h2>
<p>PVScalarArray, PVStructureArray, and PVUnionArray all enforce COW (Copy On Write) Semantics.
In order to limit memory usage the storage for raw data is managed via a new shared_vector facility.
This allows multiple instances of array data to use the shared raw data.
COW is implemented via shared_vectors of const data, i. e. data that can not be modified.</p>
<h2>String no longer defined</h2>
<p>This is replaced by std::string.</p>
<h2>timeStamp and valueAlarm name changes</h2>
<p>In timeStamp nanoSeconds is changed to nanoseconds.</p>
<p>In valueAlarm hystersis is changed to hysteresis</p>
<h2>toString replaced by stream I/O</h2>
<p>pvData.h and pvIntrospect no longer defines toString
Instead they have stream support.
pvIntrospect uses method dump and pvData uses dumpValue.
For example:</p>
<pre><code> PVDoublePtr pvValue;
String buffer;
pvValue-&gt;toString(&amp;buffer);
cout &lt;&lt; buffer &lt;&lt; endl;
buffer.clear();
pvValue-&gt;getField()-&gt;toString(&amp;buffer);
cout &lt;&lt; buffer &lt;&lt; evdl;
</code></pre>
<p>is replaced by</p>
<pre><code> PVDoublePtr pvValue;
cout &lt;&lt; *pvValue &lt;&lt; endl
cout &lt;&lt; *pvValue-&gt;getField() &lt;&lt; endl;
</code></pre>
<h2>union is a new basic type.</h2>
<p>There are two new basic types: union_t and unionArray.</p>
<p>A union is like a structure that has a single subfield.
There are two flavors:</p>
<ul>
<li><b>varient union</b> The field can have any type.</li>
<li><b>union</b> The field can any of specified set of types.</li>
</ul>
<p>The field type can be dynamically changed.</p>
<h2>copy</h2>
<p>This consists of createRequest and pvCopy.
createRequest was moved from pvAccess to here.
pvCopy is moved from pvDatabaseCPP and now depends
only on pvData, i. e. it no longer has any knowledge of PVRecord.</p>
<h2>monitorPlugin</h2>
<p>This is for is for use by code that implements pvAccess monitors.
This is prototype and is subject to debate.</p>
<h1>Release 3.0.2</h1>
<p>This was the starting point for RELEASE_NOTES</p>

View File

@@ -0,0 +1,89 @@
Release 4.0 IN DEVELOPMENT
===========
The main changes since release 3.0.2 are:
* array semantics now enforce Copy On Write.
* String no longer defined.
* timeStamp and valueAlarm name changes
* toString replaced by stream I/O
* union is new type.
* copy is new.
* monitorPlugin is new.
New Semantics for Arrays
--------
PVScalarArray, PVStructureArray, and PVUnionArray all enforce COW (Copy On Write) Semantics.
In order to limit memory usage the storage for raw data is managed via a new shared_vector facility.
This allows multiple instances of array data to use the shared raw data.
COW is implemented via shared_vectors of const data, i. e. data that can not be modified.
String no longer defined
---------
This is replaced by std::string.
timeStamp and valueAlarm name changes
--------------
In timeStamp nanoSeconds is changed to nanoseconds.
In valueAlarm hystersis is changed to hysteresis
toString replaced by stream I/O
---------
pvData.h and pvIntrospect no longer defines toString
Instead they have stream support.
pvIntrospect uses method dump and pvData uses dumpValue.
For example:
PVDoublePtr pvValue;
String buffer;
pvValue->toString(&buffer);
cout << buffer << endl;
buffer.clear();
pvValue->getField()->toString(&buffer);
cout << buffer << evdl;
is replaced by
PVDoublePtr pvValue;
cout << *pvValue << endl
cout << *pvValue->getField() << endl;
union is a new basic type.
------------
There are two new basic types: union_t and unionArray.
A union is like a structure that has a single subfield.
There are two flavors:
* <b>varient union</b> The field can have any type.
* <b>union</b> The field can any of specified set of types.
The field type can be dynamically changed.
copy
----
This consists of createRequest and pvCopy.
createRequest was moved from pvAccess to here.
pvCopy is moved from pvDatabaseCPP and now depends
only on pvData, i. e. it no longer has any knowledge of PVRecord.
monitorPlugin
-------------
This is for is for use by code that implements pvAccess monitors.
This is prototype and is subject to debate.
Release 3.0.2
==========
This was the starting point for RELEASE_NOTES

17
documentation/TODO.html Normal file
View File

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

38
documentation/TODO.md Normal file
View File

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

View File

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

BIN
documentation/examples.zip Normal file

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,179 @@
pvDataCPP cookbook
------------------
Creating introspection data interfaces
// create a scalar
getFieldCreate()->createScalar(pvDouble);
// create a scalar array
getFieldCreate()->createScalarArray(pvDouble);
// create a structure
getFieldCreate()->createFieldBuilder()->
setId("enum_t")->
add("index", pvDouble)->
addArray("choices", pvString)->
createStructure();
// create a structure (cntd.)
StructureConstPtr enum_t =
getFieldCreate()->createFieldBuilder()->
setId("enum_t")->
add("index", pvInt)->
addArray("choices", pvString)->
createStructure();
// create a structure (cntd.)
StructureConstPtr ntEnum =
getFieldCreate()->createFieldBuilder()->
setId("epics:nt/NTEnum:1.0")->
add("value", enum_t)->
addNestedStructure("timeStamp")->
setId("time_t")->
add("secondsPastEpoch", pvLong)->
add("nanoseconds", pvInt)->
add("userTag", pvInt)->
endNested()->
createStructure();
// create an union == same as structure
---
Creating data containers
// create a scalar
PVDouble::shared_pointer doubleValue = getPVDataCreate()->createPVScalar<PVDouble>();
// create a scalar array
PVDoubleArray::shared_pointer doubleArrayValue = getPVDataCreate()->createPVScalarArray<PVDouble>();
// create a structure
PVStructure::shared_pointer struct = getPVDataCreate()->createPVStructure(ntEnum);
// create an union
PVUnion::shared_pointer pvUnion = getPVDataCreate()->createPVUnion(unionIF);
// create a structure array
PVStructureArray::shared_pointer structArray = getPVDataCreate()->createPVStructureArray(ntEnum);
// scalar usage
PVInt::shared_pointer index = struct->getSubField<PVInt>("value.index");
int32 ix = index->get();
index->put(3);
std::cout << *index << std::endl;
// using <<=, >>= operators to get/set
*doubleValue <<= 12.3;
double val;
*doubleValue >>= val;
// array usage
PVStringArray::shared_pointer choices = struct->getSubField<PVStringArray>("value.choices");
// use view() to access read-only data
PVStringArray::const_svector data(choices->view());
for (std::size_t i = 0; i < data.size(); i++)
std::cout << data[i] << std::endl;
// use replace() to put new data
PVStringArray::svector newdata;
newdata.push_back("zero");
newdata.push_back("one");
newdata.push_back("two");
choices->replace(freeze(newdata));
// (add more use-cases) here
// print entire array
std::cout << *choices << std::endl;
// print elmenet at index == 1
std::cout << format::array_at(1) << *choices << std::endl;
----
Union handling
Union::const_shared_pointer punion =
getFieldCreate()->createFieldBuilder()->
add("doubleValue", pvDouble)->
add("intValue", pvInt)->
createUnion();
PVUnion::shared_pointer u = getPVDataCreate()->createPVUnion(punion);
// select and put
// this create a new instance of PVDouble (everytime select() is called)
PVDouble::shared_pointer doubleValue = u->select<PVDouble>("doubleValue");
doubeValue->put(12);
// select using index (and direct put)
u->select<PVDouble>(0)->put(12);
// select using existing PVField (PVUnion stores by-reference)
u->set("doubleValue", doubleValue);
// get selected field name or index
std::string selectedFN = u->getSelectedFieldName();
int32 selectedIndex = u->getSelectedIndex();
// get currently selected (knowing it's PVDouble)
PVDouble value = u->get<PVDouble>();
Variant Union handling
PVUnion::shared_pointer any = getPVDataCreate()->createPVVariantUnion();
PVDouble::shared_pointer doubleValue = getPVDataCreate()->createPVScalar<PVDouble>();
doubleValue->put(12.8);
any->set(doubleValue);
PVDouble::shared_pointer doubleValue2 = any->get<PVDouble>();
// variant union work by-reference (pointers match also)
// doubleValue.get() == doubleValue2.get()
------
Convert
// convert to int
int32 i = doubleValue->getAs<int32>();
// from int
doubleValue->putFrom<int32>(i);
// from string
doubleValue->putFrom<std::string>("12.3");
// from scalar field
doubleValue->assign(pvScalar);
// convert to int array
PVIntArray::const_svector intData;
doubleArrayValue->getAs<int32>(intData);
// from string array
PVStringArray::svector labels;
labels.push_back("zero");
labels.push_back("one");
labels.push_back("two");
doubleArrayValue->putFrom<std::string>(labels);
// from scalar array
doubleArrayValue->assign(pvScalarArray);

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

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

File diff suppressed because it is too large Load Diff

56
jenkins/cloudbees_build Normal file
View File

@@ -0,0 +1,56 @@
# pvData C++ implementation
# Jenkins @ Cloudbees build 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 and unpack dependencies
export STUFF=/tmp/stuff
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
###########################################
# Build
cd ${WORKSPACE}
export EPICS_BASE=${STUFF}
export EPICS_HOST_ARCH=$(${EPICS_BASE}/startup/EpicsHostArch)
export LD_LIBRARY_PATH=${EPICS_BASE}/lib/${EPICS_HOST_ARCH}
export PATH=${STUFF}/bin:${PATH}
cat > configure/RELEASE.local << EOF
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

20
jenkins/cloudbees_hgweb Normal file
View File

@@ -0,0 +1,20 @@
# 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,108 +0,0 @@
TOP = ..
include $(TOP)/configure/CONFIG
PVDATA = $(TOP)/pvDataApp/
SRC_DIRS += $(PVDATA)/misc
INC += noDefaultMethods.h
INC += linkedListVoid.h
INC += linkedList.h
INC += lock.h
INC += requester.h
INC += serialize.h
INC += bitSet.h
INC += byteBuffer.h
INC += epicsException.h
INC += serializeHelper.h
INC += event.h
INC += thread.h
INC += executor.h
INC += CDRMonitor.h
INC += timeFunction.h
INC += timer.h
INC += queueVoid.h
INC += queue.h
INC += messageQueue.h
INC += destroyable.h
INC += status.h
INC += sharedPtr.h
LIBSRCS += CDRMonitor.cpp
#LIBSRCS += byteBuffer.cpp
LIBSRCS += bitSet.cpp
LIBSRCS += epicsException.cpp
LIBSRCS += requester.cpp
LIBSRCS += serializeHelper.cpp
LIBSRCS += linkedListVoid.cpp
LIBSRCS += event.cpp
LIBSRCS += executor.cpp
LIBSRCS += timeFunction.cpp
LIBSRCS += timer.cpp
LIBSRCS += queueVoid.cpp
LIBSRCS += messageQueue.cpp
LIBSRCS += status.cpp
SRC_DIRS += $(PVDATA)/pv
INC += pvType.h
INC += pvIntrospect.h
INC += pvData.h
INC += convert.h
INC += standardField.h
INC += standardPVField.h
SRC_DIRS += $(PVDATA)/factory
INC += factory.h
LIBSRCS += TypeFunc.cpp
LIBSRCS += PVAuxInfoImpl.cpp
LIBSRCS += FieldCreateFactory.cpp
LIBSRCS += PVField.cpp
LIBSRCS += PVScalar.cpp
LIBSRCS += PVArray.cpp
LIBSRCS += PVScalarArray.cpp
LIBSRCS += PVStructure.cpp
LIBSRCS += DefaultPVStructureArray.cpp
LIBSRCS += PVDataCreateFactory.cpp
LIBSRCS += Convert.cpp
LIBSRCS += Compare.cpp
LIBSRCS += StandardField.cpp
LIBSRCS += StandardPVField.cpp
SRC_DIRS += $(PVDATA)/property
INC += alarm.h
INC += pvAlarm.h
INC += control.h
INC += pvControl.h
INC += display.h
INC += pvDisplay.h
INC += pvEnumerated.h
INC += timeStamp.h
INC += pvTimeStamp.h
LIBSRCS += alarm.cpp
LIBSRCS += pvAlarm.cpp
LIBSRCS += pvControl.cpp
LIBSRCS += pvDisplay.cpp
LIBSRCS += pvEnumerated.cpp
LIBSRCS += timeStamp.cpp
LIBSRCS += pvTimeStamp.cpp
SRC_DIRS += $(PVDATA)/pvMisc
INC += bitSetUtil.h
LIBSRCS += bitSetUtil.cpp
SRC_DIRS += $(PVDATA)/monitor
INC += monitor.h
INC += monitorQueue.h
LIBSRCS += monitorQueue.cpp
LIBRARY=pvData
pvData_LIBS += Com
include $(TOP)/configure/RULES

View File

@@ -1,97 +0,0 @@
#include <pv/convert.h>
#include <algorithm>
#include <iterator>
#include <sstream>
namespace epics { namespace pvData {
// PVXXX object comparison
bool operator==(PVField& left, PVField& right)
{
return getConvert()->equals(left,right);
}
// Introspection object comparision
/** Field equality conditions:
* 1) same instance
* 2) same type (field and scalar/element), same name, same subfields (if any)
*/
bool operator==(const Field& a, const Field& b)
{
if(&a==&b)
return true;
if(a.getType()!=b.getType())
return false;
switch(a.getType()) {
case scalar: {
const Scalar &A=static_cast<const Scalar&>(a);
const Scalar &B=static_cast<const Scalar&>(b);
return A==B;
}
case scalarArray: {
const ScalarArray &A=static_cast<const ScalarArray&>(a);
const ScalarArray &B=static_cast<const ScalarArray&>(b);
return A==B;
}
case structure: {
const Structure &A=static_cast<const Structure&>(a);
const Structure &B=static_cast<const Structure&>(b);
return A==B;
}
case structureArray: {
const StructureArray &A=static_cast<const StructureArray&>(a);
const StructureArray &B=static_cast<const StructureArray&>(b);
return A==B;
}
default:
throw std::logic_error("Invalid Field type in comparision");
}
}
bool operator==(const Scalar& a, const Scalar& b)
{
if(&a==&b)
return true;
return a.getScalarType()==b.getScalarType() && a.getFieldName()==b.getFieldName();
}
bool operator==(const ScalarArray& a, const ScalarArray& b)
{
if(&a==&b)
return true;
return a.getElementType()==b.getElementType() && a.getFieldName()==b.getFieldName();
}
bool operator==(const Structure& a, const Structure& b)
{
if(&a==&b)
return true;
int nflds=a.getNumberFields();
if (b.getNumberFields()!=nflds)
return false;
if (a.getFieldName()!=b.getFieldName())
return false;
// std::equals does not work, since FieldConstPtrArray is an array of shared_pointers
FieldConstPtrArray af = a.getFields();
FieldConstPtrArray bf = b.getFields();
for (int i = 0; i < nflds; i++)
if (*(af[i].get()) != *(bf[i].get()))
return false;
return true;
}
bool operator==(const StructureArray& a, const StructureArray& b)
{
return a.structure() == b.structure();
}
namespace nconvert {
} // namespace nconvert
}} // namespace epics::pvData

File diff suppressed because it is too large Load Diff

View File

@@ -1,251 +0,0 @@
/*PVStructureArray.cpp*/
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#include <cstddef>
#include <cstdlib>
#include <string>
#include <cstdio>
#include <pv/pvData.h>
#include <pv/convert.h>
#include <pv/factory.h>
#include <pv/serializeHelper.h>
#include "DefaultPVStructureArray.h"
using std::tr1::static_pointer_cast;
using std::tr1::const_pointer_cast;
namespace epics { namespace pvData {
BasePVStructureArray::BasePVStructureArray(
PVStructure *parent,StructureArrayConstPtr structureArray)
: PVStructureArray(parent,structureArray),
structureArray(structureArray),
structureArrayData(new StructureArrayData()),
value(new PVStructurePtr[0])
{
}
BasePVStructureArray::~BasePVStructureArray()
{
delete structureArrayData;
int number = getCapacity();
for(int i=0; i<number; i++) {
if(value[i]!=0) {
delete value[i];
}
}
delete[] value;
}
int BasePVStructureArray::append(int number)
{
int currentLength = getCapacity();
int newLength = currentLength + number;
setCapacity(newLength);
StructureConstPtr structure = structureArray->getStructure();
for(int i=currentLength; i<newLength; i++) {
value[i] = getPVDataCreate()->createPVStructure(0,structure);
}
return newLength;
}
bool BasePVStructureArray::remove(int offset,int number)
{
int length = getCapacity();
if(offset+number>length) return false;
for(int i=offset;i<offset+number;i++) {
if(value[i]!=0) {
delete value[i];
value[i] = 0;
}
}
return true;
}
void BasePVStructureArray::compress() {
int length = getCapacity();
int newLength = 0;
for(int i=0; i<length; i++) {
if(value[i]!=0) {
newLength++;
continue;
}
// find first non 0
int notNull = 0;
for(int j=i+1;j<length;j++) {
if(value[j]!=0) {
notNull = j;
break;
}
}
if(notNull!=0) {
value[i] = value[notNull];
value[notNull] = 0;
newLength++;
continue;
}
break;
}
setCapacity(newLength);
}
void BasePVStructureArray::setCapacity(int capacity) {
if(getCapacity()==capacity) return;
if(!isCapacityMutable()) {
std::string message("not capacityMutable");
PVField::message(message, errorMessage);
return;
}
int length = getCapacity();
int numRemove = length - capacity;
if(numRemove>0) remove(length,numRemove);
PVStructurePtrArray newValue = new PVStructurePtr[capacity];
int limit = length;
if(length>capacity) limit = capacity;
for(int i=0; i<limit; i++) newValue[i] = value[i];
for(int i=limit; i<capacity; i++) newValue[i] = 0;
if(length>capacity) length = capacity;
delete[] value;
value = newValue;
setCapacityLength(capacity,length);
}
StructureArrayConstPtr BasePVStructureArray::getStructureArray()
{
return structureArray;
}
int BasePVStructureArray::get(
int offset, int len, StructureArrayData *data)
{
int n = len;
int length = getLength();
if(offset+len > length) {
n = length - offset;
if(n<0) n = 0;
}
data->data = value;
data->offset = offset;
return n;
}
int BasePVStructureArray::put(int offset,int len,
PVStructurePtrArray from, int fromOffset)
{
if(isImmutable()) {
message(String("field is immutable"), errorMessage);
return 0;
}
if(from==value) return len;
if(len<1) return 0;
int length = getLength();
int capacity = getCapacity();
if(offset+len > length) {
int newlength = offset + len;
if(newlength>capacity) {
setCapacity(newlength);
capacity = getCapacity();
newlength = capacity;
len = newlength - offset;
if(len<=0) return 0;
}
length = newlength;
setLength(length);
}
StructureConstPtr structure = structureArray->getStructure();
for(int i=0; i<len; i++) {
if(value[i+offset]!=0) delete value[i+offset];
PVStructurePtr frompv = from[i+fromOffset];
if(frompv==0) {
value[i+offset] = 0;
continue;
}
if(frompv->getStructure()!=structure) {
throw std::invalid_argument(String(
"Element is not a compatible structure"));
}
value[i+offset] = frompv;
}
postPut();
return len;
}
void BasePVStructureArray::shareData(
PVStructurePtrArray newValue,int capacity,int length)
{
for(int i=0; i<getLength(); i++) {
if(value[i]!=0) delete value[i];
}
delete[] value;
value = newValue;
setCapacity(capacity);
setLength(length);
}
void BasePVStructureArray::serialize(ByteBuffer *pbuffer,
SerializableControl *pflusher) const {
serialize(pbuffer, pflusher, 0, getLength());
}
void BasePVStructureArray::deserialize(ByteBuffer *pbuffer,
DeserializableControl *pcontrol) {
int size = SerializeHelper::readSize(pbuffer, pcontrol);
if(size>=0) {
// prepare array, if necessary
if(size>getCapacity()) setCapacity(size);
for(int i = 0; i<size; i++) {
pcontrol->ensureData(1);
int8 temp = pbuffer->getByte();
if(temp==0) {
if (value[i]) {
delete value[i];
value[i] = NULL;
}
}
else {
if(value[i]==NULL) {
value[i] = getPVDataCreate()->createPVStructure(
NULL, structureArray->getStructure());
}
value[i]->deserialize(pbuffer, pcontrol);
}
}
setLength(size);
postPut();
}
}
void BasePVStructureArray::serialize(ByteBuffer *pbuffer,
SerializableControl *pflusher, int offset, int count) const {
// cache
int length = getLength();
// check bounds
if(offset<0)
offset = 0;
else if(offset>length) offset = length;
if(count<0) count = length;
int maxCount = length-offset;
if(count>maxCount) count = maxCount;
// write
SerializeHelper::writeSize(count, pbuffer, pflusher);
for(int i = 0; i<count; i++) {
if(pbuffer->getRemaining()<1) pflusher->flushSerializeBuffer();
PVStructure* pvStructure = value[i+offset];
if(pvStructure==NULL) {
pbuffer->putByte(0);
}
else {
pbuffer->putByte(1);
pvStructure->serialize(pbuffer, pflusher);
}
}
}
}}

View File

@@ -1,48 +0,0 @@
/*DefaultPVStructureArray.h*/
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#ifndef DEFAULTPVSTRUCTUREARRAY_H
#define DEFAULTPVSTRUCTUREARRAY_H
#include <cstddef>
#include <cstdlib>
#include <string>
#include <cstdio>
#include <pv/pvData.h>
#include <pv/convert.h>
#include <pv/factory.h>
#include <pv/serializeHelper.h>
namespace epics { namespace pvData {
class BasePVStructureArray : public PVStructureArray {
public:
BasePVStructureArray(PVStructure *parent,
StructureArrayConstPtr structureArray);
virtual ~BasePVStructureArray();
virtual StructureArrayConstPtr getStructureArray();
virtual int append(int number);
virtual bool remove(int offset,int number);
virtual void compress();
virtual void setCapacity(int capacity);
virtual int get(int offset, int length,
StructureArrayData *data);
virtual int put(int offset,int length,
PVStructurePtrArray from, int fromOffset);
virtual void shareData( PVStructurePtrArray value,int capacity,int length);
virtual void serialize(ByteBuffer *pbuffer,
SerializableControl *pflusher) const;
virtual void deserialize(ByteBuffer *buffer,
DeserializableControl *pflusher);
virtual void serialize(ByteBuffer *pbuffer,
SerializableControl *pflusher, int offset, int count) const;
private:
StructureArrayConstPtr structureArray;
StructureArrayData *structureArrayData;
PVStructurePtrArray value;
};
}}
#endif /*DEFAULTPVSTRUCTUREARRAY_H*/

View File

@@ -1,260 +0,0 @@
/*FieldCreateFactory.cpp*/
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#include <cstddef>
#include <cstdlib>
#include <string>
#include <cstdio>
#include <pv/lock.h>
#include <pv/pvIntrospect.h>
#include <pv/convert.h>
#include <pv/factory.h>
#include <pv/CDRMonitor.h>
using std::tr1::static_pointer_cast;
namespace epics { namespace pvData {
static DebugLevel debugLevel = lowDebug;
static void newLine(StringBuilder buffer, int indentLevel)
{
*buffer += "\n";
for(int i=0; i<indentLevel; i++) *buffer += " ";
}
PVDATA_REFCOUNT_MONITOR_DEFINE(field);
Field::Field(String fieldName,Type type)
:m_fieldName(fieldName)
,m_type(type)
{
PVDATA_REFCOUNT_MONITOR_CONSTRUCT(field);
}
Field::~Field() {
PVDATA_REFCOUNT_MONITOR_DESTRUCT(field);
// note that compiler automatically calls destructor for fieldName
if(debugLevel==highDebug) printf("~Field %s\n",m_fieldName.c_str());
}
void Field::renameField(String newName)
{
m_fieldName = newName;
}
void Field::toString(StringBuilder buffer,int indentLevel) const{
*buffer += " ";
*buffer += m_fieldName.c_str();
}
Scalar::Scalar(String fieldName,ScalarType scalarType)
: Field(fieldName,scalar),scalarType(scalarType){}
Scalar::~Scalar(){}
void Scalar::toString(StringBuilder buffer,int indentLevel) const{
ScalarTypeFunc::toString(buffer,scalarType);
Field::toString(buffer,indentLevel);
}
ScalarArray::ScalarArray(String fieldName,ScalarType elementType)
: Field(fieldName,scalarArray),elementType(elementType){}
ScalarArray::~ScalarArray() {}
void ScalarArray::toString(StringBuilder buffer,int indentLevel) const{
ScalarTypeFunc::toString(buffer,elementType);
*buffer += "[]";
Field::toString(buffer,indentLevel);
}
StructureArray::StructureArray(String fieldName,StructureConstPtr structure)
: Field(fieldName,structureArray),pstructure(structure)
{
}
StructureArray::~StructureArray() {
if(debugLevel==highDebug) printf("~StructureArray\n");
}
void StructureArray::toString(StringBuilder buffer,int indentLevel) const {
*buffer += "structure[]";
Field::toString(buffer,indentLevel);
newLine(buffer,indentLevel + 1);
pstructure->toString(buffer,indentLevel + 1);
}
Structure::Structure (String fieldName,
int numberFields, FieldConstPtrArray infields)
: Field(fieldName,structure),
numberFields(numberFields),
fields(infields)
{
for(int i=0; i<numberFields; i++) {
String name = fields[i]->getFieldName();
// look for duplicates
for(int j=i+1; j<numberFields; j++) {
String otherName = fields[j]->getFieldName();
int result = name.compare(otherName);
if(result==0) {
String message("duplicate fieldName ");
message += name;
delete[] fields;
throw std::invalid_argument(message);
}
}
}
}
Structure::~Structure() {
if(debugLevel==highDebug)
printf("~Structure %s\n",Field::getFieldName().c_str());
delete[] fields;
}
FieldConstPtr Structure::getField(String fieldName) const {
for(int i=0; i<numberFields; i++) {
FieldConstPtr pfield = fields[i];
int result = fieldName.compare(pfield->getFieldName());
if(result==0) return pfield;
}
return FieldConstPtr();
}
int Structure::getFieldIndex(String fieldName) const {
for(int i=0; i<numberFields; i++) {
FieldConstPtr pfield = fields[i];
int result = fieldName.compare(pfield->getFieldName());
if(result==0) return i;
}
return -1;
}
void Structure::appendField(FieldConstPtr field)
{
FieldConstPtr *newFields = new FieldConstPtr[numberFields+1];
for(int i=0; i<numberFields; i++) newFields[i] = fields[i];
newFields[numberFields] = field;
delete[] fields;
fields = newFields;
numberFields++;
}
void Structure::appendFields(int numberNew,FieldConstPtrArray nfields)
{
FieldConstPtr *newFields = new FieldConstPtr[numberFields+numberNew];
for(int i=0; i<numberFields; i++) newFields[i] = fields[i];
for(int i=0; i<numberNew; i++) newFields[numberFields+i] = nfields[i];
delete[] fields;
fields = newFields;
numberFields += numberNew;
}
void Structure::removeField(int index)
{
if(index<0 || index>=numberFields) {
throw std::invalid_argument(
String("Structure::removeField index out of bounds"));
}
FieldConstPtr *newFields = new FieldConstPtr[numberFields-1];
int ind=0;
for(int i=0; i<numberFields; i++) {
if(i==index) continue;
newFields[ind++] = fields[i];
}
delete[] fields;
fields = newFields;
--numberFields;
}
void Structure::toString(StringBuilder buffer,int indentLevel) const{
*buffer += "structure";
Field::toString(buffer,indentLevel);
newLine(buffer,indentLevel+1);
for(int i=0; i<numberFields; i++) {
FieldConstPtr pfield = fields[i];
pfield->toString(buffer,indentLevel+1);
if(i<numberFields-1) newLine(buffer,indentLevel+1);
}
}
ScalarConstPtr FieldCreate::createScalar(String fieldName,
ScalarType scalarType) const
{
ScalarConstPtr scalar(new Scalar(fieldName,scalarType), Field::Deleter());
return scalar;
}
ScalarArrayConstPtr FieldCreate::createScalarArray(
String fieldName,ScalarType elementType) const
{
ScalarArrayConstPtr scalarArray(new ScalarArray(fieldName,elementType), Field::Deleter());
return scalarArray;
}
StructureConstPtr FieldCreate::createStructure (
String fieldName,int numberFields,
FieldConstPtr fields[]) const
{
StructureConstPtr structure(new Structure(
fieldName,numberFields,fields), Field::Deleter());
return structure;
}
StructureArrayConstPtr FieldCreate::createStructureArray(
String fieldName,StructureConstPtr structure) const
{
StructureArrayConstPtr structureArray(new StructureArray(fieldName,structure), Field::Deleter());
return structureArray;
}
FieldConstPtr FieldCreate::create(String fieldName,
FieldConstPtr pfield) const
{
FieldConstPtr ret;
Type type = pfield->getType();
switch(type) {
case scalar: {
ScalarConstPtr pscalar = static_pointer_cast<const Scalar>(pfield);
return createScalar(fieldName,pscalar->getScalarType());
}
case scalarArray: {
ScalarArrayConstPtr pscalarArray = static_pointer_cast<const ScalarArray>(pfield);
return createScalarArray(fieldName,pscalarArray->getElementType());
}
case structure: {
StructureConstPtr pstructure = static_pointer_cast<const Structure>(pfield);
return createStructure(fieldName,pstructure->getNumberFields(),pstructure->getFields());
}
case structureArray: {
StructureArrayConstPtr pstructureArray = static_pointer_cast<const StructureArray>(pfield);
return createStructureArray(fieldName,pstructureArray->getStructure());
}
}
String message("field ");
message += fieldName;
THROW_EXCEPTION2(std::logic_error, message);
}
static FieldCreate* fieldCreate = 0;
FieldCreate::FieldCreate()
{
}
FieldCreate * getFieldCreate() {
static Mutex mutex;
Lock xx(mutex);
if(fieldCreate==0) fieldCreate = new FieldCreate();
return fieldCreate;
}
}}

View File

@@ -1,89 +0,0 @@
/*PVArray.cpp*/
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#include <cstddef>
#include <cstdlib>
#include <string>
#include <cstdio>
#include <pv/pvData.h>
#include <pv/factory.h>
namespace epics { namespace pvData {
class PVArrayPvt {
public:
PVArrayPvt() : length(0),capacity(0),capacityMutable(true)
{}
int length;
int capacity;
bool capacityMutable;
};
PVArray::PVArray(PVStructure *parent,FieldConstPtr field)
: PVField(parent,field),pImpl(new PVArrayPvt())
{ }
PVArray::~PVArray()
{
delete pImpl;
}
int PVArray::getLength() const {return pImpl->length;}
int PVArray::getCapacity() const {return pImpl->capacity;}
static String fieldImmutable("field is immutable");
void PVArray::setLength(int length) {
if(length==pImpl->length) return;
if(PVField::isImmutable()) {
PVField::message(fieldImmutable,errorMessage);
return;
}
if(length>pImpl->capacity) this->setCapacity(length);
if(length>pImpl->capacity) length = pImpl->capacity;
pImpl->length = length;
}
void PVArray::setCapacityLength(int capacity,int length) {
pImpl->capacity = capacity;
pImpl->length = length;
}
bool PVArray::isCapacityMutable()
{
if(PVField::isImmutable()) {
return false;
}
return pImpl->capacityMutable;
}
void PVArray::setCapacityMutable(bool isMutable)
{
if(isMutable && PVField::isImmutable()) {
PVField::message(fieldImmutable,errorMessage);
return;
}
pImpl->capacityMutable = isMutable;
}
static String capacityImmutable("capacity is immutable");
void PVArray::setCapacity(int capacity) {
if(PVField::isImmutable()) {
PVField::message(fieldImmutable,errorMessage);
return;
}
if(pImpl->capacityMutable==false) {
PVField::message(capacityImmutable,errorMessage);
return;
}
pImpl->capacity = capacity;
}
}}

View File

@@ -1,102 +0,0 @@
/*PVAuxInfo.cpp*/
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#include <cstddef>
#include <cstdlib>
#include <string>
#include <cstdio>
#include <pv/noDefaultMethods.h>
#include <pv/pvData.h>
#include <pv/convert.h>
#include <pv/factory.h>
#include <pv/lock.h>
#include <pv/CDRMonitor.h>
namespace epics { namespace pvData {
PVDATA_REFCOUNT_MONITOR_DEFINE(pvAuxInfo);
PVAuxInfo::PVAuxInfo(PVField *pvField)
: pvField(pvField),lengthInfo(1),numberInfo(0),
pvInfos(new PVScalar *[1])
{
PVDATA_REFCOUNT_MONITOR_CONSTRUCT(pvAuxInfo);
}
PVAuxInfo::~PVAuxInfo()
{
PVDATA_REFCOUNT_MONITOR_DESTRUCT(pvAuxInfo);
for(int i=0; i<numberInfo; i++) delete pvInfos[i];
delete[] pvInfos;
}
PVField * PVAuxInfo::getPVField() {
return pvField;
}
PVScalar * PVAuxInfo::createInfo(String key,ScalarType scalarType)
{
for(int i=0; i<numberInfo; i++) {
PVScalar *pvScalar = pvInfos[i];
if(key.compare(pvScalar->getField()->getFieldName())==0) {
String message("AuxoInfo:create key ");
message += key.c_str();
message += " already exists with scalarType ";
ScalarTypeFunc::toString(&message,scalarType);
pvField->message(message,errorMessage);
return 0;
}
}
if(lengthInfo==numberInfo) {
int newLength = lengthInfo+4;
PVScalar ** newInfos = new PVScalar *[newLength];
lengthInfo = newLength;
for(int i=0; i<numberInfo; i++) newInfos[i] = pvInfos[i];
for(int i= numberInfo; i<lengthInfo; i++) newInfos[i] = 0;
delete[] pvInfos;
pvInfos = newInfos;
}
PVScalar *pvScalar = getPVDataCreate()->createPVScalar(0,key,scalarType);
pvInfos[numberInfo++] = pvScalar;
return pvScalar;
}
PVScalar * PVAuxInfo::getInfo(String key)
{
for(int i=0; i<numberInfo; i++) {
PVScalar *pvScalar = pvInfos[i];
if(key.compare(pvScalar->getField()->getFieldName())==0) return pvScalar;
}
return 0;
}
PVScalar * PVAuxInfo::getInfo(int index)
{
if(index<0 || index>=numberInfo) return 0;
return pvInfos[index];
}
int PVAuxInfo::getNumberInfo() { return numberInfo;}
void PVAuxInfo::toString(StringBuilder buf)
{
PVAuxInfo::toString(buf,0);
}
void PVAuxInfo::toString(StringBuilder buf,int indentLevel)
{
if(numberInfo==0) return;
Convert *convert = getConvert();
convert->newLine(buf,indentLevel);
*buf += "auxInfo";
for(int i=0; i<numberInfo; i++) {
convert->newLine(buf,indentLevel+1);
PVScalar *value = pvInfos[i];
value->toString(buf,indentLevel + 1);
}
}
}}

View File

@@ -1,601 +0,0 @@
/*PVDataCreateFactory.cpp*/
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#ifdef _WIN32
#define NOMINMAX
#endif
#include <cstddef>
#include <cstdlib>
#include <string>
#include <cstdio>
#include <pv/lock.h>
#include <pv/pvIntrospect.h>
#include <pv/pvData.h>
#include <pv/convert.h>
#include <pv/factory.h>
#include <pv/serializeHelper.h>
#include "DefaultPVStructureArray.h"
using std::tr1::static_pointer_cast;
using std::tr1::const_pointer_cast;
namespace epics { namespace pvData {
static Convert* convert = 0;
static FieldCreate * fieldCreate = 0;
static PVDataCreate* pvDataCreate = 0;
/** Default storage for scalar values
*/
template<typename T>
class BasePVScalar : public PVScalarValue<T> {
public:
typedef T value_type;
typedef T* pointer;
typedef const T* const_pointer;
BasePVScalar(PVStructure *parent,ScalarConstPtr scalar);
virtual ~BasePVScalar();
virtual T get();
virtual void put(T val);
virtual void serialize(ByteBuffer *pbuffer,
SerializableControl *pflusher) const;
virtual void deserialize(ByteBuffer *pbuffer,
DeserializableControl *pflusher);
private:
T value;
};
template<typename T>
BasePVScalar<T>::BasePVScalar(PVStructure *parent,ScalarConstPtr scalar)
: PVScalarValue<T>(parent,scalar),value(0)
{}
//Note: '0' is a suitable default for all POD types (not String)
template<typename T>
BasePVScalar<T>::~BasePVScalar() {}
template<typename T>
T BasePVScalar<T>::get() { return value;}
template<typename T>
void BasePVScalar<T>::put(T val){value = val;}
template<typename T>
void BasePVScalar<T>::serialize(ByteBuffer *pbuffer,
SerializableControl *pflusher) const {
pflusher->ensureBuffer(sizeof(T));
pbuffer->put<T>(value);
}
template<typename T>
void BasePVScalar<T>::deserialize(ByteBuffer *pbuffer,
DeserializableControl *pflusher)
{
pflusher->ensureData(sizeof(T));
value = pbuffer->get<T>();
}
typedef BasePVScalar<bool> BasePVBoolean;
typedef BasePVScalar<int8> BasePVByte;
typedef BasePVScalar<int16> BasePVShort;
typedef BasePVScalar<int32> BasePVInt;
typedef BasePVScalar<int64> BasePVLong;
typedef BasePVScalar<float> BasePVFloat;
typedef BasePVScalar<double> BasePVDouble;
// BasePVString is special case, since it implements SerializableArray
class BasePVString : public PVString {
public:
typedef String value_type;
typedef String* pointer;
typedef const String* const_pointer;
BasePVString(PVStructure *parent,ScalarConstPtr scalar);
virtual ~BasePVString();
virtual String get();
virtual void put(String val);
virtual void serialize(ByteBuffer *pbuffer,
SerializableControl *pflusher) const;
virtual void deserialize(ByteBuffer *pbuffer,
DeserializableControl *pflusher);
virtual void serialize(ByteBuffer *pbuffer,
SerializableControl *pflusher, int offset, int count) const;
private:
String value;
};
BasePVString::BasePVString(PVStructure *parent,ScalarConstPtr scalar)
: PVString(parent,scalar),value()
{}
BasePVString::~BasePVString() {}
String BasePVString::get() { return value;}
void BasePVString::put(String val){value = val;}
void BasePVString::serialize(ByteBuffer *pbuffer,
SerializableControl *pflusher) const
{
SerializeHelper::serializeString(value, pbuffer, pflusher);
}
void BasePVString::deserialize(ByteBuffer *pbuffer,
DeserializableControl *pflusher)
{
value = SerializeHelper::deserializeString(pbuffer, pflusher);
}
void BasePVString::serialize(ByteBuffer *pbuffer,
SerializableControl *pflusher, int offset, int count) const
{
// check bounds
const int length = /*(value == null) ? 0 :*/ value.length();
if (offset < 0) offset = 0;
else if (offset > length) offset = length;
if (count < 0) count = length;
const int maxCount = length - offset;
if (count > maxCount)
count = maxCount;
// write
SerializeHelper::serializeSubstring(value, offset, count, pbuffer, pflusher);
}
/** Default storage for arrays
*/
template<typename T>
class DefaultPVArray : public PVValueArray<T> {
public:
typedef T value_type;
typedef T* pointer;
typedef const T* const_pointer;
DefaultPVArray(PVStructure *parent,ScalarArrayConstPtr scalarArray);
virtual ~DefaultPVArray();
virtual void setCapacity(int capacity);
virtual int get(int offset, int length, PVArrayData<T> *data) ;
virtual int put(int offset,int length, pointer from,
int fromOffset);
virtual void shareData(pointer value,int capacity,int length);
// from Serializable
virtual void serialize(ByteBuffer *pbuffer,SerializableControl *pflusher) const;
virtual void deserialize(ByteBuffer *pbuffer,DeserializableControl *pflusher);
virtual void serialize(ByteBuffer *pbuffer,
SerializableControl *pflusher, int offset, int count) const;
private:
pointer value;
};
template<typename T>
DefaultPVArray<T>::DefaultPVArray(PVStructure *parent,
ScalarArrayConstPtr scalarArray)
: PVValueArray<T>(parent,scalarArray),value(new T[0])
{ }
template<typename T>
DefaultPVArray<T>::~DefaultPVArray()
{
delete[] value;
}
template<typename T>
void DefaultPVArray<T>::setCapacity(int capacity)
{
if(PVArray::getCapacity()==capacity) return;
if(!PVArray::isCapacityMutable()) {
std::string message("not capacityMutable");
PVField::message(message, errorMessage);
return;
}
int length = PVArray::getLength();
if(length>capacity) length = capacity;
T *newValue = new T[capacity];
for(int i=0; i<length; i++) newValue[i] = value[i];
delete[]value;
value = newValue;
PVArray::setCapacityLength(capacity,length);
}
template<typename T>
int DefaultPVArray<T>::get(int offset, int len, PVArrayData<T> *data)
{
int n = len;
int length = this->getLength();
if(offset+len > length) {
n = length-offset;
if(n<0) n = 0;
}
data->data = value;
data->offset = offset;
return n;
}
template<typename T>
int DefaultPVArray<T>::put(int offset,int len,
pointer from,int fromOffset)
{
if(PVField::isImmutable()) {
PVField::message("field is immutable",errorMessage);
return 0;
}
if(from==value) return len;
if(len<1) return 0;
int length = this->getLength();
int capacity = this->getCapacity();
if(offset+len > length) {
int newlength = offset + len;
if(newlength>capacity) {
setCapacity(newlength);
newlength = this->getCapacity();
len = newlength - offset;
if(len<=0) return 0;
}
length = newlength;
}
for(int i=0;i<len;i++) {
value[i+offset] = from[i+fromOffset];
}
this->setLength(length);
this->postPut();
return len;
}
template<typename T>
void DefaultPVArray<T>::shareData(pointer shareValue,int capacity,int length)
{
delete[] value;
value = shareValue;
PVArray::setCapacityLength(capacity,length);
}
template<typename T>
void DefaultPVArray<T>::serialize(ByteBuffer *pbuffer,
SerializableControl *pflusher) const {
serialize(pbuffer, pflusher, 0, this->getLength());
}
template<typename T>
void DefaultPVArray<T>::deserialize(ByteBuffer *pbuffer,
DeserializableControl *pcontrol) {
int size = SerializeHelper::readSize(pbuffer, pcontrol);
// if (size>0) { pcontrol->ensureData(sizeof(T)-1); pbuffer->align(sizeof(T)); }
if(size>=0) {
// prepare array, if necessary
if(size>this->getCapacity()) this->setCapacity(size);
// retrieve value from the buffer
int i = 0;
while(true) {
/*
int maxIndex = std::min(size-i, (int)(pbuffer->getRemaining()/sizeof(T)))+i;
for(; i<maxIndex; i++)
value[i] = pbuffer->get<T>();
*/
int maxCount = std::min(size-i, (int)(pbuffer->getRemaining()/sizeof(T)));
pbuffer->getArray<T>(&value[i], maxCount);
i += maxCount;
if(i<size)
pcontrol->ensureData(sizeof(T)); // this is not OK since can exceen max local buffer (size-i)*sizeof(T));
else
break;
}
// set new length
this->setLength(size);
PVField::postPut();
}
// TODO null arrays (size == -1) not supported
}
template<typename T>
void DefaultPVArray<T>::serialize(ByteBuffer *pbuffer,
SerializableControl *pflusher, int offset, int count) const {
// cache
int length = this->getLength();
// check bounds
if(offset<0)
offset = 0;
else if(offset>length) offset = length;
if(count<0) count = length;
int maxCount = length-offset;
if(count>maxCount) count = maxCount;
// write
SerializeHelper::writeSize(count, pbuffer, pflusher);
//if (count == 0) return; pcontrol->ensureData(sizeof(T)-1); pbuffer->align(sizeof(T));
int end = offset+count;
int i = offset;
while(true) {
/*
int maxIndex = std::min<int>(end-i, (int)(pbuffer->getRemaining()/sizeof(T)))+i;
for(; i<maxIndex; i++)
pbuffer->put<T>(value[i]);
*/
int maxCount = std::min<int>(end-i, (int)(pbuffer->getRemaining()/sizeof(T)));
pbuffer->putArray<T>(&value[i], maxCount);
i += maxCount;
if(i<end)
pflusher->flushSerializeBuffer();
else
break;
}
}
// specializations for String
template<>
void DefaultPVArray<String>::deserialize(ByteBuffer *pbuffer,
DeserializableControl *pcontrol) {
int size = SerializeHelper::readSize(pbuffer, pcontrol);
if(size>=0) {
// prepare array, if necessary
if(size>getCapacity()) setCapacity(size);
// retrieve value from the buffer
for(int i = 0; i<size; i++)
value[i] = SerializeHelper::deserializeString(pbuffer,
pcontrol);
// set new length
setLength(size);
postPut();
}
// TODO null arrays (size == -1) not supported
}
template<>
void DefaultPVArray<String>::serialize(ByteBuffer *pbuffer,
SerializableControl *pflusher, int offset, int count) const {
int length = getLength();
// check bounds
if(offset<0)
offset = 0;
else if(offset>length) offset = length;
if(count<0) count = length;
int maxCount = length-offset;
if(count>maxCount) count = maxCount;
// write
SerializeHelper::writeSize(count, pbuffer, pflusher);
int end = offset+count;
for(int i = offset; i<end; i++)
SerializeHelper::serializeString(value[i], pbuffer, pflusher);
}
typedef DefaultPVArray<bool> DefaultPVBooleanArray;
typedef DefaultPVArray<int8> BasePVByteArray;
typedef DefaultPVArray<int16> BasePVShortArray;
typedef DefaultPVArray<int32> BasePVIntArray;
typedef DefaultPVArray<int64> BasePVLongArray;
typedef DefaultPVArray<float> BasePVFloatArray;
typedef DefaultPVArray<double> BasePVDoubleArray;
typedef DefaultPVArray<String> BasePVStringArray;
// Factory
PVDataCreate::PVDataCreate(){ }
PVField *PVDataCreate::createPVField(PVStructure *parent,
FieldConstPtr field)
{
switch(field->getType()) {
case scalar: {
ScalarConstPtr xx = static_pointer_cast<const Scalar>(field);
return createPVScalar(parent,xx);
}
case scalarArray: {
ScalarArrayConstPtr xx = static_pointer_cast<const ScalarArray>(field);
return (PVField *)createPVScalarArray(parent,xx);
}
case structure: {
StructureConstPtr xx = static_pointer_cast<const Structure>(field);
return (PVField *)createPVStructure(parent,xx);
}
case structureArray: {
StructureArrayConstPtr xx = static_pointer_cast<const StructureArray>(field);
return createPVStructureArray(parent,xx);
}
}
String message("PVDataCreate::createPVField should never get here");
throw std::logic_error(message);
}
PVField *PVDataCreate::createPVField(PVStructure *parent,
String fieldName,PVField * fieldToClone)
{
switch(fieldToClone->getField()->getType()) {
case scalar:
return createPVScalar(parent,fieldName,(PVScalar*)fieldToClone);
case scalarArray:
return (PVField *)createPVScalarArray(parent,fieldName,
(PVScalarArray *)fieldToClone);
case structure:
return (PVField *)createPVStructure(parent,fieldName,
(PVStructure *)fieldToClone);
case structureArray:
String message(
"PVDataCreate::createPVField structureArray not valid fieldToClone");
throw std::invalid_argument(message);
}
String message("PVDataCreate::createPVField should never get here");
throw std::logic_error(message);
}
PVScalar *PVDataCreate::createPVScalar(PVStructure *parent,ScalarConstPtr scalar)
{
ScalarType scalarType = scalar->getScalarType();
switch(scalarType) {
case pvBoolean:
return new BasePVBoolean(parent,scalar);
case pvByte:
return new BasePVByte(parent,scalar);
case pvShort:
return new BasePVShort(parent,scalar);
case pvInt:
return new BasePVInt(parent,scalar);
case pvLong:
return new BasePVLong(parent,scalar);
case pvFloat:
return new BasePVFloat(parent,scalar);
case pvDouble:
return new BasePVDouble(parent,scalar);
case pvString:
return new BasePVString(parent,scalar);
}
String message("PVDataCreate::createPVScalar should never get here");
throw std::logic_error(message);
}
PVScalar *PVDataCreate::createPVScalar(PVStructure *parent,
String fieldName,ScalarType scalarType)
{
ScalarConstPtr scalar = fieldCreate->createScalar(fieldName,scalarType);
return createPVScalar(parent,scalar);
}
PVScalar *PVDataCreate::createPVScalar(PVStructure *parent,
String fieldName,PVScalar * scalarToClone)
{
PVScalar *pvScalar = createPVScalar(parent,fieldName,
scalarToClone->getScalar()->getScalarType());
convert->copyScalar(scalarToClone, pvScalar);
PVAuxInfo *from = scalarToClone->getPVAuxInfo();
PVAuxInfo *to = pvScalar->getPVAuxInfo();
int numberInfo = from->getNumberInfo();
for(int i=0; i<numberInfo; i++) {
PVScalar *pvFrom = from->getInfo(i);
ScalarConstPtr scalar = pvFrom->getScalar();
PVScalar *pvTo = to->createInfo(scalar->getFieldName(),scalar->getScalarType());
convert->copyScalar(pvFrom,pvTo);
}
return pvScalar;
}
PVScalarArray *PVDataCreate::createPVScalarArray(PVStructure *parent,
ScalarArrayConstPtr scalarArray)
{
switch(scalarArray->getElementType()) {
case pvBoolean:
return new DefaultPVBooleanArray(parent,scalarArray);
case pvByte:
return new BasePVByteArray(parent,scalarArray);
case pvShort:
return new BasePVShortArray(parent,scalarArray);
case pvInt:
return new BasePVIntArray(parent,scalarArray);
case pvLong:
return new BasePVLongArray(parent,scalarArray);
case pvFloat:
return new BasePVFloatArray(parent,scalarArray);
case pvDouble:
return new BasePVDoubleArray(parent,scalarArray);
case pvString:
return new BasePVStringArray(parent,scalarArray);
}
String message("PVDataCreate::createPVScalarArray should never get here");
throw std::logic_error(message);
}
PVScalarArray *PVDataCreate::createPVScalarArray(PVStructure *parent,
String fieldName,ScalarType elementType)
{
return createPVScalarArray(parent,
fieldCreate->createScalarArray(fieldName, elementType));
}
PVScalarArray *PVDataCreate::createPVScalarArray(PVStructure *parent,
String fieldName,PVScalarArray * arrayToClone)
{
PVScalarArray *pvArray = createPVScalarArray(parent,fieldName,
arrayToClone->getScalarArray()->getElementType());
convert->copyScalarArray(arrayToClone,0, pvArray,0,arrayToClone->getLength());
PVAuxInfo *from = arrayToClone->getPVAuxInfo();
PVAuxInfo *to = pvArray->getPVAuxInfo();
int numberInfo = from->getNumberInfo();
for(int i=0; i<numberInfo; i++) {
PVScalar *pvFrom = from->getInfo(i);
ScalarConstPtr scalar = pvFrom->getScalar();
PVScalar *pvTo = to->createInfo(scalar->getFieldName(),scalar->getScalarType());
convert->copyScalar(pvFrom,pvTo);
}
return pvArray;
}
PVStructureArray *PVDataCreate::createPVStructureArray(PVStructure *parent,
StructureArrayConstPtr structureArray)
{
return new BasePVStructureArray(parent,structureArray);
}
PVStructure *PVDataCreate::createPVStructure(PVStructure *parent,
StructureConstPtr structure)
{
PVStructure *pvStructure = new PVStructure(parent,structure);
return pvStructure;
}
PVStructure *PVDataCreate::createPVStructure(PVStructure *parent,
String fieldName,int numberFields,FieldConstPtrArray fields)
{
StructureConstPtr structure = fieldCreate->createStructure(
fieldName,numberFields, fields);
return new PVStructure(parent,structure);
}
PVStructure *PVDataCreate::createPVStructure(PVStructure *parent,
String fieldName,int numberFields,PVFieldPtrArray pvFields)
{
FieldConstPtrArray fields = new FieldConstPtr[numberFields];
for(int i=0; i<numberFields;i++) {
fields[i] = pvFields[i]->getField();
}
StructureConstPtr structure = fieldCreate->createStructure(
fieldName,numberFields,fields);
PVStructure *pvStructure = new PVStructure(parent,structure,pvFields);
return pvStructure;
}
PVStructure *PVDataCreate::createPVStructure(PVStructure *parent,
String fieldName,PVStructure *structToClone)
{
FieldConstPtrArray fields = 0;
int numberFields = 0;
PVStructure *pvStructure = 0;;
if(structToClone==0) {
fields = new FieldConstPtr[0];
StructureConstPtr structure = fieldCreate->createStructure(
fieldName,numberFields,fields);
pvStructure = new PVStructure(parent,structure);
} else {
StructureConstPtr structure = structToClone->getStructure();
pvStructure = new PVStructure(parent,structure);
convert->copyStructure(structToClone,pvStructure);
}
return pvStructure;
}
PVDataCreate * getPVDataCreate() {
static Mutex mutex;
Lock xx(mutex);
if(pvDataCreate==0){
pvDataCreate = new PVDataCreate();
convert = getConvert();
fieldCreate = getFieldCreate();
}
return pvDataCreate;
}
}}

View File

@@ -1,255 +0,0 @@
/*PVField.cpp*/
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#include <cstddef>
#include <cstdlib>
#include <string>
#include <cstdio>
#include <pv/lock.h>
#include <pv/pvData.h>
#include <pv/factory.h>
#include <pv/convert.h>
#include <pv/CDRMonitor.h>
using std::tr1::const_pointer_cast;
namespace epics { namespace pvData {
static String notImplemented("not implemented");
PVDATA_REFCOUNT_MONITOR_DEFINE(pvField);
class PVFieldPvt {
public:
PVFieldPvt(PVStructure *parent,FieldConstPtr field);
~PVFieldPvt();
PVStructure *parent;
FieldConstPtr field;
int fieldOffset;
int nextFieldOffset;
PVAuxInfo *pvAuxInfo;
bool immutable;
Requester *requester;
PostHandler *postHandler;
Convert *convert;
};
PVFieldPvt::PVFieldPvt(PVStructure *parent,FieldConstPtr field)
: parent(parent),field(field),
fieldOffset(0), nextFieldOffset(0),
pvAuxInfo(0),
immutable(false),requester(0),postHandler(0),
convert(getConvert())
{
}
PVFieldPvt::~PVFieldPvt()
{
if(pvAuxInfo!=0) delete pvAuxInfo;
}
PVField::PVField(PVStructure *parent,FieldConstPtr field)
: pImpl(new PVFieldPvt(parent,field))
{
PVDATA_REFCOUNT_MONITOR_CONSTRUCT(pvField);
}
PVField::~PVField()
{
PVDATA_REFCOUNT_MONITOR_DESTRUCT(pvField);
delete pImpl;
}
void PVField::message(String fieldName,String message,MessageType messageType)
{
if(pImpl->parent!=0) {
String parentName = pImpl->parent->getField()->getFieldName();
if(parentName.length()>0) {
fieldName = parentName + "." + fieldName;
}
pImpl->parent->message(fieldName,message,messageType);
return;
}
if(pImpl->requester) {
String mess = fieldName + " " + message;
pImpl->requester->message(mess,messageType);
} else {
printf("%s %s %s\n",
messageTypeName[messageType].c_str(),
fieldName.c_str(),
message.c_str());
}
}
void PVField::message(String message,MessageType messageType)
{
PVField::message(pImpl->field->getFieldName(),message,messageType);
}
void PVField::setRequester(Requester *requester)
{
if(pImpl->parent!=0) {
throw std::logic_error(String(
"PVField::setRequester only legal for top level structure"));
}
if(pImpl->requester!=0) {
if(pImpl->requester==requester) return;
throw std::logic_error(String(
"PVField::setRequester requester is already present"));
}
pImpl->requester = requester;
}
int PVField::getFieldOffset()
{
if(pImpl->nextFieldOffset==0) computeOffset(this);
return pImpl->fieldOffset;
}
int PVField::getNextFieldOffset()
{
if(pImpl->nextFieldOffset==0) computeOffset(this);
return pImpl->nextFieldOffset;
}
int PVField::getNumberFields()
{
if(pImpl->nextFieldOffset==0) computeOffset(this);
return (pImpl->nextFieldOffset - pImpl->fieldOffset);
}
PVAuxInfo * PVField::getPVAuxInfo(){
if(pImpl->pvAuxInfo==0) {
pImpl->pvAuxInfo = new PVAuxInfo(this);
}
return pImpl->pvAuxInfo;
}
bool PVField::isImmutable() {return pImpl->immutable;}
void PVField::setImmutable() {pImpl->immutable = true;}
FieldConstPtr PVField::getField() {return pImpl->field;}
PVStructure * PVField::getParent() {return pImpl->parent;}
bool PVField::renameField(String newName)
{
if(pImpl->parent!=0) {
StructureConstPtr structure = pImpl->parent->getStructure();
int index = structure->getFieldIndex(newName);
if(index>=0) return false;
}
Field::shared_pointer field(const_pointer_cast<Field>(pImpl->field));
field->renameField(newName);
return true;
}
void PVField::postPut()
{
if(pImpl->postHandler!=0) pImpl->postHandler->postPut();
}
void PVField::setPostHandler(PostHandler *postHandler)
{
if(pImpl->postHandler!=0) {
if(postHandler==pImpl->postHandler) return;
String message(
"PVField::setPostHandler a postHandler is already registered");
throw std::logic_error(message);
}
pImpl->postHandler = postHandler;
}
void PVField::setParent(PVStructure * parent)
{
pImpl->parent = parent;
}
bool PVField::equals(PVField &pv)
{
return pImpl->convert->equals(*this,pv);
}
void PVField::toString(StringBuilder buf) {toString(buf,0);}
void PVField::toString(StringBuilder buf,int indentLevel)
{
pImpl->convert->getString(buf,this,indentLevel);
if(pImpl->pvAuxInfo==0) return;
pImpl->pvAuxInfo->toString(buf,indentLevel);
}
void PVField::computeOffset(PVField * pvField) {
PVStructure *pvTop = pvField->getParent();
if(pvTop==0) {
if(pvField->getField()->getType()!=structure) {
pvField->pImpl->fieldOffset = 0;
pvField->pImpl->nextFieldOffset = 1;
return;
}
pvTop = static_cast<PVStructure *>(pvField);
} else {
while(pvTop->getParent()!=0) pvTop = pvTop->getParent();
}
int offset = 0;
int nextOffset = 1;
PVFieldPtrArray pvFields = pvTop->getPVFields();
for(int i=0; i < pvTop->getStructure()->getNumberFields(); i++) {
offset = nextOffset;
PVField *pvField = pvFields[i];
FieldConstPtr field = pvField->getField();
switch(field->getType()) {
case scalar:
case scalarArray:
case structureArray:{
nextOffset++;
pvField->pImpl->fieldOffset = offset;
pvField->pImpl->nextFieldOffset = nextOffset;
break;
}
case structure: {
pvField->computeOffset(pvField,offset);
nextOffset = pvField->getNextFieldOffset();
}
}
}
PVField *top = (PVField *)pvTop;
top->pImpl->fieldOffset = 0;
top->pImpl->nextFieldOffset = nextOffset;
}
void PVField::computeOffset(PVField * pvField,int offset) {
int beginOffset = offset;
int nextOffset = offset + 1;
PVStructure *pvStructure = static_cast<PVStructure *>(pvField);
PVFieldPtrArray pvFields = pvStructure->getPVFields();
for(int i=0; i < pvStructure->getStructure()->getNumberFields(); i++) {
offset = nextOffset;
PVField *pvSubField = pvFields[i];
FieldConstPtr field = pvSubField->getField();
switch(field->getType()) {
case scalar:
case scalarArray:
case structureArray: {
nextOffset++;
pvSubField->pImpl->fieldOffset = offset;
pvSubField->pImpl->nextFieldOffset = nextOffset;
break;
}
case structure: {
pvSubField->computeOffset(pvSubField,offset);
nextOffset = pvSubField->getNextFieldOffset();
}
}
}
pvField->pImpl->fieldOffset = beginOffset;
pvField->pImpl->nextFieldOffset = nextOffset;
}
}}

View File

@@ -1,28 +0,0 @@
/*PVScalar.cpp*/
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#include <cstddef>
#include <cstdlib>
#include <string>
#include <cstdio>
#include <pv/pvData.h>
#include <pv/factory.h>
using std::tr1::static_pointer_cast;
namespace epics { namespace pvData {
PVScalar::~PVScalar() {}
PVScalar::PVScalar(PVStructure *parent,ScalarConstPtr scalar)
: PVField(parent,scalar) {}
ScalarConstPtr PVScalar::getScalar()
{
return static_pointer_cast<const Scalar>(PVField::getField());
}
}}

View File

@@ -1,567 +0,0 @@
/*PVStructure.cpp*/
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#include <cstddef>
#include <cstdlib>
#include <string>
#include <cstdio>
#include <vector>
#include <pv/pvData.h>
#include <pv/pvIntrospect.h>
#include <pv/convert.h>
#include <pv/factory.h>
#include <pv/bitSet.h>
using std::tr1::static_pointer_cast;
using std::tr1::const_pointer_cast;
namespace epics { namespace pvData {
class PVStructurePvt {
public:
PVStructurePvt();
~PVStructurePvt();
int numberFields;
PVFieldPtrArray pvFields;
String extendsStructureName;
};
PVStructurePvt::PVStructurePvt()
: numberFields(0), pvFields(0),extendsStructureName("")
{
}
PVStructurePvt::~PVStructurePvt()
{
for(int i=0; i<numberFields; i++) {
delete pvFields[i];
}
if (pvFields) delete[] pvFields;
}
static PVField *findSubField(String fieldName,PVStructure *pvStructure);
PVStructure::PVStructure(PVStructure *parent,StructureConstPtr structurePtr)
: PVField(parent,structurePtr),pImpl(new PVStructurePvt())
{
int numberFields = structurePtr->getNumberFields();
FieldConstPtrArray fields = structurePtr->getFields();
pImpl->numberFields = numberFields;
pImpl->pvFields = new PVFieldPtr[numberFields];
PVFieldPtrArray pvFields = pImpl->pvFields;
PVDataCreate *pvDataCreate = getPVDataCreate();
for(int i=0; i<numberFields; i++) {
pvFields[i] = pvDataCreate->createPVField(this,fields[i]);
}
}
PVStructure::PVStructure(PVStructure *parent,StructureConstPtr structurePtr,
PVFieldPtrArray pvFields
)
: PVField(parent,structurePtr),pImpl(new PVStructurePvt())
{
int numberFields = structurePtr->getNumberFields();
pImpl->numberFields = numberFields;
pImpl->pvFields = pvFields;
for(int i=0; i<numberFields; i++) {
PVField *pvField = pvFields[i];
setParentPvt(pvField,this);
}
}
void PVStructure::setParentPvt(PVField *pvField,PVStructure *parent)
{
pvField->setParent(parent);
if(pvField->getField()->getType()==structure) {
PVStructure *subStructure = static_cast<PVStructure*>(pvField);
PVFieldPtr *subFields = subStructure->getPVFields();
int numberFields = subStructure->getStructure()->getNumberFields();
for(int i=0; i<numberFields; i++) {
PVField *subField = static_cast<PVField*>(subFields[i]);
setParentPvt(subField,subStructure);
}
}
}
PVStructure::~PVStructure()
{
delete pImpl;
}
StructureConstPtr PVStructure::getStructure()
{
return static_pointer_cast<const Structure>(PVField::getField());
}
PVFieldPtrArray PVStructure::getPVFields()
{
return pImpl->pvFields;
}
PVFieldPtr PVStructure::getSubField(String fieldName)
{
return findSubField(fieldName,this);
}
PVFieldPtr PVStructure::getSubField(int fieldOffset)
{
if(fieldOffset<=getFieldOffset()) {
if(fieldOffset==getFieldOffset()) return this;
return 0;
}
if(fieldOffset>getNextFieldOffset()) return 0;
int numFields = pImpl->numberFields;
PVFieldPtrArray pvFields = pImpl->pvFields;
for(int i=0; i<numFields; i++) {
PVField *pvField = pvFields[i];
if(pvField->getFieldOffset()==fieldOffset) return pvField;
if(pvField->getNextFieldOffset()<=fieldOffset) continue;
if(pvField->getField()->getType()==structure) {
return ((PVStructure*)pvField)->getSubField(fieldOffset);
}
}
String message("PVStructure.getSubField: Logic error");
throw std::logic_error(message);
}
void PVStructure::appendPVField(PVFieldPtr pvField)
{
Structure::shared_pointer structure = const_pointer_cast<Structure>(getStructure());
structure->appendField(pvField->getField());
int origLength = pImpl->numberFields;
PVFieldPtrArray oldPVFields = pImpl->pvFields;
PVFieldPtrArray newPVFields = new PVFieldPtr[origLength + 1];
for(int i=0; i<origLength; i++) {
newPVFields[i] = oldPVFields[i];
}
// note that origLength IS new element
newPVFields[origLength] = pvField;
delete[] pImpl->pvFields;
pImpl->pvFields = newPVFields;
pImpl->numberFields = origLength + 1;
}
void PVStructure::appendPVFields(int numberNewFields,PVFieldPtrArray pvFields)
{
if (numberNewFields<0)
throw std::logic_error("Number of fields must be >=0");
Structure::shared_pointer structure = const_pointer_cast<Structure>(getStructure());
std::vector<FieldConstPtr> fields(numberNewFields);
for(int i=0; i<numberNewFields; i++) fields[i] = pvFields[i]->getField();
structure->appendFields(numberNewFields,&fields[0]);
int origLength = pImpl->numberFields;
PVFieldPtrArray oldPVFields = pImpl->pvFields;
int numberFields = origLength + numberNewFields;
PVFieldPtrArray newPVFields = new PVFieldPtr[numberFields];
for(int i=0; i<origLength; i++) {
newPVFields[i] = oldPVFields[i];
}
for(int i=0; i<numberNewFields; i++) {
newPVFields[i+origLength] = pvFields[i];
}
delete[] pImpl->pvFields;
pImpl->pvFields = newPVFields;
pImpl->numberFields = numberFields;
}
void PVStructure::removePVField(String fieldName)
{
PVField *pvField = getSubField(fieldName);
if(pvField==0) {
String message("removePVField ");
message += fieldName + " does not exist";
this->message(message, errorMessage);
return;
}
int origLength = pImpl->numberFields;
int newLength = origLength - 1;
PVFieldPtrArray origPVFields = pImpl->pvFields;
PVFieldPtrArray newPVFields = new PVFieldPtr[newLength];
int newIndex = 0;
int indRemove = -1;
for(int i=0; i<origLength; i++) {
if(origPVFields[i]==pvField) {
indRemove = i;
} else {
newPVFields[newIndex++] = origPVFields[i];
}
}
Structure *structure = const_cast<Structure *>(getStructure().get());
structure->removeField(indRemove);
delete origPVFields[indRemove];
delete[] pImpl->pvFields;
pImpl->pvFields = newPVFields;
pImpl->numberFields = newLength;
}
PVBoolean *PVStructure::getBooleanField(String fieldName)
{
PVField *pvField = findSubField(fieldName,this);
if(pvField==0) {
String message("fieldName ");
message += fieldName + " does not exist";
this->message(message, errorMessage);
return 0;
}
if(pvField->getField()->getType()==scalar) {
ScalarConstPtr pscalar = static_pointer_cast<const Scalar>(
pvField->getField());
if(pscalar->getScalarType()==pvBoolean) {
return (PVBoolean*)pvField;
}
}
String message("fieldName ");
message += fieldName + " does not have type boolean ";
this->message(message, errorMessage);
return 0;
}
PVByte *PVStructure::getByteField(String fieldName)
{
PVField *pvField = findSubField(fieldName,this);
if(pvField==0) {
String message("fieldName ");
message += fieldName + " does not exist";
this->message(message, errorMessage);
return 0;
}
if(pvField->getField()->getType()==scalar) {
ScalarConstPtr pscalar = static_pointer_cast<const Scalar>(
pvField->getField());
if(pscalar->getScalarType()==pvByte) {
return (PVByte*)pvField;
}
}
String message("fieldName ");
message += fieldName + " does not have type byte ";
this->message(message, errorMessage);
return 0;
}
PVShort *PVStructure::getShortField(String fieldName)
{
PVField *pvField = findSubField(fieldName,this);
if(pvField==0) {
String message("fieldName ");
message += fieldName + " does not exist";
this->message(message, errorMessage);
return 0;
}
if(pvField->getField()->getType()==scalar) {
ScalarConstPtr pscalar = static_pointer_cast<const Scalar>(
pvField->getField());
if(pscalar->getScalarType()==pvShort) {
return (PVShort*)pvField;
}
}
String message("fieldName ");
message += fieldName + " does not have type short ";
this->message(message, errorMessage);
return 0;
}
PVInt *PVStructure::getIntField(String fieldName)
{
PVField *pvField = findSubField(fieldName,this);
if(pvField==0) {
String message("fieldName ");
message += fieldName + " does not exist";
this->message(message, errorMessage);
return 0;
}
if(pvField->getField()->getType()==scalar) {
ScalarConstPtr pscalar = static_pointer_cast<const Scalar>(
pvField->getField());
if(pscalar->getScalarType()==pvInt) {
return (PVInt*)pvField;
}
}
String message("fieldName ");
message += fieldName + " does not have type int ";
this->message(message, errorMessage);
return 0;
}
PVLong *PVStructure::getLongField(String fieldName)
{
PVField *pvField = findSubField(fieldName,this);
if(pvField==0) {
String message("fieldName ");
message += fieldName + " does not exist";
this->message(message, errorMessage);
return 0;
}
if(pvField->getField()->getType()==scalar) {
ScalarConstPtr pscalar = static_pointer_cast<const Scalar>(
pvField->getField());
if(pscalar->getScalarType()==pvLong) {
return (PVLong*)pvField;
}
}
String message("fieldName ");
message += fieldName + " does not have type long ";
this->message(message, errorMessage);
return 0;
}
PVFloat *PVStructure::getFloatField(String fieldName)
{
PVField *pvField = findSubField(fieldName,this);
if(pvField==0) {
String message("fieldName ");
message += fieldName + " does not exist";
this->message(message, errorMessage);
return 0;
}
if(pvField->getField()->getType()==scalar) {
ScalarConstPtr pscalar = static_pointer_cast<const Scalar>(
pvField->getField());
if(pscalar->getScalarType()==pvFloat) {
return (PVFloat*)pvField;
}
}
String message("fieldName ");
message += fieldName + " does not have type float ";
this->message(message, errorMessage);
return 0;
}
PVDouble *PVStructure::getDoubleField(String fieldName)
{
PVField *pvField = findSubField(fieldName,this);
if(pvField==0) {
String message("fieldName ");
message += fieldName + " does not exist";
this->message(message, errorMessage);
return 0;
}
if(pvField->getField()->getType()==scalar) {
ScalarConstPtr pscalar = static_pointer_cast<const Scalar>(
pvField->getField());
if(pscalar->getScalarType()==pvDouble) {
return (PVDouble*)pvField;
}
}
String message("fieldName ");
message += fieldName + " does not have type double ";
this->message(message, errorMessage);
return 0;
}
PVString *PVStructure::getStringField(String fieldName)
{
PVField *pvField = findSubField(fieldName,this);
if(pvField==0) {
String message("fieldName ");
message += fieldName + " does not exist";
this->message(message, errorMessage);
return 0;
}
if(pvField->getField()->getType()==scalar) {
ScalarConstPtr pscalar = static_pointer_cast<const Scalar>(
pvField->getField());
if(pscalar->getScalarType()==pvString) {
return (PVString*)pvField;
}
}
String message("fieldName ");
message += fieldName + " does not have type string ";
this->message(message, errorMessage);
return 0;
}
PVStructure *PVStructure::getStructureField(String fieldName)
{
PVField *pvField = findSubField(fieldName,this);
if(pvField==0) {
String message("fieldName ");
message += fieldName + " does not exist";
this->message(message, errorMessage);
return 0;
}
if(pvField->getField()->getType()==structure) {
return((PVStructure *)pvField);
}
String message("fieldName ");
message += fieldName + " does not have type structure ";
this->message(message, errorMessage);
return 0;
}
PVScalarArray *PVStructure::getScalarArrayField(
String fieldName,ScalarType elementType)
{
PVField *pvField = findSubField(fieldName,this);
if(pvField==0) {
String message("fieldName ");
message += fieldName + " does not exist";
this->message(message, errorMessage);
return 0;
}
FieldConstPtr field = pvField->getField();
Type type = field->getType();
if(type!=scalarArray) {
String message("fieldName ");
message += fieldName + " does not have type array ";
this->message(message, errorMessage);
return 0;
}
ScalarArrayConstPtr pscalarArray
= static_pointer_cast<const ScalarArray>(pvField->getField());
if(pscalarArray->getElementType()!=elementType) {
String message("fieldName ");
message += fieldName + " is array but does not have elementType ";
ScalarTypeFunc::toString(&message,elementType);
this->message(message, errorMessage);
return 0;
}
return (PVScalarArray*)pvField;
}
PVStructureArray *PVStructure::getStructureArrayField(
String fieldName)
{
PVField *pvField = findSubField(fieldName,this);
if(pvField==0) {
String message("fieldName ");
message += fieldName + " does not exist";
this->message(message, errorMessage);
return 0;
}
if(pvField->getField()->getType()==structureArray) {
return((PVStructureArray *)pvField);
}
String message("fieldName ");
message += fieldName + " does not have type structureArray ";
this->message(message, errorMessage);
return 0;
}
String PVStructure::getExtendsStructureName()
{
return pImpl->extendsStructureName;
}
bool PVStructure::putExtendsStructureName(
String extendsStructureName)
{
if(pImpl->extendsStructureName.length()!=0) return false;
pImpl->extendsStructureName = extendsStructureName;
return true;
}
void PVStructure::serialize(ByteBuffer *pbuffer,
SerializableControl *pflusher) const {
for(int i = 0; i<pImpl->numberFields; i++)
pImpl->pvFields[i]->serialize(pbuffer, pflusher);
}
void PVStructure::deserialize(ByteBuffer *pbuffer,
DeserializableControl *pcontrol) {
for(int i = 0; i<pImpl->numberFields; i++)
pImpl->pvFields[i]->deserialize(pbuffer, pcontrol);
}
void PVStructure::serialize(ByteBuffer *pbuffer,
SerializableControl *pflusher, BitSet *pbitSet) const {
int offset = const_cast<PVStructure*>(this)->getFieldOffset();
int numberFields = const_cast<PVStructure*>(this)->getNumberFields();
int next = pbitSet->nextSetBit(offset);
// no more changes or no changes in this structure
if(next<0||next>=offset+numberFields) return;
// entire structure
if(offset==next) {
serialize(pbuffer, pflusher);
return;
}
for(int i = 0; i<pImpl->numberFields; i++) {
PVField* pvField = pImpl->pvFields[i];
offset = pvField->getFieldOffset();
numberFields = pvField->getNumberFields();
next = pbitSet->nextSetBit(offset);
// no more changes
if(next<0) return;
// no change in this pvField
if(next>=offset+numberFields) continue;
// serialize field or fields
if(numberFields==1)
pvField->serialize(pbuffer, pflusher);
else
((PVStructure*)pvField)->serialize(pbuffer, pflusher,
pbitSet);
}
}
void PVStructure::deserialize(ByteBuffer *pbuffer,
DeserializableControl *pcontrol, BitSet *pbitSet) {
int offset = getFieldOffset();
int numberFields = getNumberFields();
int next = pbitSet->nextSetBit(offset);
// no more changes or no changes in this structure
if(next<0||next>=offset+numberFields) return;
// entire structure
if(offset==next) {
deserialize(pbuffer, pcontrol);
return;
}
for(int i = 0; i<pImpl->numberFields; i++) {
PVField* pvField = pImpl->pvFields[i];
offset = pvField->getFieldOffset();
numberFields = pvField->getNumberFields();
next = pbitSet->nextSetBit(offset);
// no more changes
if(next<0) return;
// no change in this pvField
if(next>=offset+numberFields) continue;
// deserialize field or fields
if(numberFields==1)
pvField->deserialize(pbuffer, pcontrol);
else
((PVStructure*)pvField)->deserialize(pbuffer, pcontrol,
pbitSet);
}
}
static PVField *findSubField(String fieldName,PVStructure *pvStructure) {
if( fieldName.length()<1) return 0;
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();
PVField *pvField = 0;
int numFields = pvStructure->getStructure()->getNumberFields();
for(int i=0; i<numFields; i++) {
PVField *pvf = pvFields[i];
int result = pvf->getField()->getFieldName().compare(name);
if(result==0) {
pvField = pvf;
break;
}
}
if(pvField==0) return 0;
if(restOfName.length()==0) return pvField;
if(pvField->getField()->getType()!=structure) return 0;
return findSubField(restOfName,(PVStructure*)pvField);
}
}}

View File

@@ -1,501 +0,0 @@
/* StandardField.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#include <string>
#include <cstdio>
#include <stdexcept>
#include <epicsThread.h>
#include <epicsExit.h>
#include <pv/lock.h>
#include <pv/pvIntrospect.h>
#include <pv/standardField.h>
#include <pv/CDRMonitor.h>
using std::tr1::static_pointer_cast;
namespace epics { namespace pvData {
static StandardField* standardField = 0;
static String notImplemented("not implemented");
static FieldCreate* fieldCreate = 0;
static String valueFieldName("value");
// following are preallocated structures
static StructureConstPtr alarmField;
static StructureConstPtr timeStampField;
static StructureConstPtr displayField;
static StructureConstPtr controlField;
static StructureConstPtr booleanAlarmField;
static StructureConstPtr byteAlarmField;
static StructureConstPtr shortAlarmField;
static StructureConstPtr intAlarmField;
static StructureConstPtr longAlarmField;
static StructureConstPtr floatAlarmField;
static StructureConstPtr doubleAlarmField;
static StructureConstPtr enumeratedAlarmField;
static void createAlarm() {
FieldConstPtrArray fields = new FieldConstPtr[3];
fields[0] = fieldCreate->createScalar(String("severity"),pvInt);
fields[1] = fieldCreate->createScalar(String("status"),pvInt);
fields[2] = fieldCreate->createScalar(String("message"),pvString);
alarmField = fieldCreate->createStructure(String("alarm"),3,fields);
}
static void createTimeStamp() {
FieldConstPtrArray fields = new FieldConstPtr[3];
fields[0] = fieldCreate->createScalar(String("secondsPastEpoch"),pvLong);
fields[1] = fieldCreate->createScalar(String("nanoSeconds"),pvInt);
fields[2] = fieldCreate->createScalar(String("userTag"),pvInt);
timeStampField = fieldCreate->createStructure(String("timeStamp"),3,fields);
}
static void createDisplay() {
FieldConstPtrArray limitFields = new FieldConstPtr[2];
limitFields[0] = fieldCreate->createScalar(String("low"),pvDouble);
limitFields[1] = fieldCreate->createScalar(String("high"),pvDouble);
FieldConstPtrArray fields = new FieldConstPtr[4];
fields[0] = fieldCreate->createScalar(String("description"),pvString);
fields[1] = fieldCreate->createScalar(String("format"),pvString);
fields[2] = fieldCreate->createScalar(String("units"),pvString);
fields[3] = fieldCreate->createStructure(String("limit"),2,limitFields);
displayField = fieldCreate->createStructure(String("display"),4,fields);
}
static void createControl() {
FieldConstPtrArray limitFields = new FieldConstPtr[2];
limitFields[0] = fieldCreate->createScalar(String("low"),pvDouble);
limitFields[1] = fieldCreate->createScalar(String("high"),pvDouble);
FieldConstPtrArray fields = new FieldConstPtr[2];
fields[0] = fieldCreate->createStructure(String("limit"),2,limitFields);
fields[1] = fieldCreate->createScalar(String("minStep"),pvDouble);
controlField = fieldCreate->createStructure(String("control"),2,fields);
}
static void createBooleanAlarm() {
FieldConstPtrArray fields = new FieldConstPtr[4];
fields[0] = fieldCreate->createScalar(String("active"),pvBoolean);
fields[1] = fieldCreate->createScalar(String("falseSeverity"),pvInt);
fields[2] = fieldCreate->createScalar(String("trueSeverity"),pvInt);
fields[3] = fieldCreate->createScalar(String("changeStateSeverity"),pvInt);
booleanAlarmField = fieldCreate->createStructure(String("valueAlarm"),4,fields);
}
static void createByteAlarm() {
int numFields = 10;
FieldConstPtrArray fields = new FieldConstPtr[numFields];
fields[0] = fieldCreate->createScalar(String("active"),pvBoolean);
fields[1] = fieldCreate->createScalar(String("lowAlarmLimit"),pvByte);
fields[2] = fieldCreate->createScalar(String("lowWarningLimit"),pvByte);
fields[3] = fieldCreate->createScalar(String("highWarningLimit"),pvByte);
fields[4] = fieldCreate->createScalar(String("highAlarmLimit"),pvByte);
fields[5] = fieldCreate->createScalar(String("lowAlarmSeverity"),pvInt);
fields[6] = fieldCreate->createScalar(String("lowWarningSeverity"),pvInt);
fields[7] = fieldCreate->createScalar(String("highWarningSeverity"),pvInt);
fields[8] = fieldCreate->createScalar(String("highAlarmSeverity"),pvInt);
fields[9] = fieldCreate->createScalar(String("hystersis"),pvByte);
byteAlarmField = fieldCreate->createStructure(String("valueAlarm"),numFields,fields);
}
static void createShortAlarm() {
int numFields = 10;
FieldConstPtrArray fields = new FieldConstPtr[numFields];
fields[0] = fieldCreate->createScalar(String("active"),pvBoolean);
fields[1] = fieldCreate->createScalar(String("lowAlarmLimit"),pvShort);
fields[2] = fieldCreate->createScalar(String("lowWarningLimit"),pvShort);
fields[3] = fieldCreate->createScalar(String("highWarningLimit"),pvShort);
fields[4] = fieldCreate->createScalar(String("highAlarmLimit"),pvShort);
fields[5] = fieldCreate->createScalar(String("lowAlarmSeverity"),pvInt);
fields[6] = fieldCreate->createScalar(String("lowWarningSeverity"),pvInt);
fields[7] = fieldCreate->createScalar(String("highWarningSeverity"),pvInt);
fields[8] = fieldCreate->createScalar(String("highAlarmSeverity"),pvInt);
fields[9] = fieldCreate->createScalar(String("hystersis"),pvShort);
shortAlarmField = fieldCreate->createStructure(String("valueAlarm"),numFields,fields);
}
static void createIntAlarm() {
int numFields = 10;
FieldConstPtrArray fields = new FieldConstPtr[numFields];
fields[0] = fieldCreate->createScalar(String("active"),pvBoolean);
fields[1] = fieldCreate->createScalar(String("lowAlarmLimit"),pvInt);
fields[2] = fieldCreate->createScalar(String("lowWarningLimit"),pvInt);
fields[3] = fieldCreate->createScalar(String("highWarningLimit"),pvInt);
fields[4] = fieldCreate->createScalar(String("highAlarmLimit"),pvInt);
fields[5] = fieldCreate->createScalar(String("lowAlarmSeverity"),pvInt);
fields[6] = fieldCreate->createScalar(String("lowWarningSeverity"),pvInt);
fields[7] = fieldCreate->createScalar(String("highWarningSeverity"),pvInt);
fields[8] = fieldCreate->createScalar(String("highAlarmSeverity"),pvInt);
fields[9] = fieldCreate->createScalar(String("hystersis"),pvInt);
intAlarmField = fieldCreate->createStructure(String("valueAlarm"),numFields,fields);
}
static void createLongAlarm() {
int numFields = 10;
FieldConstPtrArray fields = new FieldConstPtr[numFields];
fields[0] = fieldCreate->createScalar(String("active"),pvBoolean);
fields[1] = fieldCreate->createScalar(String("lowAlarmLimit"),pvLong);
fields[2] = fieldCreate->createScalar(String("lowWarningLimit"),pvLong);
fields[3] = fieldCreate->createScalar(String("highWarningLimit"),pvLong);
fields[4] = fieldCreate->createScalar(String("highAlarmLimit"),pvLong);
fields[5] = fieldCreate->createScalar(String("lowAlarmSeverity"),pvInt);
fields[6] = fieldCreate->createScalar(String("lowWarningSeverity"),pvInt);
fields[7] = fieldCreate->createScalar(String("highWarningSeverity"),pvInt);
fields[8] = fieldCreate->createScalar(String("highAlarmSeverity"),pvInt);
fields[9] = fieldCreate->createScalar(String("hystersis"),pvLong);
longAlarmField = fieldCreate->createStructure(String("valueAlarm"),numFields,fields);
}
static void createFloatAlarm() {
int numFields = 10;
FieldConstPtrArray fields = new FieldConstPtr[numFields];
fields[0] = fieldCreate->createScalar(String("active"),pvBoolean);
fields[1] = fieldCreate->createScalar(String("lowAlarmLimit"),pvFloat);
fields[2] = fieldCreate->createScalar(String("lowWarningLimit"),pvFloat);
fields[3] = fieldCreate->createScalar(String("highWarningLimit"),pvFloat);
fields[4] = fieldCreate->createScalar(String("highAlarmLimit"),pvFloat);
fields[5] = fieldCreate->createScalar(String("lowAlarmSeverity"),pvInt);
fields[6] = fieldCreate->createScalar(String("lowWarningSeverity"),pvInt);
fields[7] = fieldCreate->createScalar(String("highWarningSeverity"),pvInt);
fields[8] = fieldCreate->createScalar(String("highAlarmSeverity"),pvInt);
fields[9] = fieldCreate->createScalar(String("hystersis"),pvFloat);
floatAlarmField = fieldCreate->createStructure(String("valueAlarm"),numFields,fields);
}
static void createDoubleAlarm() {
int numFields = 10;
FieldConstPtrArray fields = new FieldConstPtr[numFields];
fields[0] = fieldCreate->createScalar(String("active"),pvBoolean);
fields[1] = fieldCreate->createScalar(String("lowAlarmLimit"),pvDouble);
fields[2] = fieldCreate->createScalar(String("lowWarningLimit"),pvDouble);
fields[3] = fieldCreate->createScalar(String("highWarningLimit"),pvDouble);
fields[4] = fieldCreate->createScalar(String("highAlarmLimit"),pvDouble);
fields[5] = fieldCreate->createScalar(String("lowAlarmSeverity"),pvInt);
fields[6] = fieldCreate->createScalar(String("lowWarningSeverity"),pvInt);
fields[7] = fieldCreate->createScalar(String("highWarningSeverity"),pvInt);
fields[8] = fieldCreate->createScalar(String("highAlarmSeverity"),pvInt);
fields[9] = fieldCreate->createScalar(String("hystersis"),pvDouble);
doubleAlarmField = fieldCreate->createStructure(String("valueAlarm"),numFields,fields);
}
static void createEnumeratedAlarm() {
int numFields = 3;
FieldConstPtrArray fields = new FieldConstPtr[numFields];
fields[0] = fieldCreate->createScalar(String("active"),pvBoolean);
fields[1] = fieldCreate->createScalar(String("stateSeverity"),pvInt);
fields[2] = fieldCreate->createScalar(String("changeStateSeverity"),pvInt);
enumeratedAlarmField = fieldCreate->createStructure(String("valueAlarm"),numFields,fields);
}
static StructureConstPtr createProperties(String fieldName,FieldConstPtr field,String properties) {
bool gotAlarm = false;
bool gotTimeStamp = false;
bool gotDisplay = false;
bool gotControl = false;
bool gotValueAlarm = false;
int numProp = 0;
if(properties.find("alarm")!=String::npos) { gotAlarm = true; numProp++; }
if(properties.find("timeStamp")!=String::npos) { gotTimeStamp = true; numProp++; }
if(properties.find("display")!=String::npos) { gotDisplay = true; numProp++; }
if(properties.find("control")!=String::npos) { gotControl = true; numProp++; }
if(properties.find("valueAlarm")!=String::npos) { gotValueAlarm = true; numProp++; }
StructureConstPtr valueAlarm;
Type type= field->getType();
while(gotValueAlarm) {
if(type==scalar) {
ScalarConstPtr scalar = static_pointer_cast<const Scalar>(field);
ScalarType scalarType = scalar->getScalarType();
switch(scalarType) {
case pvBoolean: valueAlarm = booleanAlarmField; break;
case pvByte: valueAlarm = byteAlarmField; break;
case pvShort: valueAlarm = shortAlarmField; break;
case pvInt: valueAlarm = intAlarmField; break;
case pvLong: valueAlarm = longAlarmField; break;
case pvFloat: valueAlarm = floatAlarmField; break;
case pvDouble: valueAlarm = doubleAlarmField; break;
default:
throw std::logic_error(String("valueAlarm property for illegal type"));
}
break;
}
if(type==structure) {
StructureConstPtr structurePtr = static_pointer_cast<const Structure>(field);
if(structurePtr->getNumberFields()==2) {
FieldConstPtrArray fields = structurePtr->getFields();
FieldConstPtr first = fields[0];
FieldConstPtr second = fields[1];
String nameFirst = first->getFieldName();
String nameSecond = second->getFieldName();
int compareFirst = nameFirst.compare("index");
int compareSecond = nameSecond.compare("choices");
if(compareFirst==0 && compareSecond==0) {
if(first->getType()==scalar
&& second->getType()==scalarArray) {
ScalarConstPtr scalarFirst = static_pointer_cast<const Scalar>(first);
ScalarArrayConstPtr scalarArraySecond =
static_pointer_cast<const ScalarArray>(second);
if(scalarFirst->getScalarType()==pvInt
&& scalarArraySecond->getElementType()==pvString) {
valueAlarm = enumeratedAlarmField;
break;
}
}
}
}
}
throw std::logic_error(String("valueAlarm property for illegal type"));
}
int numFields = numProp+1;
FieldConstPtrArray fields = new FieldConstPtr[numFields];
int next = 0;
fields[next++] = field;
if(gotAlarm) {fields[next++] = alarmField;}
if(gotTimeStamp) {fields[next++] = timeStampField;}
if(gotDisplay) {fields[next++] = displayField;}
if(gotControl) {fields[next++] = controlField;}
if(gotValueAlarm) {fields[next++] = valueAlarm;}
return fieldCreate->createStructure(fieldName,numFields,fields);
}
ScalarConstPtr StandardField::scalar(String fieldName,ScalarType type)
{
return fieldCreate->createScalar(fieldName,type);
}
StructureConstPtr StandardField::scalar(
String fieldName,ScalarType type,String properties)
{
ScalarConstPtr field = fieldCreate->createScalar(valueFieldName,type);
return createProperties(fieldName,field,properties);
}
ScalarArrayConstPtr StandardField::scalarArray(
String fieldName,ScalarType elementType)
{
return fieldCreate->createScalarArray(fieldName,elementType);
}
StructureConstPtr StandardField::scalarArray(
String fieldName,ScalarType elementType, String properties)
{
ScalarArrayConstPtr field = fieldCreate->createScalarArray(
valueFieldName,elementType);
return createProperties(fieldName,field,properties);
}
StructureArrayConstPtr StandardField::structureArray(
String fieldName,StructureConstPtr structure)
{
return fieldCreate->createStructureArray(fieldName,structure);
}
StructureConstPtr StandardField::structureArray(
String fieldName,StructureConstPtr structure,String properties)
{
StructureArrayConstPtr field = fieldCreate->createStructureArray(
valueFieldName,structure);
return createProperties(fieldName,field,properties);
}
StructureConstPtr StandardField::structure(
String fieldName,int numFields,FieldConstPtrArray fields)
{
return fieldCreate->createStructure(fieldName,numFields,fields);
}
StructureConstPtr StandardField::enumerated(String fieldName)
{
FieldConstPtrArray fields = new FieldConstPtr[2];
fields[0] = fieldCreate->createScalar(String("index"),pvInt);
fields[1] = fieldCreate->createScalarArray(String("choices"),pvString);
return fieldCreate->createStructure(fieldName,2,fields);
}
StructureConstPtr StandardField::enumerated(
String fieldName,String properties)
{
StructureConstPtr field = standardField->enumerated(valueFieldName);
return createProperties(fieldName,field,properties);
}
ScalarConstPtr StandardField::scalarValue(ScalarType type)
{
return fieldCreate->createScalar(valueFieldName,type);
}
StructureConstPtr StandardField::scalarValue(ScalarType type,String properties)
{
ScalarConstPtr field = fieldCreate->createScalar(valueFieldName,type);
return createProperties(valueFieldName,field,properties);
}
ScalarArrayConstPtr StandardField::scalarArrayValue(ScalarType elementType)
{
return fieldCreate->createScalarArray(valueFieldName,elementType);
}
StructureConstPtr StandardField::scalarArrayValue(
ScalarType elementType, String properties)
{
ScalarArrayConstPtr field = fieldCreate->createScalarArray(
valueFieldName,elementType);
return createProperties(valueFieldName,field,properties);
}
StructureArrayConstPtr StandardField::structureArrayValue(
StructureConstPtr structure)
{
return fieldCreate->createStructureArray(valueFieldName,structure);
}
StructureConstPtr StandardField::structureArrayValue(
StructureConstPtr structure,String properties)
{
StructureArrayConstPtr field = fieldCreate->createStructureArray(
valueFieldName,structure);
return createProperties(valueFieldName,field,properties);
}
StructureConstPtr StandardField::structureValue(
int numFields,FieldConstPtrArray fields)
{
return fieldCreate->createStructure(valueFieldName,numFields,fields);
}
StructureConstPtr StandardField::enumeratedValue()
{
FieldConstPtrArray fields = new FieldConstPtr[2];
fields[0] = fieldCreate->createScalar(String("index"),pvInt);
fields[1] = fieldCreate->createScalarArray(String("choices"),pvString);
return fieldCreate->createStructure(valueFieldName,2,fields);
}
StructureConstPtr StandardField::enumeratedValue( String properties)
{
StructureConstPtr field = standardField->enumerated(valueFieldName);
return createProperties(valueFieldName,field,properties);
}
StructureConstPtr StandardField::alarm()
{
return alarmField;
}
StructureConstPtr StandardField::timeStamp()
{
return timeStampField;
}
StructureConstPtr StandardField::display()
{
return displayField;
}
StructureConstPtr StandardField::control()
{
return controlField;
}
StructureConstPtr StandardField::booleanAlarm()
{
return booleanAlarmField;
}
StructureConstPtr StandardField::byteAlarm()
{
return byteAlarmField;
}
StructureConstPtr StandardField::shortAlarm()
{
return shortAlarmField;
}
StructureConstPtr StandardField::intAlarm()
{
return intAlarmField;
}
StructureConstPtr StandardField::longAlarm()
{
return longAlarmField;
}
StructureConstPtr StandardField::floatAlarm()
{
return floatAlarmField;
}
StructureConstPtr StandardField::doubleAlarm()
{
return doubleAlarmField;
}
StructureConstPtr StandardField::enumeratedAlarm()
{
return enumeratedAlarmField;
}
void StandardField::init()
{
createAlarm();
createTimeStamp();
createDisplay();
createControl();
createBooleanAlarm();
createByteAlarm();
createShortAlarm();
createIntAlarm();
createLongAlarm();
createFloatAlarm();
createDoubleAlarm();
createEnumeratedAlarm();
}
StandardField::StandardField(){init();}
StandardField::~StandardField(){
}
static void myDeleteStatic(void*)
{
alarmField.reset();
timeStampField.reset();
displayField.reset();
controlField.reset();
booleanAlarmField.reset();
byteAlarmField.reset();
shortAlarmField.reset();
intAlarmField.reset();
longAlarmField.reset();
floatAlarmField.reset();
doubleAlarmField.reset();
enumeratedAlarmField.reset();
}
static void myInitStatic(void*)
{
standardField = new StandardField();
fieldCreate = getFieldCreate();
epicsAtExit(&myDeleteStatic,0);
}
static
epicsThreadOnceId myInitOnce = EPICS_THREAD_ONCE_INIT;
StandardField * getStandardField() {
epicsThreadOnce(&myInitOnce,&myInitStatic,0);
return standardField;
}
}}

View File

@@ -1,353 +0,0 @@
/* StandardPVField.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#include <string>
#include <stdexcept>
#include <epicsThread.h>
#include <epicsExit.h>
#include <pv/lock.h>
#include <pv/pvIntrospect.h>
#include <pv/pvData.h>
#include <pv/convert.h>
#include <pv/standardField.h>
#include <pv/standardPVField.h>
#include <pv/CDRMonitor.h>
namespace epics { namespace pvData {
static StandardField *standardField = 0;
static String notImplemented("not implemented");
static FieldCreate* fieldCreate = 0;
static PVDataCreate* pvDataCreate = 0;
static StandardPVField *standardPVField = 0;
static void addExtendsStructureName(PVStructure *pvStructure,String properties)
{
bool gotAlarm = false;
bool gotTimeStamp = false;
bool gotDisplay = false;
bool gotControl = false;
if(properties.find("alarm")!=String::npos) gotAlarm = true;
if(properties.find("timeStamp")!=String::npos) gotTimeStamp = true;
if(properties.find("display")!=String::npos) gotDisplay = true;
if(properties.find("control")!=String::npos) gotControl = true;
if(gotAlarm) {
PVStructure *pv = pvStructure->getStructureField(String("alarm"));
if(pv!=0) pv->putExtendsStructureName(String("alarm"));
}
if(gotTimeStamp) {
PVStructure *pv = pvStructure->getStructureField(String("timeStamp"));
if(pv!=0) pv->putExtendsStructureName(String("timeStamp"));
}
if(gotDisplay) {
PVStructure *pv = pvStructure->getStructureField(String("display"));
if(pv!=0) pv->putExtendsStructureName(String("display"));
}
if(gotControl) {
PVStructure *pv = pvStructure->getStructureField(String("control"));
if(pv!=0) pv->putExtendsStructureName(String("control"));
}
}
StandardPVField::StandardPVField(){}
StandardPVField::~StandardPVField(){}
PVScalar * StandardPVField::scalar(PVStructure *parent,
String fieldName,ScalarType type)
{
ScalarConstPtr field = standardField->scalar(fieldName,type);
return pvDataCreate->createPVScalar(parent,field);
}
PVStructure * StandardPVField::scalar(PVStructure *parent,
String fieldName,ScalarType type,String properties)
{
StructureConstPtr field = standardField->scalar(fieldName,type,properties);
PVStructure * pvStructure = pvDataCreate->createPVStructure(parent,field);
addExtendsStructureName(pvStructure,properties);
return pvStructure;
}
PVScalarArray * StandardPVField::scalarArray(PVStructure *parent,
String fieldName,ScalarType elementType)
{
ScalarArrayConstPtr field = standardField->scalarArray(
fieldName,elementType);
return pvDataCreate->createPVScalarArray(parent,field);
}
PVStructure * StandardPVField::scalarArray(PVStructure *parent,
String fieldName,ScalarType elementType, String properties)
{
StructureConstPtr field = standardField->scalarArray(
fieldName,elementType,properties);
PVStructure * pvStructure = pvDataCreate->createPVStructure(parent,field);
addExtendsStructureName(pvStructure,properties);
return pvStructure;
}
PVStructureArray * StandardPVField::structureArray(PVStructure *parent,
String fieldName,StructureConstPtr structure)
{
StructureArrayConstPtr field = standardField->structureArray(
fieldName,structure);
return pvDataCreate->createPVStructureArray(parent,field);
}
PVStructure* StandardPVField::structureArray(PVStructure *parent,
String fieldName,StructureConstPtr structure,String properties)
{
StructureConstPtr field = standardField->structureArray(
fieldName,structure,properties);
PVStructure * pvStructure = pvDataCreate->createPVStructure(parent,field);
addExtendsStructureName(pvStructure,properties);
return pvStructure;
}
PVStructure * StandardPVField::enumerated(PVStructure *parent,
String fieldName,StringArray choices,int number)
{
StructureConstPtr field = standardField->enumerated(fieldName);
PVStructure *pvStructure = pvDataCreate->createPVStructure(parent,field);
PVScalarArray *pvScalarArray = pvStructure->getScalarArrayField(
"choices",pvString);
if(pvScalarArray==0) {
throw std::logic_error(String("StandardPVField::enumerated"));
}
PVStringArray *pvChoices = static_cast<PVStringArray *>(pvScalarArray);
pvChoices->put(0,number,choices,0);
return pvStructure;
}
PVStructure * StandardPVField::enumerated(PVStructure *parent,
String fieldName,StringArray choices,int number, String properties)
{
StructureConstPtr field = standardField->enumerated(
fieldName,properties);
PVStructure *pvStructure = pvDataCreate->createPVStructure(parent,field);
addExtendsStructureName(pvStructure,properties);
PVScalarArray *pvScalarArray = pvStructure->getScalarArrayField(
fieldName += ".choices",pvString);
if(pvScalarArray==0) {
throw std::logic_error(String("StandardPVField::enumerated"));
}
PVStringArray *pvChoices = static_cast<PVStringArray *>(pvScalarArray);
pvChoices->put(0,number,choices,0);
return pvStructure;
}
PVScalar * StandardPVField::scalarValue(PVStructure *parent,
ScalarType scalarType)
{
ScalarConstPtr field = standardField->scalarValue(scalarType);
return pvDataCreate->createPVScalar(parent,field);
}
PVStructure * StandardPVField::scalarValue(PVStructure *parent,
ScalarType type,String properties)
{
StructureConstPtr field = standardField->scalarValue(type,properties);
PVStructure * pvStructure = pvDataCreate->createPVStructure(parent,field);
addExtendsStructureName(pvStructure,properties);
return pvStructure;
}
PVScalarArray * StandardPVField::scalarArrayValue(PVStructure *parent,
ScalarType elementType)
{
ScalarArrayConstPtr scalarArray =
standardField->scalarArrayValue(elementType);
return pvDataCreate->createPVScalarArray(0,scalarArray);
}
PVStructure * StandardPVField::scalarArrayValue(PVStructure *parent,
ScalarType elementType, String properties)
{
StructureConstPtr field = standardField->scalarArrayValue(
elementType,properties);
PVStructure * pvStructure = pvDataCreate->createPVStructure(parent,field);
addExtendsStructureName(pvStructure,properties);
return pvStructure;
}
PVStructureArray * StandardPVField::structureArrayValue(PVStructure *parent,
StructureConstPtr structure)
{
StructureArrayConstPtr field = standardField->structureArrayValue(
structure);
return pvDataCreate->createPVStructureArray(parent,field);
}
PVStructure * StandardPVField::structureArrayValue(PVStructure *parent,
StructureConstPtr structure,String properties)
{
StructureConstPtr field = standardField->structureArrayValue(
structure,properties);
PVStructure * pvStructure = pvDataCreate->createPVStructure(parent,field);
addExtendsStructureName(pvStructure,properties);
return pvStructure;
}
PVStructure * StandardPVField::enumeratedValue(PVStructure *parent,
StringArray choices,int number)
{
StructureConstPtr field = standardField->enumeratedValue();
PVStructure *pvStructure = pvDataCreate->createPVStructure(parent,field);
PVScalarArray *pvScalarArray = pvStructure->getScalarArrayField(
"choices",pvString);
if(pvScalarArray==0) {
throw std::logic_error(String("StandardPVField::enumerated"));
}
PVStringArray *pvChoices = static_cast<PVStringArray *>(pvScalarArray);
pvChoices->put(0,number,choices,0);
return pvStructure;
}
PVStructure * StandardPVField::enumeratedValue(PVStructure *parent,
StringArray choices, int number,String properties)
{
StructureConstPtr field = standardField->enumeratedValue( properties);
PVStructure *pvStructure = pvDataCreate->createPVStructure(parent,field);
addExtendsStructureName(pvStructure,properties);
PVScalarArray *pvScalarArray = pvStructure->getScalarArrayField(
String("value.choices"),pvString);
if(pvScalarArray==0) {
throw std::logic_error(String("StandardPVField::enumerated"));
}
PVStringArray *pvChoices = static_cast<PVStringArray *>(pvScalarArray);
pvChoices->put(0,number,choices,0);
return pvStructure;
}
PVStructure * StandardPVField::alarm(PVStructure *parent)
{
StructureConstPtr field = standardField->alarm();
return pvDataCreate->createPVStructure(parent,field);
}
PVStructure * StandardPVField::timeStamp(PVStructure *parent)
{
StructureConstPtr field = standardField->timeStamp();
return pvDataCreate->createPVStructure(parent,field);
}
PVStructure * StandardPVField::display(PVStructure *parent)
{
StructureConstPtr field = standardField->display();
return pvDataCreate->createPVStructure(parent,field);
}
PVStructure * StandardPVField::control(PVStructure *parent)
{
StructureConstPtr field = standardField->control();
return pvDataCreate->createPVStructure(parent,field);
}
PVStructure * StandardPVField::booleanAlarm(PVStructure *parent)
{
StructureConstPtr field = standardField->booleanAlarm();
return pvDataCreate->createPVStructure(parent,field);
}
PVStructure * StandardPVField::byteAlarm(PVStructure *parent)
{
StructureConstPtr field = standardField->byteAlarm();
return pvDataCreate->createPVStructure(parent,field);
}
PVStructure * StandardPVField::shortAlarm(PVStructure *parent)
{
StructureConstPtr field = standardField->shortAlarm();
return pvDataCreate->createPVStructure(parent,field);
}
PVStructure * StandardPVField::intAlarm(PVStructure *parent)
{
StructureConstPtr field = standardField->intAlarm();
return pvDataCreate->createPVStructure(parent,field);
}
PVStructure * StandardPVField::longAlarm(PVStructure *parent)
{
StructureConstPtr field = standardField->longAlarm();
return pvDataCreate->createPVStructure(parent,field);
}
PVStructure * StandardPVField::floatAlarm(PVStructure *parent)
{
StructureConstPtr field = standardField->floatAlarm();
return pvDataCreate->createPVStructure(parent,field);
}
PVStructure * StandardPVField::doubleAlarm(PVStructure *parent)
{
StructureConstPtr field = standardField->doubleAlarm();
return pvDataCreate->createPVStructure(parent,field);
}
PVStructure * StandardPVField::enumeratedAlarm(PVStructure *parent)
{
StructureConstPtr field = standardField->enumeratedAlarm();
return pvDataCreate->createPVStructure(parent,field);
}
PVStructure * StandardPVField::powerSupply(PVStructure *parent)
{
StructureConstPtr alarmField = standardField->alarm();
StructureConstPtr timeStampField = standardField->timeStamp();
StructureConstPtr voltageField = standardField->scalar(
String("voltage"),pvDouble,String("alarm"));
StructureConstPtr powerField = standardField->scalar(
String("power"),pvDouble,String("alarm"));
StructureConstPtr currentField = standardField->scalar(
String("current"),pvDouble,String("alarm"));
FieldConstPtr fields[3];
fields[0] = voltageField;
fields[1] = powerField;
fields[2] = currentField;
StructureConstPtr valueField = standardField->structureValue( 3,fields);
fields[0] = alarmField;
fields[1] = timeStampField;
fields[2] = valueField;
StructureConstPtr structureField = standardField->structureValue(3,fields);
return pvDataCreate->createPVStructure(parent,structureField);
}
class StandardPVFieldExt : public StandardPVField {
public:
StandardPVFieldExt(): StandardPVField(){};
};
static void myDeleteStatic(void*)
{
delete standardPVField;
}
static void myInitStatic(void*)
{
fieldCreate = getFieldCreate();
pvDataCreate = getPVDataCreate();
standardField = getStandardField();
standardPVField = new StandardPVFieldExt();
epicsAtExit(&myDeleteStatic, 0);
}
static
epicsThreadOnceId myInitOnce = EPICS_THREAD_ONCE_INIT;
StandardPVField * getStandardPVField() {
epicsThreadOnce(&myInitOnce, &myInitStatic, 0);
return standardPVField;
}
}}

View File

@@ -1,73 +0,0 @@
/*TypeFunc.cpp*/
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#include <cstddef>
#include <cstdlib>
#include <string>
#include <cstdio>
#include <pv/pvIntrospect.h>
#include <pv/epicsException.h>
#include "dbDefs.h" // for NELEMENTS
namespace epics { namespace pvData {
namespace TypeFunc {
static const char* names[] = {
"scalar", "scalarArray", "structure", "structureArray",
};
const char* name(Type t) {
if (t<int(pvBoolean) || t>int(pvString))
THROW_EXCEPTION2(std::invalid_argument, "logic error unknown Type");
return names[t];
}
void toString(StringBuilder buf,const Type type) {
*buf += name(type);
}
} // namespace TypeFunc
namespace ScalarTypeFunc {
bool isInteger(ScalarType type) {
if(type>=pvByte && type<=pvLong) return true;
return false;
}
bool isNumeric(ScalarType type) {
if(type>=pvByte && type<=pvDouble) return true;
return false;
}
bool isPrimitive(ScalarType type) {
if(type>=pvBoolean && type<=pvDouble) return true;
return false;
}
static const char* names[] = {
"boolean", "byte", "short", "int", "long",
"float", "double", "string",
};
ScalarType getScalarType(String pvalue) {
for(size_t i=0; i<NELEMENTS(names); i++)
if(pvalue==names[i])
return ScalarType(i);
THROW_EXCEPTION2(std::invalid_argument, "error unknown ScalarType");
}
const char* name(ScalarType t) {
if (t<pvBoolean || t>pvString)
THROW_EXCEPTION2(std::invalid_argument, "error unknown ScalarType");
return names[t];
}
void toString(StringBuilder buf,const ScalarType scalarType) {
*buf += name(scalarType);
}
} // namespace ScalarTypeFunc
}}

View File

@@ -1,160 +0,0 @@
/* CDRMonitor.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#include <stddef.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <stdio.h>
#include <stdexcept>
#include <epicsThread.h>
#include <pv/noDefaultMethods.h>
#include <pv/lock.h>
#include <pv/pvType.h>
#include <pv/linkedList.h>
#include <pv/CDRMonitor.h>
#ifdef _WIN32
#include <BaseTsd.h>
typedef SSIZE_T ssize_t;
#endif
namespace epics { namespace pvData {
static
epicsThreadOnceId monitorInit = EPICS_THREAD_ONCE_INIT;
// Must use a pointer w/ lazy init due to lack of
// initialization order guarantees
CDRMonitor* CDRMonitor::theone = 0;
CDRMonitor&
CDRMonitor::get()
{
epicsThreadOnce(&monitorInit, &CDRMonitor::init, 0);
assert(theone);
return *theone;
}
void
CDRMonitor::init(void *)
{
//BUG: No idea how to handle allocation failure at this stage.
theone=new CDRMonitor;
}
void
CDRMonitor::destroy()
{
if (theone)
{
CDRNode *node = theone->first();
while (node)
{
CDRNode* tmp = node;
node = node->next();
delete tmp;
}
delete theone;
theone = 0;
}
}
CDRMonitor::CDRMonitor()
:firstNode(0)
{}
CDRCount
CDRMonitor::current()
{
CDRCount total;
for(CDRNode *cur=first(); !!cur; cur=cur->next())
{
total+=cur->get();
}
return total;
}
void
CDRMonitor::show(FILE *fd, bool destroy)
{
for(CDRNode *cur=first(); !!cur; cur=cur->next())
{
cur->show(fd);
}
if (destroy)
CDRMonitor::destroy();
}
void
CDRMonitor::show(std::ostream& out, bool destroy) const
{
for(CDRNode *cur=first(); !!cur; cur=cur->next())
{
cur->show(out);
}
if (destroy)
CDRMonitor::destroy();
}
void
CDRNode::show(FILE *fd)
{
Lock x(guard);
if(!current.cons && !current.dtys && !current.refs)
return;
fprintf(fd,"%s: totalConstruct %lu totalDestruct %lu",
nodeName.c_str(), (unsigned long)current.cons,
(unsigned long)current.dtys);
ssize_t alive=current.cons;
alive-=current.dtys;
if(current.refs)
fprintf(fd," totalReference %ld", current.refs);
if(alive)
fprintf(fd," ACTIVE %ld\n", (long)alive);
else
fprintf(fd,"\n");
}
void
CDRNode::show(std::ostream& out) const
{
Lock x(guard);
if(!current.cons && !current.dtys && !current.refs)
return;
out<<nodeName<<" totalConstruct "<<current.cons
<<" totalDestruct "<<current.dtys;
ssize_t alive=current.cons;
alive-=current.dtys;
if(current.refs)
out<<" totalReference "<<current.refs;
if(alive)
out<<" ACTIVE "<<alive;
out<<"\n";
}
void
onceNode(void* raw)
{
CDRNodeInstance* inst=static_cast<CDRNodeInstance*>(raw);
inst->node=new CDRNode(inst->name);
}
}} // namespace epics::pvData
std::ostream& operator<<(std::ostream& out,const epics::pvData::CDRMonitor& mon)
{
mon.show(out);
return out;
}
std::ostream& operator<<(std::ostream& out,const epics::pvData::CDRNode& node)
{
node.show(out);
return out;
}

View File

@@ -1,140 +0,0 @@
/* CDRMonitor.h */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#ifndef CDRMONITOR_H
#define CDRMONITOR_H
#include <ostream>
#include <cstddef>
#include <cstdlib>
#include <string>
#include <cstdio>
#include <epicsThread.h>
#include <pv/noDefaultMethods.h>
#include <pv/lock.h>
#include <pv/pvType.h>
namespace epics { namespace pvData {
//! Used to pass around snapshots
struct CDRCount { // default copy and assignment are ok
size_t cons, dtys;
long refs;
CDRCount():cons(0),dtys(0),refs(0){}
CDRCount& operator+=(const CDRCount& o)
{cons+=o.cons; dtys+=o.dtys; refs+=o.refs; return *this;}
CDRCount& operator=(size_t count) // reset counters
{cons=count; dtys=count; refs=count; return *this;}
};
class CDRNode;
//! @brief Global registrar for CDRNodes
class CDRMonitor : private NoDefaultMethods {
public:
static CDRMonitor& get();
static void destroy();
CDRNode* addNode(CDRNode& next)
{
CDRNode *ret=firstNode;
firstNode=&next;
return ret;
}
CDRCount current(); //!< current global count
CDRNode* first() const{return firstNode;}
void show(FILE*, bool destroy = false);
void show(std::ostream&, bool destroy = false) const;
private:
// Private ctor for singleton
CDRMonitor();
CDRNode *firstNode;
static CDRMonitor *theone;
static void init(void*);
};
//! Counters for Construction, Destruction, and References of one class
class CDRNode : private NoDefaultMethods {
public:
CDRNode(const String& name)
:nodeName(name)
,current()
,guard()
,nextNode(CDRMonitor::get().addNode(*this))
{}
void construct(){Lock x(guard); current.cons++;}
void destruct(){Lock x(guard); current.dtys++;}
void incRef(){Lock x(guard); current.refs++;}
void decRef(){Lock x(guard); current.refs--;}
CDRNode* next() const{return nextNode;}
CDRCount get() const{Lock x(guard); return current;}
void show(FILE*);
void show(std::ostream&) const;
private:
const String nodeName;
CDRCount current;
mutable Mutex guard;
CDRNode * const nextNode;
};
struct CDRNodeInstance
{
CDRNode *node;
epicsThreadOnceId once;
const char* const name;
};
void onceNode(void* raw);
static inline
CDRNode*
getNode(CDRNodeInstance *inst)
{
epicsThreadOnce(&inst->once,&onceNode,
static_cast<void*>(inst));
return inst->node;
}
#ifndef NDEBUG
#define PVDATA_REFCOUNT_MONITOR_DEFINE(NAME) \
static CDRNodeInstance NAME ## _node={0,EPICS_THREAD_ONCE_INIT,#NAME}
#define PVDATA_REFCOUNT_MONITOR_DESTRUCT(NAME) \
getNode(&NAME ## _node)->destruct()
#define PVDATA_REFCOUNT_MONITOR_CONSTRUCT(NAME) \
getNode(&NAME ## _node)->construct()
#define PVDATA_REFCOUNT_MONITOR_INCREF(NAME) \
getNode(&NAME ## _node)->incRef()
#define PVDATA_REFCOUNT_MONITOR_DECREF(NAME) \
getNode(&NAME ## _node)->decRef()
#else
#define PVDATA_REFCOUNT_MONITOR_DEFINE(NAME)
#define PVDATA_REFCOUNT_MONITOR_DESTRUCT(NAME)
#define PVDATA_REFCOUNT_MONITOR_CONSTRUCT(NAME)
#define PVDATA_REFCOUNT_MONITOR_INCREF(NAME)
#define PVDATA_REFCOUNT_MONITOR_DECREF(NAME)
#endif
}}
std::ostream& operator<<(std::ostream&,const epics::pvData::CDRMonitor&);
std::ostream& operator<<(std::ostream&,const epics::pvData::CDRNode&);
#endif /* CDRMONITOR_H */

View File

@@ -1,162 +0,0 @@
/* executor.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#include <cstddef>
#include <cstdlib>
#include <cstddef>
#include <string>
#include <cstdio>
#include <memory>
#include <vector>
#include <pv/linkedList.h>
#include <pv/lock.h>
#include <pv/thread.h>
#include <pv/event.h>
#include <pv/executor.h>
#include <pv/CDRMonitor.h>
namespace epics { namespace pvData {
// special instance to stop the executor thread
static
class ExecutorShutdown : public Command {
virtual void command(){};
} executorShutdown;
static
Command *shutdown=&executorShutdown;
PVDATA_REFCOUNT_MONITOR_DEFINE(executor);
typedef LinkedListNode<ExecutorNode> ExecutorListNode;
typedef LinkedList<ExecutorNode> ExecutorList;
class ExecutorNode {
public:
ExecutorNode(Command *command);
Command *command;
ExecutorListNode node;
ExecutorListNode runNode;
};
ExecutorNode::ExecutorNode(Command *command)
: command(command),
node(*this),
runNode(*this)
{}
class ExecutorPvt : public Runnable{
public:
ExecutorPvt(String threadName,ThreadPriority priority);
~ExecutorPvt();
ExecutorNode * createNode(Command *command);
void execute(ExecutorNode *node);
virtual void run();
private:
ExecutorList executorList;
ExecutorList runList;
Event moreWork;
Event stopped;
Mutex mutex;
Thread thread;
};
ExecutorPvt::ExecutorPvt(String threadName,ThreadPriority priority)
: executorList(),
runList(),
moreWork(),
stopped(),
mutex(),
thread(threadName,priority,this)
{}
ExecutorPvt::~ExecutorPvt()
{
ExecutorNode shutdownNode(shutdown);
execute(&shutdownNode);
stopped.wait();
// The thread signals 'stopped' while still holding
// the lock. By taking it we wait for the run() function
// to actually return
Lock xx(mutex);
ExecutorListNode *node;
while((node=executorList.removeHead())!=0) {
delete &node->getObject();
}
}
void ExecutorPvt::run()
{
Lock xx(mutex);
while(true) {
ExecutorListNode * executorListNode = 0;
while(runList.isEmpty()) {
xx.unlock();
moreWork.wait();
xx.lock();
}
executorListNode = runList.removeHead();
if(!executorListNode) continue;
Command *cmd=executorListNode->getObject().command;
if(cmd==shutdown) break;
xx.unlock();
try {
executorListNode->getObject().command->command();
}catch(std::exception& e){
//TODO: feed into logging mechanism
fprintf(stderr, "Executor: Unhandled exception: %s",e.what());
}catch(...){
fprintf(stderr, "Executor: Unhandled exception");
}
xx.lock();
}
stopped.signal();
}
ExecutorNode * ExecutorPvt::createNode(Command *command)
{
Lock xx(mutex);
ExecutorNode *executorNode = new ExecutorNode(command);
executorList.addTail(executorNode->node);
return executorNode;
}
void ExecutorPvt::execute(ExecutorNode *node)
{
Lock xx(mutex);
if(node->runNode.isOnList()) return;
bool isEmpty = runList.isEmpty();
runList.addTail(node->runNode);
if(isEmpty) moreWork.signal();
}
Executor::Executor(String threadName,ThreadPriority priority)
: pImpl(new ExecutorPvt(threadName,priority))
{
PVDATA_REFCOUNT_MONITOR_CONSTRUCT(executor);
}
Executor::~Executor() {
delete pImpl;
PVDATA_REFCOUNT_MONITOR_DESTRUCT(executor);
}
ExecutorNode * Executor::createNode(Command*command)
{return pImpl->createNode(command);}
void Executor::execute(ExecutorNode *node) {pImpl->execute(node);}
}}

View File

@@ -1,37 +0,0 @@
/* executor.h */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#ifndef EXECUTOR_H
#define EXECUTOR_H
#include <memory>
#include <vector>
#include <pv/noDefaultMethods.h>
#include <pv/pvType.h>
#include <pv/thread.h>
namespace epics { namespace pvData {
// This is created by Executor.createNode and passed to Executor.execute
class ExecutorNode;
class Command {
public:
virtual ~Command(){}
virtual void command() = 0;
};
class Executor : private NoDefaultMethods {
public:
Executor(String threadName,ThreadPriority priority);
~Executor();
ExecutorNode * createNode(Command *command);
void execute(ExecutorNode *node);
private:
class ExecutorPvt *pImpl;
};
}}
#endif /* EXECUTOR_H */

View File

@@ -1,84 +0,0 @@
/* linkedList.h */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#ifndef LINKEDLIST_H
#define LINKEDLIST_H
#include <pv/linkedListVoid.h>
namespace epics { namespace pvData {
template <typename T>
class LinkedList;
template <typename T>
class LinkedListNode : private LinkedListVoidNode {
public:
LinkedListNode(T &object) : LinkedListVoidNode(&object){}
~LinkedListNode() {}
T &getObject() { return *static_cast<T *>(LinkedListVoidNode::getObject());}
bool isOnList() {return LinkedListVoidNode::isOnList();}
friend class LinkedList<T>;
};
template <typename T>
class LinkedList : private LinkedListVoid {
public:
LinkedList() : LinkedListVoid() {}
~LinkedList() {}
int getLength() {return LinkedListVoid::getLength();}
void addTail(LinkedListNode<T> &listNode)
{
LinkedListVoid::addTail(static_cast<LinkedListVoidNode &>(listNode));
}
void addHead(LinkedListNode<T> &listNode)
{
LinkedListVoid::addHead(static_cast<LinkedListVoidNode &>(listNode));
}
void insertAfter(LinkedListNode<T> &listNode,
LinkedListNode<T> &addNode)
{
LinkedListVoid::insertAfter(
static_cast<LinkedListVoidNode &>(listNode),
static_cast<LinkedListVoidNode &>(addNode));
}
void insertBefore(LinkedListNode<T> &listNode,
LinkedListNode<T> &addNode)
{
LinkedListVoid::insertBefore(
static_cast<LinkedListVoidNode &>(listNode),
static_cast<LinkedListVoidNode &>(addNode));
}
LinkedListNode<T> *removeTail(){
return static_cast<LinkedListNode<T> *>(LinkedListVoid::removeTail());
}
LinkedListNode<T> *removeHead(){
return static_cast<LinkedListNode<T> *>(LinkedListVoid::removeHead());
}
void remove(LinkedListNode<T> &listNode){
LinkedListVoid::remove(static_cast<LinkedListVoidNode &>(listNode));
}
LinkedListNode<T> *getHead(){
return static_cast<LinkedListNode<T> *>(LinkedListVoid::getHead());
}
LinkedListNode<T> *getTail(){
return static_cast<LinkedListNode<T> *>(LinkedListVoid::getTail());
}
LinkedListNode<T> *getNext(LinkedListNode<T> &listNode){
return static_cast<LinkedListNode<T> *>(LinkedListVoid::getNext(
static_cast<LinkedListVoidNode &>(listNode)));
}
LinkedListNode<T> *getPrev(LinkedListNode<T> &listNode){
return static_cast<LinkedListNode<T> *>(LinkedListVoid::getPrev(
static_cast<LinkedListVoidNode &>(listNode)));
}
bool isEmpty() { return LinkedListVoid::isEmpty();}
};
}}
#endif /* LINKEDLIST_H */

View File

@@ -1,210 +0,0 @@
/* linkedListVoid.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#include <cstddef>
#include <cstdlib>
#include <cstddef>
#include <string>
#include <cstdio>
#include <stdexcept>
#include <pv/lock.h>
#include <pv/pvType.h>
#include <pv/linkedListVoid.h>
#include <pv/CDRMonitor.h>
namespace epics { namespace pvData {
static String alreadyOnList("already on list");
PVDATA_REFCOUNT_MONITOR_DEFINE(LinkedListNode);
PVDATA_REFCOUNT_MONITOR_DEFINE(LinkedList);
LinkedListVoidNode::LinkedListVoidNode(void *object)
: object(object),before(0),after(0),linkedListVoid(0)
{
PVDATA_REFCOUNT_MONITOR_CONSTRUCT(LinkedListNode);
}
LinkedListVoidNode::LinkedListVoidNode(bool isHead)
: object(this),before(this),after(this)
{
PVDATA_REFCOUNT_MONITOR_CONSTRUCT(LinkedListNode);
}
LinkedListVoidNode::~LinkedListVoidNode()
{
PVDATA_REFCOUNT_MONITOR_DESTRUCT(LinkedListNode);
}
void *LinkedListVoidNode::getObject() {
return object;
}
bool LinkedListVoidNode::isOnList()
{
if(before==0 && after==0) return false;
return true;
}
LinkedListVoid::LinkedListVoid()
: head(new LinkedListVoidNode(true)),length(0)
{
PVDATA_REFCOUNT_MONITOR_CONSTRUCT(LinkedList);
}
LinkedListVoid::~LinkedListVoid()
{
delete head;
PVDATA_REFCOUNT_MONITOR_DESTRUCT(LinkedList);
}
int LinkedListVoid::getLength()
{
return length;
}
void LinkedListVoid::addTail(LinkedListVoidNode &node)
{
if(node.before!=0 || node.after!=0) {
throw std::logic_error(alreadyOnList);
}
node.linkedListVoid = this;
node.before = head->before;
node.after = head;
head->before->after = &node;
head->before = &node;
++length;
}
void LinkedListVoid::addHead(LinkedListVoidNode &node)
{
if(node.before!=0 || node.after!=0) {
throw std::logic_error(alreadyOnList);
}
node.linkedListVoid = this;
node.after = head->after;
node.before = head;
head->after->before = &node;
head->after = &node;
++length;
}
void LinkedListVoid::insertAfter(LinkedListVoidNode &node,
LinkedListVoidNode &addNode)
{
LinkedListVoidNode *existingNode = &node;
LinkedListVoidNode *newNode = &addNode;
if(existingNode->after==0 || existingNode->before==0) {
throw std::logic_error(String("listNode not on list"));
}
if(newNode->before!=0 || newNode->after!=0) {
throw std::logic_error(alreadyOnList);
}
if(node.linkedListVoid!=this) {
throw std::logic_error(String("node not on this list"));
}
newNode->linkedListVoid = this;
newNode->after = existingNode->after;
newNode->before = existingNode;
existingNode->after->before = newNode;
existingNode->after = newNode;
++length;
}
void LinkedListVoid::insertBefore(LinkedListVoidNode &node,
LinkedListVoidNode &addNode)
{
LinkedListVoidNode *existingNode = &node;
LinkedListVoidNode *newNode = &addNode;
if(existingNode->after==0 || existingNode->before==0) {
throw std::logic_error(String("listNode not on list"));
}
if(newNode->before!=0 || newNode->after!=0) {
throw std::logic_error(alreadyOnList);
}
if(node.linkedListVoid!=this) {
throw std::logic_error(String("node not on this list"));
}
newNode->linkedListVoid = this;
newNode->after = existingNode;
newNode->before = existingNode->before;
existingNode->before->after = newNode;
existingNode->before = newNode;
++length;
}
LinkedListVoidNode *LinkedListVoid::removeTail()
{
if(head->after==head) return 0;
LinkedListVoidNode *node = head->before;
remove(*head->before);
return node;
}
LinkedListVoidNode *LinkedListVoid::removeHead()
{
if(head->after==head) return 0;
LinkedListVoidNode *node = head->after;
remove(*head->after);
return node;
}
void LinkedListVoid::remove(LinkedListVoidNode &node)
{
if(node.before==0 || node.after==0) {
throw std::logic_error(String("node not on list"));
}
if(node.linkedListVoid!=this) {
throw std::logic_error(String("node not on this list"));
}
node.linkedListVoid = 0;
LinkedListVoidNode *prev = node.before;
LinkedListVoidNode *next = node.after;
node.after = node.before = 0;
prev->after = next;
next->before = prev;
length--;
}
LinkedListVoidNode *LinkedListVoid::getHead()
{
if(head->after==head) return 0;
return head->after;
}
LinkedListVoidNode *LinkedListVoid::getTail()
{
if(head->after==head) return 0;
return head->before;
}
LinkedListVoidNode *LinkedListVoid::getNext(LinkedListVoidNode &listNode)
{
if(listNode.linkedListVoid!=this) {
throw std::logic_error(String("node not on this list"));
}
if(listNode.after==head) return 0;
return listNode.after;
}
LinkedListVoidNode *LinkedListVoid::getPrev(LinkedListVoidNode &listNode)
{
if(listNode.linkedListVoid!=this) {
throw std::logic_error(String("node not on this list"));
}
if(listNode.before==head) return 0;
return listNode.before;
}
bool LinkedListVoid::isEmpty()
{
if(head->after==head) return true;
return false;
}
}}

View File

@@ -1,68 +0,0 @@
/* linkedListVoid.h */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#ifndef LINKEDLISTVOID_H
#define LINKEDLISTVOID_H
#include <pv/pvType.h>
namespace epics { namespace pvData {
class LinkedListVoid;
class LinkedListVoidNode;
class LinkedListVoidNode {
public:
~LinkedListVoidNode();
void *getObject();
bool isOnList();
protected:
LinkedListVoidNode(void *object);
private:
LinkedListVoidNode(bool isHead);
friend class LinkedListVoid;
void *object;
LinkedListVoidNode *before;
LinkedListVoidNode *after;
LinkedListVoid *linkedListVoid;
// do not implement the following
LinkedListVoidNode(const LinkedListVoidNode&);
LinkedListVoidNode & operator=(const LinkedListVoidNode&);
};
class LinkedListVoid {
public:
~LinkedListVoid();
int getLength();
void addTail(LinkedListVoidNode &listNode);
void addHead(LinkedListVoidNode &listNode);
void insertAfter(LinkedListVoidNode &listNode,
LinkedListVoidNode &addNode);
void insertBefore(LinkedListVoidNode &listNode,
LinkedListVoidNode &addNode);
LinkedListVoidNode *removeTail();
LinkedListVoidNode *removeHead();
void remove(LinkedListVoidNode &listNode);
LinkedListVoidNode *getHead();
LinkedListVoidNode *getTail();
LinkedListVoidNode *getNext(LinkedListVoidNode &listNode);
LinkedListVoidNode *getPrev(LinkedListVoidNode &listNode);
bool isEmpty();
protected:
LinkedListVoid();
private:
friend class LinkedListVoidNode;
LinkedListVoidNode *head;
int length;
// do not implement the following
LinkedListVoid(const LinkedListVoid&);
LinkedListVoid & operator=(const LinkedListVoid&);
};
}}
#endif /* LINKEDLISTVOID_H */

View File

@@ -1,136 +0,0 @@
/* messageQueue.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#include <cstddef>
#include <cstdlib>
#include <cstddef>
#include <string>
#include <cstdio>
#include <stdexcept>
#include <pv/pvType.h>
#include <pv/lock.h>
#include <pv/requester.h>
#include <pv/noDefaultMethods.h>
#include <pv/CDRMonitor.h>
#include <pv/queue.h>
#include <pv/messageQueue.h>
namespace epics { namespace pvData {
PVDATA_REFCOUNT_MONITOR_DEFINE(messageQueue);
typedef MessageNode * MessageNodePtr;
typedef QueueElement<MessageNode> MessageElement;
typedef MessageElement *MessageElementPtr;
typedef Queue<MessageNode> MessageNodeQueue;
MessageNode::MessageNode()
: message(String()),messageType(infoMessage){}
MessageNode::~MessageNode() {
}
String MessageNode::getMessage() const { return message;};
MessageType MessageNode::getMessageType() const { return messageType;}
void MessageNode::setMessageNull() {message = String();}
class MessageQueuePvt {
public:
MessageNodePtr *messageNodeArray;
MessageNodeQueue *queue;
MessageNodePtr lastPut;
MessageElementPtr lastGet;
int size;
int overrun;
};
MessageQueue::MessageQueue(int size)
: pImpl(new MessageQueuePvt)
{
PVDATA_REFCOUNT_MONITOR_CONSTRUCT(messageQueue);
pImpl->size = size;
pImpl->overrun = 0;
pImpl->lastPut = 0;
pImpl->lastGet = 0;
pImpl->messageNodeArray = new MessageNodePtr[size];
for(int i=0; i<size; i++) {
pImpl->messageNodeArray[i] = new MessageNode();
}
pImpl->queue = new MessageNodeQueue(pImpl->messageNodeArray,size);
}
MessageQueue::~MessageQueue()
{
delete pImpl->queue;
for(int i=0; i< pImpl->size; i++) {
delete pImpl->messageNodeArray[i];
}
delete[] pImpl->messageNodeArray;
PVDATA_REFCOUNT_MONITOR_DESTRUCT(messageQueue);
}
MessageNode *MessageQueue::get() {
if(pImpl->lastGet!=0) {
throw std::logic_error(
String("MessageQueue::get() but did not release last"));
}
MessageElementPtr element = pImpl->queue->getUsed();
if(element==0) return 0;
pImpl->lastGet = element;
return element->getObject();
}
void MessageQueue::release() {
if(pImpl->lastGet==0) return;
pImpl->queue->releaseUsed(pImpl->lastGet);
pImpl->lastGet = 0;
}
bool MessageQueue::put(String message,MessageType messageType,bool replaceLast)
{
MessageElementPtr element = pImpl->queue->getFree();
if(element!=0) {
MessageNodePtr node = element->getObject();
node->message = message;
node->messageType = messageType;
pImpl->lastPut = node;
pImpl->queue->setUsed(element);
return true;
}
pImpl->overrun++;
if(replaceLast) {
MessageNodePtr node = pImpl->lastPut;
node->message = message;
node->messageType = messageType;
}
return false;
}
bool MessageQueue::isEmpty() const
{
int free = pImpl->queue->getNumberFree();
if(free==pImpl->size) return true;
return false;
}
bool MessageQueue::isFull() const
{
if(pImpl->queue->getNumberFree()==0) return true;
return false;
}
int MessageQueue::getClearOverrun()
{
int num = pImpl->overrun;
pImpl->overrun = 0;
return num;
}
}}

View File

@@ -1,48 +0,0 @@
/* messageQueue.h */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#ifndef MESSAGEQUEUE_H
#define MESSAGEQUEUE_H
#include <pv/pvType.h>
#include <pv/requester.h>
#include <pv/noDefaultMethods.h>
namespace epics { namespace pvData {
class MessageNode {
public:
String getMessage() const;
MessageType getMessageType() const;
void setMessageNull();
private:
MessageNode();
~MessageNode();
friend class MessageQueue;
String message;
MessageType messageType;
};
class MessageQueue : private NoDefaultMethods {
public:
MessageQueue(int size);
~MessageQueue();
MessageNode *get();
// must call release before next get
void release();
// return (false,true) if message (was not, was) put into queue
bool put(String message,MessageType messageType,bool replaceLast);
bool isEmpty() const;
bool isFull() const;
int getClearOverrun();
private:
class MessageQueuePvt *pImpl;
};
}}
#endif /* MESSAGEQUEUE_H */

View File

@@ -1,54 +0,0 @@
/* queue.h */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#ifndef QUEUE_H
#define QUEUE_H
#include <pv/queueVoid.h>
namespace epics { namespace pvData {
template <typename T>
class Queue;
template <typename T>
class QueueElement;
template <typename T>
class QueueElement : private QueueElementVoid {
public:
T *getObject() { return static_cast<T *>(QueueElementVoid::getObject());}
protected:
QueueElement(T *object) : QueueElementVoid(static_cast<void *>(object)){}
~QueueElement() {}
friend class Queue<T>;
};
template <typename T>
class Queue : private QueueVoid {
public:
Queue(T *array[],int number)
: QueueVoid((ObjectPtr*)array,number)
//: QueueVoid(static_cast<ObjectPtr*>(array),number)
{}
~Queue() {}
void clear() {QueueVoid::clear();}
int getNumberFree() {return QueueVoid::getNumberFree();}
int capacity() {return QueueVoid::capacity();}
QueueElement<T> *getFree() {
return static_cast<QueueElement<T> *>(QueueVoid::getFree());}
void setUsed(QueueElement<T> *queueElement) {
QueueVoid::setUsed(static_cast<QueueElementVoid *>(queueElement));}
QueueElement<T> *getUsed() {
return static_cast<QueueElement<T> *>(QueueVoid::getUsed());}
void releaseUsed(QueueElement<T> *queueElement) {
QueueVoid::releaseUsed(static_cast<QueueElementVoid *>(queueElement));}
};
}}
#endif /* QUEUE_H */

View File

@@ -1,120 +0,0 @@
/* queueVoid.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#include <cstddef>
#include <cstdlib>
#include <cstddef>
#include <string>
#include <cstdio>
#include <stdexcept>
#include <pv/lock.h>
#include <pv/pvType.h>
#include <pv/queueVoid.h>
#include <pv/CDRMonitor.h>
namespace epics { namespace pvData {
PVDATA_REFCOUNT_MONITOR_DEFINE(queueElement);
PVDATA_REFCOUNT_MONITOR_DEFINE(queue);
QueueElementVoid::QueueElementVoid(ObjectPtr object)
: object(object)
{
PVDATA_REFCOUNT_MONITOR_CONSTRUCT(queueElement);
}
QueueElementVoid::~QueueElementVoid()
{
PVDATA_REFCOUNT_MONITOR_DESTRUCT(queueElement);
}
ObjectPtr QueueElementVoid::getObject() {
return object;
}
QueueVoid::QueueVoid(ObjectPtr object[],int number)
: array(new QueueElementVoidPtr[number]),number(number),
numberFree(number),numberUsed(0),
nextGetFree(0),nextSetUsed(),
nextGetUsed(0),nextReleaseUsed(0)
{
for(int i=0; i<number; i++) {
array[i] = new QueueElementVoid(object[i]);
}
PVDATA_REFCOUNT_MONITOR_CONSTRUCT(queue);
}
QueueVoid::~QueueVoid()
{
for(int i=0; i<number; i++) {
delete array[i];
}
delete[]array;
PVDATA_REFCOUNT_MONITOR_DESTRUCT(queue);
}
void QueueVoid::clear()
{
numberFree = number;
numberUsed = 0;
nextGetFree = 0;
nextSetUsed = 0;
nextGetUsed = 0;
nextReleaseUsed = 0;
}
int QueueVoid::getNumberFree()
{
return numberFree;
}
int QueueVoid::capacity()
{
return number;
}
QueueElementVoid * QueueVoid::getFree()
{
if(numberFree==0) return 0;
numberFree--;
QueueElementVoid *queueElement = array[nextGetFree++];
if(nextGetFree>=number) nextGetFree = 0;
return queueElement;
}
void QueueVoid::setUsed(QueueElementVoid *queueElement)
{
if(queueElement!=array[nextSetUsed++]) {
throw std::logic_error(String("not correct queueElement"));
}
numberUsed++;
if(nextSetUsed>=number) nextSetUsed = 0;
}
QueueElementVoid * QueueVoid::getUsed()
{
if(numberUsed==0) return 0;
QueueElementVoid *queueElement = array[nextGetUsed++];
if(nextGetUsed>=number) nextGetUsed = 0;
return queueElement;
}
void QueueVoid::releaseUsed(QueueElementVoid *queueElement)
{
if(queueElement!=array[nextReleaseUsed++]) {
throw std::logic_error(String(
"not queueElement returned by last call to getUsed"));
}
if(nextReleaseUsed>=number) nextReleaseUsed = 0;
numberUsed--;
numberFree++;
}
}}

View File

@@ -1,56 +0,0 @@
/* queueVoid.h */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#ifndef QUEUEVOID_H
#define QUEUEVOID_H
namespace epics { namespace pvData {
class QueueVoid;
class QueueElementVoid;
typedef void * ObjectPtr;
typedef QueueElementVoid * QueueElementVoidPtr;
typedef QueueElementVoidPtr * QueueElementVoidPtrArray;
class QueueElementVoid {
protected:
ObjectPtr getObject();
QueueElementVoid(ObjectPtr object);
~QueueElementVoid();
ObjectPtr object;
friend class QueueVoid;
};
class QueueVoid {
protected:
QueueVoid(ObjectPtr array[],int number);
~QueueVoid();
void clear();
int getNumberFree();
int capacity();
QueueElementVoidPtr getFree();
void setUsed(QueueElementVoid *queueElement);
QueueElementVoid *getUsed();
void releaseUsed(QueueElementVoid *queueElement);
private:
friend class QueueElementVoid;
QueueElementVoidPtrArray array;
int number;
int numberFree;
int numberUsed;
int nextGetFree;
int nextSetUsed;
int nextGetUsed;
int nextReleaseUsed;
};
}}
#endif /* QUEUEVOID_H */

View File

@@ -1,20 +0,0 @@
/* requester.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#include <string>
#include <pv/requester.h>
namespace epics { namespace pvData {
const size_t messageTypeCount = 4;
static std::string typeName[messageTypeCount] = {
String("info"),
String("warning"),
String("error"),
String("fatalError")
};
StringArray messageTypeName = typeName;
}}

View File

@@ -1,61 +0,0 @@
/* serialize.h */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#ifndef SERIALIZE_H
#define SERIALIZE_H
#include <pv/byteBuffer.h>
namespace epics { namespace pvData {
class SerializableControl;
class DeserializableControl;
class Serializable;
class BitSetSerializable;
class SerializableArray;
class BitSet;
class SerializableControl {
public:
virtual ~SerializableControl(){}
virtual void flushSerializeBuffer() =0;
virtual void ensureBuffer(int size) =0;
virtual void alignBuffer(int alignment) =0;
};
class DeserializableControl {
public:
virtual ~DeserializableControl(){}
virtual void ensureData(int size) =0;
virtual void alignData(int alignment) =0;
};
class Serializable {
public:
virtual ~Serializable(){}
virtual void serialize(ByteBuffer *buffer,
SerializableControl *flusher) const = 0;
virtual void deserialize(ByteBuffer *buffer,
DeserializableControl *flusher) = 0;
};
class BitSetSerializable {
public:
virtual ~BitSetSerializable(){}
virtual void serialize(ByteBuffer *buffer,
SerializableControl *flusher,BitSet *bitSet) const = 0;
virtual void deserialize(ByteBuffer *buffer,
DeserializableControl *flusher,BitSet *bitSet) = 0;
};
class SerializableArray : virtual public Serializable {
public:
virtual ~SerializableArray(){}
virtual void serialize(ByteBuffer *buffer,
SerializableControl *flusher, int offset, int count) const = 0;
};
}}
#endif /* SERIALIZE_H */

View File

@@ -1,31 +0,0 @@
/* timeFunction.h */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#ifndef TIMEFUNCTION_H
#define TIMEFUNCTION_H
#include <pv/noDefaultMethods.h>
#include <pv/pvType.h>
namespace epics { namespace pvData {
class TimeFunctionRequester {
public:
virtual ~TimeFunctionRequester(){}
virtual void function() = 0;
};
class TimeFunction : private NoDefaultMethods {
public:
TimeFunction(TimeFunctionRequester *requester);
~TimeFunction();
double timeCall();
private:
TimeFunctionRequester *requester;
};
}}
#endif /* TIMEFUNCTION_H */

View File

@@ -1,234 +0,0 @@
/* timer.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#include <stddef.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <stdio.h>
#include <stdexcept>
#include <pv/pvType.h>
#include <pv/lock.h>
#include <pv/noDefaultMethods.h>
#include <pv/CDRMonitor.h>
#include <pv/linkedList.h>
#include <pv/thread.h>
#include <pv/timeStamp.h>
#include <pv/timer.h>
#include <pv/event.h>
namespace epics { namespace pvData {
PVDATA_REFCOUNT_MONITOR_DEFINE(timerNode);
PVDATA_REFCOUNT_MONITOR_DEFINE(timer);
typedef LinkedListNode<TimerNode::Pvt> TimerListNode;
typedef LinkedList<TimerNode::Pvt> TimerList;
class TimerNode::Pvt {
public:
TimerNode *timerNode;
TimerCallback *callback;
TimerListNode timerListNode;
TimeStamp timeToRun;
Timer::Pvt *timerPvt;
double period;
Pvt(TimerNode &timerNode,TimerCallback &callback);
~Pvt(){}
private:
};
TimerNode::Pvt::Pvt(TimerNode &timerNode,TimerCallback &callback)
: timerNode(&timerNode),callback(&callback),
timerListNode(*this),timeToRun(),
timerPvt(0), period(0.0)
{}
struct Timer::Pvt : public Runnable{
public:
Pvt(String threadName,ThreadPriority priority);
virtual void run();
public: // only used by this source module
TimerList timerList;
Mutex mutex;
Event waitForWork;
Event waitForDone;
bool alive;
Thread thread;
void addElement(TimerNode::Pvt &node);
};
Timer::Pvt::Pvt(String threadName,ThreadPriority priority)
: timerList(),
mutex(),
waitForWork(false),
waitForDone(false),
alive(true),
thread(threadName,priority,this)
{}
void Timer::Pvt::addElement(TimerNode::Pvt &node)
{
TimerListNode *nextNode = timerList.getHead();
if(nextNode==0) {
timerList.addTail(node.timerListNode);
return;
}
while(true) {
TimerNode::Pvt &timerListNode = nextNode->getObject();
if((node.timeToRun)<(timerListNode.timeToRun)) {
timerList.insertBefore(timerListNode.timerListNode,node.timerListNode);
return;
}
nextNode = timerList.getNext(timerListNode.timerListNode);
if(nextNode==0) {
timerList.addTail(node.timerListNode);
return;
}
}
}
TimerNode::TimerNode(TimerCallback &callback)
: pImpl(new Pvt(*this,callback))
{
PVDATA_REFCOUNT_MONITOR_CONSTRUCT(timerNode);
}
TimerNode::~TimerNode()
{
cancel();
PVDATA_REFCOUNT_MONITOR_DESTRUCT(timerNode);
}
void TimerNode::cancel()
{
Timer::Pvt *timerPvt = pImpl->timerPvt;
if(timerPvt==0) return;
Lock xx(timerPvt->mutex);
if(pImpl->timerPvt==0) return;
pImpl->timerPvt->timerList.remove(pImpl->timerListNode);
pImpl->timerPvt = 0;
}
bool TimerNode::isScheduled()
{
Timer::Pvt *pvt = pImpl->timerPvt;
if(pvt==0) return false;
Lock xx(pvt->mutex);
return pImpl->timerListNode.isOnList();
}
void Timer::Pvt::run()
{
TimeStamp currentTime;
while(true) {
currentTime.getCurrent();
TimeStamp *timeToRun = 0;
double period = 0.0;
TimerNode::Pvt *nodeToCall = 0;
{
Lock xx(mutex);
if (!alive) break;
TimerListNode *timerListNode = timerList.getHead();
if(timerListNode!=0) {
TimerNode::Pvt *timerNodePvt = &timerListNode->getObject();
timeToRun = &timerNodePvt->timeToRun;
double diff = TimeStamp::diff(
*timeToRun,currentTime);
if(diff<=0.0) {
nodeToCall = timerNodePvt;
timerList.removeHead();
period = timerNodePvt->period;
if(period>0.0) {
timerNodePvt->timeToRun += period;
addElement(*timerNodePvt);
} else {
timerNodePvt->timerPvt = 0;
}
timerListNode = timerList.getHead();
if(timerListNode!=0) {
timerNodePvt = &timerListNode->getObject();
timeToRun = &timerNodePvt->timeToRun;
} else {
timeToRun = 0;
}
}
}
}
if(nodeToCall!=0) {
nodeToCall->callback->callback();
}
{
Lock xx(mutex);
if(!alive) break;
}
if(timeToRun==0) {
waitForWork.wait();
} else {
double delay = TimeStamp::diff(*timeToRun,currentTime);
waitForWork.wait(delay);
}
}
waitForDone.signal();
}
Timer::Timer(String threadName, ThreadPriority priority)
: pImpl(new Pvt(threadName,priority))
{
PVDATA_REFCOUNT_MONITOR_CONSTRUCT(timer);
}
Timer::~Timer() {
{
Lock xx(pImpl->mutex);
pImpl->alive = false;
}
pImpl->waitForWork.signal();
pImpl->waitForDone.wait();
TimerListNode *node = 0;
while((node = pImpl->timerList.removeHead())!=0) {
node->getObject().callback->timerStopped();
}
PVDATA_REFCOUNT_MONITOR_DESTRUCT(timer);
}
void Timer::scheduleAfterDelay(TimerNode &timerNode,double delay)
{
schedulePeriodic(timerNode,delay,0.0);
}
void Timer::schedulePeriodic(TimerNode &timerNode,double delay,double period)
{
TimerNode::Pvt *timerNodePvt = timerNode.pImpl.get();
if(timerNodePvt->timerListNode.isOnList()) {
throw std::logic_error(String("already queued"));
}
{
Lock xx(pImpl->mutex);
if(!pImpl->alive) {
timerNodePvt->callback->timerStopped();
return;
}
}
TimeStamp *timeStamp = &timerNodePvt->timeToRun;
timeStamp->getCurrent();
*timeStamp += delay;
timerNodePvt->period = period;
bool isFirst = false;
{
Lock xx(pImpl->mutex);
timerNodePvt->timerPvt = pImpl.get();
pImpl->addElement(*timerNodePvt);
TimerNode::Pvt *first = &pImpl->timerList.getHead()->getObject();
if(first==timerNodePvt) isFirst = true;
}
if(isFirst) pImpl->waitForWork.signal();
}
}}

View File

@@ -1,59 +0,0 @@
/* timer.h */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#ifndef TIMER_H
#define TIMER_H
#include <memory>
#include <stddef.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <stdio.h>
#include <pv/pvType.h>
#include <pv/thread.h>
#include <pv/noDefaultMethods.h>
#include <pv/sharedPtr.h>
namespace epics { namespace pvData {
class Timer;
class TimerCallback {
public:
virtual ~TimerCallback(){}
virtual void callback() = 0;
virtual void timerStopped() = 0;
};
class TimerNode {
public:
TimerNode(TimerCallback &timerCallback);
~TimerNode();
void cancel();
bool isScheduled();
class Pvt;
private:
std::auto_ptr<Pvt> pImpl;
friend class Timer;
};
class Timer : private NoDefaultMethods {
public:
POINTER_DEFINITIONS(Timer);
Timer(String threadName, ThreadPriority priority);
~Timer();
void scheduleAfterDelay(TimerNode &timerNode,double delay);
void schedulePeriodic(TimerNode &timerNode,double delay,double period);
class Pvt;
private:
std::auto_ptr<Pvt> pImpl;
};
}}
#endif /* TIMER_H */

View File

@@ -1,106 +0,0 @@
/* monitor.h */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#ifndef MONITOR_H
#define MONITOR_H
#include <pv/status.h>
#include <pv/destroyable.h>
#include <pv/pvData.h>
#include <pv/sharedPtr.h>
#include <pv/bitSet.h>
namespace epics { namespace pvData {
/**
* Class instance representing monitor element.
* @author mrk
*/
class MonitorElement {
public:
POINTER_DEFINITIONS(MonitorElement);
virtual ~MonitorElement(){}
/**
* Get the PVStructure.
* @return The PVStructure.
*/
virtual PVStructure::shared_pointer const & getPVStructure() = 0;
/**
* Get the bitSet showing which fields have changed.
* @return The bitSet.
*/
virtual BitSet::shared_pointer const & getChangedBitSet() = 0;
/**
* Get the bitSet showing which fields have been changed more than once.
* @return The bitSet.
*/
virtual BitSet::shared_pointer const & getOverrunBitSet() = 0;
};
/**
* Interface for Monitor.
* @author mrk
*/
class Monitor : public Destroyable, private NoDefaultMethods {
public:
POINTER_DEFINITIONS(Monitor);
virtual ~Monitor(){}
/**
* Start monitoring.
* @return completion status.
*/
virtual Status start() = 0;
/**
* Stop Monitoring.
* @return completion status.
*/
virtual Status stop() = 0;
/**
* If monitor has occurred return data.
* @return monitorElement for modified data.
* Must call get to determine if data is available.
*/
virtual MonitorElement::shared_pointer const & poll() = 0;
/**
* Release a MonitorElement that was returned by poll.
* @param monitorElement
*/
virtual void release(MonitorElement::shared_pointer const & monitorElement) = 0;
};
/**
* Requester for ChannelMonitor.
* @author mrk
*/
class MonitorRequester : public virtual Requester {
public:
POINTER_DEFINITIONS(MonitorRequester);
virtual ~MonitorRequester(){}
/**
* The client and server have both completed the createMonitor request.
* @param status Completion status.
* @param monitor The monitor
* @param structure The structure defining the data.
*/
virtual void monitorConnect(Status const &status,
Monitor::shared_pointer const & monitor, StructureConstPtr const & structure) = 0;
/**
* A monitor event has occurred.
* The requester must call Monitor.poll to get data.
* @param monitor The monitor.
*/
virtual void monitorEvent(Monitor::shared_pointer const &monitor) = 0;
/**
* The data source is no longer available.
* @param monitor The monitor.
*/
virtual void unlisten(Monitor::shared_pointer const &monitor) = 0;
};
}}
#endif /* MONITOR_H */

View File

@@ -1,160 +0,0 @@
/* monitorQueue.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
/* Marty Kraimer 2011.03 */
#include <pv/bitSet.h>
#include <pv/monitorQueue.h>
namespace epics { namespace pvData {
typedef QueueElement<MonitorElement::shared_pointer> MonitorQueueElement;
class MonitorElementImpl : public MonitorElement {
public:
MonitorElementImpl(PVStructure::shared_pointer pvStructure);
~MonitorElementImpl(){}
virtual PVStructure::shared_pointer const & getPVStructure();
virtual BitSet::shared_pointer const & getChangedBitSet();
virtual BitSet::shared_pointer const & getOverrunBitSet();
void setQueueElement(MonitorQueueElement *queueElement);
MonitorQueueElement *getQueueElement();
private:
PVStructure::shared_pointer pvStructure;
BitSet::shared_pointer changedBitSet;
BitSet::shared_pointer overrunBitSet;
MonitorQueueElement *queueElement;
};
MonitorElementImpl::MonitorElementImpl(PVStructure::shared_pointer pvStructure)
: pvStructure(pvStructure),
changedBitSet(BitSet::shared_pointer(
new BitSet(pvStructure->getNumberFields()))),
overrunBitSet(BitSet::shared_pointer(
new BitSet(pvStructure->getNumberFields()))),
queueElement(0)
{}
PVStructure::shared_pointer const & MonitorElementImpl::getPVStructure()
{
return pvStructure;
}
BitSet::shared_pointer const & MonitorElementImpl::getChangedBitSet()
{
return changedBitSet;
}
BitSet::shared_pointer const & MonitorElementImpl::getOverrunBitSet()
{
return overrunBitSet;
}
void MonitorElementImpl::setQueueElement(MonitorQueueElement *queueElement)
{
this->queueElement = queueElement;
}
MonitorQueueElement *MonitorElementImpl::getQueueElement()
{
return queueElement;
}
MonitorQueue::MonitorQueue(PVStructureSharedPointerPtrArray structures,int number)
: number(number),
structures(structures),
queue(0),
queueElements(new MonitorElement::shared_pointer*[number]),
nullElement(MonitorElement::shared_pointer())
{
if(number<2) {
throw std::logic_error(String("queueSize must be >=2"));
}
for(int i=0; i<number; i++) {
queueElements[i] = new MonitorElement::shared_pointer(
new MonitorElementImpl(*structures[i]));
}
queue = new Queue<MonitorElement::shared_pointer>(queueElements,number);
MonitorQueueElement *queueElement;
for(int i=0; i<number;i++) {
queueElement = queue->getFree();
MonitorElementImpl * element = static_cast<MonitorElementImpl *>(
queueElement->getObject()->get());
element->setQueueElement(queueElement);
queue->setUsed(queueElement);
queue->releaseUsed(queueElement);
}
}
MonitorQueue::~MonitorQueue()
{
delete queue;
for(int i=0; i<number; i++) {
delete queueElements[i];
}
delete[] queueElements;
for(int i=0; i<number; i++) delete structures[i];
delete[] structures;
}
PVStructureSharedPointerPtrArray MonitorQueue::createStructures(
PVStructurePtrArray array,int number)
{
PVStructureSharedPointerPtrArray elements =
new PVStructureSharedPointerPtr[number];
for(int i=0; i<number; i++){
elements[i] = new PVStructure::shared_pointer(array[i]);
}
delete[] array;
return elements;
}
void MonitorQueue::clear()
{
queue->clear();
}
int MonitorQueue::getNumberFree()
{
return queue->getNumberFree();
}
int MonitorQueue::capacity()
{
return number;
}
MonitorElement::shared_pointer const & MonitorQueue::getFree()
{
MonitorQueueElement *queueElement = queue->getFree();
if(queueElement==0) return nullElement;
return *queueElement->getObject();
}
void MonitorQueue::setUsed(MonitorElement::shared_pointer const & element)
{
MonitorElementImpl *impl = static_cast<MonitorElementImpl *>(element.get());
queue->setUsed(impl->getQueueElement());
}
MonitorElement::shared_pointer const & MonitorQueue::getUsed()
{
MonitorQueueElement *queueElement = queue->getUsed();
if(queueElement==0) return nullElement;
return *queueElement->getObject();
}
void MonitorQueue::releaseUsed(MonitorElement::shared_pointer const & element)
{
MonitorElementImpl *impl = static_cast<MonitorElementImpl *>(element.get());
queue->releaseUsed(impl->getQueueElement());
}
}}

View File

@@ -1,48 +0,0 @@
/* monitorQueue.h */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
/* Marty Kraimer 2011.03 */
#ifndef MONITORQUEUE_H
#define MONITORQUEUE_H
#include <string>
#include <stdexcept>
#include <memory>
#include <vector>
#include <pv/pvData.h>
#include <pv/monitor.h>
#include <pv/queue.h>
#include <pv/sharedPtr.h>
namespace epics { namespace pvData {
typedef PVStructure::shared_pointer* PVStructureSharedPointerPtr;
typedef PVStructureSharedPointerPtr* PVStructureSharedPointerPtrArray;
class MonitorQueue {
public:
MonitorQueue(PVStructureSharedPointerPtrArray structures,int number);
~MonitorQueue();
static PVStructureSharedPointerPtrArray createStructures(
PVStructurePtrArray array,int number);
void clear();
int getNumberFree();
int capacity();
MonitorElement::shared_pointer const & getFree();
void setUsed(MonitorElement::shared_pointer const & element);
MonitorElement::shared_pointer const & getUsed();
void releaseUsed(MonitorElement::shared_pointer const & element);
private:
int number;
PVStructureSharedPointerPtrArray structures;
Queue<MonitorElement::shared_pointer> *queue;
MonitorElement::shared_pointer **queueElements;
MonitorElement::shared_pointer nullElement;
};
}}
#endif /* MONITORQUEUE_H */

View File

@@ -1,108 +0,0 @@
/* alarm.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#include <string>
#include <stdexcept>
#include <pv/pvType.h>
#include <pv/pvIntrospect.h>
#include <pv/pvData.h>
#include <pv/alarm.h>
namespace epics { namespace pvData {
const size_t severityCount = 5;
static String severityNames[severityCount] =
{
String("NONE"),
String("MINOR"),
String("MAJOR"),
String("INVALID"),
String("UNDEFINED")
};
AlarmSeverity AlarmSeverityFunc::getSeverity(int value)
{
if(value<0 || value>4) {
throw std::logic_error(String("getSeverity value is illegal"));
}
switch (value) {
case 0: return noAlarm;
case 1: return minorAlarm;
case 2: return majorAlarm;
case 3: return invalidAlarm;
case 4: return undefinedAlarm;
}
throw std::logic_error(String("should never get here"));
}
StringArray AlarmSeverityFunc::getSeverityNames()
{
return severityNames;
}
AlarmSeverity Alarm::getSeverity() const
{
switch(severity) {
case 0: return noAlarm;
case 1: return minorAlarm;
case 2: return majorAlarm;
case 3: return invalidAlarm;
case 4: return undefinedAlarm;
}
throw std::logic_error(String("should never get here"));
}
const size_t statusCount = 8;
static String statusNames[statusCount] =
{
String("NONE"),
String("DEVICE"),
String("DRIVER"),
String("RECORD"),
String("DB"),
String("CONF"),
String("UNDEFINED"),
String("CLIENT")
};
AlarmStatus AlarmStatusFunc::getStatus(int value)
{
if(value<0 || value>7) {
throw std::logic_error(String("getStatus value is illegal"));
}
switch (value) {
case 0: return noStatus;
case 1: return deviceStatus;
case 2: return driverStatus;
case 3: return recordStatus;
case 4: return dbStatus;
case 5: return confStatus;
case 6: return undefinedStatus;
case 7: return clientStatus;
}
throw std::logic_error(String("should never get here"));
}
StringArray AlarmStatusFunc::getStatusNames()
{
return statusNames;
}
AlarmStatus Alarm::getStatus() const
{
switch(status) {
case 0: return noStatus;
case 1: return deviceStatus;
case 2: return driverStatus;
case 3: return recordStatus;
case 4: return dbStatus;
case 5: return confStatus;
case 6: return undefinedStatus;
case 7: return clientStatus;
}
throw std::logic_error(String("should never get here"));
}
}}

View File

@@ -1,39 +0,0 @@
/* display.h */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#include <string>
#include <pv/pvType.h>
#include <pv/pvData.h>
#ifndef DISPLAY_H
#define DISPLAY_H
namespace epics { namespace pvData {
class Display {
public:
Display()
: description(String("")),format(String("")),units(String("")),
low(0.0),high(0.0) {}
//default constructors and destructor are OK
double getLow() const {return low;}
double getHigh() const{ return high;}
void setLow(double value){low = value;}
void setHigh(double value){high = value;}
String getDescription() const {return description;}
void setDescription(String value) {description = value;}
String getFormat() const {return format;}
void setFormat(String value) {format = value;}
String getUnits() const {return units;}
void setUnits(String value) {units = value;}
private:
String description;
String format;
String units;
double low;
double high;
};
}}
#endif /* DISPLAY_H */

View File

@@ -1,99 +0,0 @@
/* pvAlarm.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#include <string>
#include <stdexcept>
#include <pv/pvType.h>
#include <pv/pvIntrospect.h>
#include <pv/pvData.h>
#include <pv/pvAlarm.h>
namespace epics { namespace pvData {
static String noAlarmFound("No alarm structure found");
static String notAttached("Not attached to an alarm structure");
bool PVAlarm::attach(PVField *pvField)
{
PVStructure *pvStructure = 0;
if(pvField->getField()->getFieldName().compare("alarm")!=0) {
if(pvField->getField()->getFieldName().compare("value")!=0) {
pvField->message(noAlarmFound,errorMessage);
return false;
}
PVStructure *pvParent = pvField->getParent();
if(pvParent==0) {
pvField->message(noAlarmFound,errorMessage);
return false;
}
pvStructure = pvParent->getStructureField(String("alarm"));
if(pvStructure==0) {
pvField->message(noAlarmFound,errorMessage);
return false;
}
} else {
if(pvField->getField()->getType()!=structure) {
pvField->message(noAlarmFound,errorMessage);
return false;
}
pvStructure = static_cast<PVStructure*>(pvField);
}
PVInt *pvInt = pvStructure->getIntField(String("severity"));
if(pvInt==0) {
pvField->message(noAlarmFound,errorMessage);
return false;
}
pvSeverity = pvInt;
pvInt = pvStructure->getIntField(String("status"));
if(pvInt==0) {
pvField->message(noAlarmFound,errorMessage);
return false;
}
pvStatus = pvInt;
PVString *pvString = pvStructure->getStringField(String("message"));
if(pvInt==0) {
pvField->message(noAlarmFound,errorMessage);
return false;
}
pvMessage = pvString;
return true;
}
void PVAlarm::detach()
{
pvSeverity = 0;
pvStatus = 0;
pvMessage = 0;
}
bool PVAlarm::isAttached()
{
if(pvSeverity==0 || pvMessage==0) return false;
return true;
}
void PVAlarm::get(Alarm & alarm) const
{
if(pvSeverity==0 || pvMessage==0) {
throw std::logic_error(notAttached);
}
alarm.setSeverity(AlarmSeverityFunc::getSeverity(pvSeverity->get()));
alarm.setStatus(AlarmStatusFunc::getStatus(pvStatus->get()));
alarm.setMessage(pvMessage->get());
}
bool PVAlarm::set(Alarm const & alarm)
{
if(pvSeverity==0 || pvMessage==0) {
throw std::logic_error(notAttached);
}
if(pvSeverity->isImmutable() || pvMessage->isImmutable()) return false;
pvSeverity->put(alarm.getSeverity());
pvStatus->put(alarm.getStatus());
pvMessage->put(alarm.getMessage());
return true;
}
}}

View File

@@ -1,90 +0,0 @@
/* pvControl.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#include <string>
#include <stdexcept>
#include <pv/pvType.h>
#include <pv/pvIntrospect.h>
#include <pv/pvData.h>
#include <pv/pvControl.h>
namespace epics { namespace pvData {
static String noControlFound("No control structure found");
static String notAttached("Not attached to an control structure");
bool PVControl::attach(PVField *pvField)
{
PVStructure *pvStructure = 0;
if(pvField->getField()->getFieldName().compare("control")!=0) {
if(pvField->getField()->getFieldName().compare("value")!=0) {
pvField->message(noControlFound,errorMessage);
return false;
}
PVStructure *pvParent = pvField->getParent();
if(pvParent==0) {
pvField->message(noControlFound,errorMessage);
return false;
}
pvStructure = pvParent->getStructureField(String("control"));
if(pvStructure==0) {
pvField->message(noControlFound,errorMessage);
return false;
}
} else {
if(pvField->getField()->getType()!=structure) {
pvField->message(noControlFound,errorMessage);
return false;
}
pvStructure = static_cast<PVStructure*>(pvField);
}
PVDouble *pvDouble = pvStructure->getDoubleField(String("limit.low"));
if(pvDouble==0) {
pvField->message(noControlFound,errorMessage);
return false;
}
pvLow = pvDouble;
pvDouble = pvStructure->getDoubleField(String("limit.high"));
if(pvDouble==0) {
pvLow = 0;
pvField->message(noControlFound,errorMessage);
return false;
}
pvHigh = pvDouble;
return true;
}
void PVControl::detach()
{
pvLow = 0;
pvHigh = 0;
}
bool PVControl::isAttached(){
if(pvLow==0 || pvHigh==0) return false;
return true;
}
void PVControl::get(Control &control) const
{
if(pvLow==0 || pvHigh==0) {
throw std::logic_error(notAttached);
}
control.setLow(pvLow->get());
control.setHigh(pvHigh->get());
}
bool PVControl::set(Control const & control)
{
if(pvLow==0 || pvHigh==0) {
throw std::logic_error(notAttached);
}
if(pvLow->isImmutable() || pvHigh->isImmutable()) return false;
pvLow->put(control.getLow());
pvHigh->put(control.getHigh());
return true;
}
}}

View File

@@ -1,119 +0,0 @@
/* pvDisplay.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#include <string>
#include <stdexcept>
#include <pv/pvType.h>
#include <pv/pvIntrospect.h>
#include <pv/pvData.h>
#include <pv/pvDisplay.h>
namespace epics { namespace pvData {
static String noDisplayFound("No display structure found");
static String notAttached("Not attached to an display structure");
bool PVDisplay::attach(PVField *pvField)
{
PVStructure *pvStructure = 0;
if(pvField->getField()->getFieldName().compare("display")!=0) {
if(pvField->getField()->getFieldName().compare("value")!=0) {
pvField->message(noDisplayFound,errorMessage);
return false;
}
PVStructure *pvParent = pvField->getParent();
if(pvParent==0) {
pvField->message(noDisplayFound,errorMessage);
return false;
}
pvStructure = pvParent->getStructureField(String("display"));
if(pvStructure==0) {
pvField->message(noDisplayFound,errorMessage);
return false;
}
} else {
if(pvField->getField()->getType()!=structure) {
pvField->message(noDisplayFound,errorMessage);
return false;
}
pvStructure = static_cast<PVStructure*>(pvField);
}
pvDescription = pvStructure->getStringField(String("description"));
if(pvDescription==0) {
pvField->message(noDisplayFound,errorMessage);
return false;
}
pvFormat = pvStructure->getStringField(String("format"));
if(pvFormat==0) {
pvField->message(noDisplayFound,errorMessage);
detach();
return false;
}
pvUnits = pvStructure->getStringField(String("units"));
if(pvUnits==0) {
pvField->message(noDisplayFound,errorMessage);
detach();
return false;
}
pvLow = pvStructure->getDoubleField(String("limit.low"));
if(pvLow==0) {
pvField->message(noDisplayFound,errorMessage);
detach();
return false;
}
pvHigh = pvStructure->getDoubleField(String("limit.high"));
if(pvHigh==0) {
pvField->message(noDisplayFound,errorMessage);
detach();
return false;
}
return true;
}
void PVDisplay::detach()
{
pvDescription = 0;
pvFormat = 0;
pvUnits = 0;
pvLow = 0;
pvHigh = 0;
}
bool PVDisplay::isAttached() {
if(pvDescription==0 || pvFormat==0 || pvUnits==0 || pvLow==0 || pvHigh==0)
return false;
return true;
}
void PVDisplay::get(Display & display) const
{
if(pvDescription==0 || pvFormat==0 || pvUnits==0 || pvLow==0 || pvHigh==0) {
throw std::logic_error(notAttached);
}
display.setDescription(pvDescription->get());
display.setFormat(pvFormat->get());
display.setUnits(pvUnits->get());
display.setLow(pvLow->get());
display.setHigh(pvHigh->get());
}
bool PVDisplay::set(Display const & display)
{
if(pvDescription==0 || pvFormat==0 || pvUnits==0 || pvLow==0 || pvHigh==0) {
throw std::logic_error(notAttached);
}
if(pvDescription->isImmutable() || pvFormat->isImmutable()) return false;
if(pvUnits->isImmutable() || pvLow->isImmutable() || pvHigh->isImmutable())
return false;
pvDescription->put(display.getDescription());
pvFormat->put(display.getFormat());
pvUnits->put(display.getUnits());
pvLow->put(display.getLow());
pvHigh->put(display.getHigh());
return true;
}
}}

View File

@@ -1,120 +0,0 @@
/* pvEnumerated.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#include <string>
#include <stdexcept>
#include <pv/pvType.h>
#include <pv/pvIntrospect.h>
#include <pv/pvData.h>
#include <pv/pvEnumerated.h>
namespace epics { namespace pvData {
static String notStructure("field is not a structure");
static String notEnumerated("field is not an enumerated structure");
static String notAttached("Not attached to an enumerated structure");
bool PVEnumerated::attach(PVField *pvField)
{
if(pvField->getField()->getType()!=structure) {
pvField->message(notStructure,errorMessage);
return false;
}
PVStructure *pvStructure = static_cast<PVStructure*>(pvField);
PVInt *pvInt = pvStructure->getIntField(String("index"));
if(pvInt==0) {
pvField->message(notEnumerated,errorMessage);
return false;
}
PVScalarArray *pvScalarArray = pvStructure->getScalarArrayField(
String("choices"),pvString);
if(pvScalarArray==0) {
pvField->message(notEnumerated,errorMessage);
return false;
}
pvIndex = pvInt;
pvChoices = static_cast<PVStringArray *>(pvScalarArray);
return true;
}
void PVEnumerated::detach()
{
pvIndex = 0;
pvChoices = 0;
}
bool PVEnumerated::isAttached() {
if(pvIndex==0 || pvChoices==0) return false;
return true;
}
bool PVEnumerated::setIndex(int32 index)
{
if(pvIndex==0 || pvChoices==0) {
throw std::logic_error(notAttached);
}
if(pvIndex->isImmutable()) return false;
pvIndex->put(index);
return true;
}
int32 PVEnumerated::getIndex()
{
if(pvIndex==0 || pvChoices==0) {
throw std::logic_error(notAttached);
}
return pvIndex->get();
}
String PVEnumerated::getChoice()
{
if(pvIndex==0 || pvChoices==0) {
throw std::logic_error(notAttached);
}
int index = pvIndex->get();
StringArrayData data;
pvChoices->get(0,pvChoices->getLength(),&data);
return data.data[index];
}
bool PVEnumerated::choicesMutable()
{
if(pvIndex==0 || pvChoices==0) {
throw std::logic_error(notAttached);
}
return pvChoices->isImmutable();
}
StringArray PVEnumerated:: getChoices()
{
if(pvIndex==0 || pvChoices==0) {
throw std::logic_error(notAttached);
}
StringArrayData data;
pvChoices->get(0,pvChoices->getLength(),&data);
return data.data;
}
int32 PVEnumerated::getNumberChoices()
{
if(pvIndex==0 || pvChoices==0) {
throw std::logic_error(notAttached);
}
return pvChoices->getLength();
}
bool PVEnumerated:: setChoices(StringArray choices,int32 numberChoices)
{
if(pvIndex==0 || pvChoices==0) {
throw std::logic_error(notAttached);
}
if(pvChoices->isImmutable()) return false;
pvChoices->put(0,numberChoices,choices,0);
return true;
}
}}

View File

@@ -1,105 +0,0 @@
/* pvTimeStamp.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#include <string>
#include <stdexcept>
#include <pv/pvType.h>
#include <pv/timeStamp.h>
#include <pv/pvData.h>
#include <pv/pvTimeStamp.h>
namespace epics { namespace pvData {
static String noTimeStamp("No timeStamp structure found");
static String notAttached("Not attached to a timeStamp structure");
bool PVTimeStamp::attach(PVField *pvField)
{
PVStructure *pvStructure = 0;
if(pvField->getField()->getFieldName().compare("timeStamp")!=0) {
PVStructure *pvParent = pvField->getParent();
if(pvParent==0) {
pvField->message(noTimeStamp,errorMessage);
return false;
}
if(pvField->getField()->getFieldName().compare("value")!=0) {
pvField->message(noTimeStamp,errorMessage);
return false;
}
// look up the tree for a timeSyamp
while(pvParent!=0) {
PVStructure *pvs = pvParent->getStructureField(String("timeStamp"));
if(pvs!=0) {
pvStructure = pvs;
break;
}
pvParent = pvParent->getParent();
}
if(pvStructure==0) {
pvField->message(noTimeStamp,errorMessage);
return false;
}
} else {
if(pvField->getField()->getType()!=structure) {
pvField->message(noTimeStamp,errorMessage);
return false;
}
pvStructure = static_cast<PVStructure*>(pvField);
}
PVLong *pvLong = pvStructure->getLongField(String("secondsPastEpoch"));
if(pvLong==0) {
pvField->message(noTimeStamp,errorMessage);
return false;
}
pvSecs = pvLong;
PVInt *pvInt = pvStructure->getIntField(String("nanoSeconds"));
if(pvLong==0) {
pvField->message(noTimeStamp,errorMessage);
return false;
}
pvNano = pvInt;
pvInt = pvStructure->getIntField(String("userTag"));
if(pvInt==0) {
pvField->message(noTimeStamp,errorMessage);
return false;
}
pvUserTag = pvInt;
return true;
}
void PVTimeStamp::detach()
{
pvSecs = 0;
pvUserTag = 0;
pvNano = 0;
}
bool PVTimeStamp::isAttached() {
if(pvSecs==0 || pvNano==0) return false;
return true;
}
void PVTimeStamp::get(TimeStamp & timeStamp) const
{
if(pvSecs==0 || pvNano==0) {
throw std::logic_error(notAttached);
}
timeStamp.put(pvSecs->get(),pvNano->get());
timeStamp.setUserTag(pvUserTag->get());
}
bool PVTimeStamp::set(TimeStamp const & timeStamp)
{
if(pvSecs==0 || pvNano==0 || pvUserTag==0) {
throw std::logic_error(notAttached);
}
if(pvSecs->isImmutable() || pvNano->isImmutable()) return false;
pvSecs->put(timeStamp.getSecondsPastEpoch());
pvUserTag->put(timeStamp.getUserTag());
pvNano->put(timeStamp.getNanoSeconds());
return true;
}
}}

View File

@@ -1,492 +0,0 @@
/* convert.h */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* Author - Marty Kraimer
*/
#ifndef CONVERT_H
#define CONVERT_H
#include <string>
#include <stdexcept>
#include <pv/pvIntrospect.h>
#include <pv/pvData.h>
#include <vector>
namespace epics { namespace pvData {
bool operator==(PVField&, PVField&);
static inline bool operator!=(PVField& a, PVField& b)
{return !(a==b);}
bool operator==(const Field&, const Field&);
bool operator==(const Scalar&, const Scalar&);
bool operator==(const ScalarArray&, const ScalarArray&);
bool operator==(const Structure&, const Structure&);
bool operator==(const StructureArray&, const StructureArray&);
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);}
/**
* 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
* numeric types. It is not possible to convert between a scalar
* and an array.
* Numeric conversions are between types:
* pvByte, pvShort, pvInt,
* pvLong, pvFloat, or pvDouble.</p>
*
* <p>getString converts any supported type to a String.
* Code that implements a PVField interface can implement
* method toString by calling this method.</p>
*
* <p>fromString converts a String to a scalar.
* fromStringArray converts an array of String
* to a pvArray, which must have a scaler element type.
* A scalar field is a numeric field or pvBoolean or pvString.</p>
* <p>All from methods put data into a PVField, e.g. from means where the PVField gets it's data.</p>
*/
class Convert : NoDefaultMethods {
public:
Convert();
~Convert();
/**
* Get the full fieldName for the pvField.
* @param builder The builder that will have the result.
* @param pvField The pvField.
*/
void getFullName(StringBuilder buf,PVField *pvField);
/**
* Do fields have the same definition.
*
* @param First field
* @param Second field
* @return (false, true) if the fields (are not, are) the same.
*/
bool equals(PVField &a,PVField &b);
/**
* 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
*/
void getString(StringBuilder buf,PVField * 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.
*/
void getString(StringBuilder buf,PVField *pvField);
/**
* Convert from an array of String to a PVScalar
* @param pv The PV.
* @param from The array of String value to convert and put into a PV.
* @param fromStartIndex The first element if the array of strings.
* @throws std::logic_error if the array of String does not have a valid values.
*/
int fromString(PVStructure *pv, std::vector<String>& from, int fromStartIndex = 0);
/**
* Convert from a String to a PVScalar
* @param pv The PV.
* @param from The String value to convert and put into a PV.
* @throws std::logic_error if the String does not have a valid value.
*/
void fromString(PVScalar *pv, String from);
/**
* Convert from a String to a PVScalarArray.
* The String must be a comma separated set of values optionally enclosed in []
* @param pv The PV.
* @param from The String value to convert and put into a PV.
* @return The number of elements converted.
* @throws std::invalid_argument if the element Type is not a scalar.
* @throws std::logic_error if the String does not have a valid array values.
*/
int fromString(PVScalarArray *pv, String from);
/**
* Convert a PVScalarArray from a String array.
* The array element type must be a scalar.
* @param pv The PV.
* @param offset Starting element in a PV.
* @param length The number of elements to transfer.
* @param from The array of values to put into the PV.
* @param fromOffset Starting element in the source array.
* @return The number of elements converted.
* @throws std::invalid_argument if the element Type is not a scalar.
* @throws std::logic_error if the String does not have a valid value.
*/
int fromStringArray(PVScalarArray *pv, int offset, int length,
StringArray from, int fromOffset);
/**
* Convert a PVScalarArray to a String array.
* @param pv The PV.
* @param offset Starting element in the PV array.
* @param length Number of elements to convert to the string array.
* @param to String array to receive the converted PV data.
* @param toOffset Starting element in the string array.
* @return Number of elements converted.
*/
int toStringArray(PVScalarArray *pv, int offset, int length,
StringArray to, int 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 from, FieldConstPtr 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(PVField *from,PVField *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 from, ScalarConstPtr 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(PVScalar *from, PVScalar *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 from,
ScalarArrayConstPtr to);
/**
* Convert from a source PV array to a destination PV array.
* @param from The source array.
* @param offset Starting element in the source.
* @param to The destination array.
* @param toOffset Starting element in the array.
* @param length Number of elements to transfer.
* @return Number of elements converted.
* @throws std::invalid_argument if the arguments are not compatible.
*/
int copyScalarArray(PVScalarArray *from, int offset,
PVScalarArray *to, int toOffset, int length);
/**
* 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 from, StructureConstPtr 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(PVStructure *from, PVStructure *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 from, StructureArrayConstPtr to);
/**
* Copy from a structure array to another structure array.
* @param from The source array.
* @param to The destination array.
*/
void copyStructureArray(
PVStructureArray *from, PVStructureArray *to);
/**
* Convert a PV to a <byte>.
* @param pv a PV
* @return converted value
*/
int8 toByte(PVScalar *pv);
/**
* Convert a PV to a short.
* @param pv a PV
* @return converted value
* @throws std::invalid_argument if the Type is not a numeric scalar
*/
int16 toShort(PVScalar *pv);
/**
* Convert a PV to a short.
* @param pv a PV
* @return converted value
* @throws std::invalid_argument if the Type is not a numeric scalar
*/
int32 toInt(PVScalar *pv);
/**
* Convert a PV to an int
* @param pv a PV
* @return converted value
* @throws std::invalid_argument if the Type is not a numeric scalar
*/
int64 toLong(PVScalar *pv);
/**
* Convert a PV to a float
* @param pv a PV
* @return converted value
* @throws std::invalid_argument if the Type is not a numeric scalar
*/
float toFloat(PVScalar *pv);
/**
* Convert a PV to a double
* @param pv a PV
* @return converted value
* @throws std::invalid_argument if the Type is not a numeric scalar
*/
double toDouble(PVScalar *pv);
/**
* Convert a PV to a String
* @param pv a PV
* @return converted value
*/
String toString(PVScalar *pv);
/**
* Convert a PV from a byte
* @param pv a PV
* @param from value to put into PV
* @throws std::invalid_argument if the Type is not a numeric scalar
*/
void fromByte(PVScalar *pv,int8 from);
/**
* Convert a PV from a short
* @param pv a PV
* @param from value to put into PV
* @throws std::invalid_argument if the Type is not a numeric scalar
*/
void fromShort(PVScalar *pv,int16 from);
/**
* Convert a PV from an int
* @param pv a PV
* @param from value to put into PV
* @throws std::invalid_argument if the Type is not a numeric scalar
*/
void fromInt(PVScalar *pv, int32 from);
/**
* Convert a PV from a long
* @param pv a PV
* @param from value to put into PV
* @throws std::invalid_argument if the Type is not a numeric scalar
*/
void fromLong(PVScalar *pv, int64 from);
/**
* Convert a PV from a float
* @param pv a PV
* @param from value to put into PV
* @throws std::invalid_argument if the Type is not a numeric scalar
*/
void fromFloat(PVScalar* pv, float from);
/**
* Convert a PV from a double
* @param pv a PV
* @param from value to put into PV
* @throws std::invalid_argument if the Type is not a numeric scalar
*/
void fromDouble(PVScalar *pv, double from);
/**
* Convert a PV array to a byte array.
* @param pv a PV
* @param offset starting element in a PV
* @param length number of elements to transfer
* @param to where to put the PV data
* @param toOffset starting element in the array
* @return number of elements converted
* @throws std::invalid_argument if the element type is not numeric
*/
int toByteArray(PVScalarArray *pv, int offset, int length,
ByteArray to, int toOffset);
/**
* Convert a PV array to a short array.
* @param pv a PV
* @param offset starting element in a PV
* @param length number of elements to transfer
* @param to where to put the PV data
* @param toOffset starting element in the array
* @return number of elements converted
* @throws std::invalid_argument if the element type is not numeric
*/
int toShortArray(PVScalarArray *pv, int offset, int length,
ShortArray to, int toOffset);
/**
* Convert a PV array to an int array.
* @param pv a PV
* @param offset starting element in a PV
* @param length number of elements to transfer
* @param to where to put the PV data
* @param toOffset starting element in the array
* @return number of elements converted
* @throws std::invalid_argument if the element type is not numeric
*/
int toIntArray(PVScalarArray *pv, int offset, int length,
IntArray to, int toOffset);
/**
* Convert a PV array to a long array.
* @param pv a PV
* @param offset starting element in a PV
* @param length number of elements to transfer
* @param to where to put the PV data
* @param toOffset starting element in the array
* @return number of elements converted
* @throws std::invalid_argument if the element type is not numeric
*/
int toLongArray(PVScalarArray *pv, int offset, int length,
LongArray to, int toOffset);
/**
* Convert a PV array to a float array.
* @param pv a PV
* @param offset starting element in a PV
* @param length number of elements to transfer
* @param to where to put the PV data
* @param toOffset starting element in the array
* @return number of elements converted
* @throws std::invalid_argument if the element type is not numeric
*/
int toFloatArray(PVScalarArray *pv, int offset, int length,
FloatArray to, int toOffset);
/**
* Convert a PV array to a double array.
* @param pv a PV
* @param offset starting element in a PV
* @param length number of elements to transfer
* @param to where to put the PV data
* @param toOffset starting element in the array
* @return number of elements converted
* @throws std::invalid_argument if the element type is not numeric
*/
int toDoubleArray(PVScalarArray *pv, int offset, int length,
DoubleArray to, int toOffset);
/**
* Convert a PV array from a byte array.
* @param pv a PV
* @param offset starting element in a PV
* @param length number of elements to transfer
* @param from value to put into PV
* @param fromOffset
* @return number of elements converted
* @throws std::invalid_argument if the element type is not numeric
*/
int fromByteArray(PVScalarArray *pv, int offset, int length,
ByteArray from, int fromOffset);
/**
* Convert a PV array from a short array.
* @param pv a PV
* @param offset starting element in a PV
* @param length number of elements to transfer
* @param from value to put into PV
* @param fromOffset starting element in the source array
* @return number of elements converted
* @throws std::invalid_argument if the element type is not numeric
*/
int fromShortArray(PVScalarArray *pv, int offset, int length,
ShortArray from, int fromOffset);
/**
* Convert a PV array from an int array.
* @param pv a PV
* @param offset starting element in a PV
* @param length number of elements to transfer
* @param from value to put into PV
* @param fromOffset starting element in the source array
* @return number of elements converted
* @throws std::invalid_argument if the element type is not numeric
*/
int fromIntArray(PVScalarArray *pv, int offset, int length,
IntArray from, int fromOffset);
/**
* Convert a PV array from a long array.
* @param pv a PV
* @param offset starting element in a PV
* @param length number of elements to transfer
* @param from value to put into PV
* @param fromOffset starting element in the source array
* @return number of elements converted
* @throws std::invalid_argument if the element type is not numeric
*/
int fromLongArray(PVScalarArray *pv, int offset, int length,
LongArray from, int fromOffset);
/**
* Convert a PV array from a float array.
* @param pv a PV
* @param offset starting element in a PV
* @param length number of elements to transfer
* @param from value to put into PV
* @param fromOffset starting element in the source array
* @return number of elements converted
* @throws std::invalid_argument if the element type is not numeric
*/
int fromFloatArray(PVScalarArray *pv, int offset, int length,
FloatArray from, int fromOffset);
/**
* Convert a PV array from a double array.
* @param pv a PV
* @param offset starting element in a PV
* @param length number of elements to transfer
* @param from value to put into PV
* @param fromOffset starting element in the source array
* @return number of elements converted
* @throws std::invalid_argument if the element type is not numeric
*/
int fromDoubleArray(PVScalarArray *pv, int offset, int length,
DoubleArray from, int fromOffset);
/**
* Convenience method for implementing toString.
* It generates a newline and inserts blanks at the beginning of the newline.
* @param builder The StringBuilder being constructed.
* @param indentLevel Indent level, Each level is four spaces.
*/
void newLine(StringBuilder buf, int indentLevel);
};
extern Convert * getConvert();
}}
#endif /* CONVERT_H */

View File

@@ -1,855 +0,0 @@
/* pvData.h */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* Author - Marty Kraimer
*/
#ifndef PVDATA_H
#define PVDATA_H
#include <string>
#include <stdexcept>
#include <pv/pvType.h>
#include <pv/pvIntrospect.h>
#include <pv/noDefaultMethods.h>
#include <pv/requester.h>
#include <pv/byteBuffer.h>
#include <pv/serialize.h>
namespace epics { namespace pvData {
class PVAuxInfo;
class PostHandler;
class PVField;
class PVScalar;
class PVScalarArray;
class PVStructure;
class PVStructureArray;
/**
* typedef for a pointer to a PVStructure.
*/
typedef PVStructure * PVStructurePtr;
/**
* typedef for a pointer to a array of pointer to PVStructure.
*/
typedef PVStructurePtr* PVStructurePtrArray;
/**
* typedef for a pointer to a PVField.
*/
typedef PVField* PVFieldPtr;
/**
* typedef for a pointer to a array of pointer to PVField.
*/
typedef PVFieldPtr * PVFieldPtrArray;
/**
* This class provides auxillary information about a PVField.
* Each item is stored as a PVScalar.
* A (key,value) is provided for accessing the items where the key is a String.
*/
class PVAuxInfo : private NoDefaultMethods {
public:
/**
* Constructor
* @param The fields to which the Auxinfo is attached.
*/
PVAuxInfo(PVField *pvField);
/**
* Destructor
*/
~PVAuxInfo();
/**
* Get the PVField to which the Auxinfo is attached.
* @return The fields to which the Auxinfo is attached.
*/
PVField * getPVField();
/**
* Add a new auxiliary item or retrieve the interface to an existing item.
*
* @param key The key.
* @param scalarType The scalrType for the new item being added/
* @return The new PVScalar that has been added to the Auxinfo.
*/
PVScalar * createInfo(String key,ScalarType scalarType);
/**
* Get the number of PVScalars in the Auxinfo.
* @return The number.
*/
int getNumberInfo();
/**
* Get the Auxinfo with the specified key.
* @return The PVScalar or null if it does not exist.
*/
PVScalar * getInfo(String key);
/**
* Get the Auxinfo with the specified index.
* @return The PVScalar or null if it does not exist.
*/
PVScalar * getInfo(int index);
/**
* Convert the Auxinfo to a string and add it to builder.
* @param builder The string builder.
*/
void toString(StringBuilder buf);
/**
* Convert the Auxinfo to a string and add it to builder.
* @param builder The string builder.
* @param indentLevel The number of blanks at the beginning of new lines.
*/
void toString(StringBuilder buf,int indentLevel);
private:
PVField *pvField;
int lengthInfo;
int numberInfo;
PVScalar **pvInfos; // ptr to array of PVscalar *
friend class PVDataCreate;
};
/**
* This class is implemented by code that calls setPostHander
*/
class PostHandler {
public:
/**
* Destructor
*/
virtual ~PostHandler(){}
/**
* This is called evertime postPut is called for this field.
*/
virtual void postPut() = 0;
};
/**
* PVField is the base class for each PVData field.
* Each PVData field has an interface that extends PVField.
*/
class PVField
: virtual public Serializable,
private NoDefaultMethods
{
public:
POINTER_DEFINITIONS(PVField);
/**
* Destructor
*/
virtual ~PVField();
/**
* Called to report errors associated with the field.
* @param message The message.
* @param messageType The message type.
*/
virtual void message(String message,MessageType messageType) ;
/**
* Register the message requester.
* At most one requester can be registered.
* @param prequester The requester.
*/
virtual void setRequester(Requester *prequester);
/**
* 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 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.
*/
int getFieldOffset() ;
/**
* Get the next offset. If the field is a scalar or array field then this is just offset + 1.
* If the field is a structure it is the offset of the next field after this structure.
* Thus (nextOffset - offset) is always equal to the number of fields within the field.
* @return The offset.
*/
int getNextFieldOffset() ;
/**
* Get the total number of fields in this field.
* This is equal to nextFieldOffset - fieldOffset.
*/
int getNumberFields() ;
/**
* Get the PVAuxInfo interface for the PVField.
* @return The PVAuxInfo interface.
*/
PVAuxInfo * getPVAuxInfo();
/**
* Is the field immutable, i.e. does it not allow changes.
* @return (false,true) if it (is not, is) immutable.
*/
bool isImmutable() ;
/**
* 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.
*/
virtual void setImmutable();
/**
* Get the <i>Field</i> that describes the field.
* @return Field, which is the reflection interface.
*/
FieldConstPtr getField() ;
/**
* Get the parent of this field.
* @return The parent interface or null if this is PVRecord
*/
PVStructure * getParent() ;
/**
* Rename the field name.
* @param newName The new name.
*/
bool renameField(String newName);
/**
* postPut. Called when the field is updated by the implementation.
*/
void postPut() ;
/**
* Set the handler for postPut.
* At most one handler can be set.
* @param postHandler The handler.
*/
void setPostHandler(PostHandler *postHandler);
/**
* Is this field equal to another field.
* @param pv other field
* @return (false,true) if (is not,is) equal.
*/
virtual bool equals(PVField &pv);
/**
* Convert the PVField to a string.
* @param buf buffer for the result
*/
virtual void toString(StringBuilder buf) ;
/**
* Convert the PVField to a string.
* Each line is indented.
* @param buf buffer for the result
* @param indentLevel The indentation level.
*/
virtual void toString(StringBuilder buf,int indentLevel) ;
protected:
PVField(PVStructure *parent,FieldConstPtr field);
void setParent(PVStructure * parent);
private:
void message(String fieldName,String message,MessageType messageType);
class PVFieldPvt *pImpl;
static void computeOffset(PVField *pvField);
static void computeOffset(PVField *pvField,int offset);
friend class PVDataCreate;
friend class PVStructure;
};
/**
* PVScalar is the base class for each scalar field.
*/
class PVScalar : public PVField {
public:
POINTER_DEFINITIONS(PVScalar);
/**
* Destructor
*/
virtual ~PVScalar();
/**
* Get the Scalar introspection interface for the PVScalar.
* @return the interface.
*/
ScalarConstPtr getScalar() ;
protected:
PVScalar(PVStructure *parent,ScalarConstPtr scalar);
};
/**
* Class that holds the data for each posssible scalar type.
*/
template<typename T>
class PVScalarValue : public PVScalar {
public:
POINTER_DEFINITIONS(PVScalarValue);
typedef T value_type;
typedef T* pointer;
typedef const T* const_pointer;
/**
* Destructor
*/
virtual ~PVScalarValue() {}
/**
* Get the value.
* @return The value.
*/
virtual T get() = 0;
/**
* Put a new value into the PVScalar.
* @param The value.
*/
virtual void put(T value) = 0;
protected:
PVScalarValue(PVStructure *parent,ScalarConstPtr scalar)
: PVScalar(parent,scalar) {}
private:
};
/**
* typedefs for the various possible scalar types.
*/
typedef PVScalarValue<bool> PVBoolean;
typedef PVScalarValue<int8> PVByte;
typedef PVScalarValue<int16> PVShort;
typedef PVScalarValue<int32> PVInt;
typedef PVScalarValue<int64> PVLong;
typedef PVScalarValue<float> PVFloat;
typedef PVScalarValue<double> PVDouble;
/**
* PVString is special case, since it implements SerializableArray
*/
class PVString : public PVScalarValue<String>, SerializableArray {
public:
/**
* Destructor
*/
virtual ~PVString() {}
protected:
PVString(PVStructure *parent,ScalarConstPtr scalar)
: PVScalarValue<String>(parent,scalar) {}
};
/**
* PVArray is the base class for all array types, i.e. the scalarArray types and structureArray.
*/
class PVArray : public PVField, public SerializableArray {
public:
POINTER_DEFINITIONS(PVArray);
/**
* Destructor
*/
virtual ~PVArray();
/**
* Get the array length.
* @return The length.
*/
int getLength() const;
/**
* Set the array length.
* @param The length.
*/
void setLength(int length);
/**
* Get the array capacity.
* @return The capacity.
*/
int getCapacity() const;
/**
* Can the capacity be changed.
* @return (false,true) if (can not, can) be changed.
*/
bool isCapacityMutable();
/**
* Set the mutability of the array capacity.
* @return false or true
*/
void setCapacityMutable(bool isMutable);
/**
* Set the array capacity.
* @param The capacity.
*/
virtual void setCapacity(int capacity) = 0;
protected:
PVArray(PVStructure *parent,FieldConstPtr field);
void setCapacityLength(int capacity,int length);
private:
class PVArrayPvt * pImpl;
};
/**
* Class provided by caller of get
*/
template<typename T>
class PVArrayData {
public:
POINTER_DEFINITIONS(PVArrayData);
typedef T value_type;
typedef T* pointer;
typedef const T* const_pointer;
/**
* The data array.
*/
pointer data;
/**
* The offset. This is the offset into the actual array of the first element in data,
*/
int offset;
};
/**
* Base class for a scalarArray.
*/
class PVScalarArray : public PVArray {
public:
POINTER_DEFINITIONS(PVScalarArray);
/**
* Destructor
*/
virtual ~PVScalarArray();
/**
* Get the introspection interface
* @return The interface.
*/
ScalarArrayConstPtr getScalarArray() ;
protected:
PVScalarArray(PVStructure *parent,ScalarArrayConstPtr scalarArray);
private:
};
/**
* This is provided by code that calls get.
*/
typedef PVArrayData<PVStructurePtr> StructureArrayData;
/**
* Data class for a structureArray
*/
class PVStructureArray : public PVArray {
public:
POINTER_DEFINITIONS(PVStructureArray);
/**
* Destructor
*/
virtual ~PVStructureArray() {}
/**
* Get the introspection interface
* @return The interface.
*/
virtual StructureArrayConstPtr getStructureArray() = 0;
/**
* Append new elements to the end of the array.
* @param number The number of elements to add.
* @return the new length of the array.
*/
virtual int append(int number) = 0;
/**
* Remove elements from the array.
* @param offset The offset of the first element to remove.
* @param number The number of elements to remove.
* @return (false,true) if the elements were removed.
*/
virtual bool remove(int offset,int number) = 0;
/**
* Compress. This removes all null elements from the array.
*/
virtual void compress() = 0;
/**
* Get array elements
* @param offset The offset of the first element,
* @param length The number of elements to get.
* @param data The place where the data is placed.
*/
virtual int get(int offset, int length,
StructureArrayData *data) = 0;
/**
* Put data into the array.
* @param offset The offset of the first element,
* @param length The number of elements to get.
* @param from The new values to put into the array.
* @param fromOffset The offset in from.
* @return The number of elements put into the array.
*/
virtual int put(int offset,int length,
PVStructurePtrArray from, int fromOffset) = 0;
/**
* Share data from another source.
* @param value The data to share.
* @param capacity The capacity of the array.
* @param length The length of the array.
*/
virtual void shareData( PVStructurePtrArray value,int capacity,int length) = 0;
protected:
PVStructureArray(PVStructure *parent, StructureArrayConstPtr structureArray)
: PVArray(parent,structureArray) {}
private:
};
class PVStructure : public PVField,public BitSetSerializable {
public:
POINTER_DEFINITIONS(PVStructure);
/**
* Destructor
*/
virtual ~PVStructure();
/**
* Get the introspection interface
* @return The interface.
*/
StructureConstPtr getStructure();
/**
* Get the array of pointers to the subfields in the structure.
* @return The array.
*/
PVFieldPtrArray getPVFields();
/**
* Get the subfield with the specified name.
* @param fieldName The name of the field.
* @return Pointer to the field or null if field does not exist.
*/
PVField *getSubField(String fieldName);
/**
* Get the subfield with the specified offset.
* @param fieldOffset The offset.
* @return Pointer to the field or null if field does not exist.
*/
PVField *getSubField(int fieldOffset);
/**
* Append a field to the structure.
* @param pvField The field to append.
*/
void appendPVField(PVField *pvField);
/**
* Append fields to the structure.
* @param numberFields The number of fields.
* @param pvFields The fields to append.
* @return Pointer to the field or null if field does not exist.
*/
void appendPVFields(int numberFields,PVFieldPtrArray pvFields);
/**
* Remove a field from the structure.
* @param fieldName The name of the field to remove.
*/
void removePVField(String fieldName);
/**
* Get a boolean field with the specified name.
* @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.
*/
PVBoolean *getBooleanField(String fieldName);
/**
* Get a byte field with the specified name.
* @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.
*/
PVByte *getByteField(String fieldName);
/**
* Get a short field with the specified name.
* @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.
*/
PVShort *getShortField(String fieldName);
/**
* Get a int field with the specified name.
* @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.
*/
PVInt *getIntField(String fieldName);
/**
* Get a long field with the specified name.
* @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.
*/
PVLong *getLongField(String fieldName);
/**
* Get a float field with the specified name.
* @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.
*/
PVFloat *getFloatField(String fieldName);
/**
* Get a double field with the specified name.
* @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.
*/
PVDouble *getDoubleField(String fieldName);
/**
* Get a string field with the specified name.
* @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.
*/
PVString *getStringField(String fieldName);
/**
* Get a structure field with the specified name.
* @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.
*/
PVStructure *getStructureField(String fieldName);
/**
* Get a scalarArray field with the specified name.
* @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.
*/
PVScalarArray *getScalarArrayField(
String fieldName,ScalarType elementType);
/**
* Get a structureArray field with the specified name.
* @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.
*/
PVStructureArray *getStructureArrayField(String fieldName);
/**
* Get the name if this structure extends another structure.
* @return The string which may be null.
*/
String getExtendsStructureName();
/**
* Put the extends name.
* @param extendsStructureName The name.
*/
bool putExtendsStructureName(
String extendsStructureName);
/**
* Serialize.
* @param pbuffer The byte buffer.
* @param pflusher Interface to call when buffer is full.
*/
virtual void serialize(
ByteBuffer *pbuffer,SerializableControl *pflusher) const;
/**
* Deserialize
* @param pbuffer The byte buffer.
* @param pflusher Interface to call when buffer is empty.
*/
virtual void deserialize(
ByteBuffer *pbuffer,DeserializableControl *pflusher);
/**
* Serialize.
* @param pbuffer The byte buffer.
* @param pflusher Interface to call when buffer is full.
* @param pbitSet A bitset the specifies which fields to serialize.
*/
virtual void serialize(ByteBuffer *pbuffer,
SerializableControl *pflusher,BitSet *pbitSet) const;
/**
* Deserialize
* @param pbuffer The byte buffer.
* @param pflusher Interface to call when buffer is empty.
* @param pbitSet A bitset the specifies which fields to deserialize.
*/
virtual void deserialize(ByteBuffer *pbuffer,
DeserializableControl*pflusher,BitSet *pbitSet);
/**
* Constructor
* @param parent The parent structure.
* @param structure The introspection interface.
*/
PVStructure(PVStructure *parent,StructureConstPtr structure);
/**
* Constructor
* @param parent The parent structure.
* @param structure The introspection interface.
* @param pvFields The array of fields for the structure.
*/
PVStructure(
PVStructure *parent,
StructureConstPtr structure,
PVFieldPtrArray pvFields);
private:
void setParentPvt(PVField *pvField,PVStructure *parent);
class PVStructurePvt * pImpl;
};
template<typename T>
class PVValueArray : public PVScalarArray {
public:
POINTER_DEFINITIONS(PVValueArray);
typedef T value_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef PVArrayData<T> ArrayDataType;
/**
* Destructor
*/
virtual ~PVValueArray() {}
/**
* Get array elements
* @param offset The offset of the first element,
* @param length The number of elements to get.
* @param data The place where the data is placed.
*/
virtual int get(int offset, int length, ArrayDataType *data) = 0;
/**
* Put data into the array.
* @param offset The offset of the first element,
* @param length The number of elements to get.
* @param from The new values to put into the array.
* @param fromOffset The offset in from.
* @return The number of elements put into the array.
*/
virtual int put(int offset,int length, pointer from, int fromOffset) = 0;
/**
* Share data from another source.
* @param value The data to share.
* @param capacity The capacity of the array.
* @param length The length of the array.
*/
virtual void shareData(pointer value,int capacity,int length) = 0;
protected:
PVValueArray(PVStructure *parent,ScalarArrayConstPtr scalar)
: PVScalarArray(parent,scalar) {}
private:
};
/**
* Definitions for the various scalarArray types.
*/
typedef PVArrayData<bool> BooleanArrayData;
typedef PVValueArray<bool> PVBooleanArray;
typedef PVArrayData<int8> ByteArrayData;
typedef PVValueArray<int8> PVByteArray;
typedef PVArrayData<int16> ShortArrayData;
typedef PVValueArray<int16> PVShortArray;
typedef PVArrayData<int32> IntArrayData;
typedef PVValueArray<int32> PVIntArray;
typedef PVArrayData<int64> LongArrayData;
typedef PVValueArray<int64> PVLongArray;
typedef PVArrayData<float> FloatArrayData;
typedef PVValueArray<float> PVFloatArray;
typedef PVArrayData<double> DoubleArrayData;
typedef PVValueArray<double> PVDoubleArray;
typedef PVArrayData<String> StringArrayData;
typedef PVValueArray<String> PVStringArray;
/**
* This is a singlton class for creating data instances.
*/
class PVDataCreate {
public:
/**
* Create a PVField using given Field introspection data.
* @param parent The parent interface.
* @param field The introspection data to be used to create PVField.
* @return The PVField implementation.
*/
PVField *createPVField(PVStructure *parent,
FieldConstPtr field);
/**
* Create a PVField using given a PVField to clone.
* This method calls the appropriate createPVScalar, createPVArray, or createPVStructure.
* @param parent The parent interface.
* @param fieldToClone The field to clone.
* @return The PVField implementation
*/
PVField *createPVField(PVStructure *parent,
String fieldName,PVField * fieldToClone);
/**
* Create an implementation of a scalar field reusing the Scalar introspection interface.
* @param parent The parent.
* @param scalar The introspection interface.
* @return The PVScalar implementation.
*/
PVScalar *createPVScalar(PVStructure *parent,ScalarConstPtr scalar);
/**
* Create an implementation of a scalar field. A Scalar introspection interface is created.
* @param parent The parent interface.
* @param fieldName The field name.
* @param fieldType The field type.
* @return The PVScalar implementation.
*/
PVScalar *createPVScalar(PVStructure *parent,
String fieldName,ScalarType scalarType);
/**
* Create an implementation of a scalar field by cloning an existing PVScalar.
* The new PVScalar will have the same value and auxInfo as the original.
* @param parent The parent interface.
* @param fieldName The field name.
* @param scalarToClone The PVScalar to clone.
* @return The PVScalar implementation.
*/
PVScalar *createPVScalar(PVStructure *parent,
String fieldName,PVScalar * scalarToClone);
/**
* Create an implementation of an array field reusing the Array introspection interface.
* @param parent The parent interface.
* @param array The introspection interface.
* @return The PVScalarArray implementation.
*/
PVScalarArray *createPVScalarArray(PVStructure *parent,
ScalarArrayConstPtr scalarArray);
/**
* Create an implementation for an array field. An Array introspection interface is created.
* @param parent The parent interface.
* @param fieldName The field name.
* @param elementType The element type.
* @return The PVScalarArray implementation.
*/
PVScalarArray *createPVScalarArray(PVStructure *parent,
String fieldName,ScalarType elementType);
/**
* 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 parent The parent interface.
* @param fieldName The field name.
* @param arrayToClone The PVScalarArray to clone.
* @return The PVScalarArray implementation.
*/
PVScalarArray *createPVScalarArray(PVStructure *parent,
String fieldName,PVScalarArray * scalarArrayToClone);
/**
* Create an implementation of an array with structure elements.
* @param parent The parent interface.
* @param structureArray The introspection interface.
* All elements share the same introspection interface.
* @return The PVStructureArray implementation.
*/
PVStructureArray *createPVStructureArray(PVStructure *parent,
StructureArrayConstPtr structureArray);
/**
* Create implementation for PVStructure.
* @param parent The parent interface.
* @param structure The introspection interface.
* @return The PVStructure implementation
*/
PVStructure *createPVStructure(PVStructure *parent,
StructureConstPtr structure);
/**
* Create implementation for PVStructure.
* @param parent The parent interface.
* @param fieldName The field name.
* @param fields Array of reflection interfaces for the subFields.
* @return The PVStructure implementation
*/
PVStructure *createPVStructure(PVStructure *parent,
String fieldName,int numberFields,FieldConstPtrArray fields);
/**
* Create implementation for PVStructure.
* @param parent The parent interface.
* @param fieldName The field name.
* @param pvFields Array of PVFields
* @return The PVStructure implementation
*/
PVStructure *createPVStructure(PVStructure *parent,
String fieldName,int numberFields,PVFieldPtrArray pvFields);
/**
* Create implementation for PVStructure.
* @param parent The parent interface.
* @param fieldName The field name.
* @param structToClone A structure. Each subfield and any auxInfo is cloned and added to the newly created structure.
* @return The PVStructure implementation.
*/
PVStructure *createPVStructure(PVStructure *parent,
String fieldName,PVStructure *structToClone);
protected:
PVDataCreate();
friend PVDataCreate * getPVDataCreate();
};
/**
* Get the single class that implemnents PVDataCreate
* @param The PVDataCreate factory.
*/
extern PVDataCreate * getPVDataCreate();
}}
#endif /* PVDATA_H */

View File

@@ -1,465 +0,0 @@
/* pvIntrospect.h */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* Author - Marty Kraimer
*/
#ifndef PVINTROSPECT_H
#define PVINTROSPECT_H
#include <string>
#include <stdexcept>
#include <pv/noDefaultMethods.h>
#include <pv/sharedPtr.h>
#include <pv/pvType.h>
namespace epics { namespace pvData {
class Field;
class Scalar;
class ScalarArray;
class Structure;
class StructureArray;
/**
* typedef for a shared pointer to an immutable Field.
*/
typedef std::tr1::shared_ptr<const Field> FieldConstPtr;
/**
* typedef for an array of shared pointer to an immutable Field.
*/
typedef FieldConstPtr * FieldConstPtrArray;
/**
* typedef for a shared pointer to an immutable Scalar.
*/
typedef std::tr1::shared_ptr<const Scalar> ScalarConstPtr;
/**
* typedef for a shared pointer to an immutable ScalarArray.
*/
typedef std::tr1::shared_ptr<const ScalarArray> ScalarArrayConstPtr;
/**
* typedef for a shared pointer to an immutable Structure.
*/
typedef std::tr1::shared_ptr<const Structure> StructureConstPtr;
/**
* typedef for a shared pointer to an immutable StructureArray.
*/
typedef std::tr1::shared_ptr<const StructureArray> StructureArrayConstPtr;
/**
* Definition of support field types.
*/
enum Type {
/**
* The type is scalar. It has a scalarType
*/
scalar,
/**
* The type is scalarArray. Each element is a scalar of the same scalarType.
*/
scalarArray,
/**
* The type is structure.
*/
structure,
/**
* The type is structureArray. Each element is a structure.
*/
structureArray
};
/**
* Convenience functions for Type.
*/
namespace TypeFunc {
/**
* Get a name for the type.
* @param type The type.
* @return The name for the type.
*/
const char* name(Type type);
/**
* Convert the type to a string and add it to builder.
* @param builder The string builder.
* @param type The type.
*/
void toString(StringBuilder builder,const Type type);
};
/**
* Definition of support scalar types.
*/
enum ScalarType {
/**
* The type is boolean, i. e. value can be {@code false} or {@code true}
*/
pvBoolean,
/**
* The type is byte, i. e. a 8 bit signed integer.
*/
pvByte,
/**
* The type is short, i. e. a 16 bit signed integer.
*/
pvShort,
/**
* The type is int, i. e. a 32 bit signed integer.
*/
pvInt,
/**
* The type is long, i. e. a 64 bit signed integer.
*/
pvLong,
/**
* The type is float, i. e. 32 bit IEEE floating point,
*/
pvFloat,
/**
* The type is float, i. e. 64 bit IEEE floating point,
*/
pvDouble,
/**
* The type is string, i. e. a UTF8 character string.
*/
pvString
};
/**
* Convenience functions for ScalarType.
*/
namespace ScalarTypeFunc {
/**
* Is the type an integer, i. e. is it one of byte,...long
* @param scalarType The type.
* @return (false,true) if the scalarType is an integer.
*/
bool isInteger(ScalarType scalarType);
/**
* Is the type numeric, i. e. is it one of byte,...,double
* @param scalarType The type.
* @return (false,true) if the scalarType is a numeric
*/
bool isNumeric(ScalarType scalarType);
/**
* Is the type primitive, i. e. not string
* @param scalarType The type.
* @return (false,true) if the scalarType is primitive.
*/
bool isPrimitive(ScalarType scalarType);
/**
* Get the scalarType for value.
* @param value The name of the scalar type.
* @return The scalarType.
* An exception is thrown if the name is not the name of a scalar type.
*/
ScalarType getScalarType(String value);
/**
* Get a name for the scalarType.
* @param scalarType The type.
* @return The name for the scalarType.
*/
const char* name(ScalarType scalarType);
/**
* Convert the scalarType to a string and add it to builder.
* @param builder The string builder.
* @param scalarType The type.
*/
void toString(StringBuilder builder,ScalarType scalarType);
};
/**
* This class implements introspection object for field.
*/
class Field : public std::tr1::enable_shared_from_this<Field> {
public:
POINTER_DEFINITIONS(Field);
/**
* Destructor.
*/
virtual ~Field();
/**
* Get the name of the field.
* @return The field name.
*/
String getFieldName() const{return m_fieldName;}
/**
* Get the field type.
* @return The type.
*/
Type getType() const{return m_type;}
/**
* Convert the scalarType to a string and add it to builder.
* @param builder The string builder.
*/
virtual void toString(StringBuilder builder) const{toString(builder,0);}
/**
* Convert the scalarType to a string and add it to builder.
* @param builder The string builder.
* @param indentLevel The number of blanks at the beginning of new lines.
*/
virtual void toString(StringBuilder builder,int indentLevel) const;
/**
* Rename the field.
* @param newName The new name.
* This MUST not be called after the field is put into use!!!
*/
void renameField(String newName);
protected:
/**
* Constructor
* @param fieldName The field name.
* @param fieldName The field type.
*/
Field(String fieldName,Type type);
private:
String m_fieldName;
Type m_type;
friend class StructureArray;
friend class Structure;
friend class PVFieldPvt;
friend class StandardField;
friend class BasePVStructureArray;
friend class FieldCreate;
struct Deleter{void operator()(Field *p){delete p;}};
};
/**
* This class implements introspection object for Scalar.
*/
class Scalar : public Field{
public:
POINTER_DEFINITIONS(Scalar);
/**
* Destructor.
*/
virtual ~Scalar();
typedef Scalar& reference;
typedef const Scalar& const_reference;
/**
* Get the scalarType
* @return the scalarType
*/
ScalarType getScalarType() const {return scalarType;}
/**
* Convert the scalar to a string and add it to builder.
* @param builder The string builder.
*/
virtual void toString(StringBuilder buf) const{toString(buf,0);}
/**
* Convert the scalar to a string and add it to builder.
* @param builder The string builder.
* @param indentLevel The number of blanks at the beginning of new lines.
*/
virtual void toString(StringBuilder buf,int indentLevel) const;
protected:
Scalar(String fieldName,ScalarType scalarType);
private:
ScalarType scalarType;
friend class FieldCreate;
};
/**
* This class implements introspection object for field.
*/
class ScalarArray : public Field{
public:
POINTER_DEFINITIONS(ScalarArray);
ScalarArray(String fieldName,ScalarType scalarType);
typedef ScalarArray& reference;
typedef const ScalarArray& const_reference;
/**
* Get the scalarType for the elements.
* @return the scalarType
*/
ScalarType getElementType() const {return elementType;}
/**
* Convert the scalarType to a string and add it to builder.
* @param builder The string builder.
*/
virtual void toString(StringBuilder buf) const{toString(buf,0);}
/**
* Convert the scalarType to a string and add it to builder.
* @param builder The string builder.
* @param indentLevel The number of blanks at the beginning of new lines.
*/
virtual void toString(StringBuilder buf,int indentLevel) const;
protected:
/**
* Destructor.
*/
virtual ~ScalarArray();
private:
ScalarType elementType;
friend class FieldCreate;
};
/**
* This class implements introspection object for a structureArray
*/
class StructureArray : public Field{
public:
POINTER_DEFINITIONS(StructureArray);
typedef StructureArray& reference;
typedef const StructureArray& const_reference;
const Structure& structure() const {return *pstructure;}
/**
* Get the introspection interface for the array elements.
* @return The introspection interface.
*/
StructureConstPtr getStructure() const {return pstructure;}
/**
* Convert the scalarType to a string and add it to builder.
* @param builder The string builder.
* @param indentLevel The number of blanks at the beginning of new lines.
*/
virtual void toString(StringBuilder buf,int indentLevel=0) const;
protected:
/**
* Constructor.
* @param fieldName The name for the field.
* @param structure The introspection interface for the elements.
*/
StructureArray(String fieldName,StructureConstPtr structure);
/**
* Destructor.
*/
virtual ~StructureArray();
private:
StructureConstPtr pstructure;
friend class FieldCreate;
};
/**
* This class implements introspection object for a structure.
*/
class Structure : public Field {
public:
POINTER_DEFINITIONS(Structure);
/**
* Destructor.
*/
virtual ~Structure();
typedef Structure& reference;
typedef const Structure& const_reference;
/**
* Get the number of immediate subfields in the structure/
* @return The number of fields.
*/
int getNumberFields() const {return numberFields;}
/**
* Get the field for the specified fieldName.
* @return The introspection interface.
* This will hold a null pointer if the field is not in the structure.
*/
FieldConstPtr getField(String fieldName) const;
/**
* Get the field index for the specified fieldName.
* @return The introspection interface.
* This will be -1 if the field is not in the structure.
*/
int getFieldIndex(String fieldName) const;
/**
* Get the fields in the structure.
* @return The array of fields.
*/
FieldConstPtrArray getFields() const {return fields;}
/**
* Append a field to the structure.
* @param field The field to append.
*/
void appendField(FieldConstPtr field);
/**
* Append an array of fields to the structure.
* @param field The fields to append.
* The array MUST be allocated on the heap.
* The structure takes ownership of the field array.
*/
void appendFields(int numberFields,FieldConstPtrArray fields);
/**
* Remove a field from the structure.
* @param field The field to remove.
*/
void removeField(int index);
/**
* Convert the structure to a string and add it to builder.
* @param builder The string builder.
*/
virtual void toString(StringBuilder buf) const{toString(buf,0);}
/**
* Convert the structure to a string and add it to builder.
* @param builder The string builder.
* @param indentLevel The number of blanks at the beginning of new lines.
*/
virtual void toString(StringBuilder buf,int indentLevel) const;
protected:
Structure(String fieldName, int numberFields,FieldConstPtrArray fields);
private:
int numberFields;
FieldConstPtrArray fields;
friend class FieldCreate;
};
/**
* This is a singlton class for creating introspection interfaces.
*/
class FieldCreate : NoDefaultMethods {
public:
/**
* Create a new Field like an existing field but with a different name.
* @param fieldName The field name.
* @param field An existing field
* @return a {@code Field} interface for the newly created object.
*/
FieldConstPtr create(String fieldName,FieldConstPtr field) const;
/**
* Create a {@code ScalarField}.
* @param fieldName The field name.
* @param scalarType The scalar type.
* @return a {@code Scalar} interface for the newly created object.
* @throws An {@code IllegalArgumentException} if an illegal type is specified.
*/
ScalarConstPtr createScalar(String fieldName,ScalarType scalarType) const;
/**
* Create an {@code Array} field.
* @param fieldName The field name
* @param elementType The {@code scalarType} for array elements
* @return An {@code Array} Interface for the newly created object.
*/
ScalarArrayConstPtr createScalarArray(String fieldName,
ScalarType elementType) const;
/**
* Create an {@code Array} field that is has element type <i>Structure</i>
* @param fieldName The field name
* @param elementStructure The {@code Structure} for each array element.
* @return An {@code Array} Interface for the newly created object.
*/
StructureConstPtr createStructure (String fieldName,
int numberFields,FieldConstPtrArray fields) const;
/**
* Create a {@code Structure} field.
* @param fieldName The field name
* @param fields The array of {@code Field}s for the structure.
* @return a {@code Structure} interface for the newly created object.
*/
StructureArrayConstPtr createStructureArray(String fieldName,
StructureConstPtr structure) const;
private:
FieldCreate();
friend FieldCreate * getFieldCreate();
};
/**
* Get the single class that implemnents FieldCreate,
* @param The fieldCreate factory.
*/
extern FieldCreate * getFieldCreate();
}}
#endif /* PVINTROSPECT_H */

View File

@@ -1,102 +0,0 @@
/* pvType.h */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* Author - Marty Kraimer
*/
/* Definitions for the primitive types for pvData.
* It also defines the arrays of the primitive types
*/
#ifndef PVTYPE_H
#define PVTYPE_H
#include <string>
#include <stdint.h>
namespace epics { namespace pvData {
/**
* This is a set of typdefs used by pvData.
*/
/**
* boolean, i.e. can only have the values {@code false} or {@code true}
*/
typedef bool boolean;
/**
* A 8 bit signed integer
*/
typedef int8_t int8;
/**
* A 16 bit signed integer
*/
typedef int16_t int16;
/**
* A 32 bit signed integer
*/
typedef int32_t int32;
/**
* A 64 bit signed integer
*/
typedef int64_t int64;
/**
* A 32 bit unsigned integer
*/
typedef uint32_t uint32;
/**
* A 64 bit unsigned integer
*/
typedef uint64_t uint64;
// float and double are types
/**
* A string
*/
typedef std::string String;
/**
* A boolean array.
*/
typedef bool * BooleanArray;
/**
* A byte array.
*/
typedef int8 * ByteArray;
/**
* A short array.
*/
typedef int16 * ShortArray;
/**
* A int array.
*/
typedef int32 * IntArray;
/**
* A long array.
*/
typedef int64 * LongArray;
/**
* A float array.
*/
typedef float * FloatArray;
/**
* A double array.
*/
typedef double * DoubleArray;
/**
* A string array.
*/
typedef String* StringArray;
/**
* A convenience definition for toString methods
*/
typedef std::string * StringBuilder;
}}
#endif /* PVTYPE_H */

View File

@@ -1,101 +0,0 @@
/* standardField.h */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* Author - Marty Kraimer
*/
#ifndef STANDARDFIELD_H
#define STANDARDFIELD_H
#include <string>
#include <stdexcept>
#include <pv/pvIntrospect.h>
namespace epics { namespace pvData {
/**
* 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:
* alarm, timeStamp, display, control, and valueAlarm.
* An example is "alarm,timeStamp,valueAlarm".
* The method with properties creates a structure with fields named fieldName and each of the property names.s
* Each property field is a structure defining the property.
* The details about each property is given in the section named "Property". For example the call:
* {@code
StructureConstPtr example = standardField->scalar(
String("value"),
pvDouble,
String("value,alarm,timeStamp"));
* }
* Will result in a Field definition that has the form: {@code
structure example
double value
structure alarm
structure severity
int index
string[] choices
structure timeStamp
long secondsPastEpoch
int nanoSeconds
* }
* In addition there are methods that create each of the property structures,
* i.e. the methods named: alarm, .... enumeratedAlarm."
*
* StandardField is a singleton class. The class is accessed via the statement: {@code
StandardField *standardField = getStandardField();
* }
*/
class StandardField : private NoDefaultMethods {
public:
StandardField();
~StandardField();
ScalarConstPtr scalar(String fieldName,ScalarType type);
StructureConstPtr scalar(String fieldName,
ScalarType type,String properties);
ScalarArrayConstPtr scalarArray(String fieldName,
ScalarType elementType);
StructureConstPtr scalarArray(String fieldName,
ScalarType elementType, String properties);
StructureArrayConstPtr structureArray(String fieldName,
StructureConstPtr structure);
StructureConstPtr structureArray(String fieldName,
StructureConstPtr structure,String properties);
StructureConstPtr structure(String fieldName,
int numFields,FieldConstPtrArray fields);
StructureConstPtr enumerated(String fieldName);
StructureConstPtr enumerated(String fieldName, String properties);
ScalarConstPtr scalarValue(ScalarType type);
StructureConstPtr scalarValue(ScalarType type,String properties);
ScalarArrayConstPtr scalarArrayValue(ScalarType elementType);
StructureConstPtr scalarArrayValue(ScalarType elementType,
String properties);
StructureArrayConstPtr structureArrayValue(StructureConstPtr structure);
StructureConstPtr structureArrayValue(StructureConstPtr structure,
String properties);
StructureConstPtr structureValue(
int numFields,FieldConstPtrArray fields);
StructureConstPtr enumeratedValue();
StructureConstPtr enumeratedValue(String properties);
StructureConstPtr alarm();
StructureConstPtr timeStamp();
StructureConstPtr display();
StructureConstPtr control();
StructureConstPtr booleanAlarm();
StructureConstPtr byteAlarm();
StructureConstPtr shortAlarm();
StructureConstPtr intAlarm();
StructureConstPtr longAlarm();
StructureConstPtr floatAlarm();
StructureConstPtr doubleAlarm();
StructureConstPtr enumeratedAlarm();
private:
static void init();
};
extern StandardField * getStandardField();
}}
#endif /* STANDARDFIELD_H */

View File

@@ -1,80 +0,0 @@
/* standardPVField.h */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* Author - Marty Kraimer
*/
#ifndef STANDARDPVFIELD_H
#define STANDARDPVFIELD_H
#include <string>
#include <stdexcept>
#include <pv/pvIntrospect.h>
#include <pv/pvData.h>
namespace epics { namespace pvData {
/**
* StandardPVField is a class or creating standard data fields.
* Like class StandardField it has two forms of the methods which create a fields:
* one without properties and one with properties.
* The properties are some combination of alarm, timeStamp, control, display, and valueAlarm.
* Just like StandardField there are methods to create the standard properties.
*
* StandardPVField is a singleton class. The class is accessed via the statement: {@code
StandardPVField *standardPVField = getStandardPVField();
* }
*/
class StandardPVField : private NoDefaultMethods {
public:
StandardPVField();
~StandardPVField();
PVScalar * scalar(PVStructure *parent,String fieldName,ScalarType type);
PVStructure * scalar(PVStructure *parent,
String fieldName,ScalarType type,String properties);
PVScalarArray * scalarArray(PVStructure *parent,
String fieldName,ScalarType elementType);
PVStructure * scalarArray(PVStructure *parent,
String fieldName,ScalarType elementType, String properties);
PVStructureArray * structureArray(PVStructure *parent,
String fieldName,StructureConstPtr structure);
PVStructure* structureArray(PVStructure *parent,
String fieldName,StructureConstPtr structure,String properties);
PVStructure * enumerated(PVStructure *parent,
String fieldName,StringArray choices, int number);
PVStructure * enumerated(PVStructure *parent,
String fieldName,StringArray choices, int number, String properties);
PVScalar * scalarValue(PVStructure *parent,ScalarType type);
PVStructure * scalarValue(PVStructure *parent,
ScalarType type,String properties);
PVScalarArray * scalarArrayValue(
PVStructure *parent,ScalarType elementType);
PVStructure * scalarArrayValue(PVStructure *parent,
ScalarType elementType, String properties);
PVStructureArray * structureArrayValue(PVStructure *parent,
StructureConstPtr structure);
PVStructure * structureArrayValue(PVStructure *parent,
StructureConstPtr structure,String properties);
PVStructure * enumeratedValue(
PVStructure *parent,StringArray choices,int number);
PVStructure * enumeratedValue(PVStructure *parent,
StringArray choices,int number, String properties);
PVStructure * alarm(PVStructure *parent);
PVStructure * timeStamp(PVStructure *parent);
PVStructure * display(PVStructure *parent);
PVStructure * control(PVStructure *parent);
PVStructure * booleanAlarm(PVStructure *parent);
PVStructure * byteAlarm(PVStructure *parent);
PVStructure * shortAlarm(PVStructure *parent);
PVStructure * intAlarm(PVStructure *parent);
PVStructure * longAlarm(PVStructure *parent);
PVStructure * floatAlarm(PVStructure *parent);
PVStructure * doubleAlarm(PVStructure *parent);
PVStructure * enumeratedAlarm(PVStructure *parent);
PVStructure * powerSupply(PVStructure *parent);
};
extern StandardPVField * getStandardPVField();
}}
#endif /* STANDARDPVFIELD_H */

View File

@@ -1,77 +0,0 @@
/*bitSetUtil.cpp*/
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#include <pv/noDefaultMethods.h>
#include <pv/pvData.h>
#include <pv/bitSetUtil.h>
namespace epics { namespace pvData {
static bool checkBitSetPVField(
PVField *pvField,BitSet *bitSet,int initialOffset)
{
bool atLeastOneBitSet = false;
bool allBitsSet = true;
int offset = initialOffset;
int nbits = pvField->getNumberFields();
if(nbits==1) return bitSet->get(offset);
int nextSetBit = bitSet->nextSetBit(offset);
if(nextSetBit>=(offset+nbits)) return false;
if(bitSet->get(offset)) {
if(nbits>1) {
for(int i=offset+1; i<offset+nbits; i++) bitSet->clear(i);
}
return true;
}
PVStructure *pvStructure = static_cast<PVStructure *>(pvField);
while(offset<initialOffset + nbits) {
PVField *pvSubField = pvStructure->getSubField(offset);
int nbitsNow = pvSubField->getNumberFields();
if(nbitsNow==1) {
if(bitSet->get(offset)) {
atLeastOneBitSet = true;
} else {
allBitsSet = false;
}
offset++;
} else {
offset++;
PVStructure *pvSubStructure = static_cast<PVStructure*>(pvField);
PVFieldPtrArray pvSubStructureFields =
pvSubStructure->getPVFields();
int num = pvSubStructure->getStructure()->getNumberFields();
for(int i=0; i<num; i++) {
PVField *pvSubSubField = pvSubStructureFields[i];
bool result = checkBitSetPVField(pvSubSubField,bitSet,offset);
if(result) {
atLeastOneBitSet = true;
if(!bitSet->get(offset)) {
allBitsSet = false;
}
} else {
allBitsSet = false;
}
offset += pvSubSubField->getNumberFields();
}
}
}
if(allBitsSet) {
if(nbits>1) {
for(int i=initialOffset+1; i<initialOffset+nbits; i++){
bitSet->clear(i);
}
}
bitSet->set(initialOffset);
}
return atLeastOneBitSet;
}
bool BitSetUtil::compress(BitSet *bitSet,PVStructure *pvStructure)
{
return checkBitSetPVField(pvStructure,bitSet,0);
}
}}

491
pvDataCPP.files Normal file
View File

@@ -0,0 +1,491 @@
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/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/pvData.h
pvDataApp/pv/pvIntrospect.h
pvDataApp/pv/pvType.h
pvDataApp/pv/standardField.h
pvDataApp/pv/standardPVField.h
pvDataApp/pvMisc/bitSetUtil.cpp
pvDataApp/pvMisc/bitSetUtil.h
testApp/capi/testc.cpp
testApp/capi/testc.py
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/testMonitor.cpp
testApp/property/testProperty.cpp
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
src/copy/createRequest.cpp
src/copy/createRequest.h
src/copy/pvCopy.cpp
src/copy/pvCopy.h
src/factory/Compare.cpp
src/factory/Convert.cpp
src/factory/factory.h
src/factory/FieldCreateFactory.cpp
src/factory/printer.cpp
src/factory/PVArray.cpp
src/factory/PVDataCreateFactory.cpp
src/factory/PVField.cpp
src/factory/PVScalar.cpp
src/factory/PVScalarArray.cpp
src/factory/PVStructure.cpp
src/factory/PVStructureArray.cpp
src/factory/pvSubArrayCopy.cpp
src/factory/PVUnion.cpp
src/factory/PVUnionArray.cpp
src/factory/StandardField.cpp
src/factory/StandardPVField.cpp
src/factory/TypeFunc.cpp
src/misc/bitSet.cpp
src/misc/bitSet.h
src/misc/byteBuffer.cpp
src/misc/byteBuffer.h
src/misc/current_function.h
src/misc/destroyable.h
src/misc/epicsException.cpp
src/misc/epicsException.h
src/misc/event.cpp
src/misc/event.h
src/misc/executor.cpp
src/misc/executor.h
src/misc/localStaticLock.cpp
src/misc/localStaticLock.h
src/misc/lock.h
src/misc/messageQueue.cpp
src/misc/messageQueue.h
src/misc/noDefaultMethods.h
src/misc/parseToPOD.cpp
src/misc/queue.h
src/misc/requester.cpp
src/misc/requester.h
src/misc/serialize.h
src/misc/serializeHelper.cpp
src/misc/serializeHelper.h
src/misc/sharedPtr.h
src/misc/sharedVector.h
src/misc/status.cpp
src/misc/status.h
src/misc/templateMeta.h
src/misc/thread.h
src/misc/timeFunction.cpp
src/misc/timeFunction.h
src/misc/timer.cpp
src/misc/timer.h
src/misc/typeCast.cpp
src/misc/typeCast.h
src/monitor/monitor.cpp
src/monitor/monitor.h
src/monitor/monitorPlugin.cpp
src/monitor/monitorPlugin.h
src/property/alarm.cpp
src/property/alarm.h
src/property/control.h
src/property/display.h
src/property/pvAlarm.cpp
src/property/pvAlarm.h
src/property/pvControl.cpp
src/property/pvControl.h
src/property/pvDisplay.cpp
src/property/pvDisplay.h
src/property/pvEnumerated.cpp
src/property/pvEnumerated.h
src/property/pvTimeStamp.cpp
src/property/pvTimeStamp.h
src/property/timeStamp.cpp
src/property/timeStamp.h
src/pv/convert.h
src/pv/printer.h
src/pv/pvData.h
src/pv/pvIntrospect.h
src/pv/pvSubArrayCopy.h
src/pv/pvType.h
src/pv/standardField.h
src/pv/standardPVField.h
src/pvMisc/bitSetUtil.cpp
src/pvMisc/bitSetUtil.h
testApp/copy/testCreateRequest.cpp
testApp/copy/testPVCopy.cpp
testApp/misc/testBaseException.cpp
testApp/misc/testBitSet.cpp
testApp/misc/testByteBuffer.cpp
testApp/misc/testByteOrder.cpp
testApp/misc/testMessageQueue.cpp
testApp/misc/testOverrunBitSet.cpp
testApp/misc/testQueue.cpp
testApp/misc/testSerialization.cpp
testApp/misc/testSharedVector.cpp
testApp/misc/testThread.cpp
testApp/misc/testTimer.cpp
testApp/misc/testTimeStamp.cpp
testApp/misc/testTypeCast.cpp
testApp/property/testProperty.cpp
testApp/pv/testBitSetUtil.cpp
testApp/pv/testConvert.cpp
testApp/pv/testFieldBuilder.cpp
testApp/pv/testIntrospect.cpp
testApp/pv/testOperators.cpp
testApp/pv/testPVData.cpp
testApp/pv/testPVScalarArray.cpp
testApp/pv/testPVStructureArray.cpp
testApp/pv/testPVType.cpp
testApp/pv/testStandardField.cpp
testApp/pv/testStandardPVField.cpp
src/factory/printer.cpp
configure/O.darwin-x86/Makefile
configure/Makefile
include/pv/alarm.h
include/pv/bitSet.h
include/pv/bitSetUtil.h
include/pv/byteBuffer.h
include/pv/control.h
include/pv/convert.h
include/pv/createRequest.h
include/pv/current_function.h
include/pv/destroyable.h
include/pv/display.h
include/pv/epicsException.h
include/pv/event.h
include/pv/executor.h
include/pv/factory.h
include/pv/localStaticLock.h
include/pv/lock.h
include/pv/messageQueue.h
include/pv/monitor.h
include/pv/monitorPlugin.h
include/pv/noDefaultMethods.h
include/pv/printer.h
include/pv/pvAlarm.h
include/pv/pvControl.h
include/pv/pvCopy.h
include/pv/pvData.h
include/pv/pvDisplay.h
include/pv/pvEnumerated.h
include/pv/pvIntrospect.h
include/pv/pvSubArrayCopy.h
include/pv/pvTimeStamp.h
include/pv/pvType.h
include/pv/queue.h
include/pv/requester.h
include/pv/serialize.h
include/pv/serializeHelper.h
include/pv/sharedPtr.h
include/pv/sharedVector.h
include/pv/standardField.h
include/pv/standardPVField.h
include/pv/status.h
include/pv/templateMeta.h
include/pv/thread.h
include/pv/timeFunction.h
include/pv/timer.h
include/pv/timeStamp.h
include/pv/typeCast.h
src/copy/createRequest.cpp
src/copy/createRequest.h
src/copy/Makefile
src/copy/pvCopy.cpp
src/copy/pvCopy.h
src/factory/Compare.cpp
src/factory/Convert.cpp
src/factory/factory.h
src/factory/FieldCreateFactory.cpp
src/factory/Makefile
src/factory/printer.cpp
src/factory/PVArray.cpp
src/factory/PVDataCreateFactory.cpp
src/factory/PVField.cpp
src/factory/PVScalar.cpp
src/factory/PVScalarArray.cpp
src/factory/PVStructure.cpp
src/factory/PVStructureArray.cpp
src/factory/pvSubArrayCopy.cpp
src/factory/PVUnion.cpp
src/factory/PVUnionArray.cpp
src/factory/StandardField.cpp
src/factory/StandardPVField.cpp
src/factory/TypeFunc.cpp
src/misc/bitSet.cpp
src/misc/bitSet.h
src/misc/byteBuffer.cpp
src/misc/byteBuffer.h
src/misc/current_function.h
src/misc/destroyable.h
src/misc/epicsException.cpp
src/misc/epicsException.h
src/misc/event.cpp
src/misc/event.h
src/misc/executor.cpp
src/misc/executor.h
src/misc/localStaticLock.cpp
src/misc/localStaticLock.h
src/misc/lock.h
src/misc/Makefile
src/misc/messageQueue.cpp
src/misc/messageQueue.h
src/misc/noDefaultMethods.h
src/misc/parseToPOD.cpp
src/misc/queue.h
src/misc/requester.cpp
src/misc/requester.h
src/misc/serialize.h
src/misc/serializeHelper.cpp
src/misc/serializeHelper.h
src/misc/sharedPtr.h
src/misc/sharedVector.h
src/misc/status.cpp
src/misc/status.h
src/misc/templateMeta.h
src/misc/thread.h
src/misc/timeFunction.cpp
src/misc/timeFunction.h
src/misc/timer.cpp
src/misc/timer.h
src/misc/typeCast.cpp
src/misc/typeCast.h
src/monitor/Makefile
src/monitor/monitor.cpp
src/monitor/monitor.h
src/monitor/monitorPlugin.cpp
src/monitor/monitorPlugin.h
src/O.darwin-x86/Makefile
src/property/alarm.cpp
src/property/alarm.h
src/property/control.h
src/property/display.h
src/property/Makefile
src/property/pvAlarm.cpp
src/property/pvAlarm.h
src/property/pvControl.cpp
src/property/pvControl.h
src/property/pvDisplay.cpp
src/property/pvDisplay.h
src/property/pvEnumerated.cpp
src/property/pvEnumerated.h
src/property/pvTimeStamp.cpp
src/property/pvTimeStamp.h
src/property/timeStamp.cpp
src/property/timeStamp.h
src/pv/convert.h
src/pv/Makefile
src/pv/printer.h
src/pv/pvData.h
src/pv/pvIntrospect.h
src/pv/pvSubArrayCopy.h
src/pv/pvType.h
src/pv/standardField.h
src/pv/standardPVField.h
src/pvMisc/bitSetUtil.cpp
src/pvMisc/bitSetUtil.h
src/pvMisc/Makefile
src/Makefile
testApp/copy/epicsRunPVDataTests.c
testApp/copy/Makefile
testApp/copy/testCreateRequest.cpp
testApp/copy/testPVCopy.cpp
testApp/misc/epicsRunPVDataTests.c
testApp/misc/Makefile
testApp/misc/testBaseException.cpp
testApp/misc/testBitSet.cpp
testApp/misc/testByteBuffer.cpp
testApp/misc/testByteOrder.cpp
testApp/misc/testMessageQueue.cpp
testApp/misc/testOverrunBitSet.cpp
testApp/misc/testQueue.cpp
testApp/misc/testSerialization.cpp
testApp/misc/testSharedVector.cpp
testApp/misc/testThread.cpp
testApp/misc/testTimer.cpp
testApp/misc/testTimeStamp.cpp
testApp/misc/testTypeCast.cpp
testApp/property/epicsRunPVDataTests.c
testApp/property/Makefile
testApp/property/testProperty.cpp
testApp/pv/epicsRunPVDataTests.c
testApp/pv/Makefile
testApp/pv/testBitSetUtil.cpp
testApp/pv/testConvert.cpp
testApp/pv/testFieldBuilder.cpp
testApp/pv/testIntrospect.cpp
testApp/pv/testOperators.cpp
testApp/pv/testPVData.cpp
testApp/pv/testPVScalarArray.cpp
testApp/pv/testPVStructureArray.cpp
testApp/pv/testPVType.cpp
testApp/pv/testPVUnion.cpp
testApp/pv/testStandardField.cpp
testApp/pv/testStandardPVField.cpp
testApp/Makefile
Makefile
testApp/copy/epicsRunPVDataTests.c
testApp/copy/Makefile
testApp/copy/testCreateRequest.cpp
testApp/copy/testPVCopy.cpp
testApp/misc/epicsRunPVDataTests.c
testApp/misc/Makefile
testApp/misc/testBaseException.cpp
testApp/misc/testBitSet.cpp
testApp/misc/testByteBuffer.cpp
testApp/misc/testByteOrder.cpp
testApp/misc/testMessageQueue.cpp
testApp/misc/testOverrunBitSet.cpp
testApp/misc/testQueue.cpp
testApp/misc/testSerialization.cpp
testApp/misc/testSharedVector.cpp
testApp/misc/testThread.cpp
testApp/misc/testTimer.cpp
testApp/misc/testTimeStamp.cpp
testApp/misc/testTypeCast.cpp
testApp/O.darwin-x86/Makefile
testApp/property/epicsRunPVDataTests.c
testApp/property/Makefile
testApp/property/testProperty.cpp
testApp/pv/epicsRunPVDataTests.c
testApp/pv/Makefile
testApp/pv/testBitSetUtil.cpp
testApp/pv/testConvert.cpp
testApp/pv/testFieldBuilder.cpp
testApp/pv/testIntrospect.cpp
testApp/pv/testOperators.cpp
testApp/pv/testPVData.cpp
testApp/pv/testPVScalarArray.cpp
testApp/pv/testPVStructureArray.cpp
testApp/pv/testPVType.cpp
testApp/pv/testPVUnion.cpp
testApp/pv/testStandardField.cpp
testApp/pv/testStandardPVField.cpp
testApp/Makefile
testApp/pvDataAllTests.c
testApp/copy/testCreateRequest.cpp
testApp/copy/testPVCopy.cpp
testApp/misc/testBaseException.cpp
testApp/misc/testBitSet.cpp
testApp/misc/testByteBuffer.cpp
testApp/misc/testByteOrder.cpp
testApp/misc/testMessageQueue.cpp
testApp/misc/testOverrunBitSet.cpp
testApp/misc/testQueue.cpp
testApp/misc/testSerialization.cpp
testApp/misc/testSharedVector.cpp
testApp/misc/testThread.cpp
testApp/misc/testTimer.cpp
testApp/misc/testTimeStamp.cpp
testApp/misc/testTypeCast.cpp
testApp/property/testProperty.cpp
testApp/pv/testBitSetUtil.cpp
testApp/pv/testConvert.cpp
testApp/pv/testFieldBuilder.cpp
testApp/pv/testIntrospect.cpp
testApp/pv/testOperators.cpp
testApp/pv/testPVData.cpp
testApp/pv/testPVScalarArray.cpp
testApp/pv/testPVStructureArray.cpp
testApp/pv/testPVType.cpp
testApp/pv/testPVUnion.cpp
testApp/pv/testStandardField.cpp
testApp/pv/testStandardPVField.cpp
testApp/pvDataAllTests.c
testApp/rtemsConfig.c
testApp/rtemsNetworking.h
testApp/rtemsTestHarness.c

11
pvDataCPP.includes Normal file
View File

@@ -0,0 +1,11 @@
/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
testApp/pv
testApp/copy
testApp/misc
testApp
testApp/property

24
src/Makefile Normal file
View File

@@ -0,0 +1,24 @@
# Makefile for the pvData library
TOP = ..
include $(TOP)/configure/CONFIG
INSTALL_INCLUDE = $(INSTALL_LOCATION)/include/pv
USR_INCLUDES += -I$(INSTALL_LOCATION)/include
PVDATA_SRC = $(TOP)/src
include $(PVDATA_SRC)/misc/Makefile
include $(PVDATA_SRC)/pv/Makefile
include $(PVDATA_SRC)/factory/Makefile
include $(PVDATA_SRC)/property/Makefile
include $(PVDATA_SRC)/copy/Makefile
include $(PVDATA_SRC)/pvMisc/Makefile
include $(PVDATA_SRC)/monitor/Makefile
LIBRARY = pvData
pvData_LIBS += Com
include $(TOP)/configure/RULES

9
src/copy/Makefile Normal file
View File

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

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

@@ -0,0 +1,483 @@
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* pvAccessCPP is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#include <string>
#include <sstream>
#define epicsExportSharedSymbols
#include <pv/pvData.h>
#include <pv/lock.h>
#include <pv/createRequest.h>
using namespace epics::pvData;
using std::ostringstream;
using std::tr1::static_pointer_cast;
using std::cout;
using std::endl;
using std::string;
using std::vector;
namespace epics { namespace pvData {
static PVDataCreatePtr pvDataCreate = getPVDataCreate();
static FieldCreatePtr fieldCreate = getFieldCreate();
class CreateRequestImpl : public CreateRequest {
private:
struct Node
{
string name;
vector<Node> nodes;
Node(string name)
: name(name)
{}
};
struct OptionPair
{
string name;
string value;
OptionPair(string name,string value)
: name(name),
value(value)
{}
};
vector<OptionPair> optionList;
string fullFieldName;
public:
CreateRequestImpl()
{
fullFieldName = "";
}
private:
void removeBlanks(string& str)
{
while(true) {
string::size_type pos = str.find_first_of(' ');
if(pos==string::npos) return;
str.erase(pos,1);
}
}
size_t findMatchingBrace(string& request, size_t index, int numOpen) {
size_t openBrace = request.find('{', index+1);
size_t closeBrace = request.find('}', index+1);
if(openBrace == string::npos && closeBrace == string::npos){
message = request + " mismatched {}";
throw std::logic_error("message");
}
if (openBrace != string::npos && openBrace!=0) {
if(openBrace<closeBrace) return findMatchingBrace(request,openBrace,numOpen+1);
if(numOpen==1) return closeBrace;
return findMatchingBrace(request,closeBrace,numOpen-1);
}
if(numOpen==1) return closeBrace;
return findMatchingBrace(request,closeBrace,numOpen-1);
}
size_t findMatchingBracket(string& request, size_t index) {
for(size_t i=index+1; i< request.size(); ++i) {
if(request[i] == ']') {
if(i==index+1) {
message = request + " mismatched []";
throw std::logic_error("message");
}
return i;
}
}
message = request + " missing ]";
throw std::logic_error("message");
}
size_t findEndField(string& request) {
size_t ind = 0;
size_t maxind = request.size() -1;
while(true) {
if(request[ind]==',') return ind;
if(request[ind]=='[') {
size_t closeBracket = findMatchingBracket(request,ind);
if(closeBracket==string::npos) return closeBracket;
ind = closeBracket;
continue;
}
if(request[ind]=='{') {
size_t closeBrace = findMatchingBrace(request,ind,1);
if(closeBrace==string::npos) return closeBrace;
if(ind>=request.size()) return request.size();
ind = closeBrace;
continue;
}
if(request[ind]=='.') {
++ind;
continue;
}
if(ind>=maxind) break;
++ind;
}
return request.size();
}
vector<string> split(string const & commaSeparatedList) {
string::size_type numValues = 1;
string::size_type index=0;
while(true) {
string::size_type pos = commaSeparatedList.find(',',index);
if(pos==string::npos) break;
numValues++;
index = pos +1;
}
vector<string> valueList(numValues,"");
index=0;
for(size_t i=0; i<numValues; i++) {
size_t pos = commaSeparatedList.find(',',index);
string value = commaSeparatedList.substr(index,pos-index);
valueList[i] = value;
index = pos +1;
}
return valueList;
}
Node createRequestOptions(
string const & request)
{
if(request.length()<=1) {
throw std::logic_error("logic error empty options");
}
vector<Node> top;
vector<string> items = split(request);
size_t nitems = items.size();
for(size_t j=0; j<nitems; j++) {
string item = items[j];
size_t equals = item.find('=');
if(equals==string::npos || equals==0) {
message = item + " illegal option " + request;
throw std::logic_error("message");
}
top.push_back(Node(item.substr(0,equals)));
string name = fullFieldName + "._options." + item.substr(0,equals);
string value = item.substr(equals+1);
optionList.push_back(OptionPair(name,value));
}
Node node("_options");
node.nodes = top;
return node;
}
void createSubNode(Node &node,string const & crequest)
{
string request = crequest;
size_t end = 0;
for(size_t i=0; i<request.size(); ++i) {
if(request[i]=='[') { end = i; break;}
if(request[i]=='.') { end = i; break;}
if(request[i]=='{') { end = i; break;}
if(request[i]==',') { end = i; break;}
}
char chr = request[end];
Node optionNode("");
if(chr=='[') {
string saveFullName = fullFieldName;
fullFieldName += "." + request.substr(0,end);
size_t endBracket = findMatchingBracket(request,end);
string options = request.substr(end+1,endBracket -end -1);
optionNode = createRequestOptions(options);
fullFieldName = saveFullName;
size_t next = endBracket+1;
if(next<request.size()) {
request = request.substr(0, end) + request.substr(endBracket+1);
} else {
request = request.substr(0, end);
}
end = 0;
for(size_t i=0; i<request.size(); ++i) {
if(request[i]=='.') { end = i; break;}
if(request[i]=='{') { end = i; break;}
if(request[i]==',') { end = i; break;}
}
chr = request[end];
}
if(end==0) end = request.size();
string name = request.substr(0,end);
if(name.size()<1) {
throw std::logic_error("null field name " + request);
}
string saveFullName = fullFieldName;
fullFieldName += "." + name;
if(end==request.size()) {
Node subNode(name);
if(optionNode.name.size()>0) subNode.nodes.push_back(optionNode);
node.nodes.push_back(subNode);
fullFieldName = saveFullName;
return;
}
if(chr==',') {
Node subNode(name);
if(optionNode.name.size()>0) subNode.nodes.push_back(optionNode);
node.nodes.push_back(subNode);
string rest = request.substr(end+1);
fullFieldName = saveFullName;
createSubNode(node,rest);
return;
}
if(chr=='.') {
request = request.substr(end+1);
if(request.size()==string::npos || request.size()<1) {
throw std::logic_error("null field name " + request);
}
Node subNode(name);
if(optionNode.name.size()>0) subNode.nodes.push_back(optionNode);
size_t endField = findEndField(request);
string subRequest = request.substr(0, endField);
createSubNode(subNode,subRequest);
node.nodes.push_back(subNode);
size_t next = endField+1;
if(next>=request.size()) {
fullFieldName = saveFullName;
return;
}
request = request.substr(next);
fullFieldName = saveFullName;
createSubNode(node,request);
return;
}
if(chr=='{') {
size_t endBrace = findEndField(request);
if((end+1)>=(endBrace-1)) {
throw std::logic_error("illegal syntax " + request);
}
string subRequest = request.substr(end+1,endBrace-1 -end -1);
if(subRequest.size()<1) {
throw std::logic_error("empty {} " + request);
}
Node subNode(name);
if(optionNode.name.size()>0) subNode.nodes.push_back(optionNode);
createSubNode(subNode,subRequest);
node.nodes.push_back(subNode);
size_t next = endBrace + 1;
if(next>=request.size()) {
fullFieldName = saveFullName;
return;
}
request = request.substr(next);
fullFieldName = saveFullName;
createSubNode(node,request);
return;
}
throw std::logic_error("logic error");
}
FieldConstPtr createSubStructure(vector<Node> & nodes)
{
size_t num = nodes.size();
StringArray names(num);
FieldConstPtrArray fields(num);
for(size_t i=0; i<num; ++i) {
Node node = nodes[i];
names[i] = node.name;
if(node.name.compare("_options")==0) {
fields[i] = createOptions(node.nodes);
} else {
vector<Node> subNode = node.nodes;
if(subNode.empty()) {
fields[i] = fieldCreate->createStructure();
} else {
fields[i] = createSubStructure(subNode);
}
}
}
StructureConstPtr structure = fieldCreate->createStructure(
names, fields);
return structure;
}
StructureConstPtr createOptions(vector<Node> &nodes)
{
size_t num = nodes.size();
StringArray names(num);
FieldConstPtrArray fields(num);
for(size_t i=0; i<num; ++i) {
Node node = nodes[i];
names[i] = node.name;
fields[i] = fieldCreate->createScalar(pvString);
}
StructureConstPtr structure = fieldCreate->createStructure(names, fields);
return structure;
}
public:
virtual PVStructurePtr createRequest(
string const & crequest)
{
try {
string request = crequest;
if (!request.empty()) removeBlanks(request);
if (request.empty())
{
return pvDataCreate->createPVStructure(fieldCreate->createStructure());
}
size_t offsetRecord = request.find("record[");
size_t offsetField = request.find("field(");
size_t offsetPutField = request.find("putField(");
size_t offsetGetField = request.find("getField(");
if(offsetRecord==string::npos
&& offsetField==string::npos
&& offsetPutField==string::npos
&& offsetGetField==string::npos)
{
request = "field(" + request + ")";
offsetField = request.find("field(");
}
int numParan = 0;
int numBrace = 0;
int numBracket = 0;
for(size_t i=0; i< request.length() ; ++i) {
char chr = request[i];
if(chr=='(') numParan++;
if(chr==')') numParan--;
if(chr=='{') numBrace++;
if(chr=='}') numBrace--;
if(chr=='[') numBracket++;
if(chr==']') numBracket--;
}
if(numParan!=0) {
ostringstream oss;
oss << "mismatched () " << numParan;
message = oss.str();
return PVStructurePtr();
}
if(numBrace!=0) {
ostringstream oss;
oss << "mismatched {} " << numBrace;
message = oss.str();
return PVStructurePtr();
}
if(numBracket!=0) {
ostringstream oss;
oss << "mismatched [] " << numBracket;
message = oss.str();
return PVStructurePtr();
}
vector<Node> top;
try {
if(offsetRecord!=string::npos) {
fullFieldName = "record";
size_t openBracket = request.find('[', offsetRecord);
size_t closeBracket = request.find(']', openBracket);
if(closeBracket==string::npos) {
message = request.substr(offsetRecord) +
"record[ does not have matching ]";
return PVStructurePtr();
}
if(closeBracket-openBracket > 3) {
Node node("record");
Node optNode = createRequestOptions(
request.substr(openBracket+1,closeBracket-openBracket-1));
node.nodes.push_back(optNode);
top.push_back(node);
}
}
if(offsetField!=string::npos) {
fullFieldName = "field";
Node node("field");
size_t openParan = request.find('(', offsetField);
size_t closeParan = request.find(')', openParan);
if(closeParan==string::npos) {
message = request.substr(offsetField)
+ " field( does not have matching )";
return PVStructurePtr();
}
if(closeParan>openParan+1) {
createSubNode(node,request.substr(openParan+1,closeParan-openParan-1));
}
top.push_back(node);
}
if(offsetGetField!=string::npos) {
fullFieldName = "getField";
Node node("getField");
size_t openParan = request.find('(', offsetGetField);
size_t closeParan = request.find(')', openParan);
if(closeParan==string::npos) {
message = request.substr(offsetField)
+ " getField( does not have matching )";
return PVStructurePtr();
}
if(closeParan>openParan+1) {
createSubNode(node,request.substr(openParan+1,closeParan-openParan-1));
}
top.push_back(node);
}
if(offsetPutField!=string::npos) {
fullFieldName = "putField";
Node node("putField");
size_t openParan = request.find('(', offsetPutField);
size_t closeParan = request.find(')', openParan);
if(closeParan==string::npos) {
message = request.substr(offsetField)
+ " putField( does not have matching )";
return PVStructurePtr();
}
if(closeParan>openParan+1) {
createSubNode(node,request.substr(openParan+1,closeParan-openParan-1));
}
top.push_back(node);
}
} catch (std::exception &e) {
string xxx = e.what();
message = "while creating Structure exception " + xxx;
return PVStructurePtr();
}
size_t num = top.size();
StringArray names(num);
FieldConstPtrArray fields(num);
for(size_t i=0; i<num; ++i) {
Node node = top[i];
names[i] = node.name;
vector<Node> subNode = node.nodes;
if(subNode.empty()) {
fields[i] = fieldCreate->createStructure();
} else {
fields[i] = createSubStructure(subNode);
}
}
StructureConstPtr structure = fieldCreate->createStructure(names, fields);
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(structure);
for(size_t i=0; i<optionList.size(); ++i) {
OptionPair pair = optionList[i];
string name = pair.name;
string value = pair.value;
PVStringPtr pvField = pvStructure->getSubField<PVString>(name);
pvField->put(value);
}
optionList.clear();
return pvStructure;
} catch (std::exception &e) {
message = e.what();
return PVStructurePtr();
}
}
};
CreateRequest::shared_pointer CreateRequest::create()
{
CreateRequest::shared_pointer createRequest(new CreateRequestImpl());
return createRequest;
}
}}

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

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

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

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

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

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

349
src/factory/Compare.cpp Normal file
View File

@@ -0,0 +1,349 @@
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvData is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
/**
* @author mes
*/
#include <algorithm>
#include <iterator>
#include <sstream>
#define epicsExportSharedSymbols
#include <pv/convert.h>
using std::string;
namespace epics { namespace pvData {
// Introspection object comparision
/** Field equality conditions:
* 1) same instance
* 2) same type (field and scalar/element), same name, same subfields (if any)
*/
bool operator==(const Field& a, const Field& b)
{
if(&a==&b)
return true;
if(a.getType()!=b.getType())
return false;
switch(a.getType()) {
case scalar: {
const Scalar &A=static_cast<const Scalar&>(a);
const Scalar &B=static_cast<const Scalar&>(b);
return A==B;
}
case scalarArray: {
const ScalarArray &A=static_cast<const ScalarArray&>(a);
const ScalarArray &B=static_cast<const ScalarArray&>(b);
return A==B;
}
case structure: {
const Structure &A=static_cast<const Structure&>(a);
const Structure &B=static_cast<const Structure&>(b);
return A==B;
}
case structureArray: {
const StructureArray &A=static_cast<const StructureArray&>(a);
const StructureArray &B=static_cast<const StructureArray&>(b);
return A==B;
}
case union_: {
const Union &A=static_cast<const Union&>(a);
const Union &B=static_cast<const Union&>(b);
return A==B;
}
case unionArray: {
const UnionArray &A=static_cast<const UnionArray&>(a);
const UnionArray &B=static_cast<const UnionArray&>(b);
return A==B;
}
default:
throw std::logic_error("Invalid Field type in comparision");
}
}
bool operator==(const Scalar& a, const Scalar& b)
{
if(&a==&b)
return true;
return a.getScalarType()==b.getScalarType();
}
bool operator==(const ScalarArray& a, const ScalarArray& b)
{
if(&a==&b)
return true;
return a.getElementType()==b.getElementType();
}
bool operator==(const Structure& a, const Structure& b)
{
if(&a==&b)
return true;
if (a.getID()!=b.getID())
return false;
size_t nflds=a.getNumberFields();
if (b.getNumberFields()!=nflds)
return false;
// std::equals does not work, since FieldConstPtrArray is an array of shared_pointers
FieldConstPtrArray af = a.getFields();
FieldConstPtrArray 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();
return std::equal( an.begin(), an.end(), bn.begin() );
}
bool operator==(const StructureArray& a, const StructureArray& b)
{
return *(a.getStructure().get())==*(b.getStructure().get());
}
bool operator==(const Union& a, const Union& b)
{
if(&a==&b)
return true;
if (a.getID()!=b.getID())
return false;
size_t nflds=a.getNumberFields();
if (b.getNumberFields()!=nflds)
return false;
// std::equals does not work, since FieldConstPtrArray is an array of shared_pointers
FieldConstPtrArray af = a.getFields();
FieldConstPtrArray 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();
return std::equal( an.begin(), an.end(), bn.begin() );
}
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 {
// fully typed comparisons
template<typename T>
bool compareScalar(const PVScalarValue<T>* left, const PVScalarValue<T>* right)
{
return left->get()==right->get();
}
template<typename T>
bool compareArray(const PVValueArray<T>* left, const PVValueArray<T>* right)
{
typename PVValueArray<T>::const_svector lhs(left->view()), rhs(right->view());
return std::equal(lhs.begin(), lhs.end(), rhs.begin());
}
// partially typed comparisons
bool compareField(const PVScalar* left, const PVScalar* right)
{
ScalarType lht = left->getScalar()->getScalarType();
if(lht != right->getScalar()->getScalarType())
return false;
switch(lht) {
#define OP(ENUM, TYPE) case ENUM: return compareScalar(static_cast<const PVScalarValue<TYPE>*>(left), static_cast<const PVScalarValue<TYPE>*>(right))
OP(pvBoolean, uint8);
OP(pvUByte, uint8);
OP(pvByte, int8);
OP(pvUShort, uint16);
OP(pvShort, int16);
OP(pvUInt, uint32);
OP(pvInt, int32);
OP(pvULong, uint64);
OP(pvLong, int64);
OP(pvFloat, float);
OP(pvDouble, double);
#undef OP
case pvString: {
const PVString *a=static_cast<const PVString*>(left), *b=static_cast<const PVString*>(right);
return a->get()==b->get();
}
}
throw std::logic_error("PVScalar with invalid scalar type!");
}
bool compareField(const PVScalarArray* left, const PVScalarArray* right)
{
ScalarType lht = left->getScalarArray()->getElementType();
if(lht != right->getScalarArray()->getElementType())
return false;
if(left->getLength()!=right->getLength())
return false;
switch(lht) {
#define OP(ENUM, TYPE) case ENUM: return compareArray(static_cast<const PVValueArray<TYPE>*>(left), static_cast<const PVValueArray<TYPE>*>(right))
OP(pvBoolean, uint8);
OP(pvUByte, uint8);
OP(pvByte, int8);
OP(pvUShort, uint16);
OP(pvShort, int16);
OP(pvUInt, uint32);
OP(pvInt, int32);
OP(pvULong, uint64);
OP(pvLong, int64);
OP(pvFloat, float);
OP(pvDouble, double);
OP(pvString, string);
#undef OP
}
throw std::logic_error("PVScalarArray with invalid element type!");
}
bool compareField(const PVStructure* left, const PVStructure* right)
{
StructureConstPtr ls = left->getStructure();
if(*ls!=*right->getStructure())
return false;
const PVFieldPtrArray& lf = left->getPVFields();
const PVFieldPtrArray& rf = right->getPVFields();
for(size_t i=0, nfld=ls->getNumberFields(); i<nfld; i++) {
if(*lf[i]!=*rf[i])
return false;
}
return true;
}
bool compareField(const PVStructureArray* left, const PVStructureArray* right)
{
if(*left->getStructureArray()->getStructure()
!= *right->getStructureArray()->getStructure())
return false;
PVStructureArray::const_svector ld=left->view(), rd=right->view();
if(ld.size()!=rd.size())
return false;
PVStructureArray::const_svector::const_iterator lit, lend, rit;
for(lit=ld.begin(), lend=ld.end(), rit=rd.begin();
lit!=lend;
++lit, ++rit)
{
// element can be null
if (!(*lit) || !(*rit))
{
if (*lit || *rit)
return false;
}
else if (**lit != **rit)
return false;
}
return true;
}
bool compareField(const PVUnion* left, const PVUnion* right)
{
UnionConstPtr ls = left->getUnion();
if(*ls!=*right->getUnion())
return false;
if (ls->isVariant())
{
PVFieldPtr lval = left->get();
if (lval.get() == 0)
return right->get().get() == 0;
else
return *(lval.get()) == *(right->get().get());
}
else
{
int32 lix = left->getSelectedIndex();
if (lix == right->getSelectedIndex())
{
if (lix == PVUnion::UNDEFINED_INDEX || *(left->get()) == *(right->get().get()))
return true;
else
return false;
}
else
return false;
}
}
bool compareField(const PVUnionArray* left, const PVUnionArray* right)
{
if(*left->getUnionArray()->getUnion()
!= *right->getUnionArray()->getUnion())
return false;
PVUnionArray::const_svector ld=left->view(), rd=right->view();
if(ld.size()!=rd.size())
return false;
PVUnionArray::const_svector::const_iterator lit, lend, rit;
for(lit=ld.begin(), lend=ld.end(), rit=rd.begin();
lit!=lend;
++lit, ++rit)
{
// element can be null
if (!(*lit) || !(*rit))
{
if (*lit || *rit)
return false;
}
else if (**lit != **rit)
return false;
}
return true;
}
} // end namespace
// untyped comparison
bool operator==(const PVField& left, const PVField& right)
{
if(&left == &right)
return true;
Type lht = left.getField()->getType();
if(lht != right.getField()->getType())
return false;
switch(lht) {
case scalar: return compareField(static_cast<const PVScalar*>(&left), static_cast<const PVScalar*>(&right));
case scalarArray: return compareField(static_cast<const PVScalarArray*>(&left), static_cast<const PVScalarArray*>(&right));
case structure: return compareField(static_cast<const PVStructure*>(&left), static_cast<const PVStructure*>(&right));
case structureArray: return compareField(static_cast<const PVStructureArray*>(&left), static_cast<const PVStructureArray*>(&right));
case union_: return compareField(static_cast<const PVUnion*>(&left), static_cast<const PVUnion*>(&right));
case unionArray: return compareField(static_cast<const PVUnionArray*>(&left), static_cast<const PVUnionArray*>(&right));
}
throw std::logic_error("PVField with invalid type!");
}
}} // namespace epics::pvData

532
src/factory/Convert.cpp Normal file
View File

@@ -0,0 +1,532 @@
/* Convert.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvData is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
/**
* @author mrk
*/
#include <cstdio>
#include <string>
#include <vector>
#include <stdexcept>
#include <typeinfo>
#define epicsExportSharedSymbols
#include <pv/lock.h>
#include <pv/pvIntrospect.h>
#include <pv/pvData.h>
#include <pv/convert.h>
using std::tr1::static_pointer_cast;
using std::size_t;
using std::string;
namespace epics { namespace pvData {
static std::vector<string> split(string commaSeparatedList) {
string::size_type numValues = 1;
string::size_type index=0;
while(true) {
string::size_type pos = commaSeparatedList.find(',',index);
if(pos==string::npos) break;
numValues++;
index = pos +1;
}
std::vector<string> valueList(numValues,"");
index=0;
for(size_t i=0; i<numValues; i++) {
size_t pos = commaSeparatedList.find(',',index);
string value = commaSeparatedList.substr(index,pos);
valueList[i] = value;
index = pos +1;
}
return valueList;
}
void Convert::getString(string *buf,PVField const *pvField,int /*indentLevel*/)
{
// TODO indextLevel ignored
std::ostringstream strm;
pvField->dumpValue(strm);
strm << std::endl;
// PrinterPlain p;
// p.setStream(strm);
// p.print(*pvField);
strm.str().swap(*buf);
}
size_t Convert::fromString(PVStructurePtr const &pvStructure, StringArray const & from, size_t fromStartIndex)
{
size_t processed = 0;
PVFieldPtrArray const & fieldsData = pvStructure->getPVFields();
if (fieldsData.size() != 0) {
size_t length = pvStructure->getStructure()->getNumberFields();
for(size_t i=0; i<length; i++) {
PVFieldPtr fieldField = fieldsData[i];
Type type = fieldField->getField()->getType();
if(type==structure) {
PVStructurePtr pv = static_pointer_cast<PVStructure>(fieldField);
size_t count = fromString(pv, from, fromStartIndex);
processed += count;
fromStartIndex += count;
}
else if(type==scalarArray) {
PVScalarArrayPtr pv = static_pointer_cast<PVScalarArray>(fieldField);
size_t count = fromString(pv, from[fromStartIndex]);
processed += count;
fromStartIndex += count;
}
else if(type==scalar) {
PVScalarPtr pv = static_pointer_cast<PVScalar>(fieldField);
fromString(pv, from[fromStartIndex++]);
processed++;
}
else {
// union, structureArray, unionArray not supported
std::ostringstream oss;
oss << "Convert::fromString unsupported fieldType " << type;
throw std::logic_error(oss.str());
}
}
}
return processed;
}
size_t Convert::fromString(PVScalarArrayPtr const &pv, string from)
{
if(from[0]=='[' && from[from.length()]==']') {
size_t offset = from.rfind(']');
from = from.substr(1, offset);
}
std::vector<string> valueList(split(from));
size_t length = valueList.size();
size_t num = fromStringArray(pv,0,length,valueList,0);
if(num<length) length = num;
pv->setLength(length);
return length;
}
size_t Convert::fromStringArray(PVScalarArrayPtr const &pv,
size_t offset, size_t length,
StringArray const & from,
size_t fromOffset)
{
size_t alen = pv->getLength();
if(offset==0 && length>=alen) {
// replace all existing elements
assert(from.size()>=fromOffset+length);
PVStringArray::svector data(length);
std::copy(from.begin()+fromOffset,
from.begin()+fromOffset+length,
data.begin());
PVStringArray::const_svector temp(freeze(data));
pv->putFrom<string>(temp);
return length;
} else {
// partial update.
throw std::runtime_error("fromStringArray: partial update not implemented");
}
}
size_t Convert::toStringArray(PVScalarArrayPtr const & pv,
size_t offset, size_t length,
StringArray &to, size_t toOffset)
{
PVStringArray::const_svector data;
pv->getAs<string>(data);
data.slice(offset, length);
if(toOffset+data.size() > to.size())
to.resize(toOffset+data.size());
std::copy(data.begin()+toOffset, data.end(), to.begin());
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())
{
to->set(from->get());
}
else
{
if (fromValue.get() == 0)
to->select(PVUnion::UNDEFINED_INDEX);
else
to->set(from->getSelectedIndex(),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;
static Mutex mutex;
Lock xx(mutex);
if(convert.get()==0) {
convert = ConvertPtr(new Convert());
}
return convert;
}
}}

File diff suppressed because it is too large Load Diff

23
src/factory/Makefile Normal file
View File

@@ -0,0 +1,23 @@
# This is a Makefile fragment, see ../Makefile
SRC_DIRS += $(PVDATA_SRC)/factory
INC += factory.h
LIBSRCS += TypeFunc.cpp
LIBSRCS += FieldCreateFactory.cpp
LIBSRCS += PVField.cpp
LIBSRCS += PVScalar.cpp
LIBSRCS += PVArray.cpp
LIBSRCS += PVScalarArray.cpp
LIBSRCS += PVStructure.cpp
LIBSRCS += PVStructureArray.cpp
LIBSRCS += PVUnion.cpp
LIBSRCS += PVUnionArray.cpp
LIBSRCS += PVDataCreateFactory.cpp
LIBSRCS += Convert.cpp
LIBSRCS += pvSubArrayCopy.cpp
LIBSRCS += Compare.cpp
LIBSRCS += StandardField.cpp
LIBSRCS += StandardPVField.cpp
LIBSRCS += printer.cpp

56
src/factory/PVArray.cpp Normal file
View File

@@ -0,0 +1,56 @@
/*PVArray.cpp*/
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvData is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
/**
* @author mrk
*/
#include <cstddef>
#include <cstdlib>
#include <string>
#include <cstdio>
#define epicsExportSharedSymbols
#include <pv/pvData.h>
#include <pv/factory.h>
using std::size_t;
namespace epics { namespace pvData {
PVArray::PVArray(FieldConstPtr const & field)
: PVField(field),capacityMutable(true)
{ }
void PVArray::setImmutable()
{
capacityMutable = false;
PVField::setImmutable();
}
bool PVArray::isCapacityMutable() const
{
if(PVField::isImmutable()) {
return false;
}
return capacityMutable;
}
void PVArray::setCapacityMutable(bool isMutable)
{
if(isMutable && PVField::isImmutable()) {
throw std::runtime_error("field is immutable");
}
capacityMutable = isMutable;
}
std::ostream& operator<<(format::array_at_internal const& manip, const PVArray& array)
{
return array.dumpValue(manip.stream, manip.index);
}
}}

View File

@@ -0,0 +1,743 @@
/*PVDataCreateFactory.cpp*/
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvData is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
/**
* @author mrk
*/
#ifdef _WIN32
#define NOMINMAX
#endif
#include <cstddef>
#include <cstdlib>
#include <string>
#include <cstdio>
#define epicsExportSharedSymbols
#include <pv/lock.h>
#include <pv/pvIntrospect.h>
#include <pv/pvData.h>
#include <pv/convert.h>
#include <pv/factory.h>
#include <pv/serializeHelper.h>
using std::tr1::static_pointer_cast;
using std::size_t;
using std::string;
using std::min;
namespace epics { namespace pvData {
template<> const ScalarType PVBoolean::typeCode = pvBoolean;
template<> const ScalarType PVByte::typeCode = pvByte;
template<> const ScalarType PVShort::typeCode = pvShort;
template<> const ScalarType PVInt::typeCode = pvInt;
template<> const ScalarType PVLong::typeCode = pvLong;
template<> const ScalarType PVUByte::typeCode = pvUByte;
template<> const ScalarType PVUShort::typeCode = pvUShort;
template<> const ScalarType PVUInt::typeCode = pvUInt;
template<> const ScalarType PVULong::typeCode = pvULong;
template<> const ScalarType PVFloat::typeCode = pvFloat;
template<> const ScalarType PVDouble::typeCode = pvDouble;
template<> const ScalarType PVScalarValue<string>::typeCode = pvString;
template<> const ScalarType PVBooleanArray::typeCode = pvBoolean;
template<> const ScalarType PVByteArray::typeCode = pvByte;
template<> const ScalarType PVShortArray::typeCode = pvShort;
template<> const ScalarType PVIntArray::typeCode = pvInt;
template<> const ScalarType PVLongArray::typeCode = pvLong;
template<> const ScalarType PVUByteArray::typeCode = pvUByte;
template<> const ScalarType PVUShortArray::typeCode = pvUShort;
template<> const ScalarType PVUIntArray::typeCode = pvUInt;
template<> const ScalarType PVULongArray::typeCode = pvULong;
template<> const ScalarType PVFloatArray::typeCode = pvFloat;
template<> const ScalarType PVDoubleArray::typeCode = pvDouble;
template<> const ScalarType PVStringArray::typeCode = pvString;
/** Default storage for scalar values
*/
template<typename T>
class BasePVScalar : public PVScalarValue<T> {
public:
typedef T value_type;
typedef T* pointer;
typedef const T* const_pointer;
BasePVScalar(ScalarConstPtr const & scalar);
virtual ~BasePVScalar();
virtual T get() const ;
virtual void put(T val);
virtual void serialize(ByteBuffer *pbuffer,
SerializableControl *pflusher) const;
virtual void deserialize(ByteBuffer *pbuffer,
DeserializableControl *pflusher);
private:
T value;
};
template<typename T>
BasePVScalar<T>::BasePVScalar(ScalarConstPtr const & scalar)
: PVScalarValue<T>(scalar),value(0)
{}
//Note: '0' is a suitable default for all POD types (not string)
template<typename T>
BasePVScalar<T>::~BasePVScalar() {}
template<typename T>
T BasePVScalar<T>::get() const { return value;}
template<typename T>
void BasePVScalar<T>::put(T val)
{
value = val;
PVField::postPut();
}
template<typename T>
void BasePVScalar<T>::serialize(ByteBuffer *pbuffer,
SerializableControl *pflusher) const {
pflusher->ensureBuffer(sizeof(T));
pbuffer->put(value);
}
template<typename T>
void BasePVScalar<T>::deserialize(ByteBuffer *pbuffer,
DeserializableControl *pflusher)
{
pflusher->ensureData(sizeof(T));
value = pbuffer->GET(T);
}
typedef BasePVScalar<boolean> BasePVBoolean;
typedef BasePVScalar<int8> BasePVByte;
typedef BasePVScalar<int16> BasePVShort;
typedef BasePVScalar<int32> BasePVInt;
typedef BasePVScalar<int64> BasePVLong;
typedef BasePVScalar<uint8> BasePVUByte;
typedef BasePVScalar<uint16> BasePVUShort;
typedef BasePVScalar<uint32> BasePVUInt;
typedef BasePVScalar<uint64> BasePVULong;
typedef BasePVScalar<float> BasePVFloat;
typedef BasePVScalar<double> BasePVDouble;
// BasePVString is special case, since it implements SerializableArray
class BasePVString : public PVString {
public:
typedef string value_type;
typedef string* pointer;
typedef const string* const_pointer;
BasePVString(ScalarConstPtr const & scalar);
virtual ~BasePVString();
virtual string get() const ;
virtual void put(string val);
virtual void serialize(ByteBuffer *pbuffer,
SerializableControl *pflusher) const;
virtual void deserialize(ByteBuffer *pbuffer,
DeserializableControl *pflusher);
virtual void serialize(ByteBuffer *pbuffer,
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() {}
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();
}
void BasePVString::serialize(ByteBuffer *pbuffer,
SerializableControl *pflusher) const
{
SerializeHelper::serializeString(value, pbuffer, pflusher);
}
void BasePVString::deserialize(ByteBuffer *pbuffer,
DeserializableControl *pflusher)
{
value = SerializeHelper::deserializeString(pbuffer, pflusher);
}
void BasePVString::serialize(ByteBuffer *pbuffer,
SerializableControl *pflusher, size_t offset, size_t count) const
{
// check bounds
const size_t length = /*(value == null) ? 0 :*/ value.length();
/*if (offset < 0) offset = 0;
else*/ if (offset > length) offset = length;
//if (count < 0) count = length;
const size_t maxCount = length - offset;
if (count > maxCount)
count = maxCount;
// write
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>
class DefaultPVArray : public PVValueArray<T> {
public:
typedef T* pointer;
typedef const T* const_pointer;
typedef std::vector<T> vector;
typedef const std::vector<T> const_vector;
typedef std::tr1::shared_ptr<vector> shared_vector;
typedef ::epics::pvData::shared_vector<T> svector;
typedef ::epics::pvData::shared_vector<const T> const_svector;
DefaultPVArray(ScalarArrayConstPtr const & scalarArray);
virtual ~DefaultPVArray();
virtual size_t getLength() const {return value.size();}
virtual size_t getCapacity() const {return value.capacity();}
virtual void setCapacity(size_t capacity);
virtual void setLength(size_t length);
virtual const_svector view() const {return value;}
virtual void swap(const_svector &other);
virtual void replace(const const_svector& next);
// from Serializable
virtual void serialize(ByteBuffer *pbuffer,SerializableControl *pflusher) const;
virtual void deserialize(ByteBuffer *pbuffer,DeserializableControl *pflusher);
virtual void serialize(ByteBuffer *pbuffer,
SerializableControl *pflusher, size_t offset, size_t count) const;
private:
const_svector value;
};
template<typename T>
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()
{ }
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())
return;
this->checkLength(length);
if (length < value.size())
value.slice(0, length);
else
value.resize(length);
}
template<typename T>
void DefaultPVArray<T>::replace(const const_svector& next)
{
this->checkLength(next.size());
value = next;
this->postPut();
}
template<typename T>
void DefaultPVArray<T>::swap(const_svector &other)
{
if (this->isImmutable())
THROW_EXCEPTION2(std::logic_error, "immutable");
// no checkLength call here
value.swap(other);
}
template<typename T>
void DefaultPVArray<T>::serialize(ByteBuffer *pbuffer,
SerializableControl *pflusher) const {
serialize(pbuffer, pflusher, 0, this->getLength());
}
template<typename T>
void DefaultPVArray<T>::deserialize(ByteBuffer *pbuffer,
DeserializableControl *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
T* cur = nextvalue.data();
// try to avoid deserializing from the buffer
// this is only possible if we do not need to do endian-swapping
if (!pbuffer->reverse<T>())
if (pcontrol->directDeserialize(pbuffer, (char*)cur, size, sizeof(T)))
{
// inform about the change?
PVField::postPut();
return;
}
// retrieve value from the buffer
size_t remaining = size;
while(remaining) {
const size_t have_bytes = pbuffer->getRemaining();
// correctly rounds down in an element is partially received
const size_t available = have_bytes/sizeof(T);
if(available == 0) {
// get at least one element
pcontrol->ensureData(sizeof(T));
continue;
}
const size_t n2read = std::min(remaining, available);
pbuffer->getArray(cur, n2read);
cur += n2read;
remaining -= n2read;
}
value = freeze(nextvalue);
// TODO !!!
// inform about the change?
PVField::postPut();
}
template<typename T>
void DefaultPVArray<T>::serialize(ByteBuffer *pbuffer,
SerializableControl *pflusher, size_t offset, size_t count) const
{
//TODO: avoid incrementing the ref counter...
const_svector temp(value);
temp.slice(offset, count);
count = temp.size();
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();
// try to avoid copying into the buffer
// this is only possible if we do not need to do endian-swapping
if (!pbuffer->reverse<T>())
if (pflusher->directSerialize(pbuffer, (const char*)cur, count, sizeof(T)))
return;
while(count) {
const size_t empty = pbuffer->getRemaining();
const size_t space_for = empty/sizeof(T);
if(space_for==0) {
pflusher->flushSerializeBuffer();
// Can we be certain that more space is now free???
// If not then we spinnnnnnnnn
continue;
}
const size_t n2send = std::min(count, space_for);
pbuffer->putArray(cur, n2send);
cur += n2send;
count -= n2send;
}
}
// specializations for string
template<>
void DefaultPVArray<string>::deserialize(ByteBuffer *pbuffer,
DeserializableControl *pcontrol) {
size_t size = this->getArray()->getArraySizeType() == Array::fixed ?
this->getArray()->getMaximumCapacity() :
SerializeHelper::readSize(pbuffer, pcontrol);
svector nextvalue(thaw(value));
// Decide if we must re-allocate
if(size > nextvalue.size() || !nextvalue.unique())
nextvalue.resize(size);
else if(size < nextvalue.size())
nextvalue.slice(0, size);
string * pvalue = nextvalue.data();
for(size_t i = 0; i<size; i++) {
pvalue[i] = SerializeHelper::deserializeString(pbuffer,
pcontrol);
}
value = freeze(nextvalue);
// inform about the change?
postPut();
}
template<>
void DefaultPVArray<string>::serialize(ByteBuffer *pbuffer,
SerializableControl *pflusher, size_t offset, size_t count) const {
const_svector temp(value);
temp.slice(offset, count);
// 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++) {
SerializeHelper::serializeString(pvalue[i], pbuffer, pflusher);
}
}
typedef DefaultPVArray<boolean> DefaultPVBooleanArray;
typedef DefaultPVArray<int8> BasePVByteArray;
typedef DefaultPVArray<int16> BasePVShortArray;
typedef DefaultPVArray<int32> BasePVIntArray;
typedef DefaultPVArray<int64> BasePVLongArray;
typedef DefaultPVArray<uint8> BasePVUByteArray;
typedef DefaultPVArray<uint16> BasePVUShortArray;
typedef DefaultPVArray<uint32> BasePVUIntArray;
typedef DefaultPVArray<uint64> BasePVULongArray;
typedef DefaultPVArray<float> BasePVFloatArray;
typedef DefaultPVArray<double> BasePVDoubleArray;
typedef DefaultPVArray<string> BasePVStringArray;
// Factory
PVDataCreate::PVDataCreate()
: fieldCreate(getFieldCreate())
{ }
PVFieldPtr PVDataCreate::createPVField(FieldConstPtr const & field)
{
switch(field->getType()) {
case scalar: {
ScalarConstPtr xx = static_pointer_cast<const Scalar>(field);
return createPVScalar(xx);
}
case scalarArray: {
ScalarArrayConstPtr xx = static_pointer_cast<const ScalarArray>(field);
return createPVScalarArray(xx);
}
case structure: {
StructureConstPtr xx = static_pointer_cast<const Structure>(field);
return createPVStructure(xx);
}
case structureArray: {
StructureArrayConstPtr xx = static_pointer_cast<const StructureArray>(field);
return createPVStructureArray(xx);
}
case union_: {
UnionConstPtr xx = static_pointer_cast<const Union>(field);
return createPVUnion(xx);
}
case unionArray: {
UnionArrayConstPtr xx = static_pointer_cast<const UnionArray>(field);
return createPVUnionArray(xx);
}
}
throw std::logic_error("PVDataCreate::createPVField should never get here");
}
PVFieldPtr PVDataCreate::createPVField(PVFieldPtr const & fieldToClone)
{
switch(fieldToClone->getField()->getType()) {
case scalar:
{
PVScalarPtr pvScalar = static_pointer_cast<PVScalar>(fieldToClone);
return createPVScalar(pvScalar);
}
case scalarArray:
{
PVScalarArrayPtr pvScalarArray
= static_pointer_cast<PVScalarArray>(fieldToClone);
return createPVScalarArray(pvScalarArray);
}
case structure:
{
PVStructurePtr pvStructure
= static_pointer_cast<PVStructure>(fieldToClone);
StringArray const & fieldNames = pvStructure->getStructure()->getFieldNames();
PVFieldPtrArray pvFieldPtrArray = pvStructure->getPVFields();
return createPVStructure(fieldNames,pvFieldPtrArray);
}
case structureArray:
{
PVStructureArrayPtr from
= static_pointer_cast<PVStructureArray>(fieldToClone);
StructureArrayConstPtr structureArray = from->getStructureArray();
PVStructureArrayPtr to = createPVStructureArray(
structureArray);
getConvert()->copyStructureArray(from, to);
return to;
}
case union_:
{
PVUnionPtr pvUnion
= static_pointer_cast<PVUnion>(fieldToClone);
return createPVUnion(pvUnion);
}
case unionArray:
{
PVUnionArrayPtr from
= static_pointer_cast<PVUnionArray>(fieldToClone);
UnionArrayConstPtr unionArray = from->getUnionArray();
PVUnionArrayPtr to = createPVUnionArray(unionArray);
getConvert()->copyUnionArray(from, to);
return to;
}
}
throw std::logic_error("PVDataCreate::createPVField should never get here");
}
PVScalarPtr PVDataCreate::createPVScalar(ScalarConstPtr const & scalar)
{
ScalarType scalarType = scalar->getScalarType();
switch(scalarType) {
case pvBoolean:
return PVScalarPtr(new BasePVBoolean(scalar));
case pvByte:
return PVScalarPtr(new BasePVByte(scalar));
case pvShort:
return PVScalarPtr(new BasePVShort(scalar));
case pvInt:
return PVScalarPtr(new BasePVInt(scalar));
case pvLong:
return PVScalarPtr(new BasePVLong(scalar));
case pvUByte:
return PVScalarPtr(new BasePVUByte(scalar));
case pvUShort:
return PVScalarPtr(new BasePVUShort(scalar));
case pvUInt:
return PVScalarPtr(new BasePVUInt(scalar));
case pvULong:
return PVScalarPtr(new BasePVULong(scalar));
case pvFloat:
return PVScalarPtr(new BasePVFloat(scalar));
case pvDouble:
return PVScalarPtr(new BasePVDouble(scalar));
case pvString:
return PVScalarPtr(new BasePVString(scalar));
}
throw std::logic_error("PVDataCreate::createPVScalar should never get here");
}
PVScalarPtr PVDataCreate::createPVScalar(ScalarType scalarType)
{
ScalarConstPtr scalar = fieldCreate->createScalar(scalarType);
return createPVScalar(scalar);
}
PVScalarPtr PVDataCreate::createPVScalar(PVScalarPtr const & scalarToClone)
{
ScalarType scalarType = scalarToClone->getScalar()->getScalarType();
PVScalarPtr pvScalar = createPVScalar(scalarType);
getConvert()->copyScalar(scalarToClone, pvScalar);
return pvScalar;
}
PVScalarArrayPtr PVDataCreate::createPVScalarArray(
ScalarArrayConstPtr const & scalarArray)
{
switch(scalarArray->getElementType()) {
case pvBoolean:
return PVScalarArrayPtr(new DefaultPVBooleanArray(scalarArray));
case pvByte:
return PVScalarArrayPtr(new BasePVByteArray(scalarArray));
case pvShort:
return PVScalarArrayPtr(new BasePVShortArray(scalarArray));
case pvInt:
return PVScalarArrayPtr(new BasePVIntArray(scalarArray));
case pvLong:
return PVScalarArrayPtr(new BasePVLongArray(scalarArray));
case pvUByte:
return PVScalarArrayPtr(new BasePVUByteArray(scalarArray));
case pvUShort:
return PVScalarArrayPtr(new BasePVUShortArray(scalarArray));
case pvUInt:
return PVScalarArrayPtr(new BasePVUIntArray(scalarArray));
case pvULong:
return PVScalarArrayPtr(new BasePVULongArray(scalarArray));
case pvFloat:
return PVScalarArrayPtr(new BasePVFloatArray(scalarArray));
case pvDouble:
return PVScalarArrayPtr(new BasePVDoubleArray(scalarArray));
case pvString:
return PVScalarArrayPtr(new BasePVStringArray(scalarArray));
}
throw std::logic_error("PVDataCreate::createPVScalarArray should never get here");
}
PVScalarArrayPtr PVDataCreate::createPVScalarArray(
ScalarType elementType)
{
ScalarArrayConstPtr scalarArray = fieldCreate->createScalarArray(elementType);
return createPVScalarArray(scalarArray);
}
PVScalarArrayPtr PVDataCreate::createPVScalarArray(
PVScalarArrayPtr const & arrayToClone)
{
PVScalarArrayPtr pvArray = createPVScalarArray(
arrayToClone->getScalarArray()->getElementType());
pvArray->assign(*arrayToClone.get());
return pvArray;
}
PVStructureArrayPtr PVDataCreate::createPVStructureArray(
StructureArrayConstPtr const & structureArray)
{
return PVStructureArrayPtr(new PVStructureArray(structureArray));
}
PVStructurePtr PVDataCreate::createPVStructure(
StructureConstPtr const & structure)
{
return PVStructurePtr(new PVStructure(structure));
}
PVUnionArrayPtr PVDataCreate::createPVUnionArray(
UnionArrayConstPtr const & unionArray)
{
return PVUnionArrayPtr(new PVUnionArray(unionArray));
}
PVUnionPtr PVDataCreate::createPVUnion(
UnionConstPtr const & punion)
{
return PVUnionPtr(new PVUnion(punion));
}
PVUnionPtr PVDataCreate::createPVVariantUnion()
{
return PVUnionPtr(new PVUnion(fieldCreate->createVariantUnion()));
}
PVUnionArrayPtr PVDataCreate::createPVVariantUnionArray()
{
return PVUnionArrayPtr(new PVUnionArray(fieldCreate->createVariantUnionArray()));
}
PVStructurePtr PVDataCreate::createPVStructure(
StringArray const & fieldNames,PVFieldPtrArray const & pvFields)
{
size_t num = fieldNames.size();
FieldConstPtrArray fields(num);
for (size_t i=0;i<num;i++) fields[i] = pvFields[i]->getField();
StructureConstPtr structure = fieldCreate->createStructure(fieldNames,fields);
PVStructurePtr pvStructure(new PVStructure(structure,pvFields));
return pvStructure;
}
PVStructurePtr PVDataCreate::createPVStructure(PVStructurePtr const & structToClone)
{
FieldConstPtrArray field;
if(!structToClone) {
// is this correct?!
FieldConstPtrArray fields(0);
StringArray fieldNames(0);
StructureConstPtr structure = fieldCreate->createStructure(fieldNames,fields);
return PVStructurePtr(new PVStructure(structure));
}
StructureConstPtr structure = structToClone->getStructure();
PVStructurePtr pvStructure(new PVStructure(structure));
getConvert()->copyStructure(structToClone,pvStructure);
return pvStructure;
}
PVUnionPtr PVDataCreate::createPVUnion(PVUnionPtr const & unionToClone)
{
PVUnionPtr punion(new PVUnion(unionToClone->getUnion()));
// set cloned value
punion->set(unionToClone->getSelectedIndex(), createPVField(unionToClone->get()));
return punion;
}
// TODO not thread-safe (local static initializers)
// TODO replace with non-locking singleton pattern
PVDataCreatePtr PVDataCreate::getPVDataCreate()
{
static PVDataCreatePtr pvDataCreate;
static Mutex mutex;
Lock xx(mutex);
if(pvDataCreate.get()==0) pvDataCreate = PVDataCreatePtr(new PVDataCreate());
return pvDataCreate;
}
PVDataCreatePtr getPVDataCreate() {
return PVDataCreate::getPVDataCreate();
}
}}

183
src/factory/PVField.cpp Normal file
View File

@@ -0,0 +1,183 @@
/*PVField.cpp*/
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvData is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
/**
* @author mrk
*/
#include <cstddef>
#include <cstdlib>
#include <string>
#include <cstdio>
#define epicsExportSharedSymbols
#include <pv/lock.h>
#include <pv/pvData.h>
#include <pv/factory.h>
#include <pv/convert.h>
using std::tr1::const_pointer_cast;
using std::size_t;
using std::string;
namespace epics { namespace pvData {
PVField::PVField(FieldConstPtr field)
: notImplemented("not implemented"),
parent(NULL),field(field),
fieldOffset(0), nextFieldOffset(0),
immutable(false)
{
}
PVField::~PVField()
{ }
size_t PVField::getFieldOffset() const
{
if(nextFieldOffset==0) computeOffset(this);
return fieldOffset;
}
size_t PVField::getNextFieldOffset() const
{
if(nextFieldOffset==0) computeOffset(this);
return nextFieldOffset;
}
size_t PVField::getNumberFields() const
{
if(nextFieldOffset==0) computeOffset(this);
return (nextFieldOffset - fieldOffset);
}
bool PVField::isImmutable() const {return immutable;}
void PVField::setImmutable() {immutable = true;}
const FieldConstPtr & PVField::getField() const {return field;}
PVStructure *PVField::getParent() const {return parent;}
void PVField::postPut()
{
if(postHandler.get()!=NULL) postHandler->postPut();
}
void PVField::setPostHandler(PostHandlerPtr const &handler)
{
if(postHandler.get()!=NULL) {
if(postHandler.get()==handler.get()) return;
throw std::logic_error(
"PVField::setPostHandler a postHandler is already registered");
}
postHandler = handler;
}
void PVField::setParentAndName(PVStructure * xxx,string const & name)
{
parent = xxx;
fieldName = name;
}
bool PVField::equals(PVField &pv)
{
return pv==*this;
}
std::ostream& operator<<(std::ostream& o, const PVField& f)
{
return f.dumpValue(o);
};
string PVField::getFullName() const
{
string ret(fieldName);
for(PVField *fld=getParent(); fld; fld=fld->getParent())
{
if(fld->getFieldName().size()==0) break;
ret = fld->getFieldName() + '.' + ret;
}
return ret;
}
void PVField::computeOffset(const PVField * pvField) {
const PVStructure * pvTop = pvField->getParent();
if(pvTop==NULL) {
if(pvField->getField()->getType()!=structure) {
PVField *xxx = const_cast<PVField *>(pvField);
xxx->fieldOffset = 0;
xxx->nextFieldOffset = 1;
return;
}
pvTop = static_cast<const PVStructure *>(pvField);
} else {
while(pvTop->getParent()!=NULL) pvTop = pvTop->getParent();
}
size_t offset = 0;
size_t nextOffset = 1;
PVFieldPtrArray pvFields = pvTop->getPVFields();
for(size_t i=0; i < pvTop->getStructure()->getNumberFields(); i++) {
offset = nextOffset;
PVField *pvField = pvFields[i].get();
FieldConstPtr field = pvField->getField();
switch(field->getType()) {
case scalar:
case scalarArray:
case structureArray:
case union_:
case unionArray: {
nextOffset++;
pvField->fieldOffset = offset;
pvField->nextFieldOffset = nextOffset;
break;
}
case structure: {
pvField->computeOffset(pvField,offset);
nextOffset = pvField->getNextFieldOffset();
}
}
}
PVField *top = (PVField *)pvTop;
PVField *xxx = const_cast<PVField *>(top);
xxx->fieldOffset = 0;
xxx->nextFieldOffset = nextOffset;
}
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();
for(size_t i=0; i < pvStructure->getStructure()->getNumberFields(); i++) {
offset = nextOffset;
PVField *pvSubField = pvFields[i].get();
FieldConstPtr field = pvSubField->getField();
switch(field->getType()) {
case scalar:
case scalarArray:
case structureArray:
case union_:
case unionArray: {
nextOffset++;
pvSubField->fieldOffset = offset;
pvSubField->nextFieldOffset = nextOffset;
break;
}
case structure: {
pvSubField->computeOffset(pvSubField,offset);
nextOffset = pvSubField->getNextFieldOffset();
}
}
}
PVField *xxx = const_cast<PVField *>(pvField);
xxx->fieldOffset = beginOffset;
xxx->nextFieldOffset = nextOffset;
}
}}

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