210 Commits
4.0.0 ... 6.0.1

Author SHA1 Message Date
Andrew Johnson
e0367a2dd7 Update release notes and release date. 2016-09-14 17:01:51 -05:00
Andrew Johnson
1e0f1119e2 testTypeCast: mangle values to be printable
print  (u)int8 as integer instead of character

(cherry picked from commit da8ba56dd1)
2016-09-14 16:43:53 -05:00
Andrew Johnson
6d6314a924 #include <algorithm> required for MSVS 2015
(cherry picked from commit 4555f69733)
2016-09-14 16:33:37 -05:00
Dave Hickin
e0b881d036 Correction to documentation for 6.0.1 2016-09-14 11:25:30 +01:00
Dave Hickin
d24ff6c3d2 Update documentation for 6.0.1 2016-09-13 22:44:11 +01:00
Dave Hickin
ef17aac046 Update release notes for 6.0.1 2016-09-13 22:33:28 +01:00
Dave Hickin
83b63a9138 Fix for MinGW
Fixes #42
2016-09-07 15:14:17 +01:00
Dave Hickin
0a5ab8625d Update documentation for 6.0.0 2016-08-01 17:25:12 +01:00
Dave Hickin
a115c9cd15 Add release notes for 6.0.0 2016-08-01 17:23:11 +01:00
Dave Hickin
6ba40803d8 Add 5.0.x release notes 2016-08-01 15:00:36 +01:00
Dave Hickin
8d6094c55a jenkins: Remove COPYRIGHT from tar 2016-07-22 16:08:27 +01:00
Dave Hickin
d258acfc49 SHRLIB: Set version to 6.0 2016-07-22 16:02:21 +01:00
Dave Hickin
d9072402db Update source boilerplate for new LICENSE file 2016-07-22 15:56:43 +01:00
Dave Hickin
1a706e3842 Remove COPYRIGHT file
Copyright is now in LICENSE file
2016-07-22 15:33:50 +01:00
Dave Hickin
a227897504 Update LICENSE to new version 2016-07-22 15:33:20 +01:00
Ralph Lange
0833d68e91 jenkins: fix installE4 logic, add pvCommon dependency 2016-07-22 14:59:48 +02:00
Dave Hickin
99bab6796c Fix windows dynamic build error
Fix error introduced by #40. #include epicsThread.h in timer.cpp
before #defining epicsExportSharedSymbols. Avoids multiply-defined
symbols.
2016-07-20 15:33:20 +01:00
dhickin
0544187057 Merge pull request #40 from anjohnson/master
Resolve github #37 without cacheing epicsExportSharedSymbols
2016-07-20 14:39:25 +01:00
Andrew Johnson
e12e7b4d76 Resolve github #37 without cacheing epicsExportSharedSymbols 2016-07-19 18:40:58 -05:00
Ralph Lange
7609ac6f1e jenkins: fix syntax in local declaration 2016-07-19 22:09:03 +02:00
Ralph Lange
3c946a91e8 jenkins: use install functions, add BRANCH variable to doc script 2016-07-19 22:00:34 +02:00
Ralph Lange
2389ebd87e jenkins: fix CloudBees jobs (paths) 2016-07-12 19:39:50 +02:00
Ralph Lange
90ad497a6f Use environment variables; default Base = 3.15.4; new artifact paths 2016-07-12 15:45:30 +02:00
Ralph Lange
1bb0b6fe03 Use environment variables; new default version of Base 2016-07-12 14:53:21 +02:00
dhickin
c16c1df6fd Merge pull request #39 from dhickin/use_template_getSubField
Replace template getSubField with template version
2016-07-05 15:19:58 +01:00
dhickin
e460641711 Merge pull request #38 from dhickin/getSubField_overload
Add char* overload for non-template getSubField
2016-07-05 15:18:46 +01:00
Dave Hickin
1e980651a9 Use template getSubField when type known
Replace non-template getSubField with template version when PVField is
of a known, derived type.
2016-07-04 17:03:07 +01:00
Dave Hickin
028076e79c Add char* overload for non-template getSubField 2016-07-04 14:59:56 +01:00
dhickin
e5b6a88551 Merge pull request #30 from mdavidsaver/requestermsg
Default implementation for Requester::message()
2016-04-12 16:01:45 +01:00
Andrew Johnson
b18b4f236f Make the PVScalarValue explicit specializations inline
Microsoft's compiler seems to prefer this when building a static library.
2016-04-11 17:16:43 -05:00
Andrew Johnson
605d4e99b9 Remove remaining 'undef epicsExportSharedSymbols' stuff 2016-04-11 15:24:46 -05:00
Andrew Johnson
ad00b6465a Fix VxWorks build, add explanatory comments 2016-04-11 11:33:05 -05:00
dhickin
537ebd05f2 Merge pull request #36 from anjohnson/master
Support for additional Windows targets
2016-04-11 10:06:54 +01:00
Andrew Johnson
2ee8769752 Prevent redefinition of NOMINMAX
While this protection is not strictly necessary here, if someone
does a cut-and-paste into a header file it should be included.
2016-04-06 15:29:30 -05:00
Andrew Johnson
8d7f534d54 VxWorks fix in parseToPOD.cpp 2016-03-28 17:11:25 -05:00
Andrew Johnson
47bb62b051 Disable another useless MSVC warning 2016-03-28 16:41:29 -05:00
Andrew Johnson
50b8213781 Fix NEED_OLL_FUNCS for windows-x64 and Base-3.15 2016-03-28 16:41:29 -05:00
Andrew Johnson
fd1fe53b49 Use the EPICS_DEPRECATED macro from Base.
Neither USAGE_DEPRECATED nor USAGE_ERROR are currently used
in the V4 code-base.
2016-03-28 16:41:28 -05:00
Andrew Johnson
378def0a58 Fix logic for when to define strtoll() and strtoull()
Needed for MinGW and VxWorks when built against Base-3.15
2016-03-28 16:41:28 -05:00
Andrew Johnson
ed5f48b353 EPICS sources use vxWorks for arch-detection 2016-03-28 16:41:28 -05:00
Andrew Johnson
fa6c2c7683 EPICS sources use _MINGW for arch-detection 2016-03-28 16:41:28 -05:00
Andrew Johnson
3fadc9b481 Remove unnecessary includes from epicsException.h
Fix up byteBuffer.h and epicsException.cpp to match.
2016-03-28 16:41:28 -05:00
Andrew Johnson
c3d7fa0d26 Declare explicit specializations
Resolves duplicate symbol build error on MinGW.
2016-03-28 16:41:28 -05:00
Andrew Johnson
5c16357fe2 Don't redefine NOMINMAX (clean up MinGW warnings) 2016-03-28 16:41:28 -05:00
Andrew Johnson
ef2e6079ba Wrap WIN32 #pragma warning(disable) inside push/pop
Exclude from MinGW, G++ doesn't understand these pragmas.
2016-03-28 16:41:28 -05:00
Dave Hickin
18633288fb Documentation: Remove maturity and date comment 2016-03-18 21:48:06 +00:00
Dave Hickin
67daef7bcc Documentation: Remove old versions 2016-03-18 21:43:09 +00:00
Dave Hickin
5eb29dcfc4 Documentation: Change to release-based versioning
Replace dated documentation scheme by one using release version.
2016-03-18 21:41:33 +00:00
Michael Davidsaver
d2fc922ee7 remove unnecessary const_cast 2016-03-18 14:53:24 -04:00
Michael Davidsaver
d35010c1cb Status: remove m_emptyStringtring
No reason to have a global for this.
2016-03-18 14:53:10 -04:00
dhickin
bd4b65225c Merge pull request #28 from mdavidsaver/overhaulbitset
bitSet: macros and vector storage
2016-03-17 14:20:20 +00:00
dhickin
be95a62965 Merge pull request #31 from mdavidsaver/deprecatemonitiorplugin
Deprecate monitorPlugin.h
2016-03-15 14:46:53 +00:00
dhickin
4336d524af Merge pull request #33 from msekoranja/master
Minor Win32 compilation fix
2016-03-07 12:02:03 +00:00
Matej Sekoranja
ae7976fc01 Merge remote-tracking branch 'epics-base/master' 2016-03-06 21:33:43 +01:00
Matej Sekoranja
72f9dc4c7c win32 compilation fix 2016-03-06 21:29:04 +01:00
dhickin
84760648fe Merge pull request #29 from mdavidsaver/fixsharedvector 2016-03-02 13:56:06 +00:00
Michael Davidsaver
b0df40d9a6 testSharedVector more PG locals 2016-03-01 13:25:20 -05:00
Michael Davidsaver
139217914d deprecate monitorPlugin.h 2016-02-26 12:17:12 -05:00
Michael Davidsaver
efa5795193 Default implementation for Requester::message()
This is what many sub-classes do (or should)
so lets prepare to remove some boilerplate.
2016-02-26 12:16:28 -05:00
Michael Davidsaver
4f499aed01 remove PVField::notImplemented
An unused waste of space in every instance...
2016-02-26 12:13:23 -05:00
Michael Davidsaver
a8ba831f5e fix freeze() of shared_vector<void> 2016-02-26 12:13:23 -05:00
Michael Davidsaver
a90405c25a shared_vector update doc 2016-02-26 12:13:23 -05:00
Michael Davidsaver
4546fda8e9 note shared_vector casts which should fail 2016-02-26 12:13:23 -05:00
Michael Davidsaver
b02f771146 shared_vector: vtype lost when freeze/thaw untyped
The vtype code is not copied for freeze/thaw
of shared_vector<void> to/from shared_vector<const void>.
2016-02-26 12:13:23 -05:00
Michael Davidsaver
dc94b26e50 fix static_shared_vector_cast<>() no-op casting
Turns out that Enablers as typically used for
member functions don't work to select
constructors.

Move this selection logic to
struct detail::static_shared_vector_caster<>
to correctly allow no-op casts (eg. void to void).
Previously this would not compile.

Allows PVScalarArray getAs() and putFrom() using
shared_vector<const void>.
2016-02-26 12:13:23 -05:00
Michael Davidsaver
4c32f37ede bitSet: macros and vector storage
use std::vector<uint64> to manage storage.
Make some global variable "constants" into macros.
add swap()
2016-02-18 18:39:32 -05:00
Dave Hickin
336a8b3bc2 Fix win32 deserialization test fail 2016-02-18 18:56:04 +00:00
Dave Hickin
faecea39c8 Merge branch 'master' of github.com:msekoranja/pvDataCPP 2016-02-18 15:35:36 +00:00
Michael Davidsaver
d08d5362be testBitSet: forgot to update test count 2016-02-17 10:53:32 -05:00
Michael Davidsaver
d4292d81f2 BitSet: truncation in or_and
For "this |= set1 & set2" the result size
should be "max(this, min(set1, set2))" while
at present it is "min(set1, set2)" resulting
in truncation if the LHS is longer than the
RHS.
2016-02-17 10:17:21 -05:00
Michael Davidsaver
62893e33e9 testBitSet: demo bug in BitSet::or_and
Incorrect handling of wordsInUse truncates if
RHS (b1 & b2) is shorter than LHS (b3).
2016-02-17 10:17:16 -05:00
Michael Davidsaver
5b07ecbd01 testBitSet more diag output 2016-02-17 10:17:04 -05:00
Ralph Lange
b5c1b9178d jenkins: switch to Base 3.15.3 2016-02-16 10:18:41 +01:00
Matej Sekoranja
65ff7ab1c3 fixed bitSet serialization 2016-02-12 19:35:44 +01:00
Dave Hickin
35fd991fdc Improve directSerialize/Deserialize() documentation
Add explanation of returned values and more description of the methods.
2016-02-11 10:51:43 +00:00
Michael Davidsaver
57e1acba79 add missing epicsShareFunc 2016-02-10 11:22:07 -05:00
Michael Davidsaver
620d351946 current_function.h not executable 2016-02-10 14:43:58 +00:00
Michael Davidsaver
de3c2656ef INC += pv/ 2016-02-10 14:40:29 +00:00
Michael Davidsaver
3b2e9b2485 move all headers to pv/ 2016-02-10 14:40:29 +00:00
dhickin
75a3005d74 Merge pull request #17 from mdavidsaver/sertovector
add serializeToVector()
2016-02-10 14:04:01 +00:00
Michael Davidsaver
448f606054 update comments 2016-02-09 19:17:39 -05:00
Michael Davidsaver
e35c6f29fb add deserializeFrom* helpers 2016-02-05 18:34:16 -05:00
Michael Davidsaver
85a1a48b00 add serializeToVector 2016-01-27 11:25:09 -05:00
dhickin
45427d3202 Merge pull request #21 from mdavidsaver/getfieldnull
getSubField -> getSubFieldT to avoid potential NULL de-ref.
2016-01-26 22:14:53 +00:00
Michael Davidsaver
93c7a05dac remove redundant getSubField 2016-01-25 13:15:15 -05:00
Michael Davidsaver
a34c38c9b9 getSubField -> getSubFieldT to avoid potential NULL de-ref. 2016-01-25 12:12:06 -05:00
Michael Davidsaver
3100b77a1a Merge remote-tracking branch 'origin/master'
* origin/master:
  missing buffer capacity check in PVUnion::serialize
  byteBuffer throw invalid_argument when ctor w/ NULL
  revert incorrect doc string
  byteBuffer check for alloc failure and const
  new Thread::Config
2016-01-25 12:05:32 -05:00
Michael Davidsaver
c8429069a3 SONAME in src/Makefile 2016-01-25 11:49:05 -05:00
Michael Davidsaver
01172217dc Merge remote-tracking branch 'md/threadconfig'
* md/threadconfig:
  new Thread::Config
2015-12-29 18:34:18 -05:00
Michael Davidsaver
14b0e409f2 missing buffer capacity check in PVUnion::serialize
Allows a buffer overflow in PVUnionArray::serialize().
2015-12-28 18:16:01 -05:00
Michael Davidsaver
2107bae8dd set SHRLIB_VERSION 2015-12-18 16:07:09 -05:00
Michael Davidsaver
433676226c byteBuffer throw invalid_argument when ctor w/ NULL 2015-12-17 16:45:56 -05:00
Michael Davidsaver
f0c88234a0 revert incorrect doc string 2015-12-15 10:26:31 -05:00
Michael Davidsaver
393d711e5f byteBuffer check for alloc failure and const
Ensure that bad_alloc is thrown if allocations fail, presently unchecked.

Also add const qualifier where possible.
2015-12-14 13:25:42 -05:00
Michael Davidsaver
cb24bd9c2c Merge remote-tracking branch 'md/validatefieldnames'
* md/validatefieldnames:
  fix testCreateRequest
  field names may not begin with a digit
  fail zero length field names
  validate field names
2015-11-30 20:55:16 -05:00
Michael Davidsaver
abc5c5a374 new Thread::Config 2015-11-23 15:21:21 -05:00
Michael Davidsaver
54c94f181a add global namespace so these macros work anywhere 2015-11-23 15:21:21 -05:00
Michael Davidsaver
6641e7f5d1 fix testCreateRequest
field names may not begin with a digit
2015-11-23 14:33:43 -05:00
Michael Davidsaver
f4a00f2b0f field names may not begin with a digit
Enforce C identifer syntax

[A-Za-z_][A-Za-z0-9_]*
2015-11-23 14:31:27 -05:00
Dave Hickin
05d41f81e4 Minor correction to README 2015-10-15 10:37:12 +01:00
Dave Hickin
fdc289d888 Add new README
Replace out of date HTML README with a new markdown one
2015-10-15 09:16:20 +01:00
Dave Hickin
0a2243e033 Update TODO 2015-10-15 07:46:40 +01:00
Dave Hickin
9d877d764f Doxgen fixes and enhancements
Change &param to @param. Add missing parameter.
Add more doxygen comments in SerializeHelper.
2015-10-15 07:12:42 +01:00
Dave Hickin
f5df29cf34 Doxygen: remove @code when code block not wanted
@code produces a separate code block, rather than just displaying
contents as code.

Mostly replaced use with @c tag when block not wanted.
2015-10-15 06:50:26 +01:00
Dave Hickin
8008823ea5 Fix doxygen warnings 2015-10-14 23:01:28 +01:00
Dave Hickin
6515de4bc0 Add release notes for 5.0 2015-10-08 15:24:14 +01:00
Ralph Lange
8c5f535b79 jenkins: fix CloudBees doc job 2015-09-28 15:29:39 +02:00
Michael Davidsaver
3714be4f16 fail zero length field names 2015-09-24 13:04:49 -04:00
Michael Davidsaver
f24f565e58 validate field names
check for invalid characters in field names (eg '.').

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

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

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

Signed-off-by: Dave Hickin <david.hickin@diamond.ac.uk>
2015-07-09 13:21:45 +01:00
Dave Hickin
40952df965 Corrected spelling in test and exception messages
Signed-off-by: Dave Hickin <david.hickin@diamond.ac.uk>
2015-07-08 18:19:53 +01:00
Dave Hickin
4f2c51c480 Correct spelling and typos in doxygen and comments
Signed-off-by: Dave Hickin <david.hickin@diamond.ac.uk>
2015-07-08 18:18:37 +01:00
Marty Kraimer
fd31a0d6b0 Merge pull request #6 from mdavidsaver/dropprinter
remove unused PrinterPlain
2015-06-27 07:00:15 -04:00
Michael Davidsaver
9ad725a272 remove unused PrinterPlain 2015-06-25 16:51:04 -04:00
Marty Kraimer
2b6172ba63 Merge pull request #5 from mrkraimer/master
document new PVStructure::getAs method
2015-06-23 10:12:10 -04:00
Marty Kraimer
c521f9299d document new PVStructure::getAs method 2015-06-23 08:24:54 -04:00
Marty Kraimer
1e646f8df1 Merge pull request #4 from mdavidsaver/getasfield
Add PVStructure::getAs<>()
2015-06-23 07:24:30 -04:00
Marty Kraimer
b5a436c1b7 Merge pull request #3 from mdavidsaver/getdeprecate
Deprecated PVStructure::get*Field methods trigger a warning
2015-06-23 07:17:38 -04:00
Michael Davidsaver
4f25c7a3ea remove findSubField 2015-06-22 18:14:23 -04:00
Michael Davidsaver
eadb8ff65b add PVStructure::getAs<>() for field access w/o NULL 2015-06-22 18:14:23 -04:00
Michael Davidsaver
6a80e941a0 replace use of depercated methods 2015-06-22 14:36:27 -04:00
Michael Davidsaver
7fc9b42b3a PVStructure: compiler warning when deprecated methods are used 2015-06-22 14:27:44 -04:00
Dave Hickin
0d857999bf Make default type ID strings const.
Signed-off-by: Dave Hickin <david.hickin@diamond.ac.uk>
2015-06-17 14:51:07 +01:00
Marty Kraimer
8ba71b048e Merge pull request #1 from mdavidsaver/errmsg
Friendlier exception messages w/ stack trace during Field creation
2015-06-15 06:41:34 -04:00
Michael Davidsaver
e07f6c1703 Friendlier exception messages w/ stack trace during Field creation 2015-06-12 13:54:03 -04:00
Marty Kraimer
e4f38121d2 remove qtcreator file 2015-06-10 10:31:08 -04:00
Marty Kraimer
255ee3f151 clean up conversion from hg to got; remove qtcreator files 2015-06-09 08:43:41 -04:00
dhickin
e72dbaabe1 Add some doxygen 2015-06-08 10:06:06 +01:00
dhickin
b39662450f Fix for windows static build static initialisation errors. 2015-06-08 04:58:04 +01:00
dhickin
98da0c0bec Add template getField member functions which return specific field types to Structure and Union. 2015-03-30 09:05:59 +01:00
dhickin
45dde325fd Change the printing of structure array and union array fields of structure introspection objects. Removes superfluous information and brings it in line with pvData meta language. 2015-03-20 17:23:32 +00:00
dhickin
2967a8f798 Declare the one argument constructors of PVField and its derived classes explicit. 2015-03-06 21:05:50 +00:00
Matej Sekoranja
d4bdc73948 documentation/RELEASE_NOTES.md updated 2015-02-18 14:26:19 +01:00
Matej Sekoranja
37c2f6bb17 merge 2015-02-18 10:11:15 +01:00
Matej Sekoranja
a8e4d749e3 flow: Merged <feature> 'copy_refactoring' to <develop> ('default'). 2015-02-18 10:02:17 +01:00
Matej Sekoranja
3df16ee449 flow: Closed <feature> 'copy_refactoring'. 2015-02-18 10:02:17 +01:00
Matej Sekoranja
332c2f959b added copy() method back to convert, since it is usually used by external modules; marked as DEPRECATED 2015-02-17 22:36:28 +01:00
Matej Sekoranja
a1b89c9a3b PVScalar::copy made public; copy tests 2015-02-17 21:54:35 +01:00
Matej Sekoranja
d6921fdac0 removal of some methods from convert 2015-02-17 20:22:37 +01:00
Matej Sekoranja
4cb3c22221 update code to the new method, removed copy from convert 2015-02-17 18:56:56 +01:00
Matej Sekoranja
cc1536b6e1 moved operators to pvData/pvIntrospect, added copy/copyUnchecked methods 2015-02-17 13:59:15 +01:00
Matej Sekoranja
92a178cbf9 flow: Created branch 'feature/copy_refactoring'. 2015-02-17 09:36:44 +01:00
dhickin
fbebce0a49 Make sure postPut is called precisely once and after put in Convert::copyUnion. 2015-02-11 22:17:45 +00:00
Matej Sekoranja
b13bb9819a updated testPlan(0) to actual value 2015-02-11 20:56:38 +01:00
Matej Sekoranja
bb505b8ed9 win32: new operators were missing exports 2015-02-11 15:41:12 +01:00
dhickin
cf030bc711 Call postPut() in Convert::copyUnion(). 2015-02-11 14:04:15 +00:00
Marty Kraimer
6cb95c5cfc fixed possible SEGFAULT in ceateRequest; new stream operator for Field and PVField 2015-02-11 07:26:04 -05:00
Matej Sekoranja
a277a4fdd5 copy schematic 2015-02-11 11:30:39 +01:00
Matej Sekoranja
388799d39d monitors: minor monitor API doc update 2015-02-01 00:46:55 +01:00
Matej Sekoranja
4acf7edf95 non-copy (by reference) retrival of getFields()/getPVFields()/getFieldNames() 2015-01-30 11:35:43 +01:00
Matej Sekoranja
e39346d51e missing swap templates for unsigned types 2015-01-21 20:19:23 +01:00
Ralph Lange
5ae6de4f1d jenkins: fix cloudbees script (commands must return 0) 2014-12-19 14:01:13 +01:00
Ralph Lange
e0f1427af7 jenkins: create and update documentation in only one build configuration 2014-12-19 13:18:52 +01:00
Ralph Lange
69297bdb58 jenkins: make EPICS base a parameter in jenkins job 2014-12-12 09:49:01 +01:00
Marty Kraimer
0fa2f2c2ff merge branch release/4.0 2014-12-11 14:11:54 -05:00
Marty Kraimer
9efce46fff work on doxygen 2014-12-11 09:47:20 -05:00
dhickin
c356ecb402 make local RELEASE.local files take precedence over those in TOP/.. 2014-12-09 13:45:56 +00:00
dhickin
4c6887e7ec Added tag 4.0.3 for changeset 8543734dbf6e 2014-12-05 11:30:03 +00:00
Marty Kraimer
6d338cab15 merge branch release/4.0 2014-12-04 08:30:26 -05:00
dhickin
354fdd412f make "local" *.local files take precedence over those in TOP/.. 2014-12-03 16:55:27 +00:00
dhickin
f3f6141e6a include CONFIG_SITE.local instead of CONFIG.local at top-level. 2014-12-03 16:10:25 +00:00
Matej Sekoranja
f2b43b704c rtems compilation warnings (int32 != int) 2014-11-26 14:12:09 +01:00
Matej Sekoranja
de1478d7ba Event test added 2014-11-25 10:43:07 +01:00
Marty Kraimer
b9592eeb8c Added tag 4.0.2 for changeset af82285f71aa 2014-11-24 06:55:18 -05:00
Marty Kraimer
6a62f9c082 catch std::exception and return NULL PVStructurePtr 2014-11-24 06:54:28 -05:00
Matej Sekoranja
2e4a8b2e23 Structure/Union: bound check access for getFieldName(int)/getField(int) 2014-11-13 18:32:50 +01:00
Marty Kraimer
c5112ffa11 Added tag 4.0.1 for changeset b0d39d12d743 2014-11-11 07:05:19 -05:00
Matej Sekoranja
7b9fda4e81 merge 2014-11-10 21:33:47 +01:00
Matej Sekoranja
278e531806 PVUnion copy allways shallow 2014-11-10 21:30:48 +01:00
Marty Kraimer
047de40642 change date, this version, and previous version 2014-11-10 09:06:35 -05:00
Matej Sekoranja
4e671a1c21 win32 indent problem: local static DLL saga 2014-11-06 22:18:58 +01:00
Matej Sekoranja
f36c8ce280 testByteOrder: use MAIN instead of main 2014-11-06 14:28:49 +01:00
Matej Sekoranja
e77f2c91d7 fixed undeterministic serialization test on clang 2014-11-06 13:03:59 +01:00
Matej Sekoranja
82b0d5ce5f merge 2014-11-06 12:50:04 +01:00
Matej Sekoranja
6117035863 null element handling for structure/union array 2014-11-06 12:48:57 +01:00
Matej Sekoranja
c86e31ad99 vxWorks: type cast fixes 2014-11-06 12:38:01 +01:00
Matej Sekoranja
f506fe1c0e int/int32 compilation fix; now all test spass on RTEMS-i386 2014-11-05 14:05:28 +01:00
Matej Sekoranja
554dc06eda ScalarTypeID mapping fixed in case 'int' == 'long', e.g. RTEMS-i386 2014-11-05 13:52:10 +01:00
Matej Sekoranja
80e1dfd142 removed forces NE2K card or non i386 builds 2014-11-03 13:51:21 +01:00
Matej Sekoranja
6db5cf60dc removing file should not have been commited 2014-11-03 12:41:09 +01:00
Matej Sekoranja
63d181a0ac RTEMS QEMU tests 2014-11-03 12:37:12 +01:00
Matej Sekoranja
73c4896cce tests: VxWorks tests are now ready to be run 2014-10-31 17:49:10 -04:00
Matej Sekoranja
5b1b5ab904 tests: refactored test building so that one test object can be created for VxWorks and RTEMS 2014-10-31 18:29:55 +01:00
Matej Sekoranja
80a537bc4c vxWork tests for all subtests; still need to combine them all to one 2014-10-31 07:57:20 -04:00
Matej Sekoranja
2a8a1d3736 tests: PROD_HOST to TESTPROD_HOST; VxWorks tests for testApp/pv PASSES 2014-10-31 06:42:52 -04:00
Matej Sekoranja
61fbfa0684 Added tag 4.0.0 for changeset f9f187685032 2014-10-29 12:59:39 +01:00
Matej Sekoranja
f06a6bfe7b merge to default branch 2014-10-28 19:37:34 +01:00
183 changed files with 8442 additions and 39658 deletions

15
.gitignore vendored Normal file
View File

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

View File

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

View File

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

16
.hgtags
View File

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

View File

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

2343
Doxyfile

File diff suppressed because it is too large Load Diff

75
LICENSE
View File

@@ -1,12 +1,17 @@
Copyright and License Terms
---------------------------
Copyright (c) 2008 Martin R. Kraimer
Copyright (c) 2006 The University of Chicago, as Operator of Argonne
Copyright (c) 2006-2016 Martin R. Kraimer
Copyright (c) 2006-2016 UChicago Argonne LLC, 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,
Copyright (c) 2007-2016 Control System Laboratory,
(COSYLAB) Ljubljana Slovenia
Copyright (c) 2010-2016 Brookhaven Science Associates, as Operator
of Brookhaven National Laboratory
Copyright (c) 2011-2016 Diamond Light Source Limited,
(DLS) Didcot, United Kingdom
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
@@ -31,48 +36,30 @@ OTHER DEALINGS IN THE SOFTWARE.
________________________________________________________________________
This software is in part copyrighted by the University of Chicago (UofC)
Additional Disclaimers
----------------------
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.
This software is copyright in part by these institutions:
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.
* Brookhaven Science Associates, as Operator of Brookhaven
National Laboratory, New York, USA
* Control System Laboratory, Ljubljana, Slovenia
* Deutsches Elektronen-Synchroton, Member of the Helmholtz
Association, Hamburg, Germany
* Diamond Light Source Limited, Didcot, United Kingdom
* Helmholtz-Zentrum Berlin fuer Materialien und Energie m.b.H.,
Berlin, Germany.
* UChicage Argonne LLC, as Operator of Argonne National Laboratory,
Illinois, USA
________________________________________________________________________
In no event shall these institutions 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 advised of the possibility of such damage.
This software is in part copyrighted by the BERLINER SPEICHERRING
GESELLSCHAFT FUER SYNCHROTRONSTRAHLUNG M.B.H. (BESSY), BERLIN, GERMANY.
These institutions specifically disclaim any warranties, including, but
not limited to, the implied warranties of merchantability, fitness for a
particular purpose, and non-infringement. This software is provided on
an "as is" basis, and these institutions have no obligation to provide
maintenance, support, updates, enhancements, or modifications.
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,82 +0,0 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
<title>EPICS pvData C++</title>
</head>
<body>
<h1 style="text-align: center">EPICS pvData C++<br />
Overview<br />
2010.08.10</h1>
CONTENTS
<hr />
<h2 style="text-align: center">Introduction</h2>
<hr />
<p>This project has the begining of the C++ implementation of pvData. The
following is done:</p>
<dl>
<dt>introspection interfaces</dt>
<dd>The introspection interfaces for clients are described.</dd>
<dt>introspection implementation</dt>
<dd>The following have been implemented: Type, ScalarType, Field,
Scalar</dd>
<dt>test</dt>
<dd>A test of Scalar.</dd>
<dt>As mentioned below there are problems with the current
implementation.</dt>
</dl>
<hr />
<h2 style="text-align: center">Building</h2>
<hr />
<p>The project is structured as an epics base client application. Edit
configure/RELEASE so that it references your EPICS base and then just
type:</p>
<pre> make</pre>
<p>At the top. Then execute the test in the bin directory.</p>
<p>pvDataApp has the following sub directories:</p>
<dl>
<dt>pv</dt>
<dd>pvData.h has the interface descriptions for client code.</dd>
<dt>factory</dt>
<dd>FieldCreateFactory.cpp has the current implementation</dd>
<dt>test</dt>
<dd>Has a test for the current implementation.</dd>
</dl>
<hr />
<h2 style="text-align: center">Questions about Classes</h2>
<hr />
<p>The pure virtual classes defined in pvData.h now work. But there are still
some things that are not so nice. Amoung these are:</p>
<ul>
<li>In FieldCreateFactory.cpp look for "WHY DO I". It asks why the derived
class must also define methods defined in the base class. If it does not
then a compilation error occurs. WHY??? </li>
<li>The toString methods have an argument of "std::string &amp;buf" instead
of "std::string *". Does this seem correct?</li>
<li>Can arguments and return descriptions be defined better?</li>
<li>Is const present everywhere it should be? Remember that introspection
classes are immutable.</li>
<li>The code is NOT thread safe. When we decide for sure what thread/lock
support to choose I will fix this.</li>
</ul>
<p>HELP WILL BE GREATLY APPRECIATED. because I am still coming up to speed
with c++</p>
<hr />
<h2 style="text-align: center">Garbage Collection</h2>
<hr />
<p>Not yet implemented. Lets get class structure correct first.</p>
</body>
</html>

57
README.md Normal file
View File

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

View File

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

View File

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

View File

@@ -1,5 +1,265 @@
<h1>Release 4.0 IN DEVELOPMENT</h1>
<?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;" />
<meta name="keywords" content="EPICS, EPICSv4" />
<title>EPICS V4 pvData C++ Release Notes</title>
<link rel="stylesheet" type="text/css" href="../../base.css" />
<link rel="stylesheet" type="text/css" href="../../epicsv4.css" />
</head>
<body>
<h1>Release 6.0.1</h1>
<p>The changes since release 6.0.0 are:</p>
<ul>
<li>Fix "Problem building pvDataCPP for win32-x86-mingw" (issue #42)</li>
<li>In src/misc/bitSet.cpp #include <algorithm> required for MSVS 2015</li>
<li>In testApp/misc/testTypeCast.cpp print (u)int8 values as integers</li>
<li>Minor documentation updates</li>
</ul>
<h1>Release 6.0.0</h1>
<p>The main changes since release 5.0.4 are:</p>
<ul>
<li>Linux shared library version added</li>
<li>Headers have been moved into pv directories</li>
<li>Bitset functions declared const where possible</li>
<li>Bitset::swap added</li>
<li>Requester::message has default implementation</li>
<li>Serialization/deserialization helpers added</li>
<li>Non-template getSubField char* overload added</li>
<li>MonitorPlugin deprecated</li>
<li>Field name validation performed</li>
<li>Now builds for Cygwin and MinGW targets</li>
<li>Fix for debug build issue.</li>
<li>New license file replaces LICENSE and COPYRIGHT</li>
</ul>
<h2>Shared library version added</h2>
<p>Linux shared library version numbers have been added by setting SHRLIB_VERSION
(to 6.0 in this case). So shared object will be libpvData.so.6.0 instead of
libpvData.so.</p>
<h2>Headers have been moved into pv directories</h2>
<p>E.g. src/property/alarm.h -> src/property/pv/alarm.h</p>
<p>This facilitates using some IDEs such as Qt Creator.</p>
<h2>Requester::message has default implementation</h2>
<p>Requester::message is no longer pure virtual. Default implementation sends
string to std::cerr.</p>
<h2>Serialization/deserialization helpers added</h2>
<p>A helper function, serializeToVector, has been added which serializes a
Serializable object into a standard vector of UInt8s.</p>
<p>Similarly a function deserializeFromVector deserializes a standard vector into
a Deserializable object.</p>
<p>A function deserializeFromBuffer deserializes a ByteBuffer into a
Deserializable object.</p>
<h2>Field name validation performed</h2>
<p>On creating a Structure or Union the field names are now validated.</p>
<p>Valid characters for a field name are upper or lowercase letters, numbers and
underscores and intial numbers are invalid, i.e. names must be of the form
[A-Za-z<em>][A-Za-z0-9</em>]*.</p>
<h2>Now builds for Cygwin and MinGW targets</h2>
<p>Includes cross-compiling MinGW on Linux.</p>
<h1>Release 5.0.4</h1>
<p>The changes since release 5.0.3 are:</p>
<ul>
<li>Fixed bitset serialization (issue #24)</li>
<li>Fixed truncation in BitSet::or_and (issue #27)</li>
</ul>
<h2>Fixed bitset serialization (issue #24)</h2>
<p>C++ bitset serialization was not consistent with the C++ deserialization and
Java code in some instances (depending on the endianness of the serializer and
deserializer) when the number of bits was 56-63 modulo 64. C++ serialization
has been fixed.</p>
<p>Fix exposed issue in deserialization on 32-bit platforms which
has also been corrected. </p>
<h2>Fixed truncation in BitSet::or_and (issue #27)</h2>
<p>If n, n1 and n2 words are used to store the values of the bitsets bitset,
bitset1 and bitset2 respectively then max(n, min(n1,n2)) words are needed
to store bitset.or_(bitset1, bitset2).</p>
<p>Previously min(n1,n2) words were used and the result would be truncated in
some instances. This has been fixed.</p>
<h1>Release 5.0.3</h1>
<p>The only change since release 5.0.2 is:</p>
<h2>Fixed buffer overflow in PVUnion::serialize() (issue #20)</h2>
<p>A PVUnion whose stored value was null was serialized without checking
whether the buffer had sufficient capacity. This has been fixed by calling
ensureBuffer().</p>
<h1>Release 5.0.2</h1>
<p>The main changes since release 4.0.3 are:</p>
<ul>
<li>Deprecated getXXXField() methods have been removed from PVStructure</li>
<li>Convert copy methods and equals operators (re)moved</li>
<li>Convert::copyUnion now always copies between subfields.</li>
<li>New method getSubFieldT, like getSubField except it throws an exception</li>
<li>findSubField method removed from PVStructure</li>
<li>New stream operators for Field and PVField are provided</li>
<li>New template versions of Structure::getField</li>
<li>Fixes for static initialisation order issues</li>
<li>CreateRequest prevents a possible SEGFAULT</li>
</ul>
<h2>Deprecated getXXXField methods have been removed from PVStructure</h2>
<p>The following methods have been removed from PVStructure</p>
<ul>
<li>getBooleanField</li>
<li>getByteField, getShortField, getIntField, getLongField</li>
<li>getUByteField, getUShortField, getUIntField, getULongField</li>
<li>getStringField</li>
<li>getStructureField, getUnionField</li>
<li>getScalarArrayField, getStructureArrayField, getUnionArrayField</li>
</ul>
<p>Use template getSubField instead, e.g. use</p>
<pre><code>getSubField&lt; PVInt &gt;(fieldName)
</code></pre>
<p>in place of</p>
<pre><code>getIntField(fieldName)
</code></pre>
<h2>Convert copy methods and equals operators</h2>
<p>Convert copy methods where moved and replaced with methods
on PVField classes, i.e.</p>
<pre><code>PVField::copy(const PVField&amp; from)
</code></pre>
<p>Methods</p>
<pre><code>PVField::copyUnchecked(const PVField&amp; from)
</code></pre>
<p>were added to allow unchecked copies, to gain performance
where checked are not needed (anymore).</p>
<p>In addition:
- isCompatibleXXX methods were removed in favour of Field::operator==.
- equals methods were remove in favour of PVField::operator==.
- operator== methods where moved to pvIntrospect.h and pvData.h</p>
<h2>Convert::copyUnion</h2>
<p>Before this method, depending on types for to and from,
sometimes did a shallow copy, i.e. just made to shared_ptr for to
share the same data as from.
Now it always copies between the subfield of to and from.</p>
<h2>New method getSubFieldT, like getSubField except it throws an exception</h2>
<p>PVStructure has a new template member</p>
<pre><code>getSubFieldT(std::string const &amp;fieldName)
</code></pre>
<p>that is like <b>getSubField</b> except that it throws a runtime_error
instead of returning null.</p>
<h2>findSubField method removed from PVStructure</h2>
<p>This was mainly used in the implementation of getSubField. With a change to
the latter, findSubField was removed.</p>
<h2>New stream operators</h2>
<p>New steam operators are available for Field and PVField.
Before to print a Field (or any extension) or a PVField (or any extension)
it was necessary to have code like:</p>
<pre><code> void print(StructureConstPtr struc, PVStructurePtr pv)
{
if(struc) {
cout &lt;&lt; *struc &lt;&lt; endl;
} else {
cout &lt;&lt; "nullptr\n"
}
if(pv) {
cout &lt;&lt; *.struc &lt;&lt; endl;
} else {
cout &lt;&lt; "nullptr\n"
}
}
</code></pre>
<p>Now it can be done as follows:</p>
<pre><code> void print(StructureConstPtr struc, PVStructurePtr pv)
{
cout &lt;&lt; struc &lt;&lt; endl;
cout &lt;&lt; pv &lt;&lt; endl;
}
</code></pre>
<h2>New template version of Structure::getField</h2>
<p>A new template getField method has been added to Structure</p>
<p>template&lt;typename FT-&gt;
std::tr1::shared_ptr&lt; const FT-&gt; getField(std::string const &amp;fieldName) const </p>
<p>Can be used, for example, as follows:</p>
<pre><code>StructurePtr tsStruc = struc-&gt;getField&lt;Structure&gt;("timeStamp");
</code></pre>
<h2>Fixes for static initialisation order issues</h2>
<p>Certain static builds (in particular Windows builds) of applications using
pvData had issues due to PVStructure::DEFAULT_ID being used before being initialised. This has been fixed.</p>
<h2>CreateRequest change</h2>
<p>createRequest could cause a SEGFAULT if passed a bad argument.
This has been changed so the it returns a null pvStructure
and provides an error.</p>
<h1>Release 4.0.3</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>
@@ -9,21 +269,31 @@
<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.
In order to limit memory usage the storage for raw data is managed via a new shared<em>vector facility.
This allows multiple instances of array data to use the shared raw data.
COW is implemented via shared_vectors of const data, i. e. data that can not be modified.</p>
COW is implemented via shared</em>vectors of const data, i. e. data that can not be modified.</p>
<h2>String no longer defined</h2>
<p>This is replaced by std::string.</p>
<h2>timeStamp and valueAlarm name changes</h2>
<p>In timeStamp nanoSeconds is changed to nanoseconds.</p>
<p>In valueAlarm hystersis is changed to hysteresis</p>
<p>In valueAlarm hysteresis is changed to hysteresis</p>
<h2>toString replaced by stream I/O</h2>
<p>pvData.h and pvIntrospect no longer defines toString
Instead they have stream support.
pvIntrospect uses method dump and pvData uses dumpValue.
For example:</p>
<pre><code> PVDoublePtr pvValue;
String buffer;
pvValue-&gt;toString(&amp;buffer);
@@ -32,27 +302,44 @@ For example:</p>
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>variant union</b> The field can have any type.</li>
<li><b>union</b> The field can any of specified set of types.</li>
</ul>
<p>The field type can be dynamically changed.</p>
<h2>copy</h2>
<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>
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>
</body>
</html>

View File

@@ -1,5 +1,266 @@
Release 4.0 IN DEVELOPMENT
===========
Release 6.0.1
=============
The changes since release 6.0.0 are:
* Fix "Problem building pvDataCPP for win32-x86-mingw" (issue #42)
* In src/misc/bitSet.cpp #include <algorithm> required for MSVS 2015
* In testApp/misc/testTypeCast.cpp print (u)int8 values as integers
* Minor documentation updates
Release 6.0.0
=============
The main changes since release 5.0.4 are:
* Linux shared library version added
* Headers have been moved into pv directories
* Bitset functions declared const where possible
* Bitset::swap added
* Requester::message has default implementation
* Serialization/deserialization helpers added
* Non-template getSubField char* overload added
* MonitorPlugin deprecated
* Field name validation performed
* Now builds for Cygwin and MinGW targets
* Fix for debug build issue.
* New license file replaces LICENSE and COPYRIGHT
Shared library version added
----------------------------
Linux shared library version numbers have been added by setting SHRLIB_VERSION
(to 6.0 in this case). So shared object will be libpvData.so.6.0 instead of
libpvData.so.
Headers have been moved into pv directories
-------------------------------------------
E.g. src/property/alarm.h -> src/property/pv/alarm.h
This facilitates using some IDEs such as Qt Creator.
Requester::message has default implementation
---------------------------------------------
Requester::message is no longer pure virtual. Default implementation sends
string to std::cerr.
Serialization/deserialization helpers added
-------------------------------------------
A helper function, serializeToVector, has been added which serializes a
Serializable object into a standard vector of UInt8s.
Similarly a function deserializeFromVector deserializes a standard vector into
a Deserializable object.
A function deserializeFromBuffer deserializes a ByteBuffer into a
Deserializable object.
Field name validation performed
-------------------------------
On creating a Structure or Union the field names are now validated.
Valid characters for a field name are upper or lowercase letters, numbers and
underscores and intial numbers are invalid, i.e. names must be of the form
[A-Za-z_][A-Za-z0-9_]*.
Now builds for Cygwin and MinGW targets
---------------------------------------
Includes cross-compiling MinGW on Linux.
Release 5.0.4
=============
The changes since release 5.0.3 are:
* Fixed bitset serialization (issue #24)
* Fixed truncation in BitSet::or_and (issue #27)
Fixed bitset serialization (issue #24)
--------------------------------------
C++ bitset serialization was not consistent with the C++ deserialization and
Java code in some instances (depending on the endianness of the serializer and
deserializer) when the number of bits was 56-63 modulo 64. C++ serialization
has been fixed.
Fix exposed issue in deserialization on 32-bit platforms which
has also been corrected.
Fixed truncation in BitSet::or_and (issue #27)
----------------------------------------------
If n, n1 and n2 words are used to store the values of the bitsets bitset,
bitset1 and bitset2 respectively then max(n, min(n1,n2)) words are needed
to store bitset.or_(bitset1, bitset2).
Previously min(n1,n2) words were used and the result would be truncated in
some instances. This has been fixed.
Release 5.0.3
=============
The only change since release 5.0.2 is:
Fixed buffer overflow in PVUnion::serialize() (issue #20)
---------------------------------------------------------
A PVUnion whose stored value was null was serialized without checking
whether the buffer had sufficient capacity. This has been fixed by calling
ensureBuffer().
Release 5.0.2
=============
The main changes since release 4.0.3 are:
* Deprecated getXXXField() methods have been removed from PVStructure
* Convert copy methods and equals operators (re)moved
* Convert::copyUnion now always copies between subfields.
* New method getSubFieldT, like getSubField except it throws an exception
* findSubField method removed from PVStructure
* New stream operators for Field and PVField are provided
* New template versions of Structure::getField
* Fixes for static initialisation order issues
* CreateRequest prevents a possible SEGFAULT
Deprecated getXXXField methods have been removed from PVStructure
-----------------------------------------------------------------
The following methods have been removed from PVStructure
* getBooleanField
* getByteField, getShortField, getIntField, getLongField
* getUByteField, getUShortField, getUIntField, getULongField
* getStringField
* getStructureField, getUnionField
* getScalarArrayField, getStructureArrayField, getUnionArrayField
Use template getSubField instead, e.g. use
getSubField< PVInt >(fieldName)
in place of
getIntField(fieldName)
Convert copy methods and equals operators
-----------------------------------------
Convert copy methods where moved and replaced with methods
on PVField classes, i.e.
PVField::copy(const PVField& from)
Methods
PVField::copyUnchecked(const PVField& from)
were added to allow unchecked copies, to gain performance
where checked are not needed (anymore).
In addition:
- isCompatibleXXX methods were removed in favour of Field::operator==.
- equals methods were remove in favour of PVField::operator==.
- operator== methods where moved to pvIntrospect.h and pvData.h
Convert::copyUnion
-----------------
Before this method, depending on types for to and from,
sometimes did a shallow copy, i.e. just made to shared_ptr for to
share the same data as from.
Now it always copies between the subfield of to and from.
New method getSubFieldT, like getSubField except it throws an exception
--------------------
PVStructure has a new template member
getSubFieldT(std::string const &fieldName)
that is like <b>getSubField</b> except that it throws a runtime_error
instead of returning null.
findSubField method removed from PVStructure
--------------------------------------------
This was mainly used in the implementation of getSubField. With a change to
the latter, findSubField was removed.
New stream operators
--------------------
New steam operators are available for Field and PVField.
Before to print a Field (or any extension) or a PVField (or any extension)
it was necessary to have code like:
void print(StructureConstPtr struc, PVStructurePtr pv)
{
if(struc) {
cout << *struc << endl;
} else {
cout << "nullptr\n"
}
if(pv) {
cout << *.struc << endl;
} else {
cout << "nullptr\n"
}
}
Now it can be done as follows:
void print(StructureConstPtr struc, PVStructurePtr pv)
{
cout << struc << endl;
cout << pv << endl;
}
New template version of Structure::getField
--------------------------------------------
A new template getField method has been added to Structure
template<typename FT >
std::tr1::shared_ptr< const FT > getField(std::string const &fieldName) const
Can be used, for example, as follows:
StructurePtr tsStruc = struc->getField<Structure>("timeStamp");
Fixes for static initialisation order issues
--------------------------------------------
Certain static builds (in particular Windows builds) of applications using
pvData had issues due to PVStructure::DEFAULT_ID being used before being initialised. This has been fixed.
CreateRequest change
--------------------
createRequest could cause a SEGFAULT if passed a bad argument.
This has been changed so the it returns a null pvStructure
and provides an error.
Release 4.0.3
=============
The main changes since release 3.0.2 are:
@@ -31,7 +292,7 @@ timeStamp and valueAlarm name changes
In timeStamp nanoSeconds is changed to nanoseconds.
In valueAlarm hystersis is changed to hysteresis
In valueAlarm hysteresis is changed to hysteresis
toString replaced by stream I/O
@@ -65,7 +326,7 @@ There are two new basic types: union_t and unionArray.
A union is like a structure that has a single subfield.
There are two flavors:
* <b>varient union</b> The field can have any type.
* <b>variant union</b> The field can have any type.
* <b>union</b> The field can any of specified set of types.
The field type can be dynamically changed.
@@ -76,7 +337,7 @@ copy
This consists of createRequest and pvCopy.
createRequest was moved from pvAccess to here.
pvCopy is moved from pvDatabaseCPP and now depends
only on pvData, i. e. it no longer has any knowledge of PVRecord.
only on pvData, i.e. it no longer has any knowledge of PVRecord.
monitorPlugin
-------------

View File

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

View File

@@ -1,29 +1,11 @@
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
---------

View File

@@ -35,33 +35,16 @@
<div class="head">
<h1>EPICS pvDataCPP</h1>
<!-- Maturity: Working Draft or Request for Comments, or Recommendation, and date. -->
<h2 class="nocount">EPICS v4 Working Group, Working Draft, 08-Oct-2014</h2>
<h2 class="nocount">Release 6.0.1 - 2016-09-14</h2>
<dl>
<dt>Latest version:</dt>
<dd><a
href="pvDataCPP.html">pvDataCPP.html</a>
</dd>
<dt>This version:</dt>
<dd><a
href="pvDataCPP_20140723.html">pvDataCPP_20140723.html</a>
</dd>
<dt>Previous version:</dt>
<dd><a
href="pvDataCPP_20140708.html">pvDataCPP_20140708.html</a>
</dd>
<dt>Editors:</dt>
<dd>Marty Kraimer, BNL</dd>
<dd>Michael Davidsaver, BNL</dd>
<dd>Matej Sekoranja, CosyLab</dd>
<dd>David Hickin, Diamond Light Source</dd>
</dl>
<p class="copyright">This product is made available subject to acceptance of the <a
href="http://epics-pvdata.sourceforge.net/LICENSE.html">EPICS open source
license.</a></p>
<hr />
</div>
@@ -79,7 +62,8 @@ V4 control system programming environment:<br />
<h2 class="nocount">Status of this Document</h2>
<p>This is the 08-Oct-2014 version of the C++ implementation of pvData.
<p>This is the 14-September-2016 version for the 6.0.1 release of the
C++ implementation of pvData.
</p>
<p>RELEASE_NOTES.md provides changes since the last release.
@@ -2309,6 +2293,16 @@ public:
template&lt;typename PVT&gt;
std::tr1::shared_ptr&lt;PVT&gt; getSubField(std::size_t fieldOffset) const
PVFieldPtr getSubFieldT(std::string const &amp;fieldName) const;
template&lt;typename PVT&gt;
std::tr1::shared_ptr&lt;PVT&gt; getSubFieldT(std::string const &amp;fieldName) const
PVFieldPtr getSubFieldT(std::size_t fieldOffset) const;
template&lt;typename PVT&gt;
std::tr1::shared_ptr&lt;PVT&gt; getSubFieldT(std::size_t fieldOffset) const
virtual void serialize(
ByteBuffer *pbuffer,SerializableControl *pflusher) const ;
virtual void deserialize(
@@ -2329,7 +2323,7 @@ public:
<dt>getPVFields</dt>
<dd>Returns the array of subfields. The set of subfields must all have
different field names.</dd>
<dt>getSubField(std::string fieldName)</dt>
<dt>getSubField(std::string const &amp;fieldName)</dt>
<dd>
Get a subField of a field.d
A non-null result is
@@ -2344,9 +2338,13 @@ public:
<dd>Get the field located a fieldOffset, where fieldOffset is relative to
the top level structure. This returns null if the specified field is not
located within this PVStructure.
<br />
<b>Note</b> The template version replaces getBooleanField, etc.<br/>
</dd>
<dt>getSubFieldT(std::string const &amp;fieldName)</dt>
<dd>Like getSubField except that it throws std::runtime_error if
the field does not exists or has the wrong type.</dd>
<dt>getSubFieldT(int fieldOffset)</dt>
<dd>Like getSubField except that it throws std::runtime_error if
the field does not exists or has the wrong type.</dd>
<dt>dumpValue</dt>
<dd>Method for streams I/O.</dd>
</dl>
@@ -2662,12 +2660,6 @@ objects:</p>
</dl>
<h3>convert.h</h3>
<p>NOTE about copying immutable array fields. If an entire immutable array
field is copied to another array that has the same elementType, both offsets
are 0, and the length is the length of the source array, then the shareData
method of the target array is called and the target array is set immutable.
Thus the source and target share the same primitive array.</p>
<p>This section describes the supported conversions between data types.</p>
<ul>
<li>All supported types can be converted to a string. If you ask for a 100
@@ -2681,12 +2673,6 @@ Thus the source and target share the same primitive array.</p>
<li>Either is a string</li>
</ul>
</li>
<li>Copy between PVArrays that satisfy one of the following.
<ul>
<li>Both have the same type.</li>
<li>Either is a string.</li>
</ul>
</li>
<li>Conversions between numeric scalar types.</li>
<li>Conversion between compatible structures.</li>
<li>A utility method the returns the full field name of a field</li>
@@ -4885,7 +4871,7 @@ Monitor provides:
monitor. It, together with the queue facility, provides support for
monitor queues.
</dd>
<dt>monitorPlugin</dt>
<dt>monitorPlugin [Deprecated]</dt>
<dd>This is support for implementing monitor plugins.
A monitor plugin can be developed that has no knowledge
of pvAccess but only pvData.
@@ -5067,7 +5053,7 @@ where
<dl>
<dt>monitor</dt>
<dd>Used by code that implements pvAccess monitors.</dd>
<dt>monitorPlugin</dt>
<dt>monitorPlugin [Deprecated]</dt>
<dd>Code that provides special semantics for monitors.</dd>
</dl>
<h3>monitor</h3>
@@ -5183,6 +5169,8 @@ It has the methods:</p>
</dl>
<h3>monitorPlugin</h3>
<p>[ MonitorPlugin and related classes MonitorPluginCreator and
MonitorPluginManager are deprecated.]</p>
<pre>
class MonitorPlugin
{

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

View File

@@ -4,10 +4,41 @@
# Jenkins invokes scripts with the "-ex" option. So the build is considered a failure
# if any of the commands exits with a non-zero exit code.
#
# Author: Ralph Lange <Ralph.Lange@gmx.de>
# Author: Ralph Lange <ralph.lange@gmx.de>
# Copyright (C) 2013 Helmholtz-Zentrum Berlin für Materialien und Energie GmbH
# Copyright (C) 2014-2016 ITER Organization.
# All rights reserved. Use is subject to license terms.
installTool () {
local module=$1
local version=$2
wget -nv https://openepics.ci.cloudbees.com/job/${module}-${version}_Build/lastSuccessfulBuild/artifact/${module,,}-${version}.CB-dist.tar.gz
tar -xzf ${module,,}-${version}.CB-dist.tar.gz
}
installE4 () {
local module=$1
local branch=$2
# If microbench version does not exist, try without
if [ "${MB}" = "WITH_MICROBENCH" ]; then
if ! wget -nv https://openepics.ci.cloudbees.com/job/e4-cpp-${module}-${branch}-build/BASE=${BASE},MB=WITH_MICROBENCH/lastSuccessfulBuild/artifact/${module}.CB-dist.tar.gz; then
wget -nv https://openepics.ci.cloudbees.com/job/e4-cpp-${module}-${branch}-build/BASE=${BASE},MB=NO_MICROBENCH/lastSuccessfulBuild/artifact/${module}.CB-dist.tar.gz
fi
else
wget -nv https://openepics.ci.cloudbees.com/job/e4-cpp-${module}-${branch}-build/BASE=${BASE},MB=NO_MICROBENCH/lastSuccessfulBuild/artifact/${module}.CB-dist.tar.gz
fi
tar -xzf ${module}.CB-dist.tar.gz
}
###########################################
# Defaults for EPICS Base and MB
DEFAULT_BASE=3.15.4
BASE=${BASE:-${DEFAULT_BASE}}
MB=${MB:-"NO_MICROBENCH"}
###########################################
# Fetch and unpack dependencies
@@ -17,10 +48,8 @@ rm -fr ${STUFF}
mkdir -p ${STUFF}
cd ${STUFF}
wget -nv https://openepics.ci.cloudbees.com/job/Base-3.14.12.3_Build/lastSuccessfulBuild/artifact/baseR3.14.12.3.CB-dist.tar.gz
wget -nv https://openepics.ci.cloudbees.com/job/Doxygen-1.8.3_Build/lastSuccessfulBuild/artifact/doxygen-1.8.3.CB-dist.tar.gz
tar -xzf baseR3.14.12.3.CB-dist.tar.gz
tar -xzf doxygen-1.8.3.CB-dist.tar.gz
installTool Boost 1.61.0
installTool Base ${BASE}
###########################################
# Build
@@ -37,20 +66,13 @@ EPICS_BASE=${EPICS_BASE}
EOF
make distclean all
doxygen
###########################################
# Test
# EPICS Test Harness tests
make runtests
###########################################
# Create distribution
tar czf pvData.CB-dist.tar.gz lib include COPYRIGHT LICENSE
###########################################
# Publish documentation
rsync -aP --delete -e ssh documentation epics-jenkins@web.sourceforge.net:/home/project-web/epics-pvdata/htdocs/docbuild/pvDataCPP/tip
tar czf pvData.CB-dist.tar.gz lib include LICENSE

74
jenkins/cloudbees_doc Normal file
View File

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

View File

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

View File

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

View File

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

View File

@@ -1,236 +0,0 @@
configure/CONFIG
configure/CONFIG_SITE
configure/RELEASE
configure/RELEASE.local
configure/RULES
configure/RULES.ioc
configure/RULES_DIRS
configure/RULES_TOP
documentation/pvDataCPP.html
documentation/pvDataCPP_20120927.html
documentation/pvDataCPP_20121001.html
documentation/pvDataCPP_20121026.html
documentation/pvDataCPP_20121212.html
jenkins/cloudbees_build
pvDataApp/factory/Compare.cpp
pvDataApp/factory/Convert.cpp
pvDataApp/factory/factory.h
pvDataApp/factory/FieldCreateFactory.cpp
pvDataApp/factory/PVArray.cpp
pvDataApp/factory/PVAuxInfoImpl.cpp
pvDataApp/factory/PVDataCreateFactory.cpp
pvDataApp/factory/PVDataCreateFactory.cpp.orig
pvDataApp/factory/PVField.cpp
pvDataApp/factory/PVScalar.cpp
pvDataApp/factory/PVScalarArray.cpp
pvDataApp/factory/PVStructure.cpp
pvDataApp/factory/PVStructureArray.cpp
pvDataApp/factory/StandardField.cpp
pvDataApp/factory/StandardPVField.cpp
pvDataApp/factory/TypeFunc.cpp
pvDataApp/misc/bitSet.cpp
pvDataApp/misc/bitSet.h
pvDataApp/misc/byteBuffer.cpp
pvDataApp/misc/byteBuffer.h
pvDataApp/misc/destroyable.h
pvDataApp/misc/epicsException.cpp
pvDataApp/misc/epicsException.h
pvDataApp/misc/event.cpp
pvDataApp/misc/event.h
pvDataApp/misc/executor.cpp
pvDataApp/misc/executor.h
pvDataApp/misc/localStaticLock.cpp
pvDataApp/misc/localStaticLock.h
pvDataApp/misc/localStaticLock.h.orig
pvDataApp/misc/lock.h
pvDataApp/misc/messageQueue.cpp
pvDataApp/misc/messageQueue.h
pvDataApp/misc/noDefaultMethods.h
pvDataApp/misc/queue.h
pvDataApp/misc/requester.cpp
pvDataApp/misc/requester.h
pvDataApp/misc/requester.h.orig
pvDataApp/misc/serialize.h
pvDataApp/misc/serializeHelper.cpp
pvDataApp/misc/serializeHelper.h
pvDataApp/misc/sharedPtr.h
pvDataApp/misc/status.cpp
pvDataApp/misc/status.h
pvDataApp/misc/thread.h
pvDataApp/misc/timeFunction.cpp
pvDataApp/misc/timeFunction.h
pvDataApp/misc/timer.cpp
pvDataApp/misc/timer.h
pvDataApp/monitor/monitor.h
pvDataApp/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

View File

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

View File

@@ -3,9 +3,6 @@
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
@@ -20,5 +17,8 @@ LIBRARY = pvData
pvData_LIBS += Com
# shared library ABI version.
SHRLIB_VERSION ?= 6.0
include $(TOP)/configure/RULES

View File

@@ -2,8 +2,8 @@
SRC_DIRS += $(PVDATA_SRC)/copy
INC += createRequest.h
INC += pvCopy.h
INC += pv/createRequest.h
INC += pv/pvCopy.h
LIBSRCS += createRequest.cpp
LIBSRCS += pvCopy.cpp

View File

@@ -1,12 +1,13 @@
/**
* 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.
/*
* Copyright information and license terms for this software can be
* found in the file LICENSE that is included with the distribution
*/
#include <string>
#include <sstream>
#include <epicsMutex.h>
#define epicsExportSharedSymbols
#include <pv/pvData.h>
@@ -322,149 +323,157 @@ public:
virtual PVStructurePtr createRequest(
string const & crequest)
{
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();
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(closeBracket-openBracket > 3) {
Node node("record");
Node optNode = createRequestOptions(
request.substr(openBracket+1,closeBracket-openBracket-1));
node.nodes.push_back(optNode);
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();
}
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();
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);
}
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);
StructureConstPtr structure = fieldCreate->createStructure(names, fields);
if(!structure) throw std::invalid_argument("bad request " + crequest);
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(structure);
for(size_t i=0; i<optionList.size(); ++i) {
OptionPair pair = optionList[i];
string name = pair.name;
string value = pair.value;
PVStringPtr pvField = pvStructure->getSubField<PVString>(name);
if(!pvField) throw std::invalid_argument("bad request " + crequest);
pvField->put(value);
}
optionList.clear();
return pvStructure;
} catch (std::exception &e) {
string xxx = e.what();
message = "while creating Structure exception " + xxx;
return PVStructurePtr();
message = e.what();
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;
}
};
CreateRequest::shared_pointer CreateRequest::create()

View File

@@ -1,8 +1,7 @@
/*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.
/*
* Copyright information and license terms for this software can be
* found in the file LICENSE that is included with the distribution
*/
#ifndef CREATEREQUEST_H
@@ -18,7 +17,12 @@
namespace epics { namespace pvData {
/**
* Class to create pvRequest structures to pass to pvAccess Channel methods.
* @brief Create pvRequest structure for Channel methods.
*
* Many methods of the Channel class of pvAccess have an
* argument <b>PVStructurePtr const * pvRequest</b>.
* This class provides a method that creates a valid pvRequest.
*
*/
class epicsShareClass CreateRequest {
public:
@@ -33,7 +37,6 @@ class epicsShareClass CreateRequest {
* Create a request structure for the create calls in Channel.
* See the package overview documentation for details.
* @param request The field request. See the package overview documentation for details.
* @param requester The requester;
* @return The request PVStructure if a valid request was given.
* If a NULL PVStructure is returned then getMessage will return
* the reason.

View File

@@ -1,8 +1,7 @@
/* 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.
/*
* Copyright information and license terms for this software can be
* found in the file LICENSE that is included with the distribution
*/
/**
* @author Marty Kraimer
@@ -25,7 +24,8 @@ class PVCopyTraverseMasterCallback;
typedef std::tr1::shared_ptr<PVCopyTraverseMasterCallback> PVCopyTraverseMasterCallbackPtr;
/**
* Callback for traversing master structure
* @brief Callback for traversing master structure
*
* Must be implemented by code that creates pvCopy.
*/
class epicsShareClass PVCopyTraverseMasterCallback
@@ -53,6 +53,8 @@ typedef std::tr1::shared_ptr<CopyStructureNode> CopyStructureNodePtr;
/**
* @brief Support for subset of fields in a pvStructure.
*
* Class that manages one or more PVStructures that holds an arbitrary subset of the fields
* in another PVStructure called master.
*/
@@ -63,8 +65,8 @@ public:
POINTER_DEFINITIONS(PVCopy);
/**
* Create a new pvCopy
* @param pvMaster The top level sructure for which a copy of
* an arbritary subset of the fields in master will be created and managed.
* @param pvMaster The top-level structure for which a copy of
* an arbitrary subset of the fields in master will be created and managed.
* @param pvRequest Selects the set of subfields desired and options for each field.
* @param structureName The name for the top level of any PVStructure created.
*/
@@ -75,8 +77,8 @@ public:
virtual ~PVCopy(){}
virtual void destroy();
/**
* Get the top level structure of master
* @returns The master top level structure.
* Get the top-level structure of master
* @returns The master top-level structure.
* This should not be modified.
*/
PVStructurePtr getPVMaster();
@@ -94,7 +96,7 @@ public:
StructureConstPtr getStructure();
/**
* Create a copy instance. Monitors keep a queue of monitor elements.
* Since each element needs a PVStructure, multiple top level structures will be created.
* Since each element needs a PVStructure, multiple top-level structures will be created.
*/
PVStructurePtr createPVStructure();
/**
@@ -113,15 +115,15 @@ public:
PVStructurePtr const &masterPVStructure,
PVFieldPtr const &masterPVField);
/**
* Given a offset in the copy get the corresponding field in pvMaster.
* @param offset The offset in the copy.
* Given an offset in the copy get the corresponding field in pvMaster.
* @param structureOffset The offset in the copy.
*/
PVFieldPtr getMasterPVField(std::size_t structureOffset);
/**
* Initialize the fields in copyPVStructure by giving each field
* the value from the corresponding field in pvMaster.
* bitSet will be set to show that all fields are changed.
* @param copyPVStructure A copy top level structure.
* @param copyPVStructure A copy top-level structure.
* @param bitSet A bitSet for copyPVStructure.
*/
void initCopy(
@@ -130,7 +132,7 @@ public:
/**
* Set all fields in copyPVStructure to the value of the corresponding field in pvMaster.
* Each field that is changed has it's corresponding bit set in bitSet.
* @param copyPVStructure A copy top level structure.
* @param copyPVStructure A copy top-level structure.
* @param bitSet A bitSet for copyPVStructure.
*/
void updateCopySetBitSet(
@@ -138,8 +140,8 @@ public:
BitSetPtr const &bitSet);
/**
* For each set bit in bitSet
* set the field in copyPVStructure to the value of the corrseponding field in pvMaster.
* @param copyPVStructure A copy top level structure.
* set the field in copyPVStructure to the value of the corresponding field in pvMaster.
* @param copyPVStructure A copy top-level structure.
* @param bitSet A bitSet for copyPVStructure.
*/
void updateCopyFromBitSet(
@@ -147,8 +149,8 @@ public:
BitSetPtr const &bitSet);
/**
* For each set bit in bitSet
* set the field in pvMaster to the value of the corrseponding field in copyPVStructure
* @param copyPVStructure A copy top level structure.
* set the field in pvMaster to the value of the corresponding field in copyPVStructure
* @param copyPVStructure A copy top-level structure.
* @param bitSet A bitSet for copyPVStructure.
*/
void updateMaster(
@@ -156,7 +158,7 @@ public:
BitSetPtr const &bitSet);
/**
* Get the options for the field at the specified offset.
* @param offset the offset in copy.
* @param fieldOffset the offset in copy.
* @returns A NULL is returned if no options were specified for the field.
* If options were specified,PVStructurePtr is a structures
* with a set of PVString subfields that specify name,value pairs.s

View File

@@ -1,8 +1,7 @@
/* 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.
/*
* Copyright information and license terms for this software can be
* found in the file LICENSE that is included with the distribution
*/
/**
* @author Marty Kraimer
@@ -13,12 +12,13 @@
#include <memory>
#include <sstream>
#include <epicsThread.h>
#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;
@@ -29,6 +29,18 @@ using std::endl;
namespace epics { namespace pvData {
/**
* Convenience method for implementing dump.
* It generates a newline and inserts blanks at the beginning of the newline.
* @param builder The std::string * being constructed.
* @param indentLevel Indent level, Each level is four spaces.
*/
static void newLine(string *buffer, int indentLevel)
{
*buffer += "\n";
*buffer += string(indentLevel*4, ' ');
}
static PVCopyPtr NULLPVCopy;
static FieldConstPtr NULLField;
static StructureConstPtr NULLStructure;
@@ -67,11 +79,11 @@ PVCopyPtr PVCopy::create(
PVStructurePtr pvStructure(pvRequest);
if(structureName.size()>0) {
if(pvRequest->getStructure()->getNumberFields()>0) {
pvStructure = pvRequest->getStructureField(structureName);
pvStructure = pvRequest->getSubField<PVStructure>(structureName);
if(!pvStructure) return NULLPVCopy;
}
} else if(pvStructure->getSubField("field")) {
pvStructure = pvRequest->getStructureField("field");
} else if(pvStructure->getSubField<PVStructure>("field")) {
pvStructure = pvRequest->getSubField<PVStructure>("field");
}
PVCopyPtr pvCopy = PVCopyPtr(new PVCopy(pvMaster));
bool result = pvCopy->init(pvStructure);
@@ -243,10 +255,9 @@ void PVCopy::updateCopySetBitSet(
updateSubFieldSetBitSet(copyPVField,pvMasterField,bitSet);
return;
}
ConvertPtr convert = getConvert();
bool isEqual = convert->equals(copyPVField,pvField);
bool isEqual = (*copyPVField == *pvField);
if(!isEqual) {
convert->copy(pvField, copyPVField);
copyPVField->copyUnchecked(*pvField);
bitSet->set(copyPVField->getFieldOffset());
}
}
@@ -292,7 +303,7 @@ string PVCopy::dump()
void PVCopy::dump(string *builder,CopyNodePtr const &node,int indentLevel)
{
getConvert()->newLine(builder,indentLevel);
newLine(builder,indentLevel);
std::stringstream ss;
ss << (node->isStructure ? "structureNode" : "masterNode");
ss << " structureOffset " << node->structureOffset;
@@ -300,14 +311,14 @@ void PVCopy::dump(string *builder,CopyNodePtr const &node,int indentLevel)
*builder += ss.str();
PVStructurePtr options = node->options;
if(options) {
getConvert()->newLine(builder,indentLevel +1);
newLine(builder,indentLevel +1);
// TODO !!! ugly
std::ostringstream oss;
oss << *options;
*builder += oss.str();
getConvert()->newLine(builder,indentLevel);
newLine(builder,indentLevel);
}
if(!node->isStructure) {
CopyMasterNodePtr masterNode = static_pointer_cast<CopyMasterNode>(node);
@@ -320,7 +331,7 @@ void PVCopy::dump(string *builder,CopyNodePtr const &node,int indentLevel)
CopyNodePtrArrayPtr nodes = structureNode->nodes;
for(size_t i=0; i<nodes->size(); ++i) {
if((*nodes)[i].get()==NULL) {
getConvert()->newLine(builder,indentLevel +1);
newLine(builder,indentLevel +1);
ss.str("");
ss << "node[" << i << "] is null";
*builder += ss.str();
@@ -338,8 +349,8 @@ bool PVCopy::init(epics::pvData::PVStructurePtr const &pvRequest)
if(len==string::npos) entireMaster = true;
if(len==0) entireMaster = true;
PVStructurePtr pvOptions;
if(len==1 && pvRequest->getSubField("_options")) {
pvOptions = pvRequest->getStructureField("_options");
if(len==1) {
pvOptions = pvRequest->getSubField<PVStructure>("_options");
}
if(entireMaster) {
structure = pvMasterStructure->getStructure();
@@ -431,11 +442,8 @@ CopyNodePtr PVCopy::createStructureNodes(
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);
PVStructurePtr requestPVStructure = pvFromRequest->getSubField<PVStructure>(fieldName);
PVStructurePtr pvSubFieldOptions = requestPVStructure->getSubField<PVStructure>("_options");
PVFieldPtr pvMasterField;
PVFieldPtrArray const & pvMasterFields = pvMasterStructure->getPVFields();
for(size_t j=0; i<pvMasterFields.size(); j++ ) {
@@ -499,17 +507,16 @@ void PVCopy::updateSubFieldSetBitSet(
FieldConstPtr field = pvCopy->getField();
Type type = field->getType();
if(type!=epics::pvData::structure) {
ConvertPtr convert = getConvert();
bool isEqual = convert->equals(pvCopy,pvMaster);
bool isEqual = (*pvCopy == *pvMaster);
if(isEqual) {
if(type==structureArray) {
// always act as though a change occurred.
// Note that array elements are shared.
bitSet->set(pvCopy->getFieldOffset());
bitSet->set(pvCopy->getFieldOffset());
}
}
if(isEqual) return;
convert->copy(pvMaster, pvCopy);
pvCopy->copyUnchecked(*pvMaster);
bitSet->set(pvCopy->getFieldOffset());
return;
}
@@ -542,7 +549,7 @@ void PVCopy::updateStructureNodeFromBitSet(
CopyNodePtrArrayPtr nodes = structureNode->nodes;
for(size_t i=0; i<nodes->size(); i++) {
CopyNodePtr node = (*nodes)[i];
PVFieldPtr pvField = pvCopy->getSubField(node->structureOffset);
PVFieldPtr pvField = pvCopy->getSubFieldT(node->structureOffset);
if(node->isStructure) {
PVStructurePtr xxx = static_pointer_cast<PVStructure>(pvField);
CopyStructureNodePtr subStructureNode =
@@ -574,7 +581,6 @@ void PVCopy::updateSubFieldFromBitSet(
if(nextSet==string::npos) return;
if(nextSet>=pvCopy->getNextFieldOffset()) return;
}
ConvertPtr convert = getConvert();
if(pvCopy->getField()->getType()==epics::pvData::structure) {
PVStructurePtr pvCopyStructure =
static_pointer_cast<PVStructure>(pvCopy);
@@ -595,9 +601,9 @@ void PVCopy::updateSubFieldFromBitSet(
}
} else {
if(toCopy) {
convert->copy(pvMasterField, pvCopy);
pvCopy->copyUnchecked(*pvMasterField);
} else {
convert->copy(pvCopy, pvMasterField);
pvMasterField->copyUnchecked(*pvCopy);
}
}
}

View File

@@ -1,7 +1,6 @@
/**
* 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.
/*
* Copyright information and license terms for this software can be
* found in the file LICENSE that is included with the distribution
*/
/**
* @author mes
@@ -12,13 +11,13 @@
#include <sstream>
#define epicsExportSharedSymbols
#include <pv/convert.h>
#include <pv/pvData.h>
using std::string;
namespace epics { namespace pvData {
// Introspection object comparision
// Introspection object comparison
/** Field equality conditions:
* 1) same instance
@@ -62,7 +61,7 @@ bool operator==(const Field& a, const Field& b)
return A==B;
}
default:
throw std::logic_error("Invalid Field type in comparision");
throw std::logic_error("Invalid Field type in comparison");
}
}
@@ -91,14 +90,14 @@ bool operator==(const Structure& a, const Structure& b)
return false;
// std::equals does not work, since FieldConstPtrArray is an array of shared_pointers
FieldConstPtrArray af = a.getFields();
FieldConstPtrArray bf = b.getFields();
FieldConstPtrArray const & af = a.getFields();
FieldConstPtrArray const & bf = b.getFields();
for (size_t i = 0; i < nflds; i++)
if (*(af[i].get()) != *(bf[i].get()))
return false;
StringArray an = a.getFieldNames();
StringArray bn = b.getFieldNames();
StringArray const & an = a.getFieldNames();
StringArray const & bn = b.getFieldNames();
return std::equal( an.begin(), an.end(), bn.begin() );
}
@@ -118,14 +117,14 @@ bool operator==(const Union& a, const Union& b)
return false;
// std::equals does not work, since FieldConstPtrArray is an array of shared_pointers
FieldConstPtrArray af = a.getFields();
FieldConstPtrArray bf = b.getFields();
FieldConstPtrArray const & af = a.getFields();
FieldConstPtrArray const & bf = b.getFields();
for (size_t i = 0; i < nflds; i++)
if (*(af[i].get()) != *(bf[i].get()))
return false;
StringArray an = a.getFieldNames();
StringArray bn = b.getFieldNames();
StringArray const & an = a.getFieldNames();
StringArray const & bn = b.getFieldNames();
return std::equal( an.begin(), an.end(), bn.begin() );
}
@@ -251,7 +250,13 @@ bool compareField(const PVStructureArray* left, const PVStructureArray* right)
lit!=lend;
++lit, ++rit)
{
if(**lit != **rit)
// element can be null
if (!(*lit) || !(*rit))
{
if (*lit || *rit)
return false;
}
else if (**lit != **rit)
return false;
}
return true;
@@ -304,7 +309,13 @@ bool compareField(const PVUnionArray* left, const PVUnionArray* right)
lit!=lend;
++lit, ++rit)
{
if(**lit != **rit)
// element can be null
if (!(*lit) || !(*rit))
{
if (*lit || *rit)
return false;
}
else if (**lit != **rit)
return false;
}
return true;

View File

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

View File

@@ -1,14 +1,13 @@
/*FieldCreateFactory.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.
/*
* Copyright information and license terms for this software can be
* found in the file LICENSE that is included with the distribution
*/
/**
* @author mrk
*/
#ifdef _WIN32
#if defined(_WIN32) && !defined(NOMINMAX)
#define NOMINMAX
#endif
@@ -19,10 +18,11 @@
#include <stdexcept>
#include <sstream>
#include <epicsMutex.h>
#define epicsExportSharedSymbols
#include <pv/lock.h>
#include <pv/pvIntrospect.h>
#include <pv/convert.h>
#include <pv/factory.h>
#include <pv/serializeHelper.h>
@@ -52,7 +52,7 @@ Scalar::Scalar(ScalarType scalarType)
: Field(scalar),scalarType(scalarType)
{
if(scalarType<0 || scalarType>MAX_SCALAR_TYPE)
throw std::invalid_argument("Can't construct Scalar from invalid ScalarType");
THROW_EXCEPTION2(std::invalid_argument, "Can't construct Scalar from invalid ScalarType");
}
Scalar::~Scalar(){}
@@ -137,7 +137,7 @@ BoundedString::BoundedString(std::size_t maxStringLength) :
Scalar(pvString), maxLength(maxStringLength)
{
if (maxLength == 0)
throw std::invalid_argument("maxLength == 0");
THROW_EXCEPTION2(std::invalid_argument, "maxLength == 0");
}
BoundedString::~BoundedString() {}
@@ -400,7 +400,13 @@ void UnionArray::deserialize(ByteBuffer* /*buffer*/, DeserializableControl* /*co
throw std::runtime_error("not valid operation, use FieldCreate::deserialize instead");
}
string Structure::DEFAULT_ID = "structure";
const string Structure::DEFAULT_ID = Structure::defaultId();
const string & Structure::defaultId()
{
static const string id = "structure";
return id;
}
Structure::Structure (
StringArray const & fieldNames,
@@ -412,27 +418,27 @@ Structure::Structure (
id(inid)
{
if(inid.empty()) {
throw std::invalid_argument("id is empty");
THROW_EXCEPTION2(std::invalid_argument, "Can't construct Structure, id is empty string");
}
if(fieldNames.size()!=fields.size()) {
throw std::invalid_argument("fieldNames.size()!=fields.size()");
THROW_EXCEPTION2(std::invalid_argument, "Can't construct Structure, fieldNames.size()!=fields.size()");
}
size_t number = fields.size();
for(size_t i=0; i<number; i++) {
const string& name = fieldNames[i];
if(name.empty()) {
throw std::invalid_argument("fieldNames has a zero length string");
THROW_EXCEPTION2(std::invalid_argument, "Can't construct Structure, empty string in fieldNames");
}
if(fields[i].get()==NULL)
throw std::invalid_argument("Can't construct Structure with NULL Field");
THROW_EXCEPTION2(std::invalid_argument, "Can't construct Structure, NULL in fields");
// look for duplicates
for(size_t j=i+1; j<number; j++) {
string otherName = fieldNames[j];
int result = name.compare(otherName);
if(result==0) {
string message("duplicate fieldName ");
string message("Can't construct Structure, duplicate fieldName ");
message += name;
throw std::invalid_argument(message);
THROW_EXCEPTION2(std::invalid_argument, message);
}
}
}
@@ -497,7 +503,9 @@ void Structure::dumpFields(std::ostream& o) const
case structureArray:
{
format::indent_scope s(o);
o << *pfield;
Field const *xxx = pfield.get();
StructureArray const *pstructureArray = static_cast<StructureArray const*>(xxx);
o << *pstructureArray->getStructure();
break;
}
case union_:
@@ -511,7 +519,9 @@ void Structure::dumpFields(std::ostream& o) const
case unionArray:
{
format::indent_scope s(o);
o << *pfield;
Field const *xxx = pfield.get();
UnionArray const *punionArray = static_cast<UnionArray const*>(xxx);
o << *punionArray->getUnion();
break;
}
}
@@ -528,20 +538,30 @@ void Structure::deserialize(ByteBuffer* /*buffer*/, DeserializableControl* /*con
throw std::runtime_error("not valid operation, use FieldCreate::deserialize instead");
}
string Union::DEFAULT_ID = "union";
const string Union::DEFAULT_ID = Union::defaultId();
#define UNION_ANY_ID "any"
string Union::ANY_ID = UNION_ANY_ID;
const string & Union::defaultId()
{
static const string id = "union";
return id;
}
const string Union::ANY_ID = Union::anyId();
const string & Union::anyId()
{
static const string id = "any";
return id;
}
Union::Union ()
: Field(union_),
fieldNames(),
fields(),
id(UNION_ANY_ID)
id(anyId())
{
}
#undef UNION_ANY_ID
Union::Union (
StringArray const & fieldNames,
@@ -553,31 +573,31 @@ Union::Union (
id(inid)
{
if(inid.empty()) {
throw std::invalid_argument("id is empty");
THROW_EXCEPTION2(std::invalid_argument, "Can't construct Union, id is empty string");
}
if(fieldNames.size()!=fields.size()) {
throw std::invalid_argument("fieldNames.size()!=fields.size()");
THROW_EXCEPTION2(std::invalid_argument, "Can't construct Union, fieldNames.size()!=fields.size()");
}
if(fields.size()==0 && inid!=ANY_ID) {
throw std::invalid_argument("no fields but id is different than " + ANY_ID);
THROW_EXCEPTION2(std::invalid_argument, "Can't construct Union, no fields only allowed when id = " + ANY_ID);
}
size_t number = fields.size();
for(size_t i=0; i<number; i++) {
const string& name = fieldNames[i];
if(name.empty()) {
throw std::invalid_argument("fieldNames has a zero length string");
THROW_EXCEPTION2(std::invalid_argument, "Can't construct Union, empty string in fieldNames");
}
if(fields[i].get()==NULL)
throw std::invalid_argument("Can't construct Union with NULL Field");
THROW_EXCEPTION2(std::invalid_argument, "Can't construct Union, NULL in fields");
// look for duplicates
for(size_t j=i+1; j<number; j++) {
string otherName = fieldNames[j];
int result = name.compare(otherName);
if(result==0) {
string message("duplicate fieldName ");
string message("Can't construct Union, duplicate fieldName ");
message += name;
throw std::invalid_argument(message);
THROW_EXCEPTION2(std::invalid_argument, message);
}
}
}
@@ -759,7 +779,7 @@ FieldBuilderPtr FieldBuilder::addArray(string const & name, FieldConstPtr const
case scalar:
if (std::tr1::dynamic_pointer_cast<const BoundedString>(element).get())
throw std::invalid_argument("bounded string arrays are not supported");
THROW_EXCEPTION2(std::invalid_argument, "bounded string arrays are not supported");
fields.push_back(fieldCreate->createScalarArray(static_pointer_cast<const Scalar>(element)->getScalarType()));
break;
@@ -767,7 +787,7 @@ FieldBuilderPtr FieldBuilder::addArray(string const & name, FieldConstPtr const
default:
std::ostringstream msg("unsupported array element type: ");
msg << element->getType();
throw std::invalid_argument(msg.str());
THROW_EXCEPTION2(std::invalid_argument, msg.str());
}
fieldNames.push_back(name);
@@ -796,7 +816,7 @@ FieldConstPtr FieldBuilder::createFieldInternal(Type type)
{
std::ostringstream msg("unsupported type: ");
msg << type;
throw std::invalid_argument(msg.str());
THROW_EXCEPTION2(std::invalid_argument, msg.str());
}
}
@@ -804,7 +824,7 @@ FieldConstPtr FieldBuilder::createFieldInternal(Type type)
StructureConstPtr FieldBuilder::createStructure()
{
if (parentBuilder.get())
throw std::runtime_error("createStructure() called in nested FieldBuilder");
THROW_EXCEPTION2(std::runtime_error, "createStructure() called in nested FieldBuilder");
StructureConstPtr field(static_pointer_cast<const Structure>(createFieldInternal(structure)));
reset();
@@ -814,7 +834,7 @@ StructureConstPtr FieldBuilder::createStructure()
UnionConstPtr FieldBuilder::createUnion()
{
if (parentBuilder.get())
throw std::runtime_error("createUnion() called in nested FieldBuilder");
THROW_EXCEPTION2(std::runtime_error, "createUnion() called in nested FieldBuilder");
UnionConstPtr field(static_pointer_cast<const Union>(createFieldInternal(union_)));
reset();
@@ -846,7 +866,7 @@ FieldBuilderPtr FieldBuilder::addNestedUnionArray(string const & name)
FieldBuilderPtr FieldBuilder::endNested()
{
if (!parentBuilder.get())
throw std::runtime_error("this method can only be called to create nested fields");
THROW_EXCEPTION2(std::runtime_error, "this method can only be called to create nested fields");
FieldConstPtr nestedField = createFieldInternal(nestedClassToBuild);
if (nestedArray)
@@ -865,8 +885,11 @@ FieldBuilderPtr FieldCreate::createFieldBuilder() const
ScalarConstPtr FieldCreate::createScalar(ScalarType scalarType) const
{
if(scalarType<0 || scalarType>MAX_SCALAR_TYPE)
throw std::invalid_argument("Can't construct Scalar from invalid ScalarType");
if(scalarType<0 || scalarType>MAX_SCALAR_TYPE) {
std::ostringstream strm("Can't construct Scalar from invalid ScalarType ");
strm << scalarType;
THROW_EXCEPTION2(std::invalid_argument, strm.str());
}
return scalars[scalarType];
}
@@ -881,16 +904,22 @@ BoundedStringConstPtr FieldCreate::createBoundedString(std::size_t maxLength) co
ScalarArrayConstPtr FieldCreate::createScalarArray(ScalarType elementType) const
{
if(elementType<0 || elementType>MAX_SCALAR_TYPE)
throw std::invalid_argument("Can't construct ScalarArray from invalid ScalarType");
if(elementType<0 || elementType>MAX_SCALAR_TYPE) {
std::ostringstream strm("Can't construct ScalarArray from invalid ScalarType ");
strm << elementType;
THROW_EXCEPTION2(std::invalid_argument, strm.str());
}
return scalarArrays[elementType];
}
ScalarArrayConstPtr FieldCreate::createFixedScalarArray(ScalarType elementType, size_t size) const
{
if(elementType<0 || elementType>MAX_SCALAR_TYPE)
throw std::invalid_argument("Can't construct ScalarArray from invalid ScalarType");
if(elementType<0 || elementType>MAX_SCALAR_TYPE) {
std::ostringstream strm("Can't construct fixed ScalarArray from invalid ScalarType ");
strm << elementType;
THROW_EXCEPTION2(std::invalid_argument, strm.str());
}
// TODO use std::make_shared
std::tr1::shared_ptr<ScalarArray> s(new FixedScalarArray(elementType, size), Field::Deleter());
@@ -900,8 +929,11 @@ ScalarArrayConstPtr FieldCreate::createFixedScalarArray(ScalarType elementType,
ScalarArrayConstPtr FieldCreate::createBoundedScalarArray(ScalarType elementType, size_t size) const
{
if(elementType<0 || elementType>MAX_SCALAR_TYPE)
throw std::invalid_argument("Can't construct ScalarArray from invalid ScalarType");
if(elementType<0 || elementType>MAX_SCALAR_TYPE) {
std::ostringstream strm("Can't construct bounded ScalarArray from invalid ScalarType ");
strm << elementType;
THROW_EXCEPTION2(std::invalid_argument, strm.str());
}
// TODO use std::make_shared
std::tr1::shared_ptr<ScalarArray> s(new BoundedScalarArray(elementType, size), Field::Deleter());
@@ -916,9 +948,53 @@ StructureConstPtr FieldCreate::createStructure () const
return createStructure(fieldNames,fields);
}
namespace {
bool xisalnum(char c)
{
return (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9');
}
void validateFieldName(const std::string& n)
{
// enforce [A-Za-z_][A-Za-z0-9_]*
if(n.size()==0)
throw std::invalid_argument("zero length field names not allowed");
if(n[0]>='0' && n[0]<='9') {
std::ostringstream msg;
msg<<"Field name \""<<n<<"\" must begin with A-Z, a-z, or '_'";
throw std::invalid_argument(msg.str());
}
for(size_t i=0, N=n.size(); i<N; i++)
{
char c = n[i];
if(xisalnum(c)) {}
else {
switch(c){
case '_':
break;
default:
{
std::ostringstream msg;
msg<<"Invalid charactor '"<<c<<"' ("<<(int)c<<") in field name \""<<n<<"\" "
"must be A-Z, a-z, 0-9, or '_'";
throw std::invalid_argument(msg.str());
}
}
}
}
}
void validateFieldNames(const StringArray& l)
{
for(StringArray::const_iterator it=l.begin(), end=l.end(); it!=end; ++it)
validateFieldName(*it);
}
}
StructureConstPtr FieldCreate::createStructure (
StringArray const & fieldNames,FieldConstPtrArray const & fields) const
{
validateFieldNames(fieldNames);
// TODO use std::make_shared
std::tr1::shared_ptr<Structure> sp(new Structure(fieldNames,fields), Field::Deleter());
StructureConstPtr structure = sp;
@@ -930,6 +1006,7 @@ StructureConstPtr FieldCreate::createStructure (
StringArray const & fieldNames,
FieldConstPtrArray const & fields) const
{
validateFieldNames(fieldNames);
// TODO use std::make_shared
std::tr1::shared_ptr<Structure> sp(new Structure(fieldNames,fields,id), Field::Deleter());
StructureConstPtr structure = sp;
@@ -948,6 +1025,7 @@ StructureArrayConstPtr FieldCreate::createStructureArray(
UnionConstPtr FieldCreate::createUnion (
StringArray const & fieldNames,FieldConstPtrArray const & fields) const
{
validateFieldNames(fieldNames);
// TODO use std::make_shared
std::tr1::shared_ptr<Union> sp(new Union(fieldNames,fields), Field::Deleter());
UnionConstPtr punion = sp;
@@ -959,6 +1037,7 @@ UnionConstPtr FieldCreate::createUnion (
StringArray const & fieldNames,
FieldConstPtrArray const & fields) const
{
validateFieldNames(fieldNames);
// TODO use std::make_shared
std::tr1::shared_ptr<Union> sp(new Union(fieldNames,fields,id), Field::Deleter());
UnionConstPtr punion = sp;
@@ -989,8 +1068,8 @@ StructureConstPtr FieldCreate::appendField(
string const & fieldName,
FieldConstPtr const & field) const
{
StringArray oldNames = structure->getFieldNames();
FieldConstPtrArray oldFields = structure->getFields();
StringArray const & oldNames = structure->getFieldNames();
FieldConstPtrArray const & oldFields = structure->getFields();
size_t oldLen = oldNames.size();
StringArray newNames(oldLen+1);
FieldConstPtrArray newFields(oldLen+1);
@@ -1008,8 +1087,9 @@ StructureConstPtr FieldCreate::appendFields(
StringArray const & fieldNames,
FieldConstPtrArray const & fields) const
{
StringArray oldNames = structure->getFieldNames();
FieldConstPtrArray oldFields = structure->getFields();
validateFieldNames(fieldNames);
StringArray const & oldNames = structure->getFieldNames();
FieldConstPtrArray const & oldFields = structure->getFields();
size_t oldLen = oldNames.size();
size_t extra = fieldNames.size();
StringArray newNames(oldLen+extra);
@@ -1230,3 +1310,12 @@ FieldCreatePtr getFieldCreate() {
}
}}
namespace std{
std::ostream& operator<<(std::ostream& o, const epics::pvData::Field *ptr)
{
if(ptr) return o << *ptr;
return o << "nullptr";
}
}

View File

@@ -2,7 +2,7 @@
SRC_DIRS += $(PVDATA_SRC)/factory
INC += factory.h
INC += pv/factory.h
LIBSRCS += TypeFunc.cpp
LIBSRCS += FieldCreateFactory.cpp
LIBSRCS += PVField.cpp

View File

@@ -1,8 +1,7 @@
/*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.
/*
* Copyright information and license terms for this software can be
* found in the file LICENSE that is included with the distribution
*/
/**
* @author mrk

View File

@@ -1,14 +1,13 @@
/*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.
/*
* Copyright information and license terms for this software can be
* found in the file LICENSE that is included with the distribution
*/
/**
* @author mrk
*/
#ifdef _WIN32
#if defined(_WIN32) && !defined(NOMINMAX)
#define NOMINMAX
#endif
@@ -17,11 +16,12 @@
#include <string>
#include <cstdio>
#include <epicsMutex.h>
#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>
@@ -527,7 +527,7 @@ PVFieldPtr PVDataCreate::createPVField(PVFieldPtr const & fieldToClone)
PVStructurePtr pvStructure
= static_pointer_cast<PVStructure>(fieldToClone);
StringArray const & fieldNames = pvStructure->getStructure()->getFieldNames();
PVFieldPtrArray pvFieldPtrArray = pvStructure->getPVFields();
PVFieldPtrArray const & pvFieldPtrArray = pvStructure->getPVFields();
return createPVStructure(fieldNames,pvFieldPtrArray);
}
case structureArray:
@@ -537,7 +537,7 @@ PVFieldPtr PVDataCreate::createPVField(PVFieldPtr const & fieldToClone)
StructureArrayConstPtr structureArray = from->getStructureArray();
PVStructureArrayPtr to = createPVStructureArray(
structureArray);
getConvert()->copyStructureArray(from, to);
to->copyUnchecked(*from);
return to;
}
case union_:
@@ -552,7 +552,7 @@ PVFieldPtr PVDataCreate::createPVField(PVFieldPtr const & fieldToClone)
= static_pointer_cast<PVUnionArray>(fieldToClone);
UnionArrayConstPtr unionArray = from->getUnionArray();
PVUnionArrayPtr to = createPVUnionArray(unionArray);
getConvert()->copyUnionArray(from, to);
to->copyUnchecked(*from);
return to;
}
}
@@ -602,7 +602,7 @@ PVScalarPtr PVDataCreate::createPVScalar(PVScalarPtr const & scalarToClone)
{
ScalarType scalarType = scalarToClone->getScalar()->getScalarType();
PVScalarPtr pvScalar = createPVScalar(scalarType);
getConvert()->copyScalar(scalarToClone, pvScalar);
pvScalar->copyUnchecked(*scalarToClone);
return pvScalar;
}
@@ -712,7 +712,7 @@ PVStructurePtr PVDataCreate::createPVStructure(PVStructurePtr const & structToCl
}
StructureConstPtr structure = structToClone->getStructure();
PVStructurePtr pvStructure(new PVStructure(structure));
getConvert()->copyStructure(structToClone,pvStructure);
pvStructure->copyUnchecked(*structToClone);
return pvStructure;
}
@@ -741,3 +741,12 @@ PVDataCreatePtr getPVDataCreate() {
}
}}
namespace std{
std::ostream& operator<<(std::ostream& o, const epics::pvData::PVField *ptr)
{
if(ptr) return o << *ptr;
return o << "nullptr";
}
}

View File

@@ -1,8 +1,7 @@
/*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.
/*
* Copyright information and license terms for this software can be
* found in the file LICENSE that is included with the distribution
*/
/**
* @author mrk
@@ -12,11 +11,12 @@
#include <string>
#include <cstdio>
#include <epicsMutex.h>
#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;
@@ -25,8 +25,7 @@ using std::string;
namespace epics { namespace pvData {
PVField::PVField(FieldConstPtr field)
: notImplemented("not implemented"),
parent(NULL),field(field),
: parent(NULL),field(field),
fieldOffset(0), nextFieldOffset(0),
immutable(false)
{
@@ -121,7 +120,7 @@ void PVField::computeOffset(const PVField * pvField) {
}
size_t offset = 0;
size_t nextOffset = 1;
PVFieldPtrArray pvFields = pvTop->getPVFields();
const PVFieldPtrArray & pvFields = pvTop->getPVFields();
for(size_t i=0; i < pvTop->getStructure()->getNumberFields(); i++) {
offset = nextOffset;
PVField *pvField = pvFields[i].get();
@@ -153,7 +152,7 @@ void PVField::computeOffset(const PVField * pvField,size_t offset) {
size_t beginOffset = offset;
size_t nextOffset = offset + 1;
const PVStructure *pvStructure = static_cast<const PVStructure *>(pvField);
const PVFieldPtrArray pvFields = pvStructure->getPVFields();
const PVFieldPtrArray & pvFields = pvStructure->getPVFields();
for(size_t i=0; i < pvStructure->getStructure()->getNumberFields(); i++) {
offset = nextOffset;
PVField *pvSubField = pvFields[i].get();
@@ -180,4 +179,117 @@ void PVField::computeOffset(const PVField * pvField,size_t offset) {
xxx->nextFieldOffset = nextOffset;
}
void PVField::copy(const PVField& from)
{
if(isImmutable())
throw std::invalid_argument("destination is immutable");
if (getField()->getType() != from.getField()->getType())
throw std::invalid_argument("field types do not match");
switch(getField()->getType())
{
case scalar:
{
const PVScalar* fromS = static_cast<const PVScalar*>(&from);
PVScalar* toS = static_cast<PVScalar*>(this);
toS->copy(*fromS);
break;
}
case scalarArray:
{
const PVScalarArray* fromS = static_cast<const PVScalarArray*>(&from);
PVScalarArray* toS = static_cast<PVScalarArray*>(this);
toS->copy(*fromS);
break;
}
case structure:
{
const PVStructure* fromS = static_cast<const PVStructure*>(&from);
PVStructure* toS = static_cast<PVStructure*>(this);
toS->copy(*fromS);
break;
}
case structureArray:
{
const PVStructureArray* fromS = static_cast<const PVStructureArray*>(&from);
PVStructureArray* toS = static_cast<PVStructureArray*>(this);
toS->copy(*fromS);
break;
}
case union_:
{
const PVUnion* fromS = static_cast<const PVUnion*>(&from);
PVUnion* toS = static_cast<PVUnion*>(this);
toS->copy(*fromS);
break;
}
case unionArray:
{
const PVUnionArray* fromS = static_cast<const PVUnionArray*>(&from);
PVUnionArray* toS = static_cast<PVUnionArray*>(this);
toS->copy(*fromS);
break;
}
default:
{
throw std::logic_error("PVField::copy unknown type");
}
}
}
void PVField::copyUnchecked(const PVField& from)
{
switch(getField()->getType())
{
case scalar:
{
const PVScalar* fromS = static_cast<const PVScalar*>(&from);
PVScalar* toS = static_cast<PVScalar*>(this);
toS->copyUnchecked(*fromS);
break;
}
case scalarArray:
{
const PVScalarArray* fromS = static_cast<const PVScalarArray*>(&from);
PVScalarArray* toS = static_cast<PVScalarArray*>(this);
toS->copyUnchecked(*fromS);
break;
}
case structure:
{
const PVStructure* fromS = static_cast<const PVStructure*>(&from);
PVStructure* toS = static_cast<PVStructure*>(this);
toS->copyUnchecked(*fromS);
break;
}
case structureArray:
{
const PVStructureArray* fromS = static_cast<const PVStructureArray*>(&from);
PVStructureArray* toS = static_cast<PVStructureArray*>(this);
toS->copyUnchecked(*fromS);
break;
}
case union_:
{
const PVUnion* fromS = static_cast<const PVUnion*>(&from);
PVUnion* toS = static_cast<PVUnion*>(this);
toS->copyUnchecked(*fromS);
break;
}
case unionArray:
{
const PVUnionArray* fromS = static_cast<const PVUnionArray*>(&from);
PVUnionArray* toS = static_cast<PVUnionArray*>(this);
toS->copyUnchecked(*fromS);
break;
}
default:
{
throw std::logic_error("PVField::copy unknown type");
}
}
}
}}

View File

@@ -1,8 +1,7 @@
/*PVScalar.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.
/*
* Copyright information and license terms for this software can be
* found in the file LICENSE that is included with the distribution
*/
/**
* @author mrk
@@ -29,22 +28,4 @@ namespace epics { namespace pvData {
{
return static_pointer_cast<const Scalar>(PVField::getField());
}
template<>
std::ostream& PVScalarValue<int8>::dumpValue(std::ostream& o) const
{
return o << static_cast<int>(get());
}
template<>
std::ostream& PVScalarValue<uint8>::dumpValue(std::ostream& o) const
{
return o << static_cast<unsigned int>(get());
}
template<>
std::ostream& PVScalarValue<boolean>::dumpValue(std::ostream& o) const
{
return o << std::boolalpha << static_cast<bool>(get());
}
}}

View File

@@ -1,8 +1,7 @@
/*PVScalarArray.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.
/*
* Copyright information and license terms for this software can be
* found in the file LICENSE that is included with the distribution
*/
/**
* @author mrk

View File

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

View File

@@ -1,8 +1,7 @@
/*PVStructureArray.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.
/*
* Copyright information and license terms for this software can be
* found in the file LICENSE that is included with the distribution
*/
/**
* @author mrk
@@ -14,7 +13,6 @@
#define epicsExportSharedSymbols
#include <pv/pvData.h>
#include <pv/convert.h>
#include <pv/factory.h>
#include <pv/serializeHelper.h>
@@ -179,7 +177,7 @@ void PVStructureArray::deserialize(ByteBuffer *pbuffer,
data[i].reset();
}
else {
if(data[i].get()==NULL) {
if(data[i].get()==NULL || !data[i].unique()) {
data[i] = pvDataCreate->createPVStructure(structure);
}
data[i]->deserialize(pbuffer, pcontrol);
@@ -232,9 +230,33 @@ std::ostream& PVStructureArray::dumpValue(std::ostream& o) const
std::ostream& PVStructureArray::dumpValue(std::ostream& o, std::size_t index) const
{
const_svector temp(view());
if(index<temp.size())
o << *temp[index];
if (index<temp.size())
{
if (temp[index])
o << *temp[index];
else
o << format::indent() << "(none)" << std::endl;
}
return o;
}
void PVStructureArray::copy(const PVStructureArray& from)
{
if(isImmutable())
throw std::invalid_argument("destination is immutable");
if(*getStructureArray() != *from.getStructureArray())
throw std::invalid_argument("structureArray definitions do not match");
copyUnchecked(from);
}
void PVStructureArray::copyUnchecked(const PVStructureArray& from)
{
if (this == &from)
return;
replace(from.view());
}
}}

View File

@@ -1,8 +1,7 @@
/*PVUnion.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.
/*
* Copyright information and license terms for this software can be
* found in the file LICENSE that is included with the distribution
*/
/**
* @author mse
@@ -16,7 +15,6 @@
#define epicsExportSharedSymbols
#include <pv/pvData.h>
#include <pv/pvIntrospect.h>
#include <pv/convert.h>
#include <pv/factory.h>
#include <pv/serializeHelper.h>
@@ -29,6 +27,8 @@ namespace epics { namespace pvData {
#define PVUNION_UNDEFINED_INDEX -1
int32 PVUnion::UNDEFINED_INDEX = PVUNION_UNDEFINED_INDEX;
PVDataCreatePtr PVUnion::pvDataCreate(getPVDataCreate());
PVUnion::PVUnion(UnionConstPtr const & unionPtr)
: PVField(unionPtr),
unionPtr(unionPtr),
@@ -87,7 +87,7 @@ PVFieldPtr PVUnion::select(int32 index)
FieldConstPtr field = unionPtr->getField(index);
selector = index;
value = getPVDataCreate()->createPVField(field);
value = pvDataCreate->createPVField(field);
return value;
}
@@ -144,10 +144,10 @@ void PVUnion::serialize(ByteBuffer *pbuffer, SerializableControl *pflusher) cons
if (variant)
{
// write introspection data
if (value.get() == 0)
if (value.get() == 0) {
pflusher->ensureBuffer(1);
pbuffer->put((int8)-1);
else
{
}else {
pflusher->cachedSerialize(value->getField(), pbuffer);
value->serialize(pbuffer, pflusher);
}
@@ -171,7 +171,7 @@ void PVUnion::deserialize(ByteBuffer *pbuffer, DeserializableControl *pcontrol)
{
// try to reuse existing field instance
if (!value.get() || *value->getField() != *field)
value = getPVDataCreate()->createPVField(field);
value = pvDataCreate->createPVField(field);
value->deserialize(pbuffer, pcontrol);
}
else
@@ -188,7 +188,7 @@ void PVUnion::deserialize(ByteBuffer *pbuffer, DeserializableControl *pcontrol)
FieldConstPtr field = unionPtr->getField(selector);
// try to reuse existing field instance
if (!value.get() || *value->getField() != *field)
value = getPVDataCreate()->createPVField(field);
value = pvDataCreate->createPVField(field);
}
value->deserialize(pbuffer, pcontrol);
}
@@ -217,4 +217,57 @@ std::ostream& PVUnion::dumpValue(std::ostream& o) const
return o;
}
void PVUnion::copy(const PVUnion& from)
{
if(isImmutable())
throw std::invalid_argument("destination is immutable");
if(*getUnion() != *from.getUnion())
throw std::invalid_argument("union definitions do not match");
copyUnchecked(from);
}
void PVUnion::copyUnchecked(const PVUnion& from)
{
PVFieldPtr fromValue = from.get();
if (from.getUnion()->isVariant())
{
if (fromValue.get() == 0)
{
set(PVField::shared_pointer());
}
else
{
PVFieldPtr toValue = get();
if (toValue.get() == 0 || *toValue->getField() != *fromValue->getField())
{
toValue = pvDataCreate->createPVField(fromValue->getField());
toValue->copyUnchecked(*fromValue);
set(toValue);
}
else
{
toValue->copyUnchecked(*fromValue);
postPut();
}
}
}
else
{
if (fromValue.get() == 0)
{
select(PVUnion::UNDEFINED_INDEX);
}
else
{
select(from.getSelectedIndex())->copyUnchecked(*fromValue);
}
postPut();
}
}
}}

View File

@@ -1,8 +1,7 @@
/*PVUnionArray.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.
/*
* Copyright information and license terms for this software can be
* found in the file LICENSE that is included with the distribution
*/
/**
* @author mrk
@@ -14,7 +13,6 @@
#define epicsExportSharedSymbols
#include <pv/pvData.h>
#include <pv/convert.h>
#include <pv/factory.h>
#include <pv/serializeHelper.h>
@@ -178,7 +176,7 @@ void PVUnionArray::deserialize(ByteBuffer *pbuffer,
data[i].reset();
}
else {
if(data[i].get()==NULL) {
if(data[i].get()==NULL || !data[i].unique()) {
data[i] = pvDataCreate->createPVUnion(punion);
}
data[i]->deserialize(pbuffer, pcontrol);
@@ -231,9 +229,34 @@ std::ostream& PVUnionArray::dumpValue(std::ostream& o) const
std::ostream& PVUnionArray::dumpValue(std::ostream& o, std::size_t index) const
{
const_svector temp(view());
if(index<temp.size())
o << *temp[index];
if (index<temp.size())
{
if (temp[index])
o << *temp[index];
else
o << format::indent() << "(none)" << std::endl;
}
return o;
}
void PVUnionArray::copy(const PVUnionArray& from)
{
if(isImmutable())
throw std::invalid_argument("destination is immutable");
if(*getUnionArray() != *from.getUnionArray())
throw std::invalid_argument("unionArray definitions do not match");
copyUnchecked(from);
}
void PVUnionArray::copyUnchecked(const PVUnionArray& from)
{
if (this == &from)
return;
replace(from.view());
}
}}

View File

@@ -1,8 +1,7 @@
/* StandardField.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.
/*
* Copyright information and license terms for this software can be
* found in the file LICENSE that is included with the distribution
*/
/**
* @author mrk
@@ -11,6 +10,8 @@
#include <cstdio>
#include <stdexcept>
#include <epicsMutex.h>
#define epicsExportSharedSymbols
#include <pv/lock.h>
#include <pv/pvIntrospect.h>
@@ -89,9 +90,9 @@ StructureConstPtr StandardField::createProperties(string id,FieldConstPtr field,
}
if(type==structure) {
StructureConstPtr structurePtr = static_pointer_cast<const Structure>(field);
StringArray names = structurePtr->getFieldNames();
StringArray const & names = structurePtr->getFieldNames();
if(names.size()==2) {
FieldConstPtrArray fields = structurePtr->getFields();
FieldConstPtrArray const & fields = structurePtr->getFields();
FieldConstPtr first = fields[0];
FieldConstPtr second = fields[1];
string nameFirst = names[0];
@@ -554,7 +555,7 @@ StructureConstPtr StandardField::enumerated()
fields[0] = fieldCreate->createScalar(pvInt);
fields[1] = fieldCreate->createScalarArray(pvString);
return fieldCreate->createStructure("enum_t",names,fields);
// NOTE: if this method is used to get NTEnum wihtout properties the ID will be wrong!
// NOTE: if this method is used to get NTEnum without properties the ID will be wrong!
}
StructureConstPtr StandardField::enumerated(string const &properties)

View File

@@ -1,8 +1,7 @@
/* StandardPVField.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.
/*
* Copyright information and license terms for this software can be
* found in the file LICENSE that is included with the distribution
*/
/**
* @author mrk
@@ -10,11 +9,12 @@
#include <string>
#include <stdexcept>
#include <epicsMutex.h>
#define epicsExportSharedSymbols
#include <pv/lock.h>
#include <pv/pvIntrospect.h>
#include <pv/pvData.h>
#include <pv/convert.h>
#include <pv/standardField.h>
#include <pv/standardPVField.h>
@@ -67,11 +67,9 @@ PVStructurePtr StandardPVField::enumerated(StringArray const &choices)
{
StructureConstPtr field = standardField->enumerated();
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(field);
PVScalarArrayPtr pvScalarArray = pvStructure->getScalarArrayField(
"choices",pvString);
PVStringArray::svector cdata(choices.size());
std::copy(choices.begin(), choices.end(), cdata.begin());
static_cast<PVStringArray&>(*pvScalarArray).replace(freeze(cdata));
pvStructure->getSubFieldT<PVStringArray>("choices")->replace(freeze(cdata));
return pvStructure;
}
@@ -80,11 +78,9 @@ PVStructurePtr StandardPVField::enumerated(
{
StructureConstPtr field = standardField->enumerated(properties);
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(field);
PVScalarArrayPtr pvScalarArray = pvStructure->getScalarArrayField(
"value.choices",pvString);
PVStringArray::svector cdata(choices.size());
std::copy(choices.begin(), choices.end(), cdata.begin());
static_cast<PVStringArray&>(*pvScalarArray).replace(freeze(cdata));
pvStructure->getSubFieldT<PVStringArray>("value.choices")->replace(freeze(cdata));
return pvStructure;
}

View File

@@ -1,8 +1,7 @@
/*TypeFunc.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.
/*
* Copyright information and license terms for this software can be
* found in the file LICENSE that is included with the distribution
*/
/**
* @author mrk

View File

@@ -1,18 +0,0 @@
/*factory.h*/
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvData is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
/**
* @author mrk
*/
#ifndef FACTORY_H
#define FACTORY_H
namespace epics { namespace pvData {
enum DebugLevel{noDebug,lowDebug,highDebug};
}}
#endif /*FACTORY_H */

View File

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

17
src/factory/pv/factory.h Normal file
View File

@@ -0,0 +1,17 @@
/*factory.h*/
/*
* Copyright information and license terms for this software can be
* found in the file LICENSE that is included with the distribution
*/
/**
* @author mrk
*/
#ifndef FACTORY_H
#define FACTORY_H
namespace epics { namespace pvData {
enum DebugLevel{noDebug,lowDebug,highDebug};
}}
#endif /*FACTORY_H */

View File

@@ -1,7 +1,6 @@
/**
* 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.
/*
* Copyright information and license terms for this software can be
* found in the file LICENSE that is included with the distribution
*/
/**
* @author Marty Kraimer

View File

@@ -2,30 +2,29 @@
SRC_DIRS += $(PVDATA_SRC)/misc
INC += noDefaultMethods.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 += timeFunction.h
INC += timer.h
INC += queue.h
INC += messageQueue.h
INC += destroyable.h
INC += status.h
INC += sharedPtr.h
INC += localStaticLock.h
INC += typeCast.h
INC += printer.h
INC += sharedVector.h
INC += templateMeta.h
INC += current_function.h
INC += pv/noDefaultMethods.h
INC += pv/lock.h
INC += pv/requester.h
INC += pv/serialize.h
INC += pv/bitSet.h
INC += pv/byteBuffer.h
INC += pv/epicsException.h
INC += pv/serializeHelper.h
INC += pv/event.h
INC += pv/thread.h
INC += pv/executor.h
INC += pv/timeFunction.h
INC += pv/timer.h
INC += pv/queue.h
INC += pv/messageQueue.h
INC += pv/destroyable.h
INC += pv/status.h
INC += pv/sharedPtr.h
INC += pv/localStaticLock.h
INC += pv/typeCast.h
INC += pv/sharedVector.h
INC += pv/templateMeta.h
INC += pv/current_function.h
LIBSRCS += byteBuffer.cpp
LIBSRCS += bitSet.cpp

View File

@@ -1,8 +1,7 @@
/* bitSet.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.
/*
* Copyright information and license terms for this software can be
* found in the file LICENSE that is included with the distribution
*/
/**
* @author mes
@@ -10,12 +9,38 @@
#include <string.h>
#include <stdio.h>
#include <iostream>
#include <stdexcept>
#include <algorithm>
#include <epicsMutex.h>
#define epicsExportSharedSymbols
#include <pv/lock.h>
#include <pv/serializeHelper.h>
#include <pv/bitSet.h>
/*
* BitSets are packed into arrays of "words." Currently a word is
* a long, which consists of 64 bits, requiring 6 address bits.
* The choice of word size is determined purely by performance concerns.
*/
#define ADDRESS_BITS_PER_WORD 6u
#define BITS_PER_WORD (1u << ADDRESS_BITS_PER_WORD)
#define BYTES_PER_WORD sizeof(uint64)
#define BIT_INDEX_MASK (BITS_PER_WORD - 1u)
/** Used to shift left or right for a partial word mask */
#define WORD_MASK ~((uint64)0)
// index of work containing this bit
#define WORD_INDEX(bitn) ((bitn)>>ADDRESS_BITS_PER_WORD)
// bit offset within word
#define WORD_OFFSET(bitn) ((bitn)&BIT_INDEX_MASK)
// the words vector should be size()d as small as posible,
// so the last word should always have a bit set when the set is not empty
#define CHECK_POST() assert(words.empty() || words.back()!=0)
namespace epics { namespace pvData {
BitSet::shared_pointer BitSet::create(uint32 nbits)
@@ -23,88 +48,59 @@ namespace epics { namespace pvData {
return BitSet::shared_pointer(new BitSet(nbits));
}
BitSet::BitSet() : words(0), wordsLength(0), wordsInUse(0) {
initWords(BITS_PER_WORD);
BitSet::BitSet() {}
BitSet::BitSet(uint32 nbits)
{
words.reserve((nbits == 0) ? 1 : WORD_INDEX(nbits-1) + 1);
}
BitSet::BitSet(uint32 nbits) : words(0), wordsLength(0), wordsInUse(0) {
initWords(nbits);
}
BitSet::~BitSet() {
delete[] words;
}
void BitSet::initWords(uint32 nbits) {
uint32 length = (nbits <= 0) ? 1 : wordIndex(nbits-1) + 1;
if (words) delete[] words;
words = new uint64[length];
memset(words, 0, sizeof(uint64)*length);
wordsLength = length;
}
BitSet::~BitSet() {}
void BitSet::recalculateWordsInUse() {
// wordsInUse is unsigned
if (wordsInUse == 0)
return;
// Traverse the bitset until a used word is found
int32 i;
for (i = (int32)wordsInUse-1; i >= 0; i--)
if (words[i] != 0)
// step back from the end to find the first non-zero element
size_t nsize = words.size();
for(; nsize; nsize--) {
if(words[nsize-1])
break;
wordsInUse = i+1; // The new logical size
}
words.resize(nsize);
CHECK_POST();
}
void BitSet::ensureCapacity(uint32 wordsRequired) {
if (wordsLength < wordsRequired) {
// create and copy
uint64* newwords = new uint64[wordsRequired];
memset(newwords, 0, sizeof(uint64)*wordsRequired);
memcpy(newwords, words, sizeof(uint64)*wordsLength);
if (words) delete[] words;
words = newwords;
wordsLength = wordsRequired;
}
words.resize(std::max(words.size(), (size_t)wordsRequired), 0);
}
void BitSet::expandTo(uint32 wordIndex) {
uint32 wordsRequired = wordIndex+1;
if (wordsInUse < wordsRequired) {
ensureCapacity(wordsRequired);
wordsInUse = wordsRequired;
}
ensureCapacity(wordIndex+1);
}
void BitSet::flip(uint32 bitIndex) {
uint32 wordIdx = wordIndex(bitIndex);
uint32 wordIdx = WORD_INDEX(bitIndex);
expandTo(wordIdx);
words[wordIdx] ^= (((uint64)1) << (bitIndex % BITS_PER_WORD));
words[wordIdx] ^= (((uint64)1) << WORD_OFFSET(bitIndex));
recalculateWordsInUse();
}
void BitSet::set(uint32 bitIndex) {
uint32 wordIdx = wordIndex(bitIndex);
uint32 wordIdx = WORD_INDEX(bitIndex);
expandTo(wordIdx);
words[wordIdx] |= (((uint64)1) << (bitIndex % BITS_PER_WORD));
words[wordIdx] |= (((uint64)1) << WORD_OFFSET(bitIndex));
}
void BitSet::clear(uint32 bitIndex) {
uint32 wordIdx = wordIndex(bitIndex);
if (wordIdx >= wordsInUse)
uint32 wordIdx = WORD_INDEX(bitIndex);
if (wordIdx >= words.size())
return;
words[wordIdx] &= ~(((uint64)1) << (bitIndex % BITS_PER_WORD));
words[wordIdx] &= ~(((uint64)1) << WORD_OFFSET(bitIndex));
recalculateWordsInUse();
}
@@ -117,14 +113,13 @@ namespace epics { namespace pvData {
}
bool BitSet::get(uint32 bitIndex) const {
uint32 wordIdx = wordIndex(bitIndex);
return ((wordIdx < wordsInUse)
&& ((words[wordIdx] & (((uint64)1) << (bitIndex % BITS_PER_WORD))) != 0));
uint32 wordIdx = WORD_INDEX(bitIndex);
return ((wordIdx < words.size())
&& ((words[wordIdx] & (((uint64)1) << WORD_OFFSET(bitIndex))) != 0));
}
void BitSet::clear() {
while (wordsInUse > 0)
words[--wordsInUse] = 0;
words.clear();
}
uint32 BitSet::numberOfTrailingZeros(uint64 i) {
@@ -153,8 +148,8 @@ namespace epics { namespace pvData {
int32 BitSet::nextSetBit(uint32 fromIndex) const {
uint32 u = wordIndex(fromIndex);
if (u >= wordsInUse)
uint32 u = WORD_INDEX(fromIndex);
if (u >= words.size())
return -1;
uint64 word = words[u] & (WORD_MASK << (fromIndex % BITS_PER_WORD));
@@ -162,7 +157,7 @@ namespace epics { namespace pvData {
while (true) {
if (word != 0)
return (u * BITS_PER_WORD) + numberOfTrailingZeros(word);
if (++u == wordsInUse)
if (++u == words.size())
return -1;
word = words[u];
}
@@ -171,8 +166,8 @@ namespace epics { namespace pvData {
int32 BitSet::nextClearBit(uint32 fromIndex) const {
// Neither spec nor implementation handle bitsets of maximal length.
uint32 u = wordIndex(fromIndex);
if (u >= wordsInUse)
uint32 u = WORD_INDEX(fromIndex);
if (u >= words.size())
return fromIndex;
uint64 word = ~words[u] & (WORD_MASK << (fromIndex % BITS_PER_WORD));
@@ -180,79 +175,63 @@ namespace epics { namespace pvData {
while (true) {
if (word != 0)
return (u * BITS_PER_WORD) + numberOfTrailingZeros(word);
if (++u == wordsInUse)
return wordsInUse * BITS_PER_WORD;
if (++u == words.size())
return words.size() * BITS_PER_WORD;
word = ~words[u];
}
}
bool BitSet::isEmpty() const {
return (wordsInUse == 0);
return words.empty();
}
uint32 BitSet::cardinality() const {
uint32 sum = 0;
for (uint32 i = 0; i < wordsInUse; i++)
for (uint32 i = 0; i < words.size(); i++)
sum += bitCount(words[i]);
return sum;
}
uint32 BitSet::size() const {
return wordsLength * BITS_PER_WORD;
return words.size() * BITS_PER_WORD;
}
BitSet& BitSet::operator&=(const BitSet& set) {
// Check for self-assignment!
if (this == &set) return *this;
while (wordsInUse > set.wordsInUse)
words[--wordsInUse] = 0;
// the result length will be <= the shorter of the two inputs
words.resize(std::min(words.size(), set.words.size()), 0);
// Perform logical AND on words in common
for (uint32 i = 0; i < wordsInUse; i++)
for(size_t i=0, e=words.size(); i<e; i++)
words[i] &= set.words[i];
recalculateWordsInUse();
return *this;
}
BitSet& BitSet::operator|=(const BitSet& set) {
// Check for self-assignment!
if (this == &set) return *this;
uint32 wordsInCommon = wordsInUse;
if(wordsInUse>set.wordsInUse) wordsInCommon = set.wordsInUse;
if (wordsInUse < set.wordsInUse) {
ensureCapacity(set.wordsInUse);
wordsInUse = set.wordsInUse;
}
// Perform logical OR on words in common
for (uint32 i =0; i < wordsInCommon; i++) {
// result length will be the same as the longer of the two inputs
words.resize(std::max(words.size(), set.words.size()), 0);
// since we expand w/ zeros, then iterate using the size of the other vector
for(size_t i=0, e=set.words.size(); i<e; i++)
words[i] |= set.words[i];
}
// Copy any remaining words
for(uint32 i=wordsInCommon; i<set.wordsInUse; ++i) {
words[i] = set.words[i];
}
// recalculateWordsInUse() is not needed
CHECK_POST();
return *this;
}
BitSet& BitSet::operator^=(const BitSet& set) {
uint32 wordsInCommon = wordsInUse;
if(wordsInUse>set.wordsInUse) wordsInCommon = set.wordsInUse;
if (wordsInUse < set.wordsInUse) {
ensureCapacity(set.wordsInUse);
wordsInUse = set.wordsInUse;
}
// Perform logical OR on words in common
for (uint32 i =0; i < wordsInCommon; i++) {
// result length will <= the longer of the two inputs
words.resize(std::max(words.size(), set.words.size()), 0);
for(size_t i=0, e=set.words.size(); i<e; i++)
words[i] ^= set.words[i];
}
// Copy any remaining words
for(uint32 i=wordsInCommon; i<set.wordsInUse; ++i) {
words[i] = set.words[i];
}
recalculateWordsInUse();
return *this;
}
@@ -260,32 +239,27 @@ namespace epics { namespace pvData {
BitSet& BitSet::operator=(const BitSet &set) {
// Check for self-assignment!
if (this == &set) return *this;
// we ensure that words array size is adequate (and not wordsInUse to ensure capacity to the future)
if (wordsLength < set.wordsLength)
{
if (words) delete[] words;
words = new uint64[set.wordsLength];
wordsLength = set.wordsLength;
if (this != &set) {
words = set.words;
}
memcpy(words, set.words, sizeof(uint64)*set.wordsInUse);
wordsInUse = set.wordsInUse;
return *this;
}
void BitSet::or_and(const BitSet& set1, const BitSet& set2) {
uint32 inUse = (set1.wordsInUse < set2.wordsInUse) ? set1.wordsInUse : set2.wordsInUse;
void BitSet::swap(BitSet& set)
{
words.swap(set.words);
}
ensureCapacity(inUse);
wordsInUse = inUse;
void BitSet::or_and(const BitSet& set1, const BitSet& set2) {
const size_t andlen = std::min(set1.words.size(), set2.words.size());
words.resize(std::max(words.size(), andlen), 0);
// Perform logical AND on words in common
for (uint32 i = 0; i < inUse; i++)
for (uint32 i = 0; i < andlen; i++)
words[i] |= (set1.words[i] & set2.words[i]);
// recalculateWordsInUse()...
recalculateWordsInUse();
}
bool BitSet::operator==(const BitSet &set) const
@@ -293,11 +267,11 @@ namespace epics { namespace pvData {
if (this == &set)
return true;
if (wordsInUse != set.wordsInUse)
if (words.size() != set.words.size())
return false;
// Check words in use by both BitSets
for (uint32 i = 0; i < wordsInUse; i++)
for (uint32 i = 0; i < words.size(); i++)
if (words[i] != set.words[i])
return false;
@@ -310,56 +284,55 @@ namespace epics { namespace pvData {
}
void BitSet::serialize(ByteBuffer* buffer, SerializableControl* flusher) const {
uint32 n = wordsInUse;
uint32 n = words.size();
if (n == 0) {
SerializeHelper::writeSize(0, buffer, flusher);
return;
}
uint32 len = 8 * (n-1);
uint32 len = BYTES_PER_WORD * (n-1); // length excluding bits in the last word
// count non-zero bytes in the last word
for (uint64 x = words[n - 1]; x != 0; x >>= 8)
len++;
SerializeHelper::writeSize(len, buffer, flusher);
flusher->ensureBuffer(len);
for (uint32 i = 0; i < n - 1; i++)
n = len / 8;
for (uint32 i = 0; i < n; i++)
buffer->putLong(words[i]);
for (uint64 x = words[n - 1]; x != 0; x >>= 8)
buffer->putByte((int8) (x & 0xff));
if (n < words.size())
for (uint64 x = words[words.size() - 1]; x != 0; x >>= 8)
buffer->putByte((int8) (x & 0xff));
}
void BitSet::deserialize(ByteBuffer* buffer, DeserializableControl* control) {
uint32 bytes = static_cast<uint32>(SerializeHelper::readSize(buffer, control)); // in bytes
wordsInUse = (bytes + 7) / 8;
if (wordsInUse > wordsLength)
{
if (words) delete[] words;
words = new uint64[wordsInUse];
wordsLength = wordsInUse;
}
size_t wordsInUse = (bytes + 7) / BYTES_PER_WORD;
words.resize(wordsInUse);
if (wordsInUse == 0)
return;
control->ensureData(bytes);
uint32 i = 0;
uint32 longs = bytes / 8;
while (i < longs)
words[i++] = buffer->getLong();
for (uint32 j = i; j < wordsInUse; j++)
words[j] = 0;
for (uint32 remaining = (bytes - longs * 8), j = 0; j < remaining; j++)
words[i] |= (buffer->getByte() & 0xffL) << (8 * j);
words[i] |= (buffer->getByte() & 0xffLL) << (8 * j);
recalculateWordsInUse(); // Sender shouldn't add extra zero bytes, but don't fail it it does
}
epicsShareExtern std::ostream& operator<<(std::ostream& o, const BitSet& b)
{
o << '{';

View File

@@ -1,8 +1,10 @@
/**
* 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.
/*
* Copyright information and license terms for this software can be
* found in the file LICENSE that is included with the distribution
*/
/**
* @author mse
*/
#define epicsExportSharedSymbols
#include <pv/byteBuffer.h>

View File

@@ -1,7 +1,6 @@
/**
* 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.
/*
* Copyright information and license terms for this software can be
* found in the file LICENSE that is included with the distribution
*/
/**
* @author mes
@@ -10,6 +9,7 @@
#include <sstream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <string>
#define epicsExportSharedSymbols
@@ -50,7 +50,7 @@ ExceptionMixin::show() const
out<<symbols[i]<<"\n";
}
free(symbols);
std::free(symbols);
}
#endif

View File

@@ -1,8 +1,7 @@
/* event.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.
/*
* Copyright information and license terms for this software can be
* found in the file LICENSE that is included with the distribution
*/
/**
* @author mrk
@@ -38,8 +37,7 @@ Event::~Event() {
Event::Event(bool full)
: id(epicsEventCreate(full?epicsEventFull : epicsEventEmpty)),
alreadyOn("already on list")
: id(epicsEventCreate(full?epicsEventFull : epicsEventEmpty))
{
}

View File

@@ -1,53 +0,0 @@
/* event.h */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvData is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
/**
* @author mrk
*/
#ifndef EVENT_H
#define EVENT_H
#include <memory>
#include <vector>
#ifdef epicsExportSharedSymbols
#define eventepicsExportSharedSymbols
#undef epicsExportSharedSymbols
#endif
#include <epicsEvent.h>
#ifdef eventepicsExportSharedSymbols
#define epicsExportSharedSymbols
#undef eventepicsExportSharedSymbols
#endif
#include <pv/pvType.h>
#include <pv/sharedPtr.h>
#include <shareLib.h>
namespace epics { namespace pvData {
class Event;
typedef std::tr1::shared_ptr<Event> EventPtr;
class epicsShareClass Event {
public:
POINTER_DEFINITIONS(Event);
explicit Event(bool = false);
~Event();
void signal();
bool wait (); /* blocks until full */
bool wait ( double timeOut ); /* false if empty at time out */
bool tryWait (); /* false if empty */
private:
epicsEventId id;
std::string alreadyOn;
};
}}
#endif /* EVENT_H */

View File

@@ -1,8 +1,7 @@
/* executor.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.
/*
* Copyright information and license terms for this software can be
* found in the file LICENSE that is included with the distribution
*/
/**
* @author mrk
@@ -13,6 +12,10 @@
#include <string>
#include <cstdio>
#include <epicsEvent.h>
#include <epicsMutex.h>
#include <epicsThread.h>
#define epicsExportSharedSymbols
#include <pv/executor.h>

View File

@@ -1,8 +1,7 @@
/* localStaticLock.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.
/*
* Copyright information and license terms for this software can be
* found in the file LICENSE that is included with the distribution
*/
/**
* @author mse

View File

@@ -1,8 +1,7 @@
/* messageQueue.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.
/*
* Copyright information and license terms for this software can be
* found in the file LICENSE that is included with the distribution
*/
/**
* @author mrk

View File

@@ -1,67 +0,0 @@
/* messageQueue.h */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvData is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
/**
* @author mrk
*/
#ifndef MESSAGEQUEUE_H
#define MESSAGEQUEUE_H
#include <memory>
#include <vector>
#include <cstddef>
#include <stdexcept>
#include <pv/pvType.h>
#include <pv/requester.h>
#include <pv/queue.h>
#include <shareLib.h>
namespace epics { namespace pvData {
class MessageNode;
class MessageQueue;
typedef std::tr1::shared_ptr<MessageNode> MessageNodePtr;
typedef std::vector<MessageNodePtr> MessageNodePtrArray;
typedef std::tr1::shared_ptr<MessageQueue> MessageQueuePtr;
class epicsShareClass MessageNode {
public:
MessageNode();
std::string getMessage() const;
MessageType getMessageType() const;
private:
std::string message;
MessageType messageType;
friend class MessageQueue;
};
class epicsShareClass MessageQueue : public Queue<MessageNode> {
public:
POINTER_DEFINITIONS(MessageQueue);
static MessageQueuePtr create(int size);
MessageQueue(MessageNodePtrArray &nodeArray);
virtual ~MessageQueue();
MessageNodePtr &get();
// must call release before next get
void release();
// return (false,true) if message (was not, was) put into queue
bool put(std::string message,MessageType messageType,bool replaceLast);
bool isEmpty() ;
bool isFull() ;
int getClearOverrun();
private:
MessageNodePtr nullNode;
MessageNodePtr lastGet;
MessageNodePtr lastPut;
uint32 overrun;
};
}}
#endif /* MESSAGEQUEUE_H */

View File

@@ -1,3 +1,7 @@
/*
* Copyright information and license terms for this software can be
* found in the file LICENSE that is included with the distribution
*/
#include <ctype.h>
#include <stdio.h>
#include <errno.h>
@@ -12,7 +16,7 @@
#include <epicsConvert.h>
#define epicsExportSharedSymbols
#include "typeCast.h"
#include "pv/typeCast.h"
using std::string;
@@ -27,7 +31,7 @@ using std::string;
#endif
#if EPICS_VERSION_INT < VERSION_INT(3,15,0,1)
/* integer conversion primitives added to epicsStdlib.c in 3.15.0.1 */
/* These integer conversion primitives added to epicsStdlib.c in 3.15.0.1 */
#define S_stdlib_noConversion 1 /* No digits to convert */
#define S_stdlib_extraneous 2 /* Extraneous characters */
@@ -249,18 +253,19 @@ epicsParseFloat(const char *str, float *to, char **units)
}
#endif
// MS Visual Studio 2013 defines strtoll, etc.
#if defined(_WIN32)
# if (_MSC_VER >= 1800)
# define WIN_NEEDS_OLL_FUNC 0
# else
# define WIN_NEEDS_OLL_FUNC 1
# endif
// Sometimes we have to provide our own copy of strtoll()
#if defined(_WIN32) && !defined(_MINGW)
// On Windows with MSVC, Base-3.15 provides strtoll()
# define NEED_OLL_FUNCS (EPICS_VERSION_INT < VERSION_INT(3,15,0,1))
#elif defined(vxWorks)
// On VxWorks, Base-3.15 provides strtoll()
# define NEED_OLL_FUNCS (EPICS_VERSION_INT < VERSION_INT(3,15,0,1))
#else
# define WIN_NEEDS_OLL_FUNC 0
// Other architectures all provide strtoll()
# define NEED_OLL_FUNCS 0
#endif
#if defined(NEED_LONGLONG) && (defined(__vxworks) || WIN_NEEDS_OLL_FUNC)
#if defined(NEED_LONGLONG) && NEED_OLL_FUNCS
static
long long strtoll(const char *ptr, char ** endp, int base)
{
@@ -308,6 +313,73 @@ noconvert:
return 0;
}
#if defined(vxWorks)
/* The VxWorks version of std::istringstream >> uint64_t is buggy,
* provide our own implementation
*/
static
unsigned long long strtoull(const char *nptr, char **endptr, int base)
{
const char *s = nptr;
unsigned long long acc;
int c;
unsigned long long cutoff;
int neg = 0, any, cutlim;
do
c = *s++;
while (isspace(c));
if (c == '-')
{
neg = 1;
c = *s++;
}
else if (c == '+')
c = *s++;
if ((base == 0 || base == 16) &&
c == '0' && (*s == 'x' || *s == 'X'))
{
c = s[1];
s += 2;
base = 16;
}
if (base == 0)
base = c == '0' ? 8 : 10;
cutoff = (unsigned long long) UINT64_MAX / (unsigned long long) base;
cutlim = (unsigned long long) UINT64_MAX % (unsigned long long) base;
for (acc = 0, any = 0;; c = *s++)
{
if (isdigit(c))
c -= '0';
else if (isalpha(c))
c -= isupper(c) ? 'A' - 10 : 'a' - 10;
else
break;
if (c >= base)
break;
if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
any = -1;
else
{
any = 1;
acc *= base;
acc += c;
}
}
if (any < 0)
{
acc = UINT64_MAX;
errno = ERANGE;
}
else if (neg)
acc = -acc;
if (endptr != 0)
*endptr = any ? (char *) s - 1 : (char *) nptr;
return (acc);
}
#else
static
unsigned long long strtoull(const char *ptr, char ** endp, int base)
{
@@ -350,7 +422,7 @@ noconvert:
*endp = (char*)ptr;
return 0;
}
#endif
#endif
/* do we need long long? */
@@ -486,6 +558,27 @@ void parseToPOD(const string& in, float *out) {
void parseToPOD(const string& in, double *out) {
int err = epicsParseDouble(in.c_str(), out, NULL);
if(err) handleParseError(err);
#if defined(vxWorks)
/* vxWorks strtod returns [-]epicsINF when it should return ERANGE error.
* If [-]epicsINF is returned and the first char is a digit we translate
* this into an ERANGE error
*/
else if (*out == epicsINF || *out == -epicsINF) {
const char* s = in.c_str();
int c;
/* skip spaces and the sign */
do {
c = *s++;
} while (isspace(c));
if (c == '-' || c == '+')
c = *s++;
if (isdigit(c))
handleParseError(S_stdlib_overflow);
}
#endif
}
}}}

View File

@@ -1,8 +1,7 @@
/* bitSet.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.
/*
* Copyright information and license terms for this software can be
* found in the file LICENSE that is included with the distribution
*/
/**
* @author mse
@@ -10,7 +9,7 @@
#ifndef BITSET_H
#define BITSET_H
#include <stdexcept>
#include <vector>
#include <pv/pvType.h>
#include <pv/serialize.h>
@@ -24,16 +23,18 @@ namespace epics { namespace pvData {
typedef std::tr1::shared_ptr<BitSet> BitSetPtr;
/**
* @brief A vector of bits.
*
* This class implements a vector of bits that grows as needed. Each
* component of the bit set has a {@code bool} value. The
* bits of a {@code BitSet} are indexed by nonnegative integers.
* Individual indexed bits can be examined, set, or cleared. One
* {@code BitSet} may be used to modify the contents of another
* {@code BitSet} through logical AND, logical inclusive OR, and
* logical exclusive OR operations.
* component of the bit set has a @c bool value. The bits of a
* @c BitSet are indexed by nonnegative integers. Individual
* indexed bits can be examined, set, or cleared. One @c BitSet may
* be used to modify the contents of another @c BitSet through
* logical AND, logical inclusive OR, and logical exclusive OR
* operations.
*
* <p>By default, all bits in the set initially have the value
* {@code false}.
* @c false.
*
* <p>Every bit set has a current size, which is the number of bits
* of space currently in use by the bit set. Note that the size is
@@ -41,8 +42,8 @@ namespace epics { namespace pvData {
* implementation. The length of a bit set relates to logical length
* of a bit set and is defined independently of implementation.
*
* <p>A {@code BitSet} is not safe for multithreaded use without
* external synchronization.
* <p>A @c BitSet is not safe for multithreaded use without external
* synchronization.
*
* Based on Java implementation.
*/
@@ -51,14 +52,14 @@ namespace epics { namespace pvData {
POINTER_DEFINITIONS(BitSet);
static BitSetPtr create(uint32 nbits);
/**
* Creates a new bit set. All bits are initially {@code false}.
* Creates a new bit set. All bits are initially @c false.
*/
BitSet();
/**
* Creates a bit set whose initial size is large enough to explicitly
* represent bits with indices in the range {@code 0} through
* {@code nbits-1}. All bits are initially {@code false}.
* represent bits with indices in the range @c 0 through
* @c nbits-1. All bits are initially @c false.
*
* @param nbits the initial size of the bit set
*/
@@ -78,14 +79,14 @@ namespace epics { namespace pvData {
void flip(uint32 bitIndex);
/**
* Sets the bit at the specified index to {@code true}.
* Sets the bit at the specified index to @c true.
*
* @param bitIndex a bit index
*/
void set(uint32 bitIndex);
/**
* Sets the bit specified by the index to {@code false}.
* Sets the bit specified by the index to @c false.
*
* @param bitIndex the index of the bit to be cleared
*/
@@ -101,9 +102,8 @@ namespace epics { namespace pvData {
/**
* Returns the value of the bit with the specified index. The value
* is {@code true} if the bit with the index {@code bitIndex}
* is currently set in this {@code BitSet}; otherwise, the result
* is {@code false}.
* is @c true if the bit with the index @c bitIndex is currently
* set in this @c BitSet; otherwise, the result is @c false.
*
* @param bitIndex the bit index
* @return the value of the bit with the specified index
@@ -111,16 +111,16 @@ namespace epics { namespace pvData {
bool get(uint32 bitIndex) const;
/**
* Sets all of the bits in this BitSet to {@code false}.
* Sets all of the bits in this BitSet to @c false.
*/
void clear();
/**
* Returns the index of the first bit that is set to {@code true}
* that occurs on or after the specified starting index. If no such
* bit exists then {@code -1} is returned.
* Returns the index of the first bit that is set to @c true that
* occurs on or after the specified starting index. If no such bit
* exists then @c -1 is returned.
*
* <p>To iterate over the {@code true} bits in a {@code BitSet},
* <p>To iterate over the @c true bits in a @c BitSet,
* use the following loop:
*
* <pre> {@code
@@ -129,13 +129,13 @@ namespace epics { namespace pvData {
* }}</pre>
*
* @param fromIndex the index to start checking from (inclusive)
* @return the index of the next set bit, or {@code -1} if there
* @return the index of the next set bit, or @c -1 if there
* is no such bit
*/
int32 nextSetBit(uint32 fromIndex) const;
/**
* Returns the index of the first bit that is set to {@code false}
* Returns the index of the first bit that is set to @c false
* that occurs on or after the specified starting index.
*
* @param fromIndex the index to start checking from (inclusive)
@@ -144,23 +144,23 @@ namespace epics { namespace pvData {
int32 nextClearBit(uint32 fromIndex) const;
/**
* Returns true if this {@code BitSet} contains no bits that are set
* to {@code true}.
* Returns true if this @c BitSet contains no bits that are set
* to @c true.
*
* @return indicating whether this {@code BitSet} is empty
* @return indicating whether this @c BitSet is empty
*/
bool isEmpty() const;
/**
* Returns the number of bits set to {@code true} in this {@code BitSet}.
* Returns the number of bits set to @c true in this @c BitSet.
*
* @return the number of bits set to {@code true} in this {@code BitSet}
* @return the number of bits set to @c true in this @c BitSet
*/
uint32 cardinality() const;
/**
* Returns the number of bits of space actually in use by this
* {@code BitSet} to represent bit values.
* @c BitSet to represent bit values.
* The maximum element in the set is the size - 1st element.
*
* @return the number of bits currently in this bit set
@@ -170,9 +170,9 @@ namespace epics { namespace pvData {
/**
* Performs a logical <b>AND</b> of this target bit set with the
* argument bit set. This bit set is modified so that each bit in it
* has the value {@code true} if and only if it both initially
* had the value {@code true} and the corresponding bit in the
* bit set argument also had the value {@code true}.
* has the value @c true if and only if it both initially
* had the value @c true and the corresponding bit in the
* bit set argument also had the value @c true.
*
* @param set a bit set
*/
@@ -181,9 +181,9 @@ namespace epics { namespace pvData {
/**
* Performs a logical <b>OR</b> of this bit set with the bit set
* argument. This bit set is modified so that a bit in it has the
* value {@code true} if and only if it either already had the
* value {@code true} or the corresponding bit in the bit set
* argument has the value {@code true}.
* value @c true if and only if it either already had the
* value @c true or the corresponding bit in the bit set
* argument has the value @c true.
*
* @param set a bit set
*/
@@ -192,13 +192,13 @@ namespace epics { namespace pvData {
/**
* Performs a logical <b>XOR</b> of this bit set with the bit set
* argument. This bit set is modified so that a bit in it has the
* value {@code true} if and only if one of the following
* value @c true if and only if one of the following
* statements holds:
* <ul>
* <li>The bit initially has the value {@code true}, and the
* corresponding bit in the argument has the value {@code false}.
* <li>The bit initially has the value {@code false}, and the
* corresponding bit in the argument has the value {@code true}.
* <li>The bit initially has the value @c true, and the
* corresponding bit in the argument has the value @c false.
* <li>The bit initially has the value @c false, and the
* corresponding bit in the argument has the value @c true.
* </ul>
*
* @param set a bit set
@@ -206,10 +206,13 @@ namespace epics { namespace pvData {
BitSet& operator^=(const BitSet& set);
/**
* Assigment operator.
* Assignment operator.
*/
BitSet& operator=(const BitSet &set);
//! Swap contents
void swap(BitSet& set);
/**
* Perform AND operation on <code>set1</code> and <code>set2</code>,
* and OR on result and this instance.
@@ -232,42 +235,11 @@ namespace epics { namespace pvData {
private:
/*
* BitSets are packed into arrays of "words." Currently a word is
* a long, which consists of 64 bits, requiring 6 address bits.
* The choice of word size is determined purely by performance concerns.
*/
static const uint32 ADDRESS_BITS_PER_WORD = 6;
static const uint32 BITS_PER_WORD = 1 << ADDRESS_BITS_PER_WORD;
static const uint32 BIT_INDEX_MASK = BITS_PER_WORD - 1;
/** Used to shift left or right for a partial word mask */
static const uint64 WORD_MASK = ~((uint64)0);
typedef std::vector<uint64> words_t;
/** The internal field corresponding to the serialField "bits". */
uint64* words;
/** The internal field corresponding to the size of words[] array. */
uint32 wordsLength;
/** The number of words in the logical size of this BitSet. */
uint32 wordsInUse;
words_t words;
private:
/**
* Given a bit index, return word index containing it.
*/
static inline uint32 wordIndex(uint32 bitIndex) {
return bitIndex >> ADDRESS_BITS_PER_WORD;
}
/**
* Creates a new word array.
*/
void initWords(uint32 nbits);
/**
* Sets the field wordsInUse to the logical size in words of the bit set.
* WARNING: This method assumes that the number of words actually in use is

View File

@@ -1,8 +1,7 @@
/* byteBuffer.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.
/*
* Copyright information and license terms for this software can be
* found in the file LICENSE that is included with the distribution
*/
/**
* @author mse
@@ -11,24 +10,15 @@
#define BYTEBUFFER_H
#include <string>
#include <string.h>
#ifdef epicsExportSharedSymbols
#define byteBufferepicsExportSharedSymbols
#undef epicsExportSharedSymbols
#endif
#include <cstring>
#include <cstdlib>
#include <epicsEndian.h>
#ifdef byteBufferepicsExportSharedSymbols
#define epicsExportSharedSymbols
#undef byteBufferepicsExportSharedSymbols
#endif
#include <shareLib.h>
#include <pv/pvType.h>
#include <pv/epicsException.h>
#include <shareLib.h>
namespace epics {
namespace pvData {
@@ -144,6 +134,24 @@ inline int64 swap(int64 val)
return swap64(val);
}
template<>
inline uint16 swap(uint16 val)
{
return swap16(val);
}
template<>
inline uint32 swap(uint32 val)
{
return swap32(val);
}
template<>
inline uint64 swap(uint64 val)
{
return swap64(val);
}
template<>
inline float swap(float val)
{
@@ -188,8 +196,9 @@ inline double swap(double val)
#endif
/**
* This class implements {@code Bytebuffer} that is like the {@code java.nio.ByteBuffer}.
* <p>A {@code BitSet} is not safe for multithreaded use without
* @brief This class implements a Bytebuffer that is like the java.nio.ByteBuffer.
*
* <p>A @c BitSet is not safe for multithreaded use without
* external synchronization.
*
* Based on Java implementation.
@@ -205,19 +214,20 @@ public:
* Must be one of EPICS_BYTE_ORDER,EPICS_ENDIAN_LITTLE,EPICS_ENDIAN_BIG.
*/
ByteBuffer(std::size_t size, int byteOrder = EPICS_BYTE_ORDER) :
_buffer(0), _size(size),
_buffer((char*)std::malloc(size)), _size(size),
_reverseEndianess(byteOrder != EPICS_BYTE_ORDER),
_reverseFloatEndianess(byteOrder != EPICS_FLOAT_WORD_ORDER),
_wrapped(false)
{
_buffer = (char*)malloc(size);
if(!_buffer)
throw std::bad_alloc();
clear();
}
/**
* Constructor for wrapping existing buffers.
* Constructor for wrapping an existing buffer.
* Given buffer will not be released by the ByteBuffer instance.
* @param buffer Existing buffer.
* @param buffer Existing buffer. May not be NULL.
* @param size The number of bytes.
* @param byteOrder The byte order.
* Must be one of EPICS_BYTE_ORDER,EPICS_ENDIAN_LITTLE,EPICS_ENDIAN_BIG.
@@ -228,6 +238,8 @@ public:
_reverseFloatEndianess(byteOrder != EPICS_FLOAT_WORD_ORDER),
_wrapped(true)
{
if(!_buffer)
throw std::invalid_argument("ByteBuffer can't be constructed with NULL");
clear();
}
/**
@@ -235,7 +247,7 @@ public:
*/
~ByteBuffer()
{
if (_buffer && !_wrapped) free(_buffer);
if (_buffer && !_wrapped) std::free(_buffer);
}
/**
* Set the byte order.
@@ -252,7 +264,7 @@ public:
* Get the raw buffer data.
* @return the raw buffer data.
*/
inline const char* getBuffer()
inline const char* getBuffer() const
{
return _buffer;
}
@@ -284,7 +296,7 @@ public:
* Returns the current position.
* @return The current position in the raw data.
*/
inline std::size_t getPosition()
inline std::size_t getPosition() const
{
return (std::size_t)(((std::ptrdiff_t)(const void *)_position) - ((std::ptrdiff_t)(const void *)_buffer));
}
@@ -304,7 +316,7 @@ public:
*
* @return The offset into the raw buffer.
*/
inline std::size_t getLimit()
inline std::size_t getLimit() const
{
return (std::size_t)(((std::ptrdiff_t)(const void *)_limit) - ((std::ptrdiff_t)(const void *)_buffer));
}
@@ -325,7 +337,7 @@ public:
*
* @return The number of elements remaining in this buffer.
*/
inline std::size_t getRemaining()
inline std::size_t getRemaining() const
{
return (std::size_t)(((std::ptrdiff_t)(const void *)_limit) - ((std::ptrdiff_t)(const void *)_position));
}
@@ -334,7 +346,7 @@ public:
*
* @return The size of the raw data buffer.
*/
inline std::size_t getSize()
inline std::size_t getSize() const
{
return _size;
}
@@ -354,7 +366,7 @@ public:
template<typename T>
inline void put(std::size_t index, T value);
/**
* Get the new object from the byte buffer. The item MUST have type {@code T}.
* Get the new object from the byte buffer. The item MUST have type @c T.
* The position is adjusted based on the type.
*
* @return The object.
@@ -368,7 +380,7 @@ public:
#endif
/**
* Get the new object from the byte buffer at the specified index.
* The item MUST have type {@code T}.
* The item MUST have type @c T.
* The position is adjusted based on the type.
*
* @param index The location in the byte buffer.
@@ -380,9 +392,9 @@ public:
* Put a sub-array of bytes into the byte buffer.
* The position is increased by the count.
*
* @param src The source array.
* @param offset The starting position within src.
* @param count The number of bytes to put into the byte buffer,
* @param src The source array.
* @param src_offset The starting position within src.
* @param count The number of bytes to put into the byte buffer,
*/
inline void put(const char* src, std::size_t src_offset, std::size_t count) {
//if(count>getRemaining()) THROW_BASE_EXCEPTION("buffer overflow");
@@ -393,9 +405,9 @@ public:
* Get a sub-array of bytes from the byte buffer.
* The position is increased by the count.
*
* @param dest The destination array.
* @param offset The starting position within src.
* @param count The number of bytes to put into the byte buffer,
* @param dest The destination array.
* @param dest_offset The starting position within src.
* @param count The number of bytes to put into the byte buffer.
*/
inline void get(char* dest, std::size_t dest_offset, std::size_t count) {
//if(count>getRemaining()) THROW_BASE_EXCEPTION("buffer overflow");
@@ -403,7 +415,7 @@ public:
_position += count;
}
/**
* Put an array of type {@code T} into the byte buffer.
* Put an array of type @c T into the byte buffer.
* The position is adjusted.
*
* @param values The input array.
@@ -412,7 +424,7 @@ public:
template<typename T>
inline void putArray(const T* values, std::size_t count);
/**
* Get an array of type {@code T} from the byte buffer.
* Get an array of type @c T from the byte buffer.
* The position is adjusted.
*
* @param values The destination array.
@@ -425,7 +437,7 @@ public:
* @return (false,true) if (is, is not) the EPICS_BYTE_ORDER
*/
template<typename T>
inline bool reverse()
inline bool reverse() const
{
return _reverseEndianess;
}
@@ -618,54 +630,54 @@ public:
/**
* Get a boolean value from the byte buffer at the specified index.
*
* @param double The offset in the byte buffer.
* @param index The offset in the byte buffer.
* @return The value.
*/
inline double getDouble (std::size_t index) { return get<double>(index); }
// TODO remove
inline const char* getArray()
inline const char* getArray() const
{
return _buffer;
}
private:
char* _buffer;
char* const _buffer;
char* _position;
char* _limit;
std::size_t _size;
const std::size_t _size;
bool _reverseEndianess;
bool _reverseFloatEndianess;
bool _wrapped;
const bool _wrapped;
};
template<>
inline bool ByteBuffer::reverse<bool>()
inline bool ByteBuffer::reverse<bool>() const
{
return false;
}
template<>
inline bool ByteBuffer::reverse<int8>()
inline bool ByteBuffer::reverse<int8>() const
{
return false;
}
template<>
inline bool ByteBuffer::reverse<uint8>()
inline bool ByteBuffer::reverse<uint8>() const
{
return false;
}
template<>
inline bool ByteBuffer::reverse<float>()
inline bool ByteBuffer::reverse<float>() const
{
return _reverseFloatEndianess;
}
template<>
inline bool ByteBuffer::reverse<double>()
inline bool ByteBuffer::reverse<double>() const
{
return _reverseFloatEndianess;
}
@@ -695,7 +707,7 @@ private:
}
else
{
// NOTE: this check and branching does not always payoff
// NOTE: this check and branching does not always pay off
if (ADAPTIVE_ACCESS && is_aligned(_position, sizeof(T)))
{
*((T*)_position) = value;
@@ -738,12 +750,12 @@ private:
if (UNALIGNED_ACCESS)
{
// NOTE: some CPU handle unaligned access preety good (e.g. x86)
// NOTE: some CPU handle unaligned access pretty good (e.g. x86)
*((T*)(_buffer + index)) = value;
}
else
{
// NOTE: this check and branching does not always payoff
// NOTE: this check and branching does not always pay off
if (ADAPTIVE_ACCESS && is_aligned(_position, sizeof(T)))
{
*((T*)(_buffer + index)) = value;
@@ -786,13 +798,13 @@ private:
if (UNALIGNED_ACCESS)
{
// NOTE: some CPU handle unaligned access preety good (e.g. x86)
// NOTE: some CPU handle unaligned access pretty good (e.g. x86)
value = *((T*)_position);
_position += sizeof(T);
}
else
{
// NOTE: this check and branching does not always payoff
// NOTE: this check and branching does not always pay off
if (ADAPTIVE_ACCESS && is_aligned(_position, sizeof(T)))
{
value = *((T*)_position);
@@ -838,12 +850,12 @@ private:
if (UNALIGNED_ACCESS)
{
// NOTE: some CPU handle unaligned access preety good (e.g. x86)
// NOTE: some CPU handle unaligned access pretty good (e.g. x86)
value = *((T*)(_buffer + index));
}
else
{
// NOTE: this check and branching does not always payoff
// NOTE: this check and branching does not always pay off
if (ADAPTIVE_ACCESS && is_aligned(_position, sizeof(T)))
{
value = *((T*)(_buffer + index));
@@ -890,7 +902,7 @@ private:
memcpy(_position, values, n);
_position += n;
// ... so that we can be fast changing endianess
// ... so that we can be fast changing endianness
if (ENDIANESS_SUPPORT && reverse<T>())
{
for (std::size_t i = 0; i < count; i++)
@@ -918,7 +930,7 @@ private:
memcpy(values, _position, n);
_position += n;
// ... so that we can be fast changing endianess
// ... so that we can be fast changing endianness
if (ENDIANESS_SUPPORT && reverse<T>())
{
for (std::size_t i = 0; i < count; i++)

View File

View File

@@ -1,8 +1,7 @@
/* destroyable.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.
/*
* Copyright information and license terms for this software can be
* found in the file LICENSE that is included with the distribution
*/
/**
* @author mse
@@ -18,7 +17,8 @@ namespace epics { namespace pvData {
/**
* Instance declaring destroy method.
* @brief Instance declaring destroy method.
*
* @author mse
*/
class epicsShareClass Destroyable {

View File

@@ -1,10 +1,9 @@
/**
* 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.
/*
* Copyright information and license terms for this software can be
* found in the file LICENSE that is included with the distribution
*/
/*
* epicsException.hpp
* epicsException.h
*
* Created on: Oct 20, 2010
* Author: Matej Sekoranja
@@ -34,19 +33,14 @@
#ifndef EPICSEXCEPTION_H_
#define EPICSEXCEPTION_H_
#ifdef _WIN32
#pragma warning( push )
#pragma warning(disable: 4275) // warning C4275: non dll-interface class used as base for dll-interface class (std::logic_error)
#if defined(_WIN32) && !defined(NOMINMAX)
#define NOMINMAX
#endif
#include <stdexcept>
#include <string>
#include <cstdio>
#include <stdio.h>
#include <stdlib.h>
#include <shareLib.h>
// Users may redefine this for a large size if desired
@@ -58,7 +52,7 @@
# include <execinfo.h>
# include <cxxabi.h>
# define EXCEPT_USE_BACKTRACE
#elif defined(_WIN32) && !defined(__MINGW__) && !defined(SKIP_DBGHELP)
#elif defined(_WIN32) && !defined(_MINGW) && !defined(SKIP_DBGHELP)
# define _WINSOCKAPI_
# include <windows.h>
# include <dbghelp.h>
@@ -67,6 +61,12 @@
# define EXCEPT_USE_NONE
#endif
#if defined(_WIN32) && !defined(_MINGW)
#pragma warning( push )
#pragma warning(disable: 4275) // non dll-interface class used as base for dll-interface class (std::logic_error)
#pragma warning(disable: 4251) // class std::string needs to have dll-interface to be used by clients
#endif
namespace epics { namespace pvData {
@@ -175,7 +175,7 @@ do { \
#define PRINT_EXCEPTION2(EI, FP) \
do { \
ExceptionMixin *_em_p=dynamic_cast<ExceptionMixin*>(&EI); \
::epics::pvData::ExceptionMixin *_em_p=dynamic_cast< ::epics::pvData::ExceptionMixin*>(&EI); \
if (_em_p) {_em_p->print(FP);} \
}while(0)
@@ -185,7 +185,7 @@ do { \
# define SHOW_EXCEPTION(EI) ::epics::pvData::detail::showException(EI)
#else
# define SHOW_EXCEPTION(EI) \
({ ExceptionMixin *_mx=dynamic_cast<ExceptionMixin*>(&(EI)); \
({ ::epics::pvData::ExceptionMixin *_mx=dynamic_cast< ::epics::pvData::ExceptionMixin*>(&(EI)); \
_mx ? _mx->show() : std::string(); \
})
#endif
@@ -202,20 +202,33 @@ do { \
#define THROW_EXCEPTION2(E,A) do{throw (E)(A);}while(0)
#endif // THROW_EXCEPTION_COMPAT
/**
* @brief Base for pvData exceptions.
*
*/
class epicsShareClass BaseException : public std::logic_error {
public:
/**
* Constructor.
*/
explicit BaseException(const std::string msg) : std::logic_error(msg) {}
/**
* Destructor.
*/
virtual ~BaseException() throw(){};
/**
*
* Reason for excepton.
*/
virtual const char* what() const throw();
private:
mutable std::string base_msg;
};
#ifdef _WIN32
#if defined(_WIN32) && !defined(_MINGW)
#pragma warning( pop )
#endif

68
src/misc/pv/event.h Normal file
View File

@@ -0,0 +1,68 @@
/* event.h */
/*
* Copyright information and license terms for this software can be
* found in the file LICENSE that is included with the distribution
*/
/**
* @author mrk
*/
#ifndef EVENT_H
#define EVENT_H
#include <memory>
#include <vector>
#include <epicsEvent.h>
#include <shareLib.h>
#include <pv/pvType.h>
#include <pv/sharedPtr.h>
namespace epics { namespace pvData {
class Event;
typedef std::tr1::shared_ptr<Event> EventPtr;
/**
* @brief C++ wrapper for epicsEvent from EPICS base.
*
*/
class epicsShareClass Event {
public:
POINTER_DEFINITIONS(Event);
/**
* Constructor
*/
explicit Event(bool = false);
/**
* Destructor.
*/
~Event();
/**
* Signal the event i.e. ensures that the next or current call to wait completes.
*/
void signal();
/**
* wait
* @return (false,true) if (some error, event signaled).
* The next wait or tryWait will clear signal.
*/
bool wait (); /* blocks until full */
/**
* wait for up to timeOut seconds.
* @param timeOut max number of seconds to wait
* @return (false, true) if (timeout or error, event signaled).
*/
bool wait ( double timeOut ); /* false if empty at time out */
/**
* See if a signal has been called.
* @return (false, true) if (timeout or error, event signaled).
*/
bool tryWait (); /* false if empty */
private:
epicsEventId id;
};
}}
#endif /* EVENT_H */

View File

@@ -1,8 +1,7 @@
/* executor.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.
/*
* Copyright information and license terms for this software can be
* found in the file LICENSE that is included with the distribution
*/
/**
* @author mrk
@@ -27,22 +26,56 @@ class Executor;
typedef std::tr1::shared_ptr<Command> CommandPtr;
typedef std::tr1::shared_ptr<Executor> ExecutorPtr;
/**
* @brief A command to be called by Executor
*
*/
class epicsShareClass Command {
public:
POINTER_DEFINITIONS(Command);
/**
*
* Destructor
*/
virtual ~Command(){}
/**
*
* The command that is executed.
*/
virtual void command() = 0;
private:
CommandPtr next;
friend class Executor;
};
/**
* @brief A class that executes commands.
*
*/
class epicsShareClass Executor : public Runnable{
public:
POINTER_DEFINITIONS(Executor);
/**
* Constructor
*
* @param threadName name for the executor thread.
* @param priority The thread priority.
*/
Executor(std::string const & threadName,ThreadPriority priority);
/**
* Destructor
*/
~Executor();
void execute(CommandPtr const &node);
/**
*
* Request to execute a command.
* @param command A shared pointer to the command instance.
*/
void execute(CommandPtr const &command);
/**
*
* The thread run method.
*/
virtual void run();
private:
CommandPtr head;

View File

@@ -1,8 +1,7 @@
/* localStaticLock.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.
/*
* Copyright information and license terms for this software can be
* found in the file LICENSE that is included with the distribution
*/
/**
* @author mse

View File

@@ -1,8 +1,7 @@
/* lock.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.
/*
* Copyright information and license terms for this software can be
* found in the file LICENSE that is included with the distribution
*/
/**
* @author mrk
@@ -12,21 +11,11 @@
#include <stdexcept>
#ifdef epicsExportSharedSymbols
#define lockepicsExportSharedSymbols
#undef epicsExportSharedSymbols
#endif
#include <epicsMutex.h>
#ifdef lockepicsExportSharedSymbols
#define epicsExportSharedSymbols
#undef lockepicsExportSharedSymbols
#endif
#include <shareLib.h>
#include <pv/noDefaultMethods.h>
#include <shareLib.h>
/* This is based on item 14 of
* Effective C++, Third Edition, Scott Meyers
@@ -38,12 +27,30 @@ namespace epics { namespace pvData {
typedef epicsMutex Mutex;
/**
* @brief A lock for multithreading
*
* This is based on item 14 of
* * Effective C++, Third Edition, Scott Meyers
*/
class epicsShareClass Lock : private NoDefaultMethods {
public:
/**
* Constructor
* @param m The mutex for the facility being locked.
*/
explicit Lock(Mutex &m)
: mutexPtr(m), locked(true)
{ mutexPtr.lock();}
/**
* Destructor
* Note that destructor does an automatic unlock.
*/
~Lock(){unlock();}
/**
* Take the lock
* Recursive locks are supported but each lock must be matched with an unlock.
*/
void lock()
{
if(!locked)
@@ -52,6 +59,9 @@ public:
locked = true;
}
}
/**
* release the lock.
*/
void unlock()
{
if(locked)
@@ -60,6 +70,10 @@ public:
locked=false;
}
}
/**
* If lock is not held take the lock.
* @return (false,true) if caller (does not have, has) the lock.
*/
bool tryLock()
{
if(locked) return true;
@@ -69,6 +83,10 @@ public:
}
return false;
}
/**
* See if caller has the lock,
* @return (false,true) if caller (does not have, has) the lock.
*/
bool ownsLock() const{return locked;}
private:
Mutex &mutexPtr;

128
src/misc/pv/messageQueue.h Normal file
View File

@@ -0,0 +1,128 @@
/* messageQueue.h */
/*
* Copyright information and license terms for this software can be
* found in the file LICENSE that is included with the distribution
*/
/**
* @author mrk
*/
#ifndef MESSAGEQUEUE_H
#define MESSAGEQUEUE_H
#include <memory>
#include <vector>
#include <cstddef>
#include <stdexcept>
#include <pv/pvType.h>
#include <pv/requester.h>
#include <pv/queue.h>
#include <shareLib.h>
namespace epics { namespace pvData {
class MessageNode;
class MessageQueue;
typedef std::tr1::shared_ptr<MessageNode> MessageNodePtr;
typedef std::vector<MessageNodePtr> MessageNodePtrArray;
typedef std::tr1::shared_ptr<MessageQueue> MessageQueuePtr;
/**
* @brief A node that can be put on a MessageQueue.
*
*/
class epicsShareClass MessageNode {
public:
/**
* Constructor
*/
MessageNode();
/**
*
* Get the message value.
* @return The message value.
*/
std::string getMessage() const;
/**
* Get the message type.
* @return The message type which is defined in Requester.
*/
MessageType getMessageType() const;
private:
std::string message;
MessageType messageType;
friend class MessageQueue;
};
/**
* @brief A bounded queue for messages.
*
*
*/
class epicsShareClass MessageQueue : public Queue<MessageNode> {
public:
POINTER_DEFINITIONS(MessageQueue);
/**
* Factory method to create a MessageQueue.
* @param size The number of MessageNodes in the queue.
* @return shared_ptr to MessageQueue.
*/
static MessageQueuePtr create(int size);
/**
* Constructor
* @param nodeArray an array of shared_ptr to MessageNodes,
*/
MessageQueue(MessageNodePtrArray &nodeArray);
/**
* Destructor
*/
virtual ~MessageQueue();
/**
* get the next MessageNode of the queue.
* @return A shared_ptr to the MessageNode.
* This will be a null pointer if queue is empty.
* If get is successful then release for this MessageNode
* must be called before another get can be issued.
*/
MessageNodePtr &get();
/**
* Release the MessageNode that was returned by the previous call to get.
*/
void release();
/**
*
* put a message into the message queue
* @param message The message string.
* @param messageType The message type as defined in Requester,
* @param replaceLast If true and queue is full then replace.
* @return (false,true) if a message (was not, was) put in queiue.
*/
bool put(std::string message,MessageType messageType,bool replaceLast);
/**
* Is queue empty?
* @return (false,true) if (is not, is) empty.
*/
bool isEmpty() ;
/**
* Is queue full?
* @return (false,true) if (is not, is) full.
*/
bool isFull() ;
/**
*
* Clear number of times queue was overrun and return the number
* of times the queue was overrun.
*/
int getClearOverrun();
private:
MessageNodePtr nullNode;
MessageNodePtr lastGet;
MessageNodePtr lastPut;
uint32 overrun;
};
}}
#endif /* MESSAGEQUEUE_H */

View File

@@ -1,8 +1,7 @@
/* noDefaultMethods.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.
/*
* Copyright information and license terms for this software can be
* found in the file LICENSE that is included with the distribution
*/
/**
* @author mrk
@@ -17,17 +16,26 @@ namespace epics { namespace pvData {
* Effective C++, Third Edition, Scott Meyers
*/
class epicsShareClass NoDefaultMethods {
protected:
// allow by derived objects
/**
* @brief Base class for not allowing default methods.
*
* Note that copy constructor a copy methods are declared private.
*/
class epicsShareClass NoDefaultMethods {
protected:
/**
* Constructor
*/
NoDefaultMethods(){};
/**
* Destructor
*/
~NoDefaultMethods(){}
private:
// do not implment
// do not implement
NoDefaultMethods(const NoDefaultMethods&);
NoDefaultMethods & operator=(const NoDefaultMethods &);
};
};
}}
#endif /* NO_DEFAULT_METHODS_H */

View File

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

71
src/misc/pv/requester.h Normal file
View File

@@ -0,0 +1,71 @@
/* requester.h */
/*
* Copyright information and license terms for this software can be
* found in the file LICENSE that is included with the distribution
*/
/**
* @author mrk
*/
#ifndef REQUESTER_H
#define REQUESTER_H
#include <string>
#include <pv/pvType.h>
#include <pv/sharedPtr.h>
#include <shareLib.h>
namespace epics { namespace pvData {
class Requester;
typedef std::tr1::shared_ptr<Requester> RequesterPtr;
enum MessageType {
infoMessage,warningMessage,errorMessage,fatalErrorMessage
};
#define MESSAGE_TYPE_COUNT 4
epicsShareExtern std::string getMessageTypeName(MessageType messageType);
/**
* @brief Callback class for passing messages to a requester.
*
* This is used by many other classes and also extended by other classes.
* The request is passed a message and a messageType.
* A message is just a string and a messageType is:
@code
enum MessageType {
infoMessage,warningMessage,errorMessage,fatalErrorMessage
};
@endcode
*
*/
class epicsShareClass Requester {
public:
POINTER_DEFINITIONS(Requester);
/**
* Destructor
*/
virtual ~Requester(){}
/**
* The requester must have a name.
* @return The requester's name.
*/
virtual std::string getRequesterName() = 0;
/**
*
* A message for the requester.
* @param message The message.
* @param messageType The type of message:
@code
enum MessageType {
infoMessage,warningMessage,errorMessage,fatalErrorMessage
};
@endcode
*/
virtual void message(std::string const & message,MessageType messageType);
};
}}
#endif /* REQUESTER_H */

253
src/misc/pv/serialize.h Normal file
View File

@@ -0,0 +1,253 @@
/* serialize.h */
/*
* Copyright information and license terms for this software can be
* found in the file LICENSE that is included with the distribution
*/
/**
* @author mrk
*/
#ifndef SERIALIZE_H
#define SERIALIZE_H
#include <epicsTypes.h>
#include <pv/byteBuffer.h>
#include <pv/sharedPtr.h>
#include <shareLib.h>
namespace epics { namespace pvData {
class SerializableControl;
class DeserializableControl;
class Serializable;
class BitSetSerializable;
class SerializableArray;
class BitSet;
class Field;
/**
* @brief Callback class for serialization.
*
* This must be provided by code that calls serialize.
*/
class epicsShareClass SerializableControl {
public:
/**
* Destructor.
*/
virtual ~SerializableControl(){}
/**
* Done with this buffer. Flush it.
*/
virtual void flushSerializeBuffer() =0;
/**
* Make sure buffer has at least size bytes remaining.
* If not flush existing buffer and provide a new one.
* @param size The number of bytes.
*/
virtual void ensureBuffer(std::size_t size) =0;
/**
* Add pad bytes to buffer.
* @param alignment alignment required.
*/
virtual void alignBuffer(std::size_t alignment) =0;
/**
* Method for serializing primitive array data.
* Hook for supplying custom serialization implementation.
* The serialization implementation need not be provided.
* Returns true if method performs serialization, false otherwise.
* This should only be used for arrays of primitive types,
* i. e. boolean, byte,..., double.
* It cannot be called for string, structure, or union arrays.
* @param existingBuffer the existing buffer from the caller.
* @param toSerialize location of data to be put into buffer.
* @param elementCount number of elements.
* @param elementSize element size.
* @returns true if serialization performed, else false.
*/
virtual bool directSerialize(
ByteBuffer *existingBuffer,
const char* toSerialize,
std::size_t elementCount,
std::size_t elementSize) = 0;
/**
* serialize via cache
* @param field instance to be serialized
* @param buffer buffer to be serialized to
*/
virtual void cachedSerialize(
std::tr1::shared_ptr<const Field> const & field,
ByteBuffer* buffer) = 0;
};
/**
* @brief Callback class for deserialization.
*
* This must be provided by code that calls deserialize.
*/
class epicsShareClass DeserializableControl {
public:
/**
* Destructor.
*/
virtual ~DeserializableControl(){}
/**
* Helper method.
* Ensures specified size of bytes, provides it if necessary.
* @param size The number of bytes.
*/
virtual void ensureData(std::size_t size) =0;
/**
* Align buffer.
* Note that this takes care only current buffer alignment.
* If streaming protocol is used,
* care must be taken that entire stream is aligned.
* @param alignment size in bytes, must be power of two.
*/
virtual void alignData(std::size_t alignment) =0;
/**
* Method for deserializing array data.
* Hook for supplying custom deserialization implementation.
* The deserialization implementation need not be provided.
* Returns true if method performs deserialization, false otherwise.
* This should only be used for arrays of primitive types.
* i.e. boolean, byte,..., double.
* It cannot be called for string, structure, or union arrays.
* @param existingBuffer the existing buffer from the caller.
* @param deserializeTo location of data.
* @param elementCount number of elements.
* @param elementSize element size.
* @returns true if deserialization performed, else false.
*/
virtual bool directDeserialize(
ByteBuffer *existingBuffer,
char* deserializeTo,
std::size_t elementCount,
std::size_t elementSize) = 0;
/**
* deserialize via cache
* @param buffer buffer to be deserialized from
*/
virtual std::tr1::shared_ptr<const Field> cachedDeserialize(
ByteBuffer* buffer) = 0;
};
/**
* @brief Base class for serialization.
*
*/
class epicsShareClass Serializable {
public:
/**
* Destructor.
*/
virtual ~Serializable(){}
/**
* Serialize field into given buffer.
* @param buffer serialization buffer.
* @param flusher flush interface.
*/
virtual void serialize(ByteBuffer *buffer,
SerializableControl *flusher) const = 0;
/**
* Deserialize buffer.
* @param buffer serialization buffer.
* @param flusher deserialization control.
*/
virtual void deserialize(ByteBuffer *buffer,
DeserializableControl *flusher) = 0;
};
/**
* @brief Push serialize and append to the provided byte vector.
* No caching is done. Only complete serialization.
*
* @param S A Serializable object
* @param byteOrder Byte order to write (EPICS_ENDIAN_LITTLE or EPICS_ENDIAN_BIG)
* @param out The output vector. Results are appended
*/
void epicsShareFunc serializeToVector(const Serializable *S,
int byteOrder,
std::vector<epicsUInt8>& out);
/**
* @brief deserializeFromBuffer Deserialize into S from provided vector
* @param S A Serializeable object. The current contents will be replaced
* @param in The input buffer (byte order of this buffer is used)
* @throws std::logic_error if input buffer is too small. State of S is then undefined.
*/
void epicsShareFunc deserializeFromBuffer(Serializable *S,
ByteBuffer& in);
/**
* @brief deserializeFromBuffer Deserialize into S from provided vector
* @param S A Serializeable object. The current contents will be replaced
* @param byteOrder Byte order to write (EPICS_ENDIAN_LITTLE or EPICS_ENDIAN_BIG)
* @param in The input vector
* @throws std::logic_error if input buffer is too small. State of S is then undefined.
*/
inline void deserializeFromVector(Serializable *S,
int byteOrder,
const std::vector<epicsUInt8>& in)
{
ByteBuffer B((char*)&in[0], in.size(), byteOrder); // we promise not the modify 'in'
deserializeFromBuffer(S, B);
}
/**
* @brief Class for serializing bitSets.
*
*/
class epicsShareClass BitSetSerializable {
public:
/**
* Destructor.
*/
virtual ~BitSetSerializable(){}
/**
* Serialize field into given buffer.
* @param buffer serialization buffer.
* @param flusher flush interface.
* @param bitSet The bitSet to serialize.
*/
virtual void serialize(ByteBuffer *buffer,
SerializableControl *flusher,BitSet *bitSet) const = 0;
/**
* Deserialize buffer.
* @param buffer serialization buffer.
* @param flusher deserialization control.
* @param bitSet The bitSet to deserialize.
*/
virtual void deserialize(ByteBuffer *buffer,
DeserializableControl *flusher,BitSet *bitSet) = 0;
};
/**
* @brief Class for serializing arrays.
*
*/
class epicsShareClass SerializableArray : public virtual Serializable {
public:
/**
* Destructor.
*/
virtual ~SerializableArray(){}
using Serializable::serialize;
/**
* Serialize field into given buffer.
* @param buffer serialization buffer.
* @param flusher flush interface.
* @param offset offset in elements.
* @param count number of elements
*/
virtual void serialize(
ByteBuffer *buffer,
SerializableControl *flusher,
std::size_t offset,
std::size_t count) const = 0;
};
}}
#endif /* SERIALIZE_H */

View File

@@ -1,7 +1,6 @@
/**
* 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.
/*
* Copyright information and license terms for this software can be
* found in the file LICENSE that is included with the distribution
*/
/*
* serializeHelper.h
@@ -23,23 +22,33 @@
namespace epics {
namespace pvData {
/**
* @brief Serialization helper.
*
*/
class epicsShareClass SerializeHelper : public NoDefaultMethods {
public:
/**
* Serialize array size.
* Serialize the specified array size into the specified
* buffer, flushing when necessary.
* The specified SerializableControl manages any flushing
* required.
*
* @param[in] s size to encode
* @param[in] buffer serialization buffer
* @param[in] flusher flusher
* @param[in] flusher SerializableControl to manage the flushing
*/
static void writeSize(std::size_t s, ByteBuffer* buffer,
SerializableControl* flusher);
/**
* Deserialize array size.
* The specified DeserializableControl ensures
* sufficient bytes are available.
*
* @param[in] buffer deserialization buffer.
* @param[in] control the DeserializableControl.
* @returns array size.
*/
static std::size_t readSize(ByteBuffer* buffer,
@@ -59,7 +68,7 @@ namespace epics {
* std::string serialization helper method.
*
* @param[in] value std::string to serialize
* @param[in] offset start of the substring in {@code value}
* @param[in] offset start of the substring in value
* @param[in] count the number of characters to write
* @param[in] buffer serialization buffer
* @param[in] flusher flusher

View File

@@ -1,7 +1,6 @@
/**
* 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.
/*
* Copyright information and license terms for this software can be
* found in the file LICENSE that is included with the distribution
*/
/**
* @author Michael Davidsaver
@@ -26,7 +25,7 @@
// where should we look?
#if defined(__GNUC__) && __GNUC__>=4 && !defined(__vxworks)
#if defined(__GNUC__) && __GNUC__>=4 && !defined(vxWorks)
// GCC >=4.0.0
# define SHARED_FROM_TR1

View File

@@ -1,13 +1,12 @@
/* sharedVector.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.
/*
* Copyright information and license terms for this software can be
* found in the file LICENSE that is included with the distribution
*/
#ifndef SHAREDVECTOR_H
#define SHAREDVECTOR_H
#ifdef _WIN32
#if defined(_WIN32) && !defined(NOMINMAX)
#define NOMINMAX
#endif
@@ -230,7 +229,7 @@ namespace detail {
};
}
/** @brief A holder for a contigious piece of memory.
/** @brief A holder for a contiguous piece of memory.
*
* Data is shared, but offset and length are not.
* This allows one vector to have access to only a
@@ -326,7 +325,7 @@ public:
//! Internal for static_shared_vector_cast
template<typename FROM>
shared_vector(const shared_vector<FROM> &src,
typename meta::is_void<FROM, detail::_shared_vector_cast_tag>::type)
detail::_shared_vector_cast_tag)
:base_t(std::tr1::static_pointer_cast<E>(src.dataPtr()),
src.dataOffset()/sizeof(E),
src.dataCount()/sizeof(E))
@@ -427,13 +426,13 @@ public:
* owner of the data array.
*
* If a copy is needed, memory is allocated with new[]. If this is
* not desireable then do something like the following.
* not desirable then do something like the following.
@code
shared_vector<E> original(...);
if(!original.unique()){
shared_vector<E> temp(myallocator(original.size()),
0, original.size());
std::tr1::shared_ptr<E> sptr(myalloc(original.size()), myfree);
shared_vector<E> temp(sptr, 0, original.size());
std::copy(original.begin(), original.end(), temp.begin());
original.swap(temp);
}
@@ -527,16 +526,37 @@ public:
};
//! Specialization for storing untyped pointers
//! Does not allow access or iteration of contents
//! other than as void* or const void*
/**
* @brief Specialization for storing untyped pointers.
*
* Does not allow access or iteration of contents
* other than as void* or const void*
*
* In order to support shared_vector_convert<>()
* information about the type of the underlying allocation
* is stored.
* This is implicitly set by static_shared_vector_cast<>()
* and may be explicitly checked/changed using
* original_type()/set_original_type().
*
* A shared_vector<void> directly constructed
* from a smart pointer does not have an associated
* original_type().
* Use epics::pvData::ScalarTypeFunc::allocArray()
* to convienently allocate an array with a known
* original_type().
*/
template<typename E>
class shared_vector<E, typename meta::is_void<E>::type >
: public detail::shared_vector_base<E>
{
typedef detail::shared_vector_base<E> base_t;
ScalarType m_vtype;
// allow specialization for all E to be friends
template<typename E1, class Enable1> friend class shared_vector;
public:
typedef E value_type;
typedef E* pointer;
typedef ptrdiff_t difference_type;
typedef size_t size_type;
@@ -563,7 +583,7 @@ public:
//! Internal for static_shared_vector_cast
template<typename FROM>
shared_vector(const shared_vector<FROM> &src,
typename meta::is_not_void<FROM, detail::_shared_vector_cast_tag>::type)
detail::_shared_vector_cast_tag)
:base_t(std::tr1::static_pointer_cast<E>(src.dataPtr()),
src.dataOffset()*sizeof(FROM),
src.dataCount()*sizeof(FROM))
@@ -572,12 +592,12 @@ public:
shared_vector(shared_vector<void>& O,
detail::_shared_vector_freeze_tag t)
:base_t(O,t)
:base_t(O,t), m_vtype(O.m_vtype)
{}
shared_vector(shared_vector<const void>& O,
detail::_shared_vector_thaw_tag t)
:base_t(O,t)
:base_t(O,t), m_vtype(O.m_vtype)
{}
shared_vector& operator=(const shared_vector& o)
@@ -599,6 +619,64 @@ public:
ScalarType original_type() const {return m_vtype;}
};
namespace detail {
template<typename TO, typename FROM, class Enable = void>
struct static_shared_vector_caster { /* no default */ };
// from void to non-void with same const-ness
template<typename TO>
struct static_shared_vector_caster<TO, void,
typename meta::_and<meta::same_const<TO,void>, meta::is_not_void<TO> >::type> {
static inline shared_vector<TO> op(const shared_vector<void>& src) {
return shared_vector<TO>(src, detail::_shared_vector_cast_tag());
}
};
template<typename TO>
struct static_shared_vector_caster<TO, const void,
typename meta::_and<meta::same_const<TO,const void>, meta::is_not_void<TO> >::type> {
static inline shared_vector<TO> op(const shared_vector<const void>& src) {
return shared_vector<TO>(src, detail::_shared_vector_cast_tag());
}
};
// from non-void to void with same const-ness
template<typename FROM>
struct static_shared_vector_caster<void, FROM,
typename meta::_and<meta::same_const<void,FROM>, meta::is_not_void<FROM> >::type> {
static FORCE_INLINE shared_vector<void> op(const shared_vector<FROM>& src) {
return shared_vector<void>(src, detail::_shared_vector_cast_tag());
}
};
template<typename FROM>
struct static_shared_vector_caster<const void, FROM,
typename meta::_and<meta::same_const<const void,FROM>, meta::is_not_void<FROM> >::type> {
static FORCE_INLINE shared_vector<const void> op(const shared_vector<FROM>& src) {
return shared_vector<const void>(src, detail::_shared_vector_cast_tag());
}
};
// cast to same type, no-op
template<typename TOFRO>
struct static_shared_vector_caster<TOFRO,TOFRO,void> {
static FORCE_INLINE const shared_vector<TOFRO>& op(const shared_vector<TOFRO>& src) {
return src;
}
};
} // namespace detail
/** @brief Allow casting of shared_vector between types
*
* Currently only to/from void is implemented.
*
@warning Casting from void is undefined unless the offset and length
* are integer multiples of the size of the destination type.
*/
template<typename TO, typename FROM>
static FORCE_INLINE
shared_vector<TO>
static_shared_vector_cast(const shared_vector<FROM>& src)
{
return detail::static_shared_vector_caster<TO,FROM>::op(src);
}
namespace detail {
// Default to type conversion using castUnsafe (C++ type casting) on each element
@@ -631,7 +709,7 @@ namespace detail {
return shared_vector<TO>(src, detail::_shared_vector_cast_tag());
}
};
// convert from void uses original type or throws an exception.
template<typename TO, typename FROM>
struct shared_vector_converter<TO,FROM,
@@ -659,30 +737,16 @@ namespace detail {
};
}
/** @brief Allow casting of shared_vector between types
*
* Currently only to/from void is implemented.
*
@warning Casting from void is undefined unless the offset and length
* are integer multiples of the size of the destination type.
*/
template<typename TO, typename FROM>
static FORCE_INLINE
shared_vector<TO>
static_shared_vector_cast(const shared_vector<FROM>& src,
typename meta::same_const<TO,FROM,int>::type = 0)
{
return shared_vector<TO>(src, detail::_shared_vector_cast_tag());
}
/** @brief 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.
* Convert from void utilizes shared_vector<void>::original_type().
*
* @throws std::runtime_error if cast is not valid.
* @throws std::bad_alloc for out of memory condition
*/
template<typename TO, typename FROM>
static FORCE_INLINE
@@ -858,10 +922,13 @@ std::ostream& operator<<(std::ostream& strm, const epics::pvData::shared_vector<
* shared_vector has additional constructors from raw pointers
* and shared_ptr s.
*
* The copy constructor and assignment operator allow implicit
* casting from type 'shared_vector<T>' to 'shared_vector<const T>'.
* Implicit casting is not allowed. Instead use
* const_shared_vector_cast()/freeze()/thaw() (@ref vectorconst)
* to casting between 'T' and 'const T'.
* Use static_shared_vector_cast() to cast between
* void and non-void (same const-ness).
*
* To faciliate safe modification the methods unique() and
* To facilitate safe modification the methods unique() and
* make_unique() are provided.
*
* The slice() method selects a sub-set of the shared_vector.
@@ -961,17 +1028,15 @@ Type #2 is constant reference to a mutable value.
Type #3 is a mutable reference to a constant value.
Type #4 is a constant reference to a constant value.
Casting between const and non-const references of the same value type
is governed by the normal C++ casting rules.
Casting between const and non-const values does @b not follow the normal
C++ casting rules.
C++ casting rules (no implicit cast).
For casting between shared_vector<T> and shared_vector<const T>
explicit casting operations are required. These operations are
@b freeze() (non-const to const) and @b thaw() (const to non-const).
A shared_vector<const T> is "frozen" as its value can not be modified.
A 'shared_vector<const T>' is "frozen" as its value can not be modified.
However it can still be sliced because the reference is not const.
These functions are defined like:
@@ -995,17 +1060,18 @@ The following guarantees are provided by both functions:
# The returned reference points to a value which is only referenced by
shared_vectors with the same value const-ness as the returned reference.
Please note that the argument of both freeze and thaw is a non-const
@note The argument of both freeze() and thaw() is a non-const
reference which will always be cleared.
@section vfreeze Freezing
The act of freezing a shared_vector requires that the shared_vector
passed in must be unique() or an exception is thrown. This is
done to reduce the possibility of accidental copying.
passed in must be unique() or an exception is thrown.
No copy is made.
This possibility can be avoided by calling the make_unique() on a
The possibility of an exception can be avoided by calling the make_unique() on a
shared_vector before passing it to freeze().
This will make a copy if necessary.
@section vthaw Thawing

View File

@@ -1,8 +1,7 @@
/* status.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.
/*
* Copyright information and license terms for this software can be
* found in the file LICENSE that is included with the distribution
*/
/**
* @author mse
@@ -21,7 +20,9 @@
namespace epics { namespace pvData {
/**
* Status.
* @brief Status.
*
* This is a class for returning status to clients.
* @author mse
*/
class epicsShareClass Status : public epics::pvData::Serializable {
@@ -101,9 +102,7 @@ namespace epics { namespace pvData {
void dump(std::ostream& o) const;
private:
static std::string m_emptyStringtring;
StatusType m_statusType;
std::string m_message;
std::string m_stackDump;

View File

@@ -1,7 +1,6 @@
/**
* 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.
/*
* Copyright information and license terms for this software can be
* found in the file LICENSE that is included with the distribution
*/
/** C++ Template meta programming helpers
*/
@@ -11,7 +10,9 @@
// gently nudge the compiler to inline our wrappers
// Warning: Only use this when the template body is *small*.
// You have been warned!
#if defined(__GNUC__) && __GNUC__>=3
#if defined(__MINGW32__)
# define FORCE_INLINE inline
#elif defined(__GNUC__) && __GNUC__>=3
# define FORCE_INLINE __attribute__((always_inline)) inline
#elif defined(_MSC_VER)
# define FORCE_INLINE __forceinline

296
src/misc/pv/thread.h Normal file
View File

@@ -0,0 +1,296 @@
/* thread.h */
/*
* Copyright information and license terms for this software can be
* found in the file LICENSE that is included with the distribution
*/
/**
* @author mrk
*/
#ifndef THREAD_H
#define THREAD_H
#include <memory>
#include <sstream>
#if __cplusplus>=201103L
#include <functional>
#endif
#include <epicsThread.h>
#include <shareLib.h>
#include <pv/noDefaultMethods.h>
#include <pv/pvType.h>
namespace epics { namespace pvData {
enum ThreadPriority {
lowestPriority =epicsThreadPriorityLow,
lowerPriority =epicsThreadPriorityLow + 15,
lowPriority =epicsThreadPriorityMedium - 15,
middlePriority =epicsThreadPriorityMedium,
highPriority =epicsThreadPriorityMedium + 15,
higherPriority =epicsThreadPriorityHigh - 15,
highestPriority =epicsThreadPriorityHigh
};
class Thread;
typedef std::tr1::shared_ptr<Thread> ThreadPtr;
typedef std::tr1::shared_ptr<epicsThread> EpicsThreadPtr;
typedef epicsThreadRunable Runnable;
//! Helper for those cases where a class should have more than one runnable
template<typename C>
class epicsShareClass RunnableMethod : public Runnable, private NoDefaultMethods
{
typedef void (C::*meth_t)();
C *inst;
meth_t meth;
virtual void run()
{
(inst->*meth)();
}
public:
RunnableMethod(C* inst, void (C::*meth)())
:inst(inst), meth(meth)
{}
};
namespace detail {
struct FuncRunner : public epicsThreadRunable
{
typedef void (*fn_t)(void*);
fn_t fn;
void *arg;
FuncRunner(fn_t f, void *a) :fn(f), arg(a) {}
virtual ~FuncRunner(){}
virtual void run()
{
(*fn)(arg);
}
};
template<typename C>
struct MethRunner : public epicsThreadRunable
{
typedef void(C::*fn_t)();
fn_t fn;
C* inst;
MethRunner(C* i, fn_t f) :fn(f), inst(i) {}
virtual ~MethRunner() {}
virtual void run()
{
(inst->*fn)();
}
};
#if __cplusplus>=201103L
struct BindRunner : public epicsThreadRunable
{
typedef std::function<void()> fn_t;
fn_t fn;
BindRunner(const fn_t f) : fn(f) {}
virtual ~BindRunner() {}
virtual void run()
{
fn();
}
};
#endif
} // namespace detail
/**
* @brief C++ wrapper for epicsThread from EPICS base.
*
*/
class epicsShareClass Thread : public epicsThread, private NoDefaultMethods {
public:
/** @brief Holds all the configuration necessary to launch a @class Thread
*
* The defaults may be used except for the runnable, which must be given
* either in the constructor, or the @method run() method.
*
* @note Instances of @class Config may not be reused.
*
* Defaults:
* name: ""
* priority: epicsThreadPriorityLow (aka epics::pvData::lowestPriority)
* stack size: epicsThreadStackSmall
* auto start: true
* runner: nil (must be set explictly)
*
@code
stuct bar { void meth(); ... } X;
// with a static thread name
Thread foo(Thread::Config(&X, &bar::meth)
.name("example")
.prio(epicsThreadPriorityHigh));
// with a constructed thread name
Thread foo(Thread::Config(&X, &bar::meth)
.prio(epicsThreadPriorityHigh)
<<"example"<<1);
@endcode
*/
class epicsShareClass Config
{
unsigned int p_prio, p_stack;
std::ostringstream p_strm;
bool p_autostart;
Runnable *p_runner;
#if __cplusplus>=201103L
typedef std::unique_ptr<Runnable> p_owned_runner_t;
#else
typedef std::auto_ptr<Runnable> p_owned_runner_t;
#endif
p_owned_runner_t p_owned_runner;
friend class Thread;
Runnable& x_getrunner()
{
if(!this->p_runner)
throw std::logic_error("Thread::Config missing run()");
return *this->p_runner;
}
void x_setdefault()
{
this->p_prio = epicsThreadPriorityLow;
this->p_autostart = true;
this->p_runner = NULL;
(*this).stack(epicsThreadStackSmall);
}
public:
Config() {this->x_setdefault();}
Config(Runnable *r) {this->x_setdefault();this->run(r);}
Config(void(*fn)(void*), void *ptr) {this->x_setdefault();this->run(fn, ptr);}
template<typename C>
Config(C* inst, void(C::*meth)()) {this->x_setdefault();this->run(inst, meth);}
#if __cplusplus>=201103L
Config(const std::function<void()>& fn) {this->x_setdefault();this->run(fn);}
#endif
inline Config& name(const std::string& n)
{ this->p_strm.str(n); return *this; }
inline Config& prio(unsigned int p)
{ this->p_prio = p; return *this; }
inline Config& stack(epicsThreadStackSizeClass s)
{ this->p_stack = epicsThreadGetStackSize(s); return *this; }
inline Config& autostart(bool a)
{ this->p_autostart = a; return *this; }
//! Thread will execute Runnable::run()
Config& run(Runnable* r)
{ this->p_runner = r; return *this; }
//! Thread will execute (*fn)(ptr)
Config& run(void(*fn)(void*), void *ptr)
{
this->p_owned_runner.reset(new detail::FuncRunner(fn, ptr));
this->p_runner = this->p_owned_runner.get();
return *this;
}
//! Thread will execute (inst->*meth)()
template<typename C>
Config& run(C* inst, void(C::*meth)())
{
this->p_owned_runner.reset(new detail::MethRunner<C>(inst, meth));
this->p_runner = this->p_owned_runner.get();
return *this;
}
#if __cplusplus>=201103L
Config& run(const std::function<void()>& fn)
{
this->p_owned_runner.reset(new detail::BindRunner(fn));
this->p_runner = this->p_owned_runner.get();
return *this;
}
#endif
//! Append to thread name string. Argument must be understood by std::ostream::operator<<
template<typename T>
Config& operator<<(T x) { this->p_strm<<x; return *this; }
};
/**
*
* Constructor
* @param name thread name.
* @param priority priority is one of:
@code
enum ThreadPriority {
lowestPriority, lowerPriority, lowPriority,
middlePriority,
highPriority, higherPriority, highestPriority
};
@endcode
* @param runnable this is a c function
* @param stkcls stack size as specified by epicsThreadStackSizeClass
*/
Thread(std::string name,
ThreadPriority priority,
Runnable *runnable,
epicsThreadStackSizeClass stkcls=epicsThreadStackSmall)
:epicsThread(*runnable,
name.c_str(),
epicsThreadGetStackSize(stkcls),
priority)
{
this->start();
}
/**
*
* Constructor
* @param runnable this is a c function
* @name thread name.
* @param stkcls stack size as specified by epicsThreadStackSizeClass
* @param priority priority is one of:
@code
enum ThreadPriority {
lowestPriority, lowerPriority, lowPriority,
middlePriority,
highPriority, higherPriority, highestPriority
};
@endcode
*/
Thread(Runnable &runnable,
std::string name,
unsigned int stksize,
unsigned int priority=lowestPriority)
:epicsThread(runnable,
name.c_str(),
stksize,
priority)
{
this->start();
}
//! @brief Create a new thread using the given @class Config
//! @throws std::logic_error for improper @class Config (ie. missing runner)
Thread(Config& c)
:epicsThread(c.x_getrunner(), c.p_strm.str().c_str(),
c.p_stack, c.p_prio)
{
#if __cplusplus>=201103L
p_owned = std::move(c.p_owned_runner);
#else
p_owned = c.p_owned_runner;
#endif
if(c.p_autostart)
this->start();
}
/**
* Destructor
*/
~Thread()
{
this->exitWait();
}
Config::p_owned_runner_t p_owned;
};
}}
#endif /* THREAD_H */

View File

@@ -1,8 +1,7 @@
/* timeFunction.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.
/*
* Copyright information and license terms for this software can be
* found in the file LICENSE that is included with the distribution
*/
/**
* @author mrk
@@ -21,19 +20,46 @@ class TimeFunction;
typedef std::tr1::shared_ptr<TimeFunctionRequester> TimeFunctionRequesterPtr;
typedef std::tr1::shared_ptr<TimeFunction> TimeFunctionPtr;
/**
* @brief Class that must be implemented by timeFunction requester.
*
*/
class epicsShareClass TimeFunctionRequester {
public:
POINTER_DEFINITIONS(TimeFunctionRequester);
/**
* Destructor
*/
virtual ~TimeFunctionRequester(){}
/**
* function to be timed.
* It will get called multiple times.
*/
virtual void function() = 0;
};
/**
* @brief Class for measuring time it takes to execute a function.
*
*/
class epicsShareClass TimeFunction {
public:
POINTER_DEFINITIONS(TimeFunction);
/**
* Constructor
* @param requester The class that has a function method.
*/
TimeFunction(TimeFunctionRequesterPtr const & requester);
/**
* Destructor
*/
~TimeFunction();
/**
* Time the function.
* @return the time in seconds to execute the function.
* Note that the function may be called many times.
*/
double timeCall();
private:
TimeFunctionRequesterPtr requester;

View File

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

View File

@@ -1,7 +1,6 @@
/**
* 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.
/*
* Copyright information and license terms for this software can be
* found in the file LICENSE that is included with the distribution
*/
/* Author: Michael Davidsaver */
#ifndef PVTYPECAST_H
@@ -10,23 +9,13 @@
#include <stdexcept>
#include <sstream>
#ifdef epicsExportSharedSymbols
#define typeCastepicsExportSharedSymbols
#undef epicsExportSharedSymbols
#endif
#include <epicsConvert.h>
#ifdef typeCastepicsExportSharedSymbols
#define epicsExportSharedSymbols
#undef typeCastepicsExportSharedSymbols
#endif
#include <shareLib.h>
#include <pv/pvType.h>
#include <pv/pvIntrospect.h>
#include <pv/templateMeta.h>
#include <shareLib.h>
namespace epics { namespace pvData {
@@ -59,7 +48,7 @@ namespace detail {
typedef T return_t;
static FORCE_INLINE return_t op(const T& i) { return i; }
};
// trick std::ostream into treating char's as numbers
// trick std::ostream into treating chars as numbers
// by promoting char to int
template<>
struct print_convolute<int8> {
@@ -142,7 +131,7 @@ namespace detail {
* - float -> double
*
* Conversions where out of range inputs always produce
* a defined result, but may not be reversable.
* a defined result, but may not be reversible.
*
* - double -> float. When abs(value) is outside the range
* [FLT_MIN, FLT_MAX] the value is clipped to FLT_MIN or FLT_MAX

View File

@@ -1,14 +1,16 @@
/* requester.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.
/*
* Copyright information and license terms for this software can be
* found in the file LICENSE that is included with the distribution
*/
/**
* @author mrk
*/
#include <string>
#include <cstdio>
#include <iostream>
#include <epicsMutex.h>
#define epicsExportSharedSymbols
#include <pv/lock.h>
@@ -34,6 +36,9 @@ string getMessageTypeName(MessageType messageType)
return messageTypeName[messageType];
}
void Requester::message(std::string const & message,MessageType messageType)
{
std::cerr << "[" << getRequesterName() << "] message(" << message << ", " << getMessageTypeName(messageType) << ")\n";
}
}}

View File

@@ -1,40 +0,0 @@
/* requester.h */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvData is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
/**
* @author mrk
*/
#ifndef REQUESTER_H
#define REQUESTER_H
#include <string>
#include <pv/pvType.h>
#include <pv/sharedPtr.h>
#include <shareLib.h>
namespace epics { namespace pvData {
class Requester;
typedef std::tr1::shared_ptr<Requester> RequesterPtr;
enum MessageType {
infoMessage,warningMessage,errorMessage,fatalErrorMessage
};
#define MESSAGE_TYPE_COUNT 4
epicsShareExtern std::string getMessageTypeName(MessageType messageType);
class epicsShareClass Requester {
public:
POINTER_DEFINITIONS(Requester);
virtual ~Requester(){}
virtual std::string getRequesterName() = 0;
virtual void message(std::string const & message,MessageType messageType) = 0;
};
}}
#endif /* REQUESTER_H */

View File

@@ -1,77 +0,0 @@
/* serialize.h */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvData is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
/**
* @author mrk
*/
#ifndef SERIALIZE_H
#define SERIALIZE_H
#include <pv/byteBuffer.h>
#include <pv/sharedPtr.h>
#include <shareLib.h>
namespace epics { namespace pvData {
class SerializableControl;
class DeserializableControl;
class Serializable;
class BitSetSerializable;
class SerializableArray;
class BitSet;
class Field;
class epicsShareClass SerializableControl {
public:
virtual ~SerializableControl(){}
virtual void flushSerializeBuffer() =0;
virtual void ensureBuffer(std::size_t size) =0;
virtual void alignBuffer(std::size_t alignment) =0;
virtual bool directSerialize(ByteBuffer *existingBuffer, const char* toSerialize,
std::size_t elementCount, std::size_t elementSize) = 0;
virtual void cachedSerialize(std::tr1::shared_ptr<const Field> const & field, ByteBuffer* buffer) = 0;
};
class epicsShareClass DeserializableControl {
public:
virtual ~DeserializableControl(){}
virtual void ensureData(std::size_t size) =0;
virtual void alignData(std::size_t alignment) =0;
virtual bool directDeserialize(ByteBuffer *existingBuffer, char* deserializeTo,
std::size_t elementCount, std::size_t elementSize) = 0;
virtual std::tr1::shared_ptr<const Field> cachedDeserialize(ByteBuffer* buffer) = 0;
};
class epicsShareClass Serializable {
public:
virtual ~Serializable(){}
virtual void serialize(ByteBuffer *buffer,
SerializableControl *flusher) const = 0;
virtual void deserialize(ByteBuffer *buffer,
DeserializableControl *flusher) = 0;
};
class epicsShareClass 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 epicsShareClass SerializableArray : public virtual Serializable {
public:
virtual ~SerializableArray(){}
using Serializable::serialize;
virtual void serialize(ByteBuffer *buffer,
SerializableControl *flusher, std::size_t offset, std::size_t count) const = 0;
};
}}
#endif /* SERIALIZE_H */

View File

@@ -1,19 +1,21 @@
/**
* 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.
/*
* Copyright information and license terms for this software can be
* found in the file LICENSE that is included with the distribution
*/
/*
* serializeHelper.cpp
*
* Created on: Oct 22, 2010
* Author: Miha vitorovic
* Author: Miha Vitorovic
*/
#include <algorithm>
#include <epicsEndian.h>
#define epicsExportSharedSymbols
#include <pv/pvType.h>
#include <pv/byteBuffer.h>
#include <pv/epicsException.h>
#include <pv/byteBuffer.h>
#include <pv/serializeHelper.h>
@@ -139,6 +141,132 @@ namespace epics {
else
return emptyStringtring;
}
}
}
namespace {
using namespace epics::pvData;
struct ToString : public epics::pvData::SerializableControl
{
typedef std::vector<epicsUInt8> buf_type;
buf_type buf;
buf_type& out;
ByteBuffer bufwrap;
ToString(buf_type& out, int byteOrder = EPICS_BYTE_ORDER)
:buf(16*1024)
,out(out)
,bufwrap((char*)&buf[0], buf.size(), byteOrder)
{}
virtual void flushSerializeBuffer()
{
size_t N = out.size();
out.resize(out.size()+bufwrap.getPosition());
std::copy(buf.begin(),
buf.begin()+bufwrap.getPosition(),
out.begin()+N);
bufwrap.clear();
}
virtual void ensureBuffer(std::size_t size)
{
flushSerializeBuffer();
assert(bufwrap.getRemaining()>0);
}
virtual void alignBuffer(std::size_t alignment)
{
if(bufwrap.getRemaining()<alignment)
flushSerializeBuffer();
assert(bufwrap.getRemaining()>=alignment);
bufwrap.align(alignment);
}
virtual bool directSerialize(
ByteBuffer *existingBuffer,
const char* toSerialize,
std::size_t elementCount,
std::size_t elementSize)
{
return false;
}
virtual void cachedSerialize(
std::tr1::shared_ptr<const Field> const & field,
ByteBuffer* buffer)
{
field->serialize(buffer, this);
}
};
} // namespace
namespace epics {
namespace pvData {
void serializeToVector(const Serializable *S,
int byteOrder,
std::vector<epicsUInt8>& out)
{
ToString TS(out, byteOrder);
S->serialize(&TS.bufwrap, &TS);
TS.flushSerializeBuffer();
assert(TS.bufwrap.getPosition()==0);
}
}
}
namespace {
struct FromString : public epics::pvData::DeserializableControl
{
ByteBuffer &buf;
epics::pvData::FieldCreatePtr create;
FromString(ByteBuffer& b)
:buf(b)
,create(epics::pvData::getFieldCreate())
{}
virtual void ensureData(std::size_t size)
{
if(size>buf.getRemaining())
throw std::logic_error("Incomplete buffer");
}
virtual void alignData(std::size_t alignment)
{
size_t pos = buf.getPosition(), k = alignment-1;
if(pos&k) {
std::size_t npad = alignment-(pos&k);
ensureData(npad);
buf.align(alignment);
}
}
virtual bool directDeserialize(
ByteBuffer *existingBuffer,
char* deserializeTo,
std::size_t elementCount,
std::size_t elementSize)
{
return false;
}
virtual std::tr1::shared_ptr<const Field> cachedDeserialize(
ByteBuffer* buffer)
{
return create->deserialize(buffer, this);
}
};
}
namespace epics {
namespace pvData {
void deserializeFromBuffer(Serializable *S,
ByteBuffer& buf)
{
FromString F(buf);
S->deserialize(&buf, &F);
}
}
}

View File

@@ -1,8 +1,7 @@
/*pvData.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.
/*status.cpp*/
/*
* Copyright information and license terms for this software can be
* found in the file LICENSE that is included with the distribution
*/
/**
* @author mrk
@@ -17,7 +16,6 @@ using std::string;
namespace epics { namespace pvData {
const char* Status::StatusTypeName[] = { "OK", "WARNING", "ERROR", "FATAL" };
string Status::m_emptyStringtring;
Status Status::Ok;
@@ -102,7 +100,8 @@ void Status::deserialize(ByteBuffer *buffer, DeserializableControl *flusher)
if (m_statusType != STATUSTYPE_OK)
{
m_statusType = STATUSTYPE_OK;
m_message = m_stackDump = m_emptyStringtring;
m_message.clear();
m_stackDump.clear();
}
}
else

View File

@@ -1,85 +0,0 @@
/* thread.h */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvData is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
/**
* @author mrk
*/
#ifndef THREAD_H
#define THREAD_H
#include <memory>
#ifdef epicsExportSharedSymbols
#define threadepicsExportSharedSymbols
#undef epicsExportSharedSymbols
#endif
#include <epicsThread.h>
#ifdef threadepicsExportSharedSymbols
#define epicsExportSharedSymbols
#undef threadepicsExportSharedSymbols
#endif
#include <pv/noDefaultMethods.h>
#include <pv/pvType.h>
#include <shareLib.h>
namespace epics { namespace pvData {
enum ThreadPriority {
lowestPriority =epicsThreadPriorityLow,
lowerPriority =epicsThreadPriorityLow + 15,
lowPriority =epicsThreadPriorityMedium - 15,
middlePriority =epicsThreadPriorityMedium,
highPriority =epicsThreadPriorityMedium + 15,
higherPriority =epicsThreadPriorityHigh - 15,
highestPriority =epicsThreadPriorityHigh
};
class Thread;
typedef std::tr1::shared_ptr<Thread> ThreadPtr;
typedef std::tr1::shared_ptr<epicsThread> EpicsThreadPtr;
typedef epicsThreadRunable Runnable;
class epicsShareClass Thread : public epicsThread, private NoDefaultMethods {
public:
Thread(std::string name,
ThreadPriority priority,
Runnable *runnable,
epicsThreadStackSizeClass stkcls=epicsThreadStackSmall)
:epicsThread(*runnable,
name.c_str(),
epicsThreadGetStackSize(stkcls),
priority)
{
this->start();
}
Thread(Runnable &runnable,
std::string name,
unsigned int stksize,
unsigned int priority=lowestPriority)
:epicsThread(runnable,
name.c_str(),
stksize,
priority)
{
this->start();
}
~Thread()
{
this->exitWait();
}
};
}}
#endif /* THREAD_H */

View File

@@ -1,8 +1,7 @@
/* timeFunction.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.
/*
* Copyright information and license terms for this software can be
* found in the file LICENSE that is included with the distribution
*/
/**
* @author mrk
@@ -13,6 +12,8 @@
#include <string>
#include <cstdio>
#include <epicsTime.h>
#define epicsExportSharedSymbols
#include <pv/pvType.h>
#include <pv/timeStamp.h>

View File

@@ -1,22 +1,23 @@
/* timer.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.
/*
* Copyright information and license terms for this software can be
* found in the file LICENSE that is included with the distribution
*/
/**
* @author mrk
*/
#ifdef _WIN32
#if defined(_WIN32) && !defined(NOMINMAX)
#define NOMINMAX
#endif
#include <stdexcept>
#include <string>
#include <iostream>
#include <epicsThread.h>
#define epicsExportSharedSymbols
#include <pv/convert.h>
#include <pv/timer.h>
using std::string;

View File

@@ -1,14 +1,15 @@
/**
* 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.
/*
* Copyright information and license terms for this software can be
* found in the file LICENSE that is included with the distribution
*/
/* Author: Michael Davidsaver */
#include <algorithm>
#include <sstream>
#include <epicsConvert.h>
#define epicsExportSharedSymbols
#include "typeCast.h"
#include "pv/typeCast.h"
using epics::pvData::castUnsafe;
using epics::pvData::ScalarType;

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