Compare commits
179 Commits
3.0.0
...
before_mer
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
89da38cfa4 | ||
|
|
82b5d0e50b | ||
|
|
bb8789a9ad | ||
|
|
88aabb41e7 | ||
|
|
897059303d | ||
|
|
0b7607cf04 | ||
|
|
4a512f47de | ||
|
|
76a54d38e4 | ||
|
|
b9b03940a2 | ||
|
|
8370a97866 | ||
|
|
b659c77dbb | ||
|
|
e45b842a6c | ||
|
|
32ba6d444b | ||
|
|
95b7a04041 | ||
|
|
d81ef64799 | ||
|
|
19269735ae | ||
|
|
f7957c8ea5 | ||
|
|
1e40797bc4 | ||
|
|
ad66f8af73 | ||
|
|
d436e61bdb | ||
|
|
c71e62746d | ||
|
|
d5b0ad5d80 | ||
|
|
4a992e6e1c | ||
|
|
9593de8c0f | ||
|
|
8205be5220 | ||
|
|
39c43c4c02 | ||
|
|
8a9fa956e0 | ||
|
|
06e9c533e3 | ||
|
|
5bdcaf43db | ||
|
|
df1d13a155 | ||
|
|
6e7b19b090 | ||
|
|
279b73a477 | ||
|
|
74239303b3 | ||
|
|
134f390a5f | ||
|
|
8aa26b78bb | ||
|
|
301038664e | ||
|
|
ccad38f2db | ||
|
|
29dee42d34 | ||
|
|
f9135c81de | ||
|
|
9400635fd9 | ||
|
|
4102deceb3 | ||
|
|
86306740be | ||
|
|
8e63fc8b25 | ||
|
|
3219bd0307 | ||
|
|
bdb4430bb6 | ||
|
|
a574dbf89b | ||
|
|
47178370d5 | ||
|
|
ac67fddbcb | ||
|
|
e97fab3107 | ||
|
|
fee6f03ec2 | ||
|
|
1aff2ec112 | ||
|
|
57b3e9a8b2 | ||
|
|
35dad272eb | ||
|
|
d40c41048d | ||
|
|
03f59c94b4 | ||
|
|
87718f1c82 | ||
|
|
cbf7b69ef0 | ||
|
|
c56c976a22 | ||
|
|
3579d17a05 | ||
|
|
0f17bd23c7 | ||
|
|
db10bed951 | ||
|
|
071806f12b | ||
|
|
9cd7008efe | ||
|
|
14dc098761 | ||
|
|
8c6a895b19 | ||
|
|
01b8e69e4b | ||
|
|
11e91ac3fa | ||
|
|
70380b9a43 | ||
|
|
fa7a44f5b3 | ||
|
|
fb0329c0b5 | ||
|
|
c3d04fdd08 | ||
|
|
ebb0c97c51 | ||
|
|
aabe0f3594 | ||
|
|
7c21bf7aa1 | ||
|
|
de70d90603 | ||
|
|
31be738c10 | ||
|
|
759d268af0 | ||
|
|
f21811eb6a | ||
|
|
c643509c7e | ||
|
|
0860f8e6f9 | ||
|
|
e96b447e37 | ||
|
|
0eecd3b1fe | ||
|
|
b5b6ae100d | ||
|
|
8fd9bf10e5 | ||
|
|
9ac030169a | ||
|
|
569bd3b681 | ||
|
|
45bb461c32 | ||
|
|
105c3185f7 | ||
|
|
5565e4e30c | ||
|
|
70ae281f45 | ||
|
|
b518efd196 | ||
|
|
6e3a344caa | ||
|
|
2e3cbed520 | ||
|
|
5e2e7c81a6 | ||
|
|
cff59487ae | ||
|
|
cdcbfe7378 | ||
|
|
0c4ef8f079 | ||
|
|
c0e9dcff21 | ||
|
|
79eeb0fa2a | ||
|
|
46feb86a99 | ||
|
|
74f68c47d3 | ||
|
|
3c7a738ffc | ||
|
|
22d4a53d65 | ||
|
|
d319e2ed7b | ||
|
|
2cb07a8490 | ||
|
|
6900d4bbec | ||
|
|
73450bdbc7 | ||
|
|
776ff49ed2 | ||
|
|
00da6c88ae | ||
|
|
986f036d20 | ||
|
|
5699c43b74 | ||
|
|
b58b97a916 | ||
|
|
5f52f14094 | ||
|
|
ec6b67ffad | ||
|
|
3de28e3cef | ||
|
|
23d5aab1e8 | ||
|
|
cf8c6718dd | ||
|
|
b0c8249562 | ||
|
|
8cb0b1a7d6 | ||
|
|
7f9745c8d1 | ||
|
|
4e749cc8be | ||
|
|
70c9a7c18f | ||
|
|
11e2ee19ea | ||
|
|
a4cfab1242 | ||
|
|
be4738f59c | ||
|
|
b63c3da565 | ||
|
|
0b89f08d09 | ||
|
|
ac53153bea | ||
|
|
bc3187a3f6 | ||
|
|
4294710d9e | ||
|
|
82a33460cf | ||
|
|
3b6268a4fc | ||
|
|
41425b3fa1 | ||
|
|
57804494ef | ||
|
|
9039a10c9a | ||
|
|
9e865bc37d | ||
|
|
54ee8bf7a0 | ||
|
|
629c8346d2 | ||
|
|
1bf2ff430a | ||
|
|
572c02bf6e | ||
|
|
80777b293f | ||
|
|
3c08834377 | ||
|
|
eeae12e3d4 | ||
|
|
992ac73068 | ||
|
|
e843779555 | ||
|
|
5f4ca240b4 | ||
|
|
79cd374f16 | ||
|
|
b137b32fc6 | ||
|
|
3cd2bfdef0 | ||
|
|
461dbdf0f8 | ||
|
|
9e8a6b6304 | ||
|
|
fd5ea89340 | ||
|
|
1d1d2b31cd | ||
|
|
d75656dad7 | ||
|
|
f0aa2fe0e0 | ||
|
|
ae847aea2b | ||
|
|
00ac5bf64f | ||
|
|
61e8024c65 | ||
|
|
ee5a370c01 | ||
|
|
659ce13e98 | ||
|
|
a7fde21300 | ||
|
|
a6bfab2d74 | ||
|
|
e948af1851 | ||
|
|
2062cc5d10 | ||
|
|
e85d10c6d9 | ||
|
|
0e0ab66d45 | ||
|
|
f2635c7fdc | ||
|
|
4d92bbe541 | ||
|
|
e6e1434fc1 | ||
|
|
5e689f94f4 | ||
|
|
c1b6d26b8e | ||
|
|
f72c5dba84 | ||
|
|
704007092c | ||
|
|
2f8c434429 | ||
|
|
b0c57e7ae3 | ||
|
|
0e57391b4d | ||
|
|
7ff1a93e72 | ||
|
|
d7eada7216 | ||
|
|
c435f71592 |
8
.hgflow
Normal file
8
.hgflow
Normal file
@@ -0,0 +1,8 @@
|
||||
[branchname]
|
||||
master = master
|
||||
develop = default
|
||||
feature = feature/
|
||||
release = release/
|
||||
hotfix = hotfix/
|
||||
support = support/
|
||||
|
||||
4
.hgtags
4
.hgtags
@@ -5,3 +5,7 @@ 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
|
||||
|
||||
14
Makefile
14
Makefile
@@ -1,12 +1,14 @@
|
||||
#Makefile at top of application tree
|
||||
# Makefile for the EPICS V4 pvData module
|
||||
|
||||
TOP = .
|
||||
include $(TOP)/configure/CONFIG
|
||||
|
||||
DIRS += configure
|
||||
DIRS += pvDataApp
|
||||
pvDataApp_DEPEND_DIRS = configure
|
||||
|
||||
DIRS += src
|
||||
src_DEPEND_DIRS = configure
|
||||
|
||||
DIRS += testApp
|
||||
testApp_DEPEND_DIRS = pvDataApp
|
||||
testApp_DEPEND_DIRS = src
|
||||
|
||||
include $(TOP)/configure/RULES_TOP
|
||||
|
||||
|
||||
|
||||
@@ -1,30 +1,29 @@
|
||||
# CONFIG
|
||||
# CONFIG - Load build configuration data
|
||||
#
|
||||
# Do not make changes to this file!
|
||||
|
||||
# You might want to change this to some shared set of rules, e.g.
|
||||
# RULES=/path/to/epics/support/modules/rules/x-y
|
||||
RULES=$(EPICS_BASE)
|
||||
# Allow user to override where the build rules come from
|
||||
RULES = $(EPICS_BASE)
|
||||
|
||||
# RELEASE files point to other application tops
|
||||
include $(TOP)/configure/RELEASE
|
||||
-include $(TOP)/configure/RELEASE.$(EPICS_HOST_ARCH)
|
||||
-include $(TOP)/configure/RELEASE.$(EPICS_HOST_ARCH).Common
|
||||
ifdef T_A
|
||||
-include $(TOP)/configure/RELEASE.Common.$(T_A)
|
||||
-include $(TOP)/configure/RELEASE.$(EPICS_HOST_ARCH).$(T_A)
|
||||
endif
|
||||
|
||||
CONFIG=$(RULES)/configure
|
||||
CONFIG = $(RULES)/configure
|
||||
include $(CONFIG)/CONFIG
|
||||
|
||||
# Override for definition in base
|
||||
# Override the Base definition:
|
||||
INSTALL_LOCATION = $(TOP)
|
||||
include $(TOP)/configure/CONFIG_SITE
|
||||
-include $(TOP)/configure/CONFIG_SITE.$(EPICS_HOST_ARCH)
|
||||
-include $(TOP)/configure/CONFIG_SITE.$(EPICS_HOST_ARCH).Common
|
||||
|
||||
# CONFIG_SITE files contain other build configuration settings
|
||||
include $(TOP)/configure/CONFIG_SITE
|
||||
-include $(TOP)/configure/CONFIG_SITE.$(EPICS_HOST_ARCH).Common
|
||||
ifdef T_A
|
||||
-include $(TOP)/configure/CONFIG_SITE.Common.$(T_A)
|
||||
-include $(TOP)/configure/CONFIG_SITE.$(EPICS_HOST_ARCH).$(T_A)
|
||||
|
||||
-include $(TOP)/configure/O.$(T_A)/CONFIG_APP_INCLUDE
|
||||
endif
|
||||
|
||||
|
||||
@@ -1,36 +1,30 @@
|
||||
# CONFIG_SITE
|
||||
|
||||
# Make any application-specific changes to the EPICS build
|
||||
# configuration variables in this file.
|
||||
# configuration variables in this file.
|
||||
#
|
||||
# Host/target specific settings can be specified in files named
|
||||
# CONFIG_SITE.$(EPICS_HOST_ARCH).Common
|
||||
# CONFIG_SITE.Common.$(T_A)
|
||||
# CONFIG_SITE.$(EPICS_HOST_ARCH).$(T_A)
|
||||
# CONFIG_SITE.$(EPICS_HOST_ARCH).Common
|
||||
# CONFIG_SITE.Common.$(T_A)
|
||||
# CONFIG_SITE.$(EPICS_HOST_ARCH).$(T_A)
|
||||
|
||||
# Set this when you only want to compile this application
|
||||
# for a subset of the cross-compiled target architectures
|
||||
# that Base is built for.
|
||||
#CROSS_COMPILER_TARGET_ARCHS = vxWorks-68040
|
||||
# CHECK_RELEASE controls the consistency checking of the support
|
||||
# applications pointed to by the RELEASE* files.
|
||||
# Normally CHECK_RELEASE should be set to YES.
|
||||
# Set CHECK_RELEASE to NO to disable checking completely.
|
||||
# Set CHECK_RELEASE to WARN to perform consistency checking but
|
||||
# continue building anyway if conflicts are found.
|
||||
CHECK_RELEASE = YES
|
||||
|
||||
# Set this when your IOC and the host use different paths
|
||||
# to access the application. This will be needed to boot
|
||||
# from a Microsoft FTP server or with some NFS mounts.
|
||||
# You must rebuild in the iocBoot directory for this to
|
||||
# take effect.
|
||||
#IOCS_APPL_TOP = <path to application top as seen by IOC>
|
||||
# To install files into a location other than $(TOP) define
|
||||
# INSTALL_LOCATION here.
|
||||
#INSTALL_LOCATION=</path/name/to/install/top>
|
||||
|
||||
# If you don't want to install into $(TOP) then
|
||||
# define INSTALL_LOCATION here
|
||||
#INSTALL_LOCATION=<fullpathname>
|
||||
-include $(TOP)/configure/CONFIG_SITE.local
|
||||
-include $(TOP)/../CONFIG.local
|
||||
|
||||
ifeq ($(EPICS_TEST_COVERAGE),1)
|
||||
ifdef WITH_COVERAGE
|
||||
USR_CPPFLAGS += --coverage
|
||||
USR_LDFLAGS += --coverage
|
||||
endif
|
||||
|
||||
INSTALL_INCLUDE = $(INSTALL_LOCATION)/include/pv
|
||||
USR_INCLUDES += -I $(INSTALL_LOCATION)/include
|
||||
|
||||
-include $(TOP)/configure/CONFIG_SITE.local
|
||||
-include $(TOP)/../CONFIG.local
|
||||
|
||||
@@ -2,14 +2,6 @@ TOP=..
|
||||
|
||||
include $(TOP)/configure/CONFIG
|
||||
|
||||
# CHECK_RELEASE controls the consistency checking of the support
|
||||
# applications defined in the $(TOP)/configure/RELEASE* files.
|
||||
# Normally CHECK_RELEASE should be set to YES.
|
||||
# Set CHECK_RELEASE to NO to disable checking completely.
|
||||
# Set CHECK_RELEASE to WARN to perform consistency checking,
|
||||
# but continue the build even if conflicts are found.
|
||||
CHECK_RELEASE = YES
|
||||
|
||||
TARGETS = $(CONFIG_TARGETS)
|
||||
CONFIGS += $(subst ../,,$(wildcard $(CONFIG_INSTALLS)))
|
||||
|
||||
|
||||
@@ -16,10 +16,10 @@
|
||||
|
||||
# EPICS V4 Developers: Do not edit the locations in this file!
|
||||
#
|
||||
# Create a file RELEASE.local pointing to your EPICS_BASE
|
||||
# and PVCOMMON build directories, e.g.
|
||||
# EPICS_BASE = /home/install/epics/base
|
||||
# Create a file RELEASE.local pointing to your PVCOMMON
|
||||
# and EPICS_BASE build directories, e.g.
|
||||
# PVCOMMON = /home/install/epicsV4/pvCommonCPP
|
||||
# EPICS_BASE = /home/install/epics/base
|
||||
|
||||
-include $(TOP)/configure/RELEASE.local
|
||||
-include $(TOP)/../RELEASE.local
|
||||
|
||||
1621
documentation/Doxyfile
Normal file
1621
documentation/Doxyfile
Normal file
File diff suppressed because it is too large
Load Diff
1842
documentation/pvArray.html
Normal file
1842
documentation/pvArray.html
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
179
documentation/pvDataCPPCookbook.txt
Normal file
179
documentation/pvDataCPPCookbook.txt
Normal file
@@ -0,0 +1,179 @@
|
||||
pvDataCPP cookbook
|
||||
------------------
|
||||
|
||||
|
||||
Creating introspection data interfaces
|
||||
|
||||
// create a scalar
|
||||
getFieldCreate()->createScalar(pvDouble);
|
||||
|
||||
// create a scalar array
|
||||
getFieldCreate()->createScalarArray(pvDouble);
|
||||
|
||||
// create a structure
|
||||
getFieldCreate()->createFieldBuilder()->
|
||||
setId("enum_t")->
|
||||
add("index", pvDouble)->
|
||||
addArray("choices", pvString)->
|
||||
createStructure();
|
||||
|
||||
// create a structure (cntd.)
|
||||
PVStructure::const_shared_pointer enum_t =
|
||||
getFieldCreate()->createFieldBuilder()->
|
||||
setId("enum_t")->
|
||||
add("index", pvInt)->
|
||||
addArray("choices", pvString)->
|
||||
createStructure();
|
||||
|
||||
// create a structure (cntd.)
|
||||
PVStructure::const_shared_pointer ntEnum =
|
||||
getFieldCreate()->createFieldBuilder()->
|
||||
setId("uri:ev4:nt/2012/pwd/NTEnum")->
|
||||
add("value", enum_t)->
|
||||
addNestedStructure("timeStamp")->
|
||||
setId("time_t")->
|
||||
add("secsPastEpoch", pvLong)->
|
||||
add("nanoseconds", pvInt)->
|
||||
add("userTag", pvInt)->
|
||||
endNested()->
|
||||
createStructure();
|
||||
|
||||
// create an union == same as structure
|
||||
|
||||
---
|
||||
|
||||
Creating data containers
|
||||
|
||||
// create a scalar
|
||||
PVDouble::shared_pointer doubleValue = getPVDataCreate()->createPVScalar<PVDouble>();
|
||||
|
||||
// create a scalar array
|
||||
PVDoubleArray::shared_pointer doubleArrayValue = getPVDataCreate()->createPVScalarArray<PVDouble>();
|
||||
|
||||
// create a structure
|
||||
PVStructure::shared_pointer struct = getPVDataCreate()->createPVStructure(ntEnum);
|
||||
|
||||
// create an union
|
||||
PVUnion::shared_pointer pvUnion = getPVDataCreate()->createPVUnion(unionIF);
|
||||
|
||||
// create a structure array
|
||||
PVStructureArray::shared_pointer structArray = getPVDataCreate()->createPVStructureArray(ntEnum);
|
||||
|
||||
|
||||
// scalar usage
|
||||
PVInt::shared_pointer index = struct->getSubField<PVInt>("value.index");
|
||||
int32 ix = index->get();
|
||||
index->put(3);
|
||||
std::cout << *index << std::endl;
|
||||
|
||||
|
||||
// using <<=, >>= operators to get/set
|
||||
*doubleValue <<= 12.3;
|
||||
|
||||
double val;
|
||||
*doubleValue >>= val;
|
||||
|
||||
|
||||
|
||||
// array usage
|
||||
PVStringArray::shared_pointer choices = struct->getSubField<PVStringArray>("value.choices");
|
||||
|
||||
// use view() to access read-only data
|
||||
PVStringArray::const_svector data(choices->view());
|
||||
for (std::size_t i = 0; i < data.size(); i++)
|
||||
std::cout << data[i] << std::endl;
|
||||
|
||||
// use replace() to put new data
|
||||
PVStringArray::svector newdata;
|
||||
newdata.push_back("zero");
|
||||
newdata.push_back("one");
|
||||
newdata.push_back("two");
|
||||
choices->replace(freeze(newdata));
|
||||
|
||||
// (add more use-cases) here
|
||||
|
||||
// print entire array
|
||||
std::cout << *choices << std::endl;
|
||||
|
||||
// print elmenet at index == 1
|
||||
std::cout << format::array_at(1) << *choices << std::endl;
|
||||
|
||||
----
|
||||
|
||||
Union handling
|
||||
|
||||
|
||||
Union::const_shared_pointer punion =
|
||||
getFieldCreate()->createFieldBuilder()->
|
||||
add("doubleValue", pvDouble)->
|
||||
add("intValue", pvInt)->
|
||||
createUnion();
|
||||
|
||||
PVUnion::shared_pointer u = getPVDataCreate()->createPVUnion(punion);
|
||||
|
||||
// select and put
|
||||
// this create a new instance of PVDouble (everytime select() is called)
|
||||
PVDouble::shared_pointer doubleValue = u->select<PVDouble>("doubleValue");
|
||||
doubeValue->put(12);
|
||||
// select using index (and direct put)
|
||||
u->select<PVDouble>(0)->put(12);
|
||||
// select using existing PVField (PVUnion stores by-reference)
|
||||
u->set("doubleValue", doubleValue);
|
||||
|
||||
// get selected field name or index
|
||||
std::string selectedFN = u->getSelectedFieldName();
|
||||
int32 selectedIndex = u->getSelectedIndex();
|
||||
|
||||
// get currently selected (knowing it's PVDouble)
|
||||
PVDouble value = u->get<PVDouble>();
|
||||
|
||||
|
||||
|
||||
Variant Union handling
|
||||
|
||||
|
||||
PVUnion::shared_pointer any = getPVDataCreate()->createPVVariantUnion();
|
||||
|
||||
PVDouble::shared_pointer doubleValue = getPVDataCreate()->createPVScalar<PVDouble>();
|
||||
doubleValue->put(12.8);
|
||||
any->set(doubleValue);
|
||||
|
||||
PVDouble::shared_pointer doubleValue2 = any->get<PVDouble>();
|
||||
|
||||
// variant union work by-reference (pointers match also)
|
||||
// doubleValue.get() == doubleValue2.get()
|
||||
|
||||
|
||||
|
||||
------
|
||||
|
||||
Convert
|
||||
|
||||
|
||||
// convert to int
|
||||
int32 i = doubleValue->getAs<int32>();
|
||||
|
||||
// from int
|
||||
doubleValue->putFrom<int32>(i);
|
||||
|
||||
// from string
|
||||
doubleValue->putFrom<std::string>("12.3");
|
||||
|
||||
// from scalar field
|
||||
doubleValue->assign(pvScalar);
|
||||
|
||||
|
||||
|
||||
// convert to int array
|
||||
PVIntArray::const_svector intData;
|
||||
doubleArrayValue->getAs<int32>(intData);
|
||||
|
||||
// from string array
|
||||
PVStringArray::svector labels;
|
||||
labels.push_back("zero");
|
||||
labels.push_back("one");
|
||||
labels.push_back("two");
|
||||
doubleArrayValue->putFrom<std::string>(labels);
|
||||
|
||||
// from scalar array
|
||||
doubleArrayValue->assign(pvScalarArray);
|
||||
@@ -42,11 +42,11 @@
|
||||
<dl>
|
||||
<dt>Latest version:</dt>
|
||||
<dd><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvDataCPP/raw-file/tip/documentation/pvDataCPP.html">pvDataCPP.html</a>
|
||||
href="pvDataCPP.html">pvDataCPP.html</a>
|
||||
</dd>
|
||||
<dt>This version:</dt>
|
||||
<dd><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvDataCPP/raw-file/tip/documentation/pvDataCPP_20120927.html">pvDataCPP_20120927.html</a>
|
||||
href="pvDataCPP_20120927.html">pvDataCPP_20120927.html</a>
|
||||
</dd>
|
||||
<dt>Previous version:</dt>
|
||||
<dd>None.</dd>
|
||||
@@ -65,33 +65,9 @@ license.</a></p>
|
||||
<p>pvDataCPP is a computer software package for the efficient
|
||||
storage, access, and communication, of structured data. It is specifically the
|
||||
C++ implementation of pvData, which is one part of the set of related products in the EPICS
|
||||
V4 control system programming environment:</p>
|
||||
<dl>
|
||||
<dt><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvDataCPP/raw-file/tip/documentation/pvDataCPP.html">pvData</a></dt>
|
||||
<dd>pvData (Process Variable Data) defines and implements an efficent way
|
||||
to store, access, and communicate memory resident structured data</dd>
|
||||
<dt><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvAccessCPP/raw-file/tip/documentation/pvAccessCPP.html">pvAccess</a></dt>
|
||||
<dd>pvAccess is a software library for high speed controls network communications,
|
||||
optimized for pvData</dd>
|
||||
<dt><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvIOCCPP/raw-file/tip/documentation/pvIOCCPP.html">pvIOC</a></dt>
|
||||
<dd>pvIOC is a software framework for building network accessable "smart" real time
|
||||
databases, suitable for interfacing devices in a distributed control system,
|
||||
that can exchange pvData over pvAccess.
|
||||
</dd>
|
||||
<dt><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvServiceCPP/raw-file/tip/documentation/pvAccessCPP.html">pvService</a></dt>
|
||||
<dd>A middle layer for implementing efficient data services.</dd>
|
||||
</dl>
|
||||
|
||||
<p>Each of these products has a Java and a C++ implementation.</p>
|
||||
|
||||
<p>The products are all part of the <a
|
||||
href="http://epics-pvdata.sourceforge.net/">V4</a> implementation of <a
|
||||
href="http://www.aps.anl.gov/epics/">Experimental Physics and Industrial
|
||||
Control System (EPICS).</a></p>
|
||||
V4 control system programming environment:<br />
|
||||
<a href="http://epics-pvdata.sourceforge.net/relatedDocumentsV4.html">relatedDocumentsV4.html</a>
|
||||
</p>
|
||||
|
||||
<h2 class="nocount">Status of this Document</h2>
|
||||
|
||||
|
||||
@@ -42,15 +42,15 @@
|
||||
<dl>
|
||||
<dt>Latest version:</dt>
|
||||
<dd><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvDataCPP/raw-file/tip/documentation/pvDataCPP.html">pvDataCPP.html</a>
|
||||
href="pvDataCPP.html">pvDataCPP.html</a>
|
||||
</dd>
|
||||
<dt>This version:</dt>
|
||||
<dd><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvDataCPP/raw-file/tip/documentation/pvDataCPP_20121001.html">pvDataCPP_20121001.html</a>
|
||||
href="pvDataCPP_20121001.html">pvDataCPP_20121001.html</a>
|
||||
</dd>
|
||||
<dt>Previous version:</dt>
|
||||
<dd><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvDataCPP/raw-file/tip/documentation/pvDataCPP_20120927.html">pvDataCPP_20120927.html</a>
|
||||
href="pvDataCPP_20120927.html">pvDataCPP_20120927.html</a>
|
||||
</dd>
|
||||
<dt>Editors:</dt>
|
||||
<dd>Marty Kraimer, BNL</dd>
|
||||
@@ -67,33 +67,9 @@ license.</a></p>
|
||||
<p>pvDataCPP is a computer software package for the efficient
|
||||
storage, access, and communication, of structured data. It is specifically the
|
||||
C++ implementation of pvData, which is one part of the set of related products in the EPICS
|
||||
V4 control system programming environment:</p>
|
||||
<dl>
|
||||
<dt><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvDataCPP/raw-file/tip/documentation/pvDataCPP.html">pvData</a></dt>
|
||||
<dd>pvData (Process Variable Data) defines and implements an efficent way
|
||||
to store, access, and communicate memory resident structured data</dd>
|
||||
<dt><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvAccessCPP/raw-file/tip/documentation/pvAccessCPP.html">pvAccess</a></dt>
|
||||
<dd>pvAccess is a software library for high speed controls network communications,
|
||||
optimized for pvData</dd>
|
||||
<dt><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvIOCCPP/raw-file/tip/documentation/pvIOCCPP.html">pvIOC</a></dt>
|
||||
<dd>pvIOC is a software framework for building network accessable "smart" real time
|
||||
databases, suitable for interfacing devices in a distributed control system,
|
||||
that can exchange pvData over pvAccess.
|
||||
</dd>
|
||||
<dt><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvServiceCPP/raw-file/tip/documentation/pvAccessCPP.html">pvService</a></dt>
|
||||
<dd>A middle layer for implementing efficient data services.</dd>
|
||||
</dl>
|
||||
|
||||
<p>Each of these products has a Java and a C++ implementation.</p>
|
||||
|
||||
<p>The products are all part of the <a
|
||||
href="http://epics-pvdata.sourceforge.net/">V4</a> implementation of <a
|
||||
href="http://www.aps.anl.gov/epics/">Experimental Physics and Industrial
|
||||
Control System (EPICS).</a></p>
|
||||
V4 control system programming environment:<br />
|
||||
<a href="http://epics-pvdata.sourceforge.net/relatedDocumentsV4.html">relatedDocumentsV4.html</a>
|
||||
</p>
|
||||
|
||||
<h2 class="nocount">Status of this Document</h2>
|
||||
|
||||
|
||||
@@ -42,15 +42,15 @@
|
||||
<dl>
|
||||
<dt>Latest version:</dt>
|
||||
<dd><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvDataCPP/raw-file/tip/documentation/pvDataCPP.html">pvDataCPP.html</a>
|
||||
href="pvDataCPP.html">pvDataCPP.html</a>
|
||||
</dd>
|
||||
<dt>This version:</dt>
|
||||
<dd><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvDataCPP/raw-file/tip/documentation/pvDataCPP_20121026html">pvDataCPP_20121026html</a>
|
||||
href="pvDataCPP_20121026html">pvDataCPP_20121026html</a>
|
||||
</dd>
|
||||
<dt>Previous version:</dt>
|
||||
<dd><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvDataCPP/raw-file/tip/documentation/pvDataCPP_20121001.html">pvDataCPP_20121001.html</a>
|
||||
href="pvDataCPP_20121001.html">pvDataCPP_20121001.html</a>
|
||||
</dd>
|
||||
<dt>Editors:</dt>
|
||||
<dd>Marty Kraimer, BNL</dd>
|
||||
@@ -67,33 +67,9 @@ license.</a></p>
|
||||
<p>pvDataCPP is a computer software package for the efficient
|
||||
storage, access, and communication, of structured data. It is specifically the
|
||||
C++ implementation of pvData, which is one part of the set of related products in the EPICS
|
||||
V4 control system programming environment:</p>
|
||||
<dl>
|
||||
<dt><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvDataCPP/raw-file/tip/documentation/pvDataCPP.html">pvData</a></dt>
|
||||
<dd>pvData (Process Variable Data) defines and implements an efficent way
|
||||
to store, access, and communicate memory resident structured data</dd>
|
||||
<dt><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvAccessCPP/raw-file/tip/documentation/pvAccessCPP.html">pvAccess</a></dt>
|
||||
<dd>pvAccess is a software library for high speed controls network communications,
|
||||
optimized for pvData</dd>
|
||||
<dt><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvIOCCPP/raw-file/tip/documentation/pvIOCCPP.html">pvIOC</a></dt>
|
||||
<dd>pvIOC is a software framework for building network accessable "smart" real time
|
||||
databases, suitable for interfacing devices in a distributed control system,
|
||||
that can exchange pvData over pvAccess.
|
||||
</dd>
|
||||
<dt><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvServiceCPP/raw-file/tip/documentation/pvAccessCPP.html">pvService</a></dt>
|
||||
<dd>A middle layer for implementing efficient data services.</dd>
|
||||
</dl>
|
||||
|
||||
<p>Each of these products has a Java and a C++ implementation.</p>
|
||||
|
||||
<p>The products are all part of the <a
|
||||
href="http://epics-pvdata.sourceforge.net/">V4</a> implementation of <a
|
||||
href="http://www.aps.anl.gov/epics/">Experimental Physics and Industrial
|
||||
Control System (EPICS).</a></p>
|
||||
V4 control system programming environment:<br />
|
||||
<a href="http://epics-pvdata.sourceforge.net/relatedDocumentsV4.html">relatedDocumentsV4.html</a>
|
||||
</p>
|
||||
|
||||
<h2 class="nocount">Status of this Document</h2>
|
||||
|
||||
|
||||
@@ -42,15 +42,15 @@
|
||||
<dl>
|
||||
<dt>Latest version:</dt>
|
||||
<dd><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvDataCPP/raw-file/tip/documentation/pvDataCPP.html">pvDataCPP.html</a>
|
||||
href="pvDataCPP.html">pvDataCPP.html</a>
|
||||
</dd>
|
||||
<dt>This version:</dt>
|
||||
<dd><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvDataCPP/raw-file/tip/documentation/pvDataCPP_20121212html">pvDataCPP_20121212html</a>
|
||||
href="pvDataCPP_20121212.html">pvDataCPP_20121212.html</a>
|
||||
</dd>
|
||||
<dt>Previous version:</dt>
|
||||
<dd><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvDataCPP/raw-file/tip/documentation/pvDataCPP_20121026html">pvDataCPP_20121026html</a>
|
||||
href="pvDataCPP_20121026.html">pvDataCPP_20121026.html</a>
|
||||
</dd>
|
||||
<dt>Editors:</dt>
|
||||
<dd>Marty Kraimer, BNL</dd>
|
||||
@@ -67,33 +67,9 @@ license.</a></p>
|
||||
<p>pvDataCPP is a computer software package for the efficient
|
||||
storage, access, and communication, of structured data. It is specifically the
|
||||
C++ implementation of pvData, which is one part of the set of related products in the EPICS
|
||||
V4 control system programming environment:</p>
|
||||
<dl>
|
||||
<dt><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvDataCPP/raw-file/tip/documentation/pvDataCPP.html">pvData</a></dt>
|
||||
<dd>pvData (Process Variable Data) defines and implements an efficent way
|
||||
to store, access, and communicate memory resident structured data</dd>
|
||||
<dt><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvAccessCPP/raw-file/tip/documentation/pvAccessCPP.html">pvAccess</a></dt>
|
||||
<dd>pvAccess is a software library for high speed controls network communications,
|
||||
optimized for pvData</dd>
|
||||
<dt><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvIOCCPP/raw-file/tip/documentation/pvIOCCPP.html">pvIOC</a></dt>
|
||||
<dd>pvIOC is a software framework for building network accessable "smart" real time
|
||||
databases, suitable for interfacing devices in a distributed control system,
|
||||
that can exchange pvData over pvAccess.
|
||||
</dd>
|
||||
<dt><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvServiceCPP/raw-file/tip/documentation/pvAccessCPP.html">pvService</a></dt>
|
||||
<dd>A middle layer for implementing efficient data services.</dd>
|
||||
</dl>
|
||||
|
||||
<p>Each of these products has a Java and a C++ implementation.</p>
|
||||
|
||||
<p>The products are all part of the <a
|
||||
href="http://epics-pvdata.sourceforge.net/">V4</a> implementation of <a
|
||||
href="http://www.aps.anl.gov/epics/">Experimental Physics and Industrial
|
||||
Control System (EPICS).</a></p>
|
||||
V4 control system programming environment:<br />
|
||||
<a href="http://epics-pvdata.sourceforge.net/relatedDocumentsV4.html">relatedDocumentsV4.html</a>
|
||||
</p>
|
||||
|
||||
<h2 class="nocount">Status of this Document</h2>
|
||||
|
||||
|
||||
@@ -42,15 +42,15 @@
|
||||
<dl>
|
||||
<dt>Latest version:</dt>
|
||||
<dd><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvDataCPP/raw-file/tip/documentation/pvDataCPP.html">pvDataCPP.html</a>
|
||||
href="pvDataCPP.html">pvDataCPP.html</a>
|
||||
</dd>
|
||||
<dt>This version:</dt>
|
||||
<dd><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvDataCPP/raw-file/tip/documentation/pvDataCPP_20130516.html">pvDataCPP_20130516.html</a>
|
||||
href="pvDataCPP_20130516.html">pvDataCPP_20130516.html</a>
|
||||
</dd>
|
||||
<dt>Previous version:</dt>
|
||||
<dd><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvDataCPP/raw-file/tip/documentation/pvDataCPP_20121212.html">pvDataCPP_20121212.html</a>
|
||||
href="pvDataCPP_20121212.html">pvDataCPP_20121212.html</a>
|
||||
</dd>
|
||||
<dt>Editors:</dt>
|
||||
<dd>Marty Kraimer, BNL</dd>
|
||||
@@ -67,33 +67,10 @@ license.</a></p>
|
||||
<p>pvDataCPP is a computer software package for the efficient
|
||||
storage, access, and communication, of structured data. It is specifically the
|
||||
C++ implementation of pvData, which is one part of the set of related products in the EPICS
|
||||
V4 control system programming environment:</p>
|
||||
<dl>
|
||||
<dt><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvDataCPP/raw-file/tip/documentation/pvDataCPP.html">pvData</a></dt>
|
||||
<dd>pvData (Process Variable Data) defines and implements an efficent way
|
||||
to store, access, and communicate memory resident structured data</dd>
|
||||
<dt><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvAccessCPP/raw-file/tip/documentation/pvAccessCPP.html">pvAccess</a></dt>
|
||||
<dd>pvAccess is a software library for high speed controls network communications,
|
||||
optimized for pvData</dd>
|
||||
<dt><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvIOCCPP/raw-file/tip/documentation/pvIOCCPP.html">pvIOC</a></dt>
|
||||
<dd>pvIOC is a software framework for building network accessable "smart" real time
|
||||
databases, suitable for interfacing devices in a distributed control system,
|
||||
that can exchange pvData over pvAccess.
|
||||
</dd>
|
||||
<dt><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvServiceCPP/raw-file/tip/documentation/pvAccessCPP.html">pvService</a></dt>
|
||||
<dd>A middle layer for implementing efficient data services.</dd>
|
||||
</dl>
|
||||
V4 control system programming environment:<br />
|
||||
<a href="http://epics-pvdata.sourceforge.net/relatedDocumentsV4.html">relatedDocumentsV4.html</a>
|
||||
</p>
|
||||
|
||||
<p>Each of these products has a Java and a C++ implementation.</p>
|
||||
|
||||
<p>The products are all part of the <a
|
||||
href="http://epics-pvdata.sourceforge.net/">V4</a> implementation of <a
|
||||
href="http://www.aps.anl.gov/epics/">Experimental Physics and Industrial
|
||||
Control System (EPICS).</a></p>
|
||||
|
||||
<h2 class="nocount">Status of this Document</h2>
|
||||
|
||||
|
||||
792
documentation/pvDataDiscussion.html
Normal file
792
documentation/pvDataDiscussion.html
Normal file
@@ -0,0 +1,792 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
|
||||
<title>EPICS pvDataDiscussion</title>
|
||||
<link rel="stylesheet" type="text/css"
|
||||
href="http://epics-pvdata.sourceforge.net/base.css" />
|
||||
<link rel="stylesheet" type="text/css"
|
||||
href="http://epics-pvdata.sourceforge.net/epicsv4.css" />
|
||||
<style type="text/css">
|
||||
/*<![CDATA[*/
|
||||
.about { margin-left: 3em; margin-right: 3em; font-size: .83em}
|
||||
table { margin-left: auto; margin-right: auto }
|
||||
.diagram { text-align: center; margin: 2.5em 0 }
|
||||
span.opt { color: grey }
|
||||
span.nterm { font-style:italic }
|
||||
span.term { font-family:courier }
|
||||
span.user { font-family:courier }
|
||||
span.user:before { content:"<" }
|
||||
span.user:after { content:">" }
|
||||
.nonnorm { font-style:italic }
|
||||
p.ed { color: #AA0000 }
|
||||
span.ed { color: #AA0000 }
|
||||
p.ed.priv { display: inline; }
|
||||
span.ed.priv { display: inline; }
|
||||
/*]]>*/</style>
|
||||
<!-- Script that generates the Table of Contents -->
|
||||
<script type="text/javascript"
|
||||
src="http://epics-pvdata.sourceforge.net/script/tocgen.js">
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="head">
|
||||
<h1>EPICS pvDataDiscussion</h1>
|
||||
<!-- Maturity: Working Draft or Request for Comments, or Recommendation, and date. -->
|
||||
|
||||
<h2 class="nocount">EPICS v4 Working Group, Working Draft, 03-Jul-2013</h2>
|
||||
|
||||
<dl>
|
||||
<dt>Latest version:</dt>
|
||||
<dd><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvDataCPP/raw-file/tip/documentation/pvDataDiscussion.html">pvDataDiscussion.html</a>
|
||||
</dd>
|
||||
<dt>This version:</dt>
|
||||
<dd>none</dd>
|
||||
<dt>Previous version:</dt>
|
||||
<dd>None</dd>
|
||||
<dt>Editors:</dt>
|
||||
<dd>Marty Kraimer, BNL<dd />
|
||||
</dl>
|
||||
|
||||
<p class="copyright">This product is made available subject to acceptance of the <a
|
||||
href="http://epics-pvdata.sourceforge.net/LICENSE.html">EPICS open source
|
||||
license.</a></p>
|
||||
<hr />
|
||||
</div>
|
||||
|
||||
|
||||
<div id="toc">
|
||||
<h2 class="nocount" style="page-break-before: always">Table of Contents</h2>
|
||||
</div>
|
||||
<div id="contents" class="contents">
|
||||
|
||||
|
||||
<h2>Introduction</h2>
|
||||
<p>As pvDataCPP progressed PVField and derived classes accumulated
|
||||
more and more member functions.
|
||||
These member functions have nothing to do with the primary primary
|
||||
purpose for pvData:
|
||||
<blockquote>pvData (Process Variable Data) defines and implements an efficent
|
||||
way to store, access, and communicate memory resident data structures.</blockquote>
|
||||
This statement appears as the first sentence of pvDataJava.html.
|
||||
A few sentances later the document makes it clear that communication
|
||||
includes efficent network communication.
|
||||
Thus pvData provides an interface for network accessible structured data.
|
||||
The problem of adding member functions that have nothing to do with the primary purpose
|
||||
started with the Java API.
|
||||
It already had extra methods that solved problems that should have had a different solution.
|
||||
This document removes the extra methods so that when new problems arise in the future
|
||||
the solution will not involve adding new member functions to the introspection and data API.
|
||||
</p>
|
||||
<p>The introspection and data API for pvData should only encapuslate methods that support the primary purpose
|
||||
stated above.
|
||||
The interfaces for C++ and Java should be similar so that
|
||||
someone who understands the interface in one of the languages
|
||||
and knows both languages will quickly understand the interface of the other language.</p>
|
||||
<p>There is another problem with the existing API. There are methods that allow the "structure"
|
||||
to change after an pvData object is created. An example is PVField::renameField(String newName).
|
||||
Such methods should not exist.</p>
|
||||
<p>There are methods regarding immutability: setImmutable, isImmutablei, setCapacityMutable, and isCapacityMutable.
|
||||
Should they exists? For now lets assume no.
|
||||
</p>
|
||||
<p>One last issue is the interface for array data. This document proposes a simplified
|
||||
version of what currently exists. It requires that the implementation always provides storage for
|
||||
the complete raw array. The existing APIs allow the implementation to provide the data in
|
||||
"chunks". Giving up this requirement simplifies the array interfaces.
|
||||
The existing C++ implementation of PVValueArray has serious problems.
|
||||
The shared_vector that is implemented in pvDataCP-md provides the solution to fixing
|
||||
the problems. This document describes an API that is very similar to the new Java API
|
||||
except that raw arrays are replaced by shared_vector.</p>
|
||||
<p>This document will first describe changes to the existing Java interfaces
|
||||
and then the corresponding C++ API.</p>
|
||||
<h2>Java API</h2>
|
||||
<p>The following shows which methods will be removed from the existing interfaces
|
||||
and what will be added.
|
||||
The methods to be removed are in <font color = "red">red</font>
|
||||
and methods to add are in <font color = "blue">blue</font>
|
||||
Also the removed methods are at the end with a comment above.
|
||||
The new methods also have a comment.
|
||||
</p>
|
||||
<h3>Introspection Interfaces</h3>
|
||||
|
||||
<pre>interface Field extends Serializable {
|
||||
String getId();
|
||||
Type getType();
|
||||
// following will be removed
|
||||
<font color = "red">void toString(StringBuilder buf);</font>
|
||||
<font color = "red">void toString(StringBuilder buf,int indentLevel);</font>
|
||||
<font color = "red">String toString();</font>
|
||||
}
|
||||
|
||||
<font color = "blue">
|
||||
// new interface
|
||||
interface FieldToString {
|
||||
String toString(Field field);
|
||||
}</font>
|
||||
|
||||
interface Scalar extends Field {
|
||||
ScalarType getScalarType();
|
||||
}
|
||||
|
||||
interface ScalarArray extends Field {
|
||||
ScalarType getElementType();
|
||||
}
|
||||
|
||||
interface Structure extends Field {
|
||||
Field getField(String fieldName);
|
||||
int getFieldIndex(String fieldName);
|
||||
Field[] getFields();
|
||||
Field getField(int fieldIndex);
|
||||
String[] getFieldNames();
|
||||
String getFieldName(int fieldIndex)
|
||||
}
|
||||
|
||||
interface StructureArray extends Field {
|
||||
Structure getStructure();
|
||||
}
|
||||
|
||||
interface FieldCreate {
|
||||
Scalar createScalar(ScalarType scalarType);
|
||||
ScalarArray createScalarArray(ScalarType elementType);
|
||||
StructureArray createStructureArray(Structure elementStructure);
|
||||
Structure createStructure(String[] fieldNames, Field[] field);
|
||||
Structure createStructure(String id,String[] fieldNames, Field[] field);
|
||||
Structure createStructure(Structure structToClone);
|
||||
Field deserialize(ByteBuffer buffer, DeserializableControl control);
|
||||
// following will be removed
|
||||
<font color = "red">Structure appendField(Structure structure,String fieldName, Field field);</font>
|
||||
<font color = "red">Structure appendFields(Structure structure,String[] fieldNames, Field[] fields);</font>
|
||||
}
|
||||
</pre>
|
||||
<h3>Data Interfaces</h3>
|
||||
<pre>
|
||||
interface PVField extends Requester, Serializable {
|
||||
String getFieldName();
|
||||
void setRequester(Requester requester);
|
||||
int getFieldOffset();
|
||||
int getNextFieldOffset();
|
||||
int getNumberFields();
|
||||
Field getField();
|
||||
PVStructure getParent();
|
||||
void postPut();
|
||||
void setPostHandler(PostHandler postHandler);
|
||||
// following will be removed
|
||||
<font color = "red">PVAuxInfo getPVAuxInfo();</font>
|
||||
<font color = "red">boolean isImmutable();</font>
|
||||
<font color = "red">void setImmutable();</font>
|
||||
<font color = "red">void renameField(String newName);</font>
|
||||
<font color = "red">void toString(StringBuilder buf);</font>
|
||||
<font color = "red">void toString(StringBuilder buf,int indentLevel);</font>
|
||||
<font color = "red">String toString();</font>
|
||||
}
|
||||
|
||||
<font color = "blue">
|
||||
// The following is a new interface
|
||||
interface PVFieldToString {
|
||||
String toString(PVField pvField);
|
||||
void setMaxInitialArrayElements(int num);
|
||||
void setMaxFinalArrayElements(int num);
|
||||
int getMaxInitialArrayElements();
|
||||
int getMaxFinalArrayElements();
|
||||
}</font>
|
||||
|
||||
interface PVScalar extends PVField{
|
||||
Scalar getScalar();
|
||||
}
|
||||
|
||||
interface PVDouble extends PVScalar{
|
||||
double get();
|
||||
void put(double value);
|
||||
}
|
||||
// also PVBoolean, PVByte, PVShort, PVInt, PVLong, PVFloat, and PVString
|
||||
|
||||
interface PVArray extends PVField, SerializableArray {
|
||||
int getLength();
|
||||
void setLength(int length);
|
||||
int getCapacity();
|
||||
void setCapacity(int length);
|
||||
// following will be removed
|
||||
<font color = "red">boolean isCapacityMutable();</font>
|
||||
<font color = "red">void setCapacityMutable(boolean isMutable);</font>
|
||||
}
|
||||
|
||||
interface PVScalarArray extends PVArray {
|
||||
ScalarArray getScalarArray();
|
||||
}
|
||||
|
||||
<font color = "red">
|
||||
//following will be removed
|
||||
public class DoubleArrayData {
|
||||
public double[] data;
|
||||
public int offset;
|
||||
}</font>
|
||||
|
||||
interface PVDoubleArray extends PVArray {
|
||||
// following are new
|
||||
<font color = "blue"> double[] get();</font>
|
||||
<font color = "blue"> void swap(double[] value);</font>
|
||||
//following will be removed
|
||||
<font color = "red"> int get(int offset, int len, DoubleArrayData data);</font>
|
||||
<font color = "red"> int put(int offset,int len, double[] from, int fromOffset)</font>;
|
||||
<font color = "red"> void shareData(double[] from);</font>
|
||||
}
|
||||
|
||||
// also PVBooleanArray, ..., PVStringArray
|
||||
|
||||
|
||||
interface PVStructure extends PVField , BitSetSerializable{
|
||||
Structure getStructure();
|
||||
PVField[] getPVFields();
|
||||
PVField getSubField(String fieldName);
|
||||
PVField getSubField(int fieldOffset);
|
||||
// The following are convenience methods
|
||||
PVBoolean getBooleanField(String fieldName);
|
||||
PVByte getByteField(String fieldName);
|
||||
PVShort getShortField(String fieldName);
|
||||
PVInt getIntField(String fieldName);
|
||||
PVLong getLongField(String fieldName);
|
||||
PVFloat getFloatField(String fieldName);
|
||||
PVDouble getDoubleField(String fieldName);
|
||||
PVString getStringField(String fieldName);
|
||||
PVScalarArray getScalarArrayField(String fieldName);
|
||||
PVStructureArray getStructureArrayField(String fieldName);
|
||||
PVStructure getStructureField(String fieldName);
|
||||
PVArray getArrayField(String fieldName,ScalarType elementType);
|
||||
// following will be removed
|
||||
<font color = "red"> void appendPVField(String fieldName,PVField pvField);</font>
|
||||
<font color = "red"> void appendPVFields(String[] fieldNames,PVField[] pvFields);</font>
|
||||
<font color = "red"> void removePVField(String fieldName);</font>
|
||||
<font color = "red"> void replacePVField(PVField oldPVField,PVField newPVField);</font>
|
||||
<font color = "red"> String getExtendsStructureName();</font>
|
||||
<font color = "red"> boolean putExtendsStructureName(String extendsStructureName);</font>
|
||||
<font color = "red"> public boolean checkValid();</font>
|
||||
}
|
||||
|
||||
<font color = "red">
|
||||
//following will be removed
|
||||
public class StructureArrayData {
|
||||
public PVStructure[] data;
|
||||
public int offset;
|
||||
}
|
||||
</font>
|
||||
|
||||
interface PVStructureArray extends PVArray{
|
||||
StructureArray getStructureArray();
|
||||
// following are new
|
||||
<font color = "blue"> PVStructure[] get();</font>
|
||||
<font color = "blue"> void swap(PVStructure[] value);</font>
|
||||
// following will be removed
|
||||
<font color = "red"> int get(int offset, int length, StructureArrayData data);</font>
|
||||
<font color = "red"> int put(int offset,int length, PVStructure[] from, int fromOffset);</font>
|
||||
<font color = "red"> void shareData(PVStructure[] from);</font>
|
||||
}
|
||||
|
||||
|
||||
public interface PVDataCreate {
|
||||
PVField createPVField(Field field);
|
||||
PVField createPVField(PVField fieldToClone);
|
||||
PVScalar createPVScalar(Scalar scalar);
|
||||
PVScalar createPVScalar(ScalarType fieldType);
|
||||
PVScalar createPVScalar(PVScalar scalarToClone);
|
||||
PVScalarArray createPVScalarArray(ScalarArray array);
|
||||
PVScalarArray createPVScalarArray(ScalarType elementType);
|
||||
PVScalarArray createPVScalarArray(PVScalarArray arrayToClone;
|
||||
PVStructureArray createPVStructureArray(StructureArray structureArray);
|
||||
PVStructure createPVStructure(Structure structure);
|
||||
PVStructure createPVStructure(String[] fieldNames,Field[] fields);
|
||||
PVStructure createPVStructure(PVStructure structToClone);
|
||||
// following will be removed
|
||||
<font color = "red">PVField[] flattenPVStructure(PVStructure pvStructure);</font>
|
||||
}
|
||||
</pre>
|
||||
<h3>PVFieldToString</h3>
|
||||
<p>In addition to toString this has methods to limit the number of array element to display.
|
||||
The existing Java implementation of toString displayed all elements.
|
||||
For large arrays this is not desirable.
|
||||
The new methods provide a way for the client to limit the number of elements.
|
||||
The default might be set to something like display up to 10 elements with 5 fron the beginning and 5 from the end.</p>
|
||||
<p>For C++ this can be a replacement for dumpValue.</p>
|
||||
<h3>PVBooleanArray, ..., PVStructureArray</h3>
|
||||
<p>The old get and put are replaced by two new and simpler methods:
|
||||
<dl>
|
||||
<dt>get</dt>
|
||||
<dd>Returns the raw array. If the client code modifies the elements in the array then
|
||||
the client must call postPut. The client also has to realize that if the raw array held by the PVXXXArray changes
|
||||
then the client is no longer sharing data
|
||||
<dt>swap</dt>
|
||||
<dd>This exchanges the old raw data with the new raw data.</dd>
|
||||
</dl>
|
||||
</p>
|
||||
<p>
|
||||
The method <b>setCapacity</b> will always create a new raw array and copy old data from the old to the new array.
|
||||
This is not true now since the implementation does not create a new array if the old capacity is equal to the requested capacity.
|
||||
</p>
|
||||
<h2>C++ API</h2>
|
||||
<p>The C++ class definitions are similar to the Java definitions with two main exceptions:
|
||||
<dl>
|
||||
<dt>toString</dt>
|
||||
<dd>In c++ this is replaced by std::ostream.</dd>
|
||||
<dt>raw array data</dt>
|
||||
<dd>Java supports array data like <b>double[]</b>
|
||||
The C++ replacement is shared_vector<double>, which is implemented
|
||||
in pvDataCPP-md.</dd
|
||||
</dl>
|
||||
<h3>Introspection Interfaces</h3>
|
||||
|
||||
<pre>
|
||||
class Field :
|
||||
virtual public Serializable,
|
||||
public std::tr1::enable_shared_from_this<Field>
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(Field);
|
||||
virtual ~Field();
|
||||
Type getType() const{return m_type;}
|
||||
virtual String getID() const = 0;
|
||||
<font color = "red">
|
||||
// following will be removed
|
||||
virtual void toString(StringBuilder buf) const{toString(buf,0);}
|
||||
virtual void toString(StringBuilder buf,int indentLevel) const;
|
||||
</font>
|
||||
...
|
||||
};
|
||||
<font color = "blue">
|
||||
// new function
|
||||
std::ostream &toString(Field::const_reference field, std::ostream& o);
|
||||
</font>
|
||||
|
||||
class Scalar : public Field{
|
||||
public:
|
||||
POINTER_DEFINITIONS(Scalar);
|
||||
virtual ~Scalar();
|
||||
typedef Scalar& reference;
|
||||
typedef const Scalar& const_reference;
|
||||
|
||||
ScalarType getScalarType() const {return scalarType;}
|
||||
virtual void serialize(ByteBuffer *buffer, SerializableControl *control) const;
|
||||
virtual void deserialize(ByteBuffer *buffer, DeserializableContol *control);
|
||||
<font color = "red">
|
||||
// following will be removed
|
||||
virtual void toString(StringBuilder buf) const{toString(buf,0);}
|
||||
virtual void toString(StringBuilder buf,int indentLevel) const;
|
||||
virtual String getID() const;
|
||||
</font>
|
||||
...
|
||||
};
|
||||
class ScalarArray : public Field{
|
||||
public:
|
||||
POINTER_DEFINITIONS(ScalarArray);
|
||||
typedef ScalarArray& reference;
|
||||
typedef const ScalarArray& const_reference;
|
||||
|
||||
ScalarArray(ScalarType scalarType);
|
||||
ScalarType getElementType() const {return elementType;}
|
||||
virtual void serialize(ByteBuffer *buffer, SerializableControl *control) const;
|
||||
virtual void deserialize(ByteBuffer *buffer, DeserializableControl *control);
|
||||
<font color = "red">
|
||||
// following will be removed
|
||||
virtual void toString(StringBuilder buf) const{toString(buf,0);}
|
||||
virtual void toString(StringBuilder buf,int indentLevel) const;
|
||||
virtual String getID() const;
|
||||
</font>
|
||||
...
|
||||
};
|
||||
|
||||
class Structure : public Field {
|
||||
public:
|
||||
POINTER_DEFINITIONS(Structure);
|
||||
typedef Structure& reference;
|
||||
typedef const Structure& const_reference;
|
||||
|
||||
std::size_t getNumberFields() const {return numberFields;}
|
||||
FieldConstPtr getField(String const & fieldName) const;
|
||||
FieldConstPtr getField(std::size_t index) const;
|
||||
std::size_t getFieldIndex(String const &fieldName) const;
|
||||
FieldConstPtrArray const & getFields() const {return fields;}
|
||||
StringArray const & getFieldNames() const;
|
||||
String getFieldName(std::size_t fieldIndex);
|
||||
virtual void serialize(ByteBuffer *buffer, SerializableControl *control) const;
|
||||
virtual void deserialize(ByteBuffer *buffer, DeserializableControl *control);
|
||||
<font color = "red">
|
||||
// following will be removed
|
||||
void renameField(std::size_t fieldIndex,String const &newName);
|
||||
virtual void toString(StringBuilder buf,int indentLevel) const;
|
||||
virtual String getID() const;
|
||||
</font>
|
||||
...
|
||||
};
|
||||
|
||||
class StructureArray : public Field{
|
||||
public:
|
||||
POINTER_DEFINITIONS(StructureArray);
|
||||
typedef StructureArray& reference;
|
||||
typedef const StructureArray& const_reference;
|
||||
|
||||
StructureConstPtr getStructure() const {return pstructure;}
|
||||
virtual void serialize(ByteBuffer *buffer, SerializableControl *control) const;
|
||||
virtual void deserialize(ByteBuffer *buffer, DeserializableControl *control);
|
||||
<font color = "red">
|
||||
// following will be removed
|
||||
virtual void toString(StringBuilder buf,int indentLevel=0) const;
|
||||
virtual String getID() const;
|
||||
</font>
|
||||
...
|
||||
};
|
||||
|
||||
class FieldCreate {
|
||||
public:
|
||||
static FieldCreatePtr getFieldCreate();
|
||||
ScalarConstPtr createScalar(ScalarType scalarType) const
|
||||
ScalarArrayConstPtr createScalarArray(ScalarType elementType) const;
|
||||
StructureArrayConstPtr createStructureArray(StructureConstPtr const & structure) const;
|
||||
StructureConstPtr createStructure (
|
||||
StringArray const & fieldNames,
|
||||
FieldConstPtrArray const & fields) const;
|
||||
StructureConstPtr createStructure (
|
||||
String const &id,
|
||||
StringArray const & fieldNames,
|
||||
FieldConstPtrArray const & fields) const;
|
||||
FieldConstPtr deserialize(ByteBuffer* buffer, DeserializableControl* control) const;
|
||||
<font color = "red">
|
||||
// following will be removed
|
||||
StructureConstPtr appendField(
|
||||
StructureConstPtr const & structure,
|
||||
String const &fieldName, FieldConstPtr const & field) const;
|
||||
StructureConstPtr appendFields(
|
||||
StructureConstPtr const & structure,
|
||||
StringArray const & fieldNames,
|
||||
FieldConstPtrArray const & fields) const;
|
||||
</font>
|
||||
...
|
||||
};
|
||||
|
||||
extern FieldCreatePtr getFieldCreate();
|
||||
</pre>
|
||||
<h3>Data Interfaces</h3>
|
||||
<pre>
|
||||
class PVField
|
||||
: virtual public Serializable,
|
||||
public std::tr1::enable_shared_from_this<PVField>
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(PVField);
|
||||
virtual ~PVField();
|
||||
inline const String &getFieldName() const ;
|
||||
virtual void setRequester(RequesterPtr const &prequester);
|
||||
std::size_t getFieldOffset() const;
|
||||
std::size_t getNextFieldOffset() const;
|
||||
std::size_t getNumberFields() const;
|
||||
const FieldConstPtr & getField() const ;
|
||||
PVStructure * getParent() const
|
||||
void postPut() ;
|
||||
void setPostHandler(PostHandlerPtr const &postHandler);
|
||||
// following will be removed
|
||||
<font color = "red">
|
||||
virtual void message(String message,MessageType messageType);
|
||||
void replacePVField(const PVFieldPtr& newPVField);
|
||||
String getFullName() const;
|
||||
virtual bool equals(PVField &pv);
|
||||
PVAuxInfoPtr & getPVAuxInfo()
|
||||
bool isImmutable() const;
|
||||
virtual void setImmutable();
|
||||
void replacePVField(const PVFieldPtr& newPVField);
|
||||
void renameField(String const &newName);
|
||||
virtual void toString(StringBuilder buf) ;
|
||||
virtual void toString(StringBuilder buf,int indentLevel);
|
||||
std::ostream& dumpValue(std::ostream& o) const;
|
||||
</font>
|
||||
...
|
||||
};
|
||||
|
||||
<font color = "blue">
|
||||
// The following is a new class
|
||||
class PVFieldToString {
|
||||
String toString(const PVFieldPtr &pvField);
|
||||
void setMaxInitialArrayElements(size_t num);
|
||||
void setMaxFinalArrayElements(size_t num);
|
||||
size_t getMaxInitialArrayElements();
|
||||
size_t getMaxFinalArrayElements();
|
||||
...
|
||||
}</font>
|
||||
|
||||
class PVScalar : public PVField {
|
||||
public:
|
||||
POINTER_DEFINITIONS(PVScalar);
|
||||
virtual ~PVScalar();
|
||||
typedef PVScalar &reference;
|
||||
typedef const PVScalar& const_reference;
|
||||
|
||||
const ScalarConstPtr getScalar() const ;
|
||||
...
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
class PVScalarValue : public PVScalar {
|
||||
public:
|
||||
POINTER_DEFINITIONS(PVScalarValue);
|
||||
typedef T value_type;
|
||||
typedef T* pointer;
|
||||
typedef const T* const_pointer;
|
||||
|
||||
virtual ~PVScalarValue() {}
|
||||
virtual T get() const = 0;
|
||||
virtual void put(T value) = 0;
|
||||
<font color = "red">
|
||||
// following will be removed
|
||||
std::ostream& dumpValue(std::ostream& o)
|
||||
void operator>>=(T& value) const;
|
||||
void operator<<=(T value);
|
||||
</font>
|
||||
...
|
||||
}
|
||||
|
||||
// PVString is special case, since it implements SerializableArray
|
||||
class PVString : public PVScalarValue<String>, SerializableArray {
|
||||
public:
|
||||
virtual ~PVString() {}
|
||||
...
|
||||
}
|
||||
class PVArray : public PVField, public SerializableArray {
|
||||
public:
|
||||
POINTER_DEFINITIONS(PVArray);
|
||||
virtual ~PVArray();
|
||||
std::size_t getLength() const;
|
||||
virtual void setLength(std::size_t length);
|
||||
std::size_t getCapacity() const;
|
||||
virtual void setCapacity(std::size_t capacity) = 0;
|
||||
<font color = "red">
|
||||
// following will be removed
|
||||
virtual void setImmutable();
|
||||
bool isCapacityMutable() const;
|
||||
void setCapacityMutable(bool isMutable);
|
||||
virtual std::ostream& dumpValue(std::ostream& o, std::size_t index) const = 0;
|
||||
</font>
|
||||
...
|
||||
};
|
||||
|
||||
class PVScalarArray : public PVArray {
|
||||
public:
|
||||
POINTER_DEFINITIONS(PVScalarArray);
|
||||
virtual ~PVScalarArray();
|
||||
typedef PVScalarArray &reference;
|
||||
typedef const PVScalarArray& const_reference;
|
||||
|
||||
const ScalarArrayConstPtr getScalarArray() const ;
|
||||
<font color = "red">
|
||||
// following will be removed
|
||||
virtual std::ostream& dumpValue(std::ostream& o, size_t index) const = 0;
|
||||
</font>
|
||||
...
|
||||
}
|
||||
|
||||
<font color = "red">
|
||||
// following will be removed
|
||||
template<typename T>
|
||||
class PVArrayData {
|
||||
private:
|
||||
std::vector<T> init;
|
||||
public:
|
||||
POINTER_DEFINITIONS(PVArrayData);
|
||||
typedef T value_type;
|
||||
typedef T* pointer;
|
||||
typedef const T* const_pointer;
|
||||
std::vector<T> & data;
|
||||
std::size_t offset;
|
||||
PVArrayData()
|
||||
: data(init)
|
||||
{}
|
||||
};
|
||||
</font>
|
||||
|
||||
template<typename T>
|
||||
class PVValueArray : public PVScalarArray {
|
||||
public:
|
||||
POINTER_DEFINITIONS(PVValueArray);
|
||||
typedef T value_type;
|
||||
typedef T* pointer;
|
||||
typedef const T* const_pointer;
|
||||
// following are new typeDefs
|
||||
<font color = "blue">typedef shared_vector<T> svector;</font>
|
||||
<font color = "blue">typedef shared_vector<const T> const_svector; </font>
|
||||
|
||||
virtual ~PVValueArray() {}
|
||||
// following are added
|
||||
<font color = "blue">svector get();</font>
|
||||
<font color = "blue">void swap(svector& value);</font>
|
||||
<font color = "red">
|
||||
// following are removed
|
||||
typedef PVValueArray & reference;
|
||||
typedef const PVValueArray & const_reference;
|
||||
typedef PVArrayData<T> ArrayDataType;
|
||||
typedef std::vector<T> vector;
|
||||
typedef const std::vector<T> const_vector;
|
||||
typedef std::tr1::shared_ptr<vector> shared_vector;
|
||||
|
||||
virtual std::size_t get(
|
||||
std::size_t offset, std::size_t length, ArrayDataType &data) = 0;
|
||||
virtual std::size_t put(std::size_t offset,
|
||||
std::size_t length, const_pointer from, std::size_t fromOffset) = 0;
|
||||
virtual std::size_t put(std::size_t offset,
|
||||
std::size_t length, const_vector &from, std::size_t fromOffset);
|
||||
virtual void shareData(
|
||||
shared_vector const & value,
|
||||
std::size_t capacity,
|
||||
std::size_t length) = 0;
|
||||
virtual pointer get() = 0;
|
||||
virtual pointer get() const = 0;
|
||||
virtual vector const & getVector() = 0;
|
||||
virtual shared_vector const & getSharedVector() = 0;
|
||||
std::ostream& dumpValue(std::ostream& o) const;
|
||||
std::ostream& dumpValue(std::ostream& o, size_t index) const;
|
||||
</font>
|
||||
...
|
||||
};
|
||||
|
||||
typedef PVValueArray<uint8> PVBooleanArray;
|
||||
typedef std::tr1::shared_ptr<PVBooleanArray> PVBooleanArrayPtr;
|
||||
...
|
||||
typedef PVValueArray<String> PVStringArray;
|
||||
typedef std::tr1::shared_ptr<PVStringArray> PVStringArrayPtr;
|
||||
|
||||
class PVStructure : public PVField,public BitSetSerializable {
|
||||
public:
|
||||
POINTER_DEFINITIONS(PVStructure);
|
||||
virtual ~PVStructure();
|
||||
typedef PVStructure & reference;
|
||||
typedef const PVStructure & const_reference;
|
||||
|
||||
StructureConstPtr getStructure() const;
|
||||
const PVFieldPtrArray & getPVFields() const;
|
||||
PVFieldPtr getSubField(String const &fieldName) const;
|
||||
PVFieldPtr getSubField(std::size_t fieldOffset) const;
|
||||
PVBooleanPtr getBooleanField(String const &fieldName) ;
|
||||
PVBytePtr getByteField(String const &fieldName) ;
|
||||
PVShortPtr getShortField(String const &fieldName) ;
|
||||
PVIntPtr getIntField(String const &fieldName) ;
|
||||
PVLongPtr getLongField(String const &fieldName) ;
|
||||
PVUBytePtr getUByteField(String const &fieldName) ;
|
||||
PVUShortPtr getUShortField(String const &fieldName) ;
|
||||
PVUIntPtr getUIntField(String const &fieldName) ;
|
||||
PVULongPtr getULongField(String const &fieldName) ;
|
||||
PVFloatPtr getFloatField(String const &fieldName) ;
|
||||
PVDoublePtr getDoubleField(String const &fieldName) ;
|
||||
PVStringPtr getStringField(String const &fieldName) ;
|
||||
PVStructurePtr getStructureField(String const &fieldName) ;
|
||||
PVScalarArrayPtr getScalarArrayField(
|
||||
String const &fieldName,ScalarType elementType) ;
|
||||
PVStructureArrayPtr getStructureArrayField(String const &fieldName) ;
|
||||
virtual void serialize(
|
||||
ByteBuffer *pbuffer,SerializableControl *pflusher) const ;
|
||||
virtual void deserialize(
|
||||
ByteBuffer *pbuffer,DeserializableControl *pflusher);
|
||||
virtual void serialize(ByteBuffer *pbuffer,
|
||||
SerializableControl *pflusher,BitSet *pbitSet) const;
|
||||
virtual void deserialize(ByteBuffer *pbuffer,
|
||||
DeserializableControl*pflusher,BitSet *pbitSet);
|
||||
PVStructure(StructureConstPtr const & structure);
|
||||
PVStructure(StructureConstPtr const & structure,PVFieldPtrArray const & pvFields);
|
||||
<font color = "red">
|
||||
// following are removed
|
||||
void appendPVField(
|
||||
String const &fieldName,
|
||||
PVFieldPtr const & pvField);
|
||||
void appendPVFields(
|
||||
StringArray const & fieldNames,
|
||||
PVFieldPtrArray const & pvFields);
|
||||
void removePVField(String const &fieldName);
|
||||
virtual void setImmutable();
|
||||
String getExtendsStructureName() const;
|
||||
bool putExtendsStructureName(
|
||||
String const &extendsStructureName);
|
||||
</font>
|
||||
};
|
||||
|
||||
<font color = "red">
|
||||
// following will be removed
|
||||
typedef PVArrayData<PVStructurePtr> StructureArrayData;
|
||||
</font>
|
||||
|
||||
class PVStructureArray : public PVArray
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(PVStructureArray);
|
||||
typedef PVStructurePtr value_type;
|
||||
typedef PVStructurePtr* pointer;
|
||||
typedef const PVStructurePtr* const_pointer;
|
||||
<font color = "blue">
|
||||
// following are new typeDefs
|
||||
typedef shared_vector<PVStructurePtr> svector;
|
||||
typedef shared_vector<const PVStructurePtr> const_svector;
|
||||
</font>
|
||||
|
||||
virtual ~PVStructureArray() {}
|
||||
virtual void setCapacity(size_t capacity);
|
||||
virtual void setLength(std::size_t length);
|
||||
virtual StructureArrayConstPtr getStructureArray() const ;
|
||||
virtual void serialize(ByteBuffer *pbuffer,
|
||||
SerializableControl *pflusher) const;
|
||||
virtual void deserialize(ByteBuffer *buffer,
|
||||
virtual void serialize(ByteBuffer *pbuffer,
|
||||
SerializableControl *pflusher, std::size_t offset, std::size_t count) const ;
|
||||
// following are new
|
||||
<font color = "blue"> svector get();</font>
|
||||
<font color = "blue"> void swap(svector & value);</font>
|
||||
<font color = "red">
|
||||
// following are removed
|
||||
typedef PVArrayData<PVStructurePtr> ArrayDataType;
|
||||
typedef std::vector<PVStructurePtr> vector;
|
||||
typedef const std::vector<PVStructurePtr> const_vector;
|
||||
typedef std::tr1::shared_ptr<vector> shared_vector;
|
||||
typedef PVStructureArray &reference;
|
||||
typedef const PVStructureArray& const_reference;
|
||||
|
||||
virtual std::size_t append(std::size_t number);
|
||||
virtual bool remove(std::size_t offset,std::size_t number);
|
||||
virtual void compress();
|
||||
virtual std::size_t get(std::size_t offset, std::size_t length,
|
||||
StructureArrayData &data);
|
||||
virtual std::size_t put(std::size_t offset,std::size_t length,
|
||||
const_vector const & from, std::size_t fromOffset);
|
||||
virtual void shareData(
|
||||
shared_vector const & value,
|
||||
std::size_t capacity,
|
||||
std::size_t length);
|
||||
virtual pointer get() { return &((*value.get())[0]); }
|
||||
virtual pointer get() const { return &((*value.get())[0]); }
|
||||
virtual vector const & getVector() {return *value;}
|
||||
virtual shared_vector const & getSharedVector() {return value;}
|
||||
</font>
|
||||
...
|
||||
};
|
||||
|
||||
class PVDataCreate {
|
||||
public:
|
||||
static PVDataCreatePtr getPVDataCreate();
|
||||
PVFieldPtr createPVField(FieldConstPtr const & field);
|
||||
PVFieldPtr createPVField(PVFieldPtr const & fieldToClone);
|
||||
PVScalarPtr createPVScalar(ScalarConstPtr const & scalar);
|
||||
PVScalarPtr createPVScalar(ScalarType scalarType);
|
||||
PVScalarPtr createPVScalar(PVScalarPtr const & scalarToClone);
|
||||
PVScalarArrayPtr createPVScalarArray(ScalarArrayConstPtr const & scalarArray);
|
||||
PVScalarArrayPtr createPVScalarArray(ScalarType elementType);
|
||||
PVScalarArrayPtr createPVScalarArray(PVScalarArrayPtr const & scalarArrayToClone);
|
||||
PVStructureArrayPtr createPVStructureArray(StructureArrayConstPtr const & structureArray);
|
||||
PVStructurePtr createPVStructure(StructureConstPtr const & structure);
|
||||
PVStructurePtr createPVStructure(
|
||||
StringArray const & fieldNames,PVFieldPtrArray const & pvFields);
|
||||
PVStructurePtr createPVStructure(PVStructurePtr const & structToClone);
|
||||
...
|
||||
};
|
||||
|
||||
extern PVDataCreatePtr getPVDataCreate();
|
||||
</pre>
|
||||
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,29 +0,0 @@
|
||||
# pvData C++ implementation
|
||||
# Jenkins @ APS build script
|
||||
#
|
||||
# Jenkins invokes scripts with the "-ex" option. So the build is considered a failure
|
||||
# if any of the commands exits with a non-zero exit code.
|
||||
#
|
||||
# Author: Ralph Lange <Ralph.Lange@gmx.de> and Andrew Johnson <anj@aps.anl.gov>
|
||||
# Copyright (C) 2013 Helmholtz-Zentrum Berlin für Materialien und Energie GmbH
|
||||
# All rights reserved. Use is subject to license terms.
|
||||
|
||||
###########################################
|
||||
# Build
|
||||
|
||||
export EPICS_BASE=${HOME}/jobs/epics-base-3.14/workspace
|
||||
export EPICS_HOST_ARCH=$(${EPICS_BASE}/startup/EpicsHostArch)
|
||||
|
||||
cat > configure/RELEASE.local << EOF
|
||||
PVCOMMON=${HOME}/jobs/epics-pvCommon/workspace
|
||||
EPICS_BASE=${EPICS_BASE}
|
||||
EOF
|
||||
|
||||
make distclean all
|
||||
|
||||
###########################################
|
||||
# Test
|
||||
|
||||
for t in bin/linux-x86_64/test*; do
|
||||
$t
|
||||
done
|
||||
@@ -42,9 +42,8 @@ doxygen
|
||||
###########################################
|
||||
# Test
|
||||
|
||||
for t in bin/linux-x86_64/test*; do
|
||||
$t
|
||||
done
|
||||
# EPICS Test Harness tests
|
||||
make runtests
|
||||
|
||||
###########################################
|
||||
# Create distribution
|
||||
|
||||
@@ -1,99 +0,0 @@
|
||||
TOP = ..
|
||||
include $(TOP)/configure/CONFIG
|
||||
|
||||
PVDATA = $(TOP)/pvDataApp/
|
||||
|
||||
SRC_DIRS += $(PVDATA)/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
|
||||
|
||||
LIBSRCS += byteBuffer.cpp
|
||||
LIBSRCS += bitSet.cpp
|
||||
LIBSRCS += epicsException.cpp
|
||||
LIBSRCS += requester.cpp
|
||||
LIBSRCS += serializeHelper.cpp
|
||||
LIBSRCS += event.cpp
|
||||
LIBSRCS += executor.cpp
|
||||
LIBSRCS += timeFunction.cpp
|
||||
LIBSRCS += timer.cpp
|
||||
LIBSRCS += status.cpp
|
||||
LIBSRCS += messageQueue.cpp
|
||||
LIBSRCS += localStaticLock.cpp
|
||||
|
||||
SRC_DIRS += $(PVDATA)/pv
|
||||
|
||||
INC += pvType.h
|
||||
INC += pvIntrospect.h
|
||||
INC += pvData.h
|
||||
INC += convert.h
|
||||
INC += standardField.h
|
||||
INC += standardPVField.h
|
||||
|
||||
SRC_DIRS += $(PVDATA)/factory
|
||||
|
||||
INC += factory.h
|
||||
LIBSRCS += TypeFunc.cpp
|
||||
LIBSRCS += FieldCreateFactory.cpp
|
||||
LIBSRCS += PVAuxInfoImpl.cpp
|
||||
LIBSRCS += PVField.cpp
|
||||
LIBSRCS += PVScalar.cpp
|
||||
LIBSRCS += PVArray.cpp
|
||||
LIBSRCS += PVScalarArray.cpp
|
||||
LIBSRCS += PVStructure.cpp
|
||||
LIBSRCS += PVStructureArray.cpp
|
||||
LIBSRCS += PVDataCreateFactory.cpp
|
||||
LIBSRCS += Convert.cpp
|
||||
LIBSRCS += Compare.cpp
|
||||
LIBSRCS += StandardField.cpp
|
||||
LIBSRCS += StandardPVField.cpp
|
||||
|
||||
SRC_DIRS += $(PVDATA)/property
|
||||
|
||||
INC += alarm.h
|
||||
INC += pvAlarm.h
|
||||
INC += control.h
|
||||
INC += pvControl.h
|
||||
INC += display.h
|
||||
INC += pvDisplay.h
|
||||
INC += pvEnumerated.h
|
||||
INC += timeStamp.h
|
||||
INC += pvTimeStamp.h
|
||||
|
||||
LIBSRCS += alarm.cpp
|
||||
LIBSRCS += pvAlarm.cpp
|
||||
LIBSRCS += pvControl.cpp
|
||||
LIBSRCS += pvDisplay.cpp
|
||||
LIBSRCS += pvEnumerated.cpp
|
||||
LIBSRCS += timeStamp.cpp
|
||||
LIBSRCS += pvTimeStamp.cpp
|
||||
|
||||
SRC_DIRS += $(PVDATA)/pvMisc
|
||||
INC += bitSetUtil.h
|
||||
LIBSRCS += bitSetUtil.cpp
|
||||
|
||||
SRC_DIRS += $(PVDATA)/monitor
|
||||
INC += monitor.h
|
||||
|
||||
LIBRARY = pvData
|
||||
pvData_LIBS += Com
|
||||
|
||||
include $(TOP)/configure/RULES
|
||||
|
||||
@@ -1,108 +0,0 @@
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mes
|
||||
*/
|
||||
|
||||
#include <pv/convert.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <sstream>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
// PVXXX object comparison
|
||||
|
||||
bool operator==(PVField& left, PVField& right)
|
||||
{
|
||||
return getConvert()->equals(left,right);
|
||||
}
|
||||
|
||||
// Introspection object comparision
|
||||
|
||||
/** Field equality conditions:
|
||||
* 1) same instance
|
||||
* 2) same type (field and scalar/element), same name, same subfields (if any)
|
||||
*/
|
||||
bool operator==(const Field& a, const Field& b)
|
||||
{
|
||||
if(&a==&b)
|
||||
return true;
|
||||
if(a.getType()!=b.getType())
|
||||
return false;
|
||||
switch(a.getType()) {
|
||||
case scalar: {
|
||||
const Scalar &A=static_cast<const Scalar&>(a);
|
||||
const Scalar &B=static_cast<const Scalar&>(b);
|
||||
return A==B;
|
||||
}
|
||||
case scalarArray: {
|
||||
const ScalarArray &A=static_cast<const ScalarArray&>(a);
|
||||
const ScalarArray &B=static_cast<const ScalarArray&>(b);
|
||||
return A==B;
|
||||
}
|
||||
case structure: {
|
||||
const Structure &A=static_cast<const Structure&>(a);
|
||||
const Structure &B=static_cast<const Structure&>(b);
|
||||
return A==B;
|
||||
}
|
||||
case structureArray: {
|
||||
const StructureArray &A=static_cast<const StructureArray&>(a);
|
||||
const StructureArray &B=static_cast<const StructureArray&>(b);
|
||||
return A==B;
|
||||
}
|
||||
default:
|
||||
throw std::logic_error("Invalid Field type in comparision");
|
||||
}
|
||||
}
|
||||
|
||||
bool operator==(const Scalar& a, const Scalar& b)
|
||||
{
|
||||
if(&a==&b)
|
||||
return true;
|
||||
return a.getScalarType()==b.getScalarType();
|
||||
}
|
||||
|
||||
bool operator==(const ScalarArray& a, const ScalarArray& b)
|
||||
{
|
||||
if(&a==&b)
|
||||
return true;
|
||||
return a.getElementType()==b.getElementType();
|
||||
}
|
||||
|
||||
bool operator==(const Structure& a, const Structure& b)
|
||||
{
|
||||
if(&a==&b)
|
||||
return true;
|
||||
if (a.getID()!=b.getID())
|
||||
return false;
|
||||
size_t nflds=a.getNumberFields();
|
||||
if (b.getNumberFields()!=nflds)
|
||||
return false;
|
||||
|
||||
// std::equals does not work, since FieldConstPtrArray is an array of shared_pointers
|
||||
FieldConstPtrArray af = a.getFields();
|
||||
FieldConstPtrArray bf = b.getFields();
|
||||
for (size_t i = 0; i < nflds; i++)
|
||||
if (*(af[i].get()) != *(bf[i].get()))
|
||||
return false;
|
||||
|
||||
StringArray an = a.getFieldNames();
|
||||
StringArray bn = b.getFieldNames();
|
||||
return std::equal( an.begin(), an.end(), bn.begin() );
|
||||
}
|
||||
|
||||
bool operator==(const StructureArray& a, const StructureArray& b)
|
||||
{
|
||||
return *(a.getStructure().get())==*(b.getStructure().get());
|
||||
}
|
||||
|
||||
namespace nconvert {
|
||||
|
||||
} // namespace nconvert
|
||||
|
||||
}} // namespace epics::pvData
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,563 +0,0 @@
|
||||
/*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.
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
*/
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <pv/lock.h>
|
||||
#include <pv/pvIntrospect.h>
|
||||
#include <pv/convert.h>
|
||||
#include <pv/factory.h>
|
||||
#include <pv/serializeHelper.h>
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using std::size_t;
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
static DebugLevel debugLevel = lowDebug;
|
||||
|
||||
static void newLine(StringBuilder buffer, int indentLevel)
|
||||
{
|
||||
*buffer += "\n";
|
||||
for(int i=0; i<indentLevel; i++) *buffer += " ";
|
||||
}
|
||||
|
||||
Field::Field(Type type)
|
||||
: m_fieldType(type)
|
||||
{
|
||||
}
|
||||
|
||||
Field::~Field() {
|
||||
}
|
||||
|
||||
|
||||
void Field::toString(StringBuilder /*buffer*/,int /*indentLevel*/) const{
|
||||
}
|
||||
|
||||
|
||||
// TODO move all these to a header file
|
||||
|
||||
struct ScalarHashFunction {
|
||||
size_t operator() (const Scalar& scalar) const { return scalar.getScalarType(); }
|
||||
};
|
||||
|
||||
struct ScalarArrayHashFunction {
|
||||
size_t operator() (const ScalarArray& scalarArray) const { return 0x10 | scalarArray.getElementType(); }
|
||||
};
|
||||
|
||||
struct StructureHashFunction {
|
||||
size_t operator() (const Structure& /*structure*/) const { return 0; }
|
||||
// TODO
|
||||
// final int PRIME = 31;
|
||||
// return PRIME * Arrays.hashCode(fieldNames) + Arrays.hashCode(fields);
|
||||
};
|
||||
|
||||
struct StructureArrayHashFunction {
|
||||
size_t operator() (const StructureArray& structureArray) const { StructureHashFunction shf; return (0x10 | shf(*(structureArray.getStructure()))); }
|
||||
};
|
||||
|
||||
|
||||
Scalar::Scalar(ScalarType scalarType)
|
||||
: Field(scalar),scalarType(scalarType){}
|
||||
|
||||
Scalar::~Scalar(){}
|
||||
|
||||
void Scalar::toString(StringBuilder buffer,int /*indentLevel*/) const{
|
||||
*buffer += getID();
|
||||
}
|
||||
|
||||
|
||||
String Scalar::getID() const
|
||||
{
|
||||
static const String idScalarLUT[] = {
|
||||
"boolean", // pvBoolean
|
||||
"byte", // pvByte
|
||||
"short", // pvShort
|
||||
"int", // pvInt
|
||||
"long", // pvLong
|
||||
"ubyte", // pvUByte
|
||||
"ushort", // pvUShort
|
||||
"uint", // pvUInt
|
||||
"ulong", // pvULong
|
||||
"float", // pvFloat
|
||||
"double", // pvDouble
|
||||
"string" // pvString
|
||||
};
|
||||
return idScalarLUT[scalarType];
|
||||
}
|
||||
|
||||
int8 Scalar::getTypeCodeLUT() const
|
||||
{
|
||||
static const int8 typeCodeLUT[] = {
|
||||
0x00, // pvBoolean
|
||||
0x20, // pvByte
|
||||
0x21, // pvShort
|
||||
0x22, // pvInt
|
||||
0x23, // pvLong
|
||||
0x28, // pvUByte
|
||||
0x29, // pvUShort
|
||||
0x2A, // pvUInt
|
||||
0x2B, // pvULong
|
||||
0x42, // pvFloat
|
||||
0x43, // pvDouble
|
||||
0x60 // pvString
|
||||
};
|
||||
return typeCodeLUT[scalarType];
|
||||
}
|
||||
|
||||
|
||||
void Scalar::serialize(ByteBuffer *buffer, SerializableControl *control) const {
|
||||
control->ensureBuffer(1);
|
||||
buffer->putByte(getTypeCodeLUT());
|
||||
}
|
||||
|
||||
void Scalar::deserialize(ByteBuffer */*buffer*/, DeserializableControl */*control*/) {
|
||||
// must be done via FieldCreate
|
||||
throw std::runtime_error("not valid operation, use FieldCreate::deserialize instead");
|
||||
}
|
||||
|
||||
static String emptyString;
|
||||
|
||||
static void serializeStructureField(const Structure* structure, ByteBuffer* buffer, SerializableControl* control)
|
||||
{
|
||||
// to optimize default (non-empty) IDs optimization
|
||||
// empty IDs are not allowed
|
||||
String id = structure->getID();
|
||||
if (id == Structure::DEFAULT_ID) // TODO slow comparison
|
||||
SerializeHelper::serializeString(emptyString, buffer, control);
|
||||
else
|
||||
SerializeHelper::serializeString(id, buffer, control);
|
||||
|
||||
FieldConstPtrArray const & fields = structure->getFields();
|
||||
StringArray const & fieldNames = structure->getFieldNames();
|
||||
std::size_t len = fields.size();
|
||||
SerializeHelper::writeSize(len, buffer, control);
|
||||
for (std::size_t i = 0; i < len; i++)
|
||||
{
|
||||
SerializeHelper::serializeString(fieldNames[i], buffer, control);
|
||||
control->cachedSerialize(fields[i], buffer);
|
||||
}
|
||||
}
|
||||
|
||||
static StructureConstPtr deserializeStructureField(const FieldCreate* fieldCreate, ByteBuffer* buffer, DeserializableControl* control)
|
||||
{
|
||||
String id = SerializeHelper::deserializeString(buffer, control);
|
||||
const std::size_t size = SerializeHelper::readSize(buffer, control);
|
||||
FieldConstPtrArray fields; fields.reserve(size);
|
||||
StringArray fieldNames; fieldNames.reserve(size);
|
||||
for (std::size_t i = 0; i < size; i++)
|
||||
{
|
||||
fieldNames.push_back(SerializeHelper::deserializeString(buffer, control));
|
||||
fields.push_back(control->cachedDeserialize(buffer));
|
||||
}
|
||||
|
||||
if (id.empty())
|
||||
return fieldCreate->createStructure(fieldNames, fields);
|
||||
else
|
||||
return fieldCreate->createStructure(id, fieldNames, fields);
|
||||
}
|
||||
|
||||
ScalarArray::ScalarArray(ScalarType elementType)
|
||||
: Field(scalarArray),elementType(elementType){}
|
||||
|
||||
ScalarArray::~ScalarArray() {}
|
||||
|
||||
int8 ScalarArray::getTypeCodeLUT() const
|
||||
{
|
||||
static const int8 typeCodeLUT[] = {
|
||||
0x00, // pvBoolean
|
||||
0x20, // pvByte
|
||||
0x21, // pvShort
|
||||
0x22, // pvInt
|
||||
0x23, // pvLong
|
||||
0x28, // pvUByte
|
||||
0x29, // pvUShort
|
||||
0x2A, // pvUInt
|
||||
0x2B, // pvULong
|
||||
0x42, // pvFloat
|
||||
0x43, // pvDouble
|
||||
0x60 // pvString
|
||||
};
|
||||
return typeCodeLUT[elementType];
|
||||
}
|
||||
|
||||
const String ScalarArray::getIDScalarArrayLUT() const
|
||||
{
|
||||
static const String idScalarArrayLUT[] = {
|
||||
"boolean[]", // pvBoolean
|
||||
"byte[]", // pvByte
|
||||
"short[]", // pvShort
|
||||
"int[]", // pvInt
|
||||
"long[]", // pvLong
|
||||
"ubyte[]", // pvUByte
|
||||
"ushort[]", // pvUShort
|
||||
"uint[]", // pvUInt
|
||||
"ulong[]", // pvULong
|
||||
"float[]", // pvFloat
|
||||
"double[]", // pvDouble
|
||||
"string[]" // pvString
|
||||
};
|
||||
return idScalarArrayLUT[elementType];
|
||||
}
|
||||
|
||||
String ScalarArray::getID() const
|
||||
{
|
||||
return getIDScalarArrayLUT();
|
||||
}
|
||||
|
||||
void ScalarArray::toString(StringBuilder buffer,int /*indentLevel*/) const{
|
||||
*buffer += getID();
|
||||
}
|
||||
|
||||
void ScalarArray::serialize(ByteBuffer *buffer, SerializableControl *control) const {
|
||||
control->ensureBuffer(1);
|
||||
buffer->putByte(0x10 | getTypeCodeLUT());
|
||||
}
|
||||
|
||||
void ScalarArray::deserialize(ByteBuffer */*buffer*/, DeserializableControl */*control*/) {
|
||||
throw std::runtime_error("not valid operation, use FieldCreate::deserialize instead");
|
||||
}
|
||||
|
||||
StructureArray::StructureArray(StructureConstPtr const & structure)
|
||||
: Field(structureArray),pstructure(structure)
|
||||
{
|
||||
}
|
||||
|
||||
StructureArray::~StructureArray() {
|
||||
if(debugLevel==highDebug) printf("~StructureArray\n");
|
||||
}
|
||||
|
||||
String StructureArray::getID() const
|
||||
{
|
||||
return pstructure->getID() + "[]";
|
||||
}
|
||||
|
||||
void StructureArray::toString(StringBuilder buffer,int indentLevel) const {
|
||||
*buffer += getID();
|
||||
newLine(buffer,indentLevel + 1);
|
||||
pstructure->toString(buffer,indentLevel + 1);
|
||||
}
|
||||
|
||||
void StructureArray::serialize(ByteBuffer *buffer, SerializableControl *control) const {
|
||||
control->ensureBuffer(1);
|
||||
buffer->putByte(0x90);
|
||||
control->cachedSerialize(pstructure, buffer);
|
||||
}
|
||||
|
||||
void StructureArray::deserialize(ByteBuffer */*buffer*/, DeserializableControl */*control*/) {
|
||||
throw std::runtime_error("not valid operation, use FieldCreate::deserialize instead");
|
||||
}
|
||||
|
||||
String Structure::DEFAULT_ID = "structure";
|
||||
|
||||
Structure::Structure (
|
||||
StringArray const & fieldNames,
|
||||
FieldConstPtrArray const & infields,
|
||||
String const & inid)
|
||||
: Field(structure),
|
||||
fieldNames(fieldNames),
|
||||
fields(infields),
|
||||
id(inid)
|
||||
{
|
||||
if(inid.empty()) {
|
||||
throw std::invalid_argument("id is empty");
|
||||
}
|
||||
if(fieldNames.size()!=fields.size()) {
|
||||
throw std::invalid_argument("fieldNames.size()!=fields.size()");
|
||||
}
|
||||
size_t number = fields.size();
|
||||
for(size_t i=0; i<number; i++) {
|
||||
String name = fieldNames[i];
|
||||
if(name.size()<1) {
|
||||
throw std::invalid_argument("fieldNames has a zero length string");
|
||||
}
|
||||
// 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 ");
|
||||
message += name;
|
||||
throw std::invalid_argument(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Structure::~Structure() { }
|
||||
|
||||
|
||||
String Structure::getID() const
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
FieldConstPtr Structure::getField(String const & fieldName) const {
|
||||
size_t numberFields = fields.size();
|
||||
for(size_t i=0; i<numberFields; i++) {
|
||||
FieldConstPtr pfield = fields[i];
|
||||
int result = fieldName.compare(fieldNames[i]);
|
||||
if(result==0) return pfield;
|
||||
}
|
||||
return FieldConstPtr();
|
||||
}
|
||||
|
||||
size_t Structure::getFieldIndex(String const &fieldName) const {
|
||||
size_t numberFields = fields.size();
|
||||
for(size_t i=0; i<numberFields; i++) {
|
||||
FieldConstPtr pfield = fields[i];
|
||||
int result = fieldName.compare(fieldNames[i]);
|
||||
if(result==0) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void Structure::toString(StringBuilder buffer,int indentLevel) const{
|
||||
*buffer += getID();
|
||||
toStringCommon(buffer,indentLevel+1);
|
||||
}
|
||||
|
||||
void Structure::toStringCommon(StringBuilder buffer,int indentLevel) const{
|
||||
newLine(buffer,indentLevel);
|
||||
size_t numberFields = fields.size();
|
||||
for(size_t i=0; i<numberFields; i++) {
|
||||
FieldConstPtr pfield = fields[i];
|
||||
*buffer += pfield->getID() + " " + fieldNames[i];
|
||||
switch(pfield->getType()) {
|
||||
case scalar:
|
||||
case scalarArray:
|
||||
break;
|
||||
case structure:
|
||||
{
|
||||
Field const *xxx = pfield.get();
|
||||
Structure const *pstruct = static_cast<Structure const*>(xxx);
|
||||
pstruct->toStringCommon(buffer,indentLevel + 1);
|
||||
break;
|
||||
}
|
||||
case structureArray:
|
||||
newLine(buffer,indentLevel +1);
|
||||
pfield->toString(buffer,indentLevel +1);
|
||||
break;
|
||||
}
|
||||
if(i<numberFields-1) newLine(buffer,indentLevel);
|
||||
}
|
||||
}
|
||||
|
||||
void Structure::serialize(ByteBuffer *buffer, SerializableControl *control) const {
|
||||
control->ensureBuffer(1);
|
||||
buffer->putByte(0x80);
|
||||
serializeStructureField(this, buffer, control);
|
||||
}
|
||||
|
||||
void Structure::deserialize(ByteBuffer */*buffer*/, DeserializableControl */*control*/) {
|
||||
throw std::runtime_error("not valid operation, use FieldCreate::deserialize instead");
|
||||
}
|
||||
|
||||
ScalarConstPtr FieldCreate::createScalar(ScalarType scalarType) const
|
||||
{
|
||||
// TODO use singleton instance
|
||||
ScalarConstPtr scalar(new Scalar(scalarType), Field::Deleter());
|
||||
return scalar;
|
||||
}
|
||||
|
||||
ScalarArrayConstPtr FieldCreate::createScalarArray(ScalarType elementType) const
|
||||
{
|
||||
// TODO use singleton instance
|
||||
ScalarArrayConstPtr scalarArray(new ScalarArray(elementType), Field::Deleter());
|
||||
return scalarArray;
|
||||
}
|
||||
|
||||
StructureConstPtr FieldCreate::createStructure (
|
||||
StringArray const & fieldNames,FieldConstPtrArray const & fields) const
|
||||
{
|
||||
StructureConstPtr structure(
|
||||
new Structure(fieldNames,fields), Field::Deleter());
|
||||
return structure;
|
||||
}
|
||||
|
||||
StructureConstPtr FieldCreate::createStructure (
|
||||
String const & id,
|
||||
StringArray const & fieldNames,
|
||||
FieldConstPtrArray const & fields) const
|
||||
{
|
||||
StructureConstPtr structure(
|
||||
new Structure(fieldNames,fields,id), Field::Deleter());
|
||||
return structure;
|
||||
}
|
||||
|
||||
StructureArrayConstPtr FieldCreate::createStructureArray(
|
||||
StructureConstPtr const & structure) const
|
||||
{
|
||||
StructureArrayConstPtr structureArray(
|
||||
new StructureArray(structure), Field::Deleter());
|
||||
return structureArray;
|
||||
}
|
||||
|
||||
StructureConstPtr FieldCreate::appendField(
|
||||
StructureConstPtr const & structure,
|
||||
String const & fieldName,
|
||||
FieldConstPtr const & field) const
|
||||
{
|
||||
StringArray oldNames = structure->getFieldNames();
|
||||
FieldConstPtrArray oldFields = structure->getFields();
|
||||
size_t oldLen = oldNames.size();
|
||||
StringArray newNames(oldLen+1);
|
||||
FieldConstPtrArray newFields(oldLen+1);
|
||||
for(size_t i = 0; i<oldLen; i++) {
|
||||
newNames[i] = oldNames[i];
|
||||
newFields[i] = oldFields[i];
|
||||
}
|
||||
newNames[oldLen] = fieldName;
|
||||
newFields[oldLen] = field;
|
||||
return createStructure(structure->getID(),newNames,newFields);
|
||||
}
|
||||
|
||||
StructureConstPtr FieldCreate::appendFields(
|
||||
StructureConstPtr const & structure,
|
||||
StringArray const & fieldNames,
|
||||
FieldConstPtrArray const & fields) const
|
||||
{
|
||||
StringArray oldNames = structure->getFieldNames();
|
||||
FieldConstPtrArray oldFields = structure->getFields();
|
||||
size_t oldLen = oldNames.size();
|
||||
size_t extra = fieldNames.size();
|
||||
StringArray newNames(oldLen+extra);
|
||||
FieldConstPtrArray newFields(oldLen+extra);
|
||||
for(size_t i = 0; i<oldLen; i++) {
|
||||
newNames[i] = oldNames[i];
|
||||
newFields[i] = oldFields[i];
|
||||
}
|
||||
for(size_t i = 0; i<extra; i++) {
|
||||
newNames[oldLen +i] = fieldNames[i];
|
||||
newFields[oldLen +i] = fields[i];
|
||||
}
|
||||
return createStructure(structure->getID(),newNames,newFields);
|
||||
}
|
||||
|
||||
|
||||
static int decodeScalar(int8 code)
|
||||
{
|
||||
static const int integerLUT[] =
|
||||
{
|
||||
pvByte, // 8-bits
|
||||
pvShort, // 16-bits
|
||||
pvInt, // 32-bits
|
||||
pvLong, // 64-bits
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
pvUByte, // unsigned 8-bits
|
||||
pvUShort, // unsigned 16-bits
|
||||
pvUInt, // unsigned 32-bits
|
||||
pvULong, // unsigned 64-bits
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1
|
||||
};
|
||||
|
||||
static const int floatLUT[] =
|
||||
{
|
||||
-1, // reserved
|
||||
-1, // 16-bits
|
||||
pvFloat, // 32-bits
|
||||
pvDouble, // 64-bits
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1
|
||||
};
|
||||
// bits 7-5
|
||||
switch (code >> 5)
|
||||
{
|
||||
case 0: return pvBoolean;
|
||||
case 1: return integerLUT[code & 0x0F];
|
||||
case 2: return floatLUT[code & 0x0F];
|
||||
case 3: return pvString;
|
||||
default: return -1;
|
||||
}
|
||||
}
|
||||
|
||||
FieldConstPtr FieldCreate::deserialize(ByteBuffer* buffer, DeserializableControl* control) const
|
||||
{
|
||||
control->ensureData(1);
|
||||
int8 code = buffer->getByte();
|
||||
if (code == -1)
|
||||
return FieldConstPtr();
|
||||
|
||||
int typeCode = code & 0xE0;
|
||||
bool notArray = ((code & 0x10) == 0);
|
||||
if (notArray)
|
||||
{
|
||||
if (typeCode < 0x80)
|
||||
{
|
||||
// Type type = Type.scalar;
|
||||
int scalarType = decodeScalar(code);
|
||||
if (scalarType == -1)
|
||||
throw std::invalid_argument("invalid scalar type encoding");
|
||||
return FieldConstPtr(new Scalar(static_cast<ScalarType>(scalarType)), Field::Deleter());
|
||||
}
|
||||
else if (typeCode == 0x80)
|
||||
{
|
||||
// Type type = Type.structure;
|
||||
return deserializeStructureField(this, buffer, control);
|
||||
}
|
||||
else
|
||||
throw std::invalid_argument("invalid type encoding");
|
||||
}
|
||||
else // array
|
||||
{
|
||||
if (typeCode < 0x80)
|
||||
{
|
||||
// Type type = Type.scalarArray;
|
||||
int scalarType = decodeScalar(code);
|
||||
if (scalarType == -1)
|
||||
throw std::invalid_argument("invalid scalarArray type encoding");
|
||||
return FieldConstPtr(new ScalarArray(static_cast<ScalarType>(scalarType)), Field::Deleter());
|
||||
}
|
||||
else if (typeCode == 0x80)
|
||||
{
|
||||
// Type type = Type.structureArray;
|
||||
StructureConstPtr elementStructure = std::tr1::static_pointer_cast<const Structure>(control->cachedDeserialize(buffer));
|
||||
return FieldConstPtr(new StructureArray(elementStructure), Field::Deleter());
|
||||
}
|
||||
else
|
||||
throw std::invalid_argument("invalid type encoding");
|
||||
}
|
||||
}
|
||||
|
||||
FieldCreatePtr FieldCreate::getFieldCreate()
|
||||
{
|
||||
LOCAL_STATIC_LOCK;
|
||||
static FieldCreatePtr fieldCreate;
|
||||
static Mutex mutex;
|
||||
|
||||
Lock xx(mutex);
|
||||
if(fieldCreate.get()==0) fieldCreate = FieldCreatePtr(new FieldCreate());
|
||||
return fieldCreate;
|
||||
}
|
||||
|
||||
FieldCreate::FieldCreate(){}
|
||||
|
||||
FieldCreatePtr getFieldCreate() {
|
||||
return FieldCreate::getFieldCreate();
|
||||
}
|
||||
|
||||
}}
|
||||
@@ -1,105 +0,0 @@
|
||||
/*PVArray.cpp*/
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
*/
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/factory.h>
|
||||
|
||||
using std::size_t;
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
class PVArrayPvt {
|
||||
public:
|
||||
PVArrayPvt() : length(0),capacity(0),capacityMutable(true)
|
||||
{}
|
||||
size_t length;
|
||||
size_t capacity;
|
||||
bool capacityMutable;
|
||||
};
|
||||
|
||||
PVArray::PVArray(FieldConstPtr const & field)
|
||||
: PVField(field),pImpl(new PVArrayPvt())
|
||||
{ }
|
||||
|
||||
PVArray::~PVArray()
|
||||
{
|
||||
delete pImpl;
|
||||
}
|
||||
|
||||
void PVArray::setImmutable()
|
||||
{
|
||||
pImpl->capacityMutable = false;
|
||||
PVField::setImmutable();
|
||||
}
|
||||
|
||||
size_t PVArray::getLength() const {return pImpl->length;}
|
||||
|
||||
size_t PVArray::getCapacity() const {return pImpl->capacity;}
|
||||
|
||||
static String fieldImmutable("field is immutable");
|
||||
|
||||
void PVArray::setLength(size_t length) {
|
||||
if(length==pImpl->length) return;
|
||||
if(PVField::isImmutable()) {
|
||||
PVField::message(fieldImmutable,errorMessage);
|
||||
return;
|
||||
}
|
||||
if(length>pImpl->capacity) this->setCapacity(length);
|
||||
if(length>pImpl->capacity) length = pImpl->capacity;
|
||||
pImpl->length = length;
|
||||
}
|
||||
|
||||
void PVArray::setCapacityLength(size_t capacity,size_t length) {
|
||||
pImpl->capacity = capacity;
|
||||
pImpl->length = length;
|
||||
}
|
||||
|
||||
|
||||
bool PVArray::isCapacityMutable() const
|
||||
{
|
||||
if(PVField::isImmutable()) {
|
||||
return false;
|
||||
}
|
||||
return pImpl->capacityMutable;
|
||||
}
|
||||
|
||||
void PVArray::setCapacityMutable(bool isMutable)
|
||||
{
|
||||
if(isMutable && PVField::isImmutable()) {
|
||||
PVField::message(fieldImmutable,errorMessage);
|
||||
return;
|
||||
}
|
||||
pImpl->capacityMutable = isMutable;
|
||||
}
|
||||
|
||||
static String capacityImmutable("capacity is immutable");
|
||||
|
||||
void PVArray::setCapacity(size_t capacity) {
|
||||
if(PVField::isImmutable()) {
|
||||
PVField::message(fieldImmutable,errorMessage);
|
||||
return;
|
||||
}
|
||||
if(pImpl->capacityMutable==false) {
|
||||
PVField::message(capacityImmutable,errorMessage);
|
||||
return;
|
||||
}
|
||||
pImpl->capacity = capacity;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(format::array_at_internal const& manip, const PVArray& array)
|
||||
{
|
||||
return array.dumpValue(manip.stream, manip.index);
|
||||
}
|
||||
|
||||
}}
|
||||
@@ -1,276 +0,0 @@
|
||||
/*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.
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
*/
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/convert.h>
|
||||
#include <pv/factory.h>
|
||||
#include <pv/serializeHelper.h>
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using std::size_t;
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
PVStructureArray::PVStructureArray(StructureArrayConstPtr const & structureArray)
|
||||
: PVArray(structureArray),
|
||||
structureArray(structureArray),
|
||||
value(std::tr1::shared_ptr<PVStructurePtrArray>(new PVStructurePtrArray()))
|
||||
{
|
||||
}
|
||||
|
||||
size_t PVStructureArray::append(size_t number)
|
||||
{
|
||||
size_t currentLength = getLength();
|
||||
size_t newLength = currentLength + number;
|
||||
setCapacity(newLength);
|
||||
setLength(newLength);
|
||||
StructureConstPtr structure = structureArray->getStructure();
|
||||
PVStructurePtrArray *to = value.get();
|
||||
for(size_t i=currentLength; i<newLength; i++) {
|
||||
(*to)[i] =getPVDataCreate()->createPVStructure(structure);
|
||||
}
|
||||
return newLength;
|
||||
}
|
||||
|
||||
bool PVStructureArray::remove(size_t offset,size_t number)
|
||||
{
|
||||
size_t length = getLength();
|
||||
if(offset+number>length) return false;
|
||||
PVStructurePtrArray vec = *value.get();
|
||||
for(size_t i = offset; i+number < length; i++) {
|
||||
vec[i] = vec[i + number];
|
||||
}
|
||||
size_t newLength = length - number;
|
||||
setCapacityLength(newLength,newLength);
|
||||
return true;
|
||||
}
|
||||
|
||||
void PVStructureArray::compress() {
|
||||
size_t length = getCapacity();
|
||||
size_t newLength = 0;
|
||||
PVStructurePtrArray vec = *value.get();
|
||||
for(size_t i=0; i<length; i++) {
|
||||
if(vec[i].get()!=NULL) {
|
||||
newLength++;
|
||||
continue;
|
||||
}
|
||||
// find first non 0
|
||||
size_t notNull = 0;
|
||||
for(size_t j=i+1;j<length;j++) {
|
||||
if(vec[j].get()!=NULL) {
|
||||
notNull = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(notNull!=0) {
|
||||
vec[i] = vec[notNull];
|
||||
vec[notNull].reset();
|
||||
newLength++;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
setCapacityLength(newLength,newLength);
|
||||
}
|
||||
|
||||
void PVStructureArray::setCapacity(size_t capacity) {
|
||||
if(getCapacity()==capacity) return;
|
||||
if(!isCapacityMutable()) {
|
||||
std::string message("not capacityMutable");
|
||||
PVField::message(message, errorMessage);
|
||||
return;
|
||||
}
|
||||
size_t length = getLength();
|
||||
if(length>capacity) length = capacity;
|
||||
size_t oldCapacity = getCapacity();
|
||||
if(oldCapacity>capacity) {
|
||||
PVStructurePtrArray array;
|
||||
array.reserve(capacity);
|
||||
array.resize(length);
|
||||
PVStructurePtr * from = get();
|
||||
for (size_t i=0; i<length; i++) array[i] = from[i];
|
||||
value->swap(array);
|
||||
} else {
|
||||
value->reserve(capacity);
|
||||
}
|
||||
setCapacityLength(capacity,length);
|
||||
}
|
||||
|
||||
void PVStructureArray::setLength(size_t length) {
|
||||
if(PVArray::getLength()==length) return;
|
||||
size_t capacity = PVArray::getCapacity();
|
||||
if(length>capacity) {
|
||||
if(!PVArray::isCapacityMutable()) {
|
||||
std::string message("not capacityMutable");
|
||||
PVField::message(message, errorMessage);
|
||||
return;
|
||||
}
|
||||
setCapacity(length);
|
||||
}
|
||||
value->resize(length);
|
||||
PVArray::setCapacityLength(capacity,length);
|
||||
}
|
||||
|
||||
StructureArrayConstPtr PVStructureArray::getStructureArray() const
|
||||
{
|
||||
return structureArray;
|
||||
}
|
||||
|
||||
size_t PVStructureArray::get(
|
||||
size_t offset, size_t len, StructureArrayData &data)
|
||||
{
|
||||
size_t n = len;
|
||||
size_t length = getLength();
|
||||
if(offset+len > length) {
|
||||
n = length - offset;
|
||||
//if(n<0) n = 0;
|
||||
}
|
||||
data.data = *value.get();
|
||||
data.offset = offset;
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t PVStructureArray::put(size_t offset,size_t len,
|
||||
const_vector const & from, size_t fromOffset)
|
||||
{
|
||||
if(isImmutable()) {
|
||||
message(String("field is immutable"), errorMessage);
|
||||
return 0;
|
||||
}
|
||||
if(&from==value.get()) return 0;
|
||||
if(len<1) return 0;
|
||||
size_t length = getLength();
|
||||
size_t capacity = getCapacity();
|
||||
if(offset+len > length) {
|
||||
size_t newlength = offset + len;
|
||||
if(newlength>capacity) {
|
||||
setCapacity(newlength);
|
||||
capacity = getCapacity();
|
||||
newlength = capacity;
|
||||
len = newlength - offset;
|
||||
if(len<=0) return 0;
|
||||
}
|
||||
length = newlength;
|
||||
setLength(length);
|
||||
}
|
||||
PVStructurePtrArray *to = value.get();
|
||||
StructureConstPtr structure = structureArray->getStructure();
|
||||
for(size_t i=0; i<len; i++) {
|
||||
PVStructurePtr frompv = from[i+fromOffset];
|
||||
if(frompv.get()!=NULL) {
|
||||
if(frompv->getStructure()!=structure) {
|
||||
throw std::invalid_argument(String(
|
||||
"Element is not a compatible structure"));
|
||||
}
|
||||
}
|
||||
(*to)[i+offset] = frompv;
|
||||
}
|
||||
postPut();
|
||||
setLength(length);
|
||||
return len;
|
||||
}
|
||||
|
||||
void PVStructureArray::shareData(
|
||||
std::tr1::shared_ptr<std::vector<PVStructurePtr> > const & sharedValue,
|
||||
std::size_t capacity,
|
||||
std::size_t length)
|
||||
{
|
||||
value = sharedValue;
|
||||
setCapacityLength(capacity,length);
|
||||
}
|
||||
|
||||
void PVStructureArray::serialize(ByteBuffer *pbuffer,
|
||||
SerializableControl *pflusher) const {
|
||||
serialize(pbuffer, pflusher, 0, getLength());
|
||||
}
|
||||
|
||||
void PVStructureArray::deserialize(ByteBuffer *pbuffer,
|
||||
DeserializableControl *pcontrol) {
|
||||
size_t size = SerializeHelper::readSize(pbuffer, pcontrol);
|
||||
//if(size>=0) {
|
||||
// prepare array, if necessary
|
||||
if(size>getCapacity()) setCapacity(size);
|
||||
setLength(size);
|
||||
PVStructurePtrArray *pvArray = value.get();
|
||||
for(size_t i = 0; i<size; i++) {
|
||||
pcontrol->ensureData(1);
|
||||
size_t temp = pbuffer->getByte();
|
||||
if(temp==0) {
|
||||
(*pvArray)[i].reset();
|
||||
}
|
||||
else {
|
||||
if((*pvArray)[i].get()==NULL) {
|
||||
StructureConstPtr structure = structureArray->getStructure();
|
||||
(*pvArray)[i] = getPVDataCreate()->createPVStructure(structure);
|
||||
}
|
||||
(*pvArray)[i]->deserialize(pbuffer, pcontrol);
|
||||
}
|
||||
}
|
||||
postPut();
|
||||
//}
|
||||
}
|
||||
|
||||
void PVStructureArray::serialize(ByteBuffer *pbuffer,
|
||||
SerializableControl *pflusher, size_t offset, size_t count) const {
|
||||
// cache
|
||||
size_t length = getLength();
|
||||
|
||||
// check bounds
|
||||
/*if(offset<0)
|
||||
offset = 0;
|
||||
else*/ if(offset>length) offset = length;
|
||||
//if(count<0) count = length;
|
||||
|
||||
size_t maxCount = length-offset;
|
||||
if(count>maxCount) count = maxCount;
|
||||
|
||||
PVStructurePtrArray pvArray = *value.get();
|
||||
// write
|
||||
SerializeHelper::writeSize(count, pbuffer, pflusher);
|
||||
for(size_t i = 0; i<count; i++) {
|
||||
if(pbuffer->getRemaining()<1) pflusher->flushSerializeBuffer();
|
||||
PVStructurePtr pvStructure = pvArray[i+offset];
|
||||
if(pvStructure.get()==NULL) {
|
||||
pbuffer->putByte(0);
|
||||
}
|
||||
else {
|
||||
pbuffer->putByte(1);
|
||||
pvStructure->serialize(pbuffer, pflusher);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::ostream& PVStructureArray::dumpValue(std::ostream& o) const
|
||||
{
|
||||
o << format::indent() << getStructureArray()->getID() << ' ' << getFieldName() << std::endl;
|
||||
size_t length = getLength();
|
||||
if (length > 0)
|
||||
{
|
||||
format::indent_scope s(o);
|
||||
|
||||
for (size_t i = 0; i < length; i++)
|
||||
dumpValue(o, i);
|
||||
}
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
std::ostream& PVStructureArray::dumpValue(std::ostream& o, std::size_t index) const
|
||||
{
|
||||
PVStructurePtrArray pvArray = *value.get();
|
||||
PVStructurePtr pvStructure = pvArray[index];
|
||||
return o << *(pvStructure.get());
|
||||
return o;
|
||||
}
|
||||
|
||||
}}
|
||||
@@ -1,768 +0,0 @@
|
||||
/* convert.h */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
* Author - Marty Kraimer
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
*/
|
||||
#ifndef CONVERT_H
|
||||
#define CONVERT_H
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <pv/pvIntrospect.h>
|
||||
#include <pv/pvData.h>
|
||||
#include <vector>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
bool operator==(PVField&, PVField&);
|
||||
|
||||
static inline bool operator!=(PVField& a, PVField& b)
|
||||
{return !(a==b);}
|
||||
|
||||
|
||||
bool operator==(const Field&, const Field&);
|
||||
bool operator==(const Scalar&, const Scalar&);
|
||||
bool operator==(const ScalarArray&, const ScalarArray&);
|
||||
bool operator==(const Structure&, const Structure&);
|
||||
bool operator==(const StructureArray&, const StructureArray&);
|
||||
|
||||
static inline bool operator!=(const Field& a, const Field& b)
|
||||
{return !(a==b);}
|
||||
static inline bool operator!=(const Scalar& a, const Scalar& b)
|
||||
{return !(a==b);}
|
||||
static inline bool operator!=(const ScalarArray& a, const ScalarArray& b)
|
||||
{return !(a==b);}
|
||||
static inline bool operator!=(const Structure& a, const Structure& b)
|
||||
{return !(a==b);}
|
||||
static inline bool operator!=(const StructureArray& a, const StructureArray& b)
|
||||
{return !(a==b);}
|
||||
|
||||
|
||||
/**
|
||||
* Convert between numeric types, convert any field to a string,
|
||||
* or convert from a string to a scalar field.
|
||||
* <p>Numeric conversions are between scalar numeric types or between arrays of
|
||||
* numeric types. It is not possible to convert between a scalar
|
||||
* and an array.
|
||||
* Numeric conversions are between types:
|
||||
* pvByte, pvShort, pvInt, pvLong,
|
||||
* pvUByte, pvUShort, pvUInt, pvULong,
|
||||
* pvFloat, or pvDouble.</p>
|
||||
*
|
||||
* <p>getString converts any supported type to a String.
|
||||
* Code that implements a PVField interface should implement
|
||||
* method toString by calling this method.</p>
|
||||
*
|
||||
* <p>fromString converts a String to a scalar.
|
||||
* fromStringArray converts an array of Strings
|
||||
* to a pvArray, which must have a scaler element type.
|
||||
* A scalar field is a numeric field or pvBoolean or pvString.</p>
|
||||
* <p>All from methods put data into a PVField, e.g. from means where the PVField gets it's data.</p>
|
||||
*/
|
||||
|
||||
class Convert;
|
||||
typedef std::tr1::shared_ptr<Convert> ConvertPtr;
|
||||
|
||||
class Convert {
|
||||
public:
|
||||
static ConvertPtr getConvert();
|
||||
~Convert();
|
||||
/**
|
||||
* Get the full fieldName for the pvField.
|
||||
* @param builder The builder that will have the result.
|
||||
* @param pvField The pvField.
|
||||
*/
|
||||
void getFullName(StringBuilder buf,PVFieldPtr const & pvField);
|
||||
/**
|
||||
* Do fields have the same definition.
|
||||
*
|
||||
* @param First field
|
||||
* @param Second field
|
||||
* @return (false, true) if the fields (are not, are) the same.
|
||||
*/
|
||||
bool equals(PVFieldPtr const &a,PVFieldPtr const &b);
|
||||
/**
|
||||
* Do fields have the same definition.
|
||||
*
|
||||
* @param First field
|
||||
* @param Second field
|
||||
* @return (false, true) if the fields (are not, are) the same.
|
||||
*/
|
||||
bool equals(PVField &a,PVField &b);
|
||||
/**
|
||||
* Convert a PVField to a string.
|
||||
* @param buf buffer for the result
|
||||
* @param pv a PVField to convert to a string.
|
||||
* If a PVField is a structure or array be prepared for a very long string.
|
||||
* @param indentLevel indentation level
|
||||
*/
|
||||
void getString(StringBuilder buf,PVFieldPtr const & pvField,int indentLevel);
|
||||
/**
|
||||
* Convert a PVField to a string.
|
||||
* param buf buffer for the result
|
||||
* @param pv The PVField to convert to a string.
|
||||
* If the PVField is a structure or array be prepared for a very long string.
|
||||
*/
|
||||
void getString(StringBuilder buf,PVFieldPtr const & pvField);
|
||||
/**
|
||||
* Convert a PVField to a string.
|
||||
* @param buf buffer for the result
|
||||
* @param pv a PVField to convert to a string.
|
||||
* If a PVField is a structure or array be prepared for a very long string.
|
||||
* @param indentLevel indentation level
|
||||
*/
|
||||
void getString(StringBuilder buf,PVField const * pvField,int indentLevel);
|
||||
/**
|
||||
* Convert a PVField to a string.
|
||||
* param buf buffer for the result
|
||||
* @param pv The PVField to convert to a string.
|
||||
* If the PVField is a structure or array be prepared for a very long string.
|
||||
*/
|
||||
void getString(StringBuilder buf,PVField const * pvField);
|
||||
/**
|
||||
* Convert from an array of String to a PVScalar
|
||||
* @param pv The PV.
|
||||
* @param from The array of String value to convert and put into a PV.
|
||||
* @param fromStartIndex The first element if the array of strings.
|
||||
* @throws std::logic_error if the array of String does not have a valid values.
|
||||
*/
|
||||
std::size_t fromString(
|
||||
PVStructurePtr const &pv,
|
||||
StringArray const & from,
|
||||
std::size_t fromStartIndex = 0);
|
||||
/**
|
||||
* Convert from a String to a PVScalar
|
||||
* @param pv The PV.
|
||||
* @param from The String value to convert and put into a PV.
|
||||
* @throws std::logic_error if the String does not have a valid value.
|
||||
*/
|
||||
void fromString(PVScalarPtr const & pv, String const & from);
|
||||
/**
|
||||
* Convert from a String to a PVScalarArray.
|
||||
* The String must be a comma separated set of values optionally enclosed in []
|
||||
* @param pv The PV.
|
||||
* @param from The String value to convert and put into a PV.
|
||||
* @return The number of elements converted.
|
||||
* @throws std::invalid_argument if the element Type is not a scalar.
|
||||
* @throws std::logic_error if the String does not have a valid array values.
|
||||
*/
|
||||
std::size_t fromString(PVScalarArrayPtr const & pv, String from);
|
||||
/**
|
||||
* Convert a PVScalarArray from a String array.
|
||||
* The array element type must be a scalar.
|
||||
* @param pv The PV.
|
||||
* @param offset Starting element in a PV.
|
||||
* @param length The number of elements to transfer.
|
||||
* @param from The array of values to put into the PV.
|
||||
* @param fromOffset Starting element in the source array.
|
||||
* @return The number of elements converted.
|
||||
* @throws std::invalid_argument if the element Type is not a scalar.
|
||||
* @throws std::logic_error if the String does not have a valid value.
|
||||
*/
|
||||
std::size_t fromStringArray(
|
||||
PVScalarArrayPtr const & pv,
|
||||
std::size_t offset, std::size_t length,
|
||||
StringArray const & from,
|
||||
std::size_t fromOffset);
|
||||
/**
|
||||
* Convert a PVScalarArray to a String array.
|
||||
* @param pv The PV.
|
||||
* @param offset Starting element in the PV array.
|
||||
* @param length Number of elements to convert to the string array.
|
||||
* @param to String array to receive the converted PV data.
|
||||
* @param toOffset Starting element in the string array.
|
||||
* @return Number of elements converted.
|
||||
*/
|
||||
std::size_t toStringArray(PVScalarArrayPtr const & pv,
|
||||
std::size_t offset,
|
||||
std::size_t length,
|
||||
StringArray & to,
|
||||
std::size_t toOffset);
|
||||
/**
|
||||
* Are from and to valid arguments to copy.
|
||||
* This first checks of both arguments have the same Type.
|
||||
* Then calls one of isCopyScalarCompatible,
|
||||
* isCopyArrayCompatible, or isCopyStructureCompatible.
|
||||
* @param from The source.
|
||||
* @param to The destination.
|
||||
* @return (false,true) is the arguments (are not, are) compatible.
|
||||
*/
|
||||
bool isCopyCompatible(FieldConstPtr const & from, FieldConstPtr const & to);
|
||||
/**
|
||||
* Copy from a PVField to another PVField.
|
||||
* This calls one on copyScalar, copyArray, copyStructure.
|
||||
* The two arguments must be compatible.
|
||||
* @param from The source.
|
||||
* @param to The destination
|
||||
* @throws std::invalid_argument if the arguments are not compatible.
|
||||
*/
|
||||
void copy(PVFieldPtr const & from, PVFieldPtr const & to);
|
||||
/**
|
||||
* Are from and to valid arguments to copyScalar.
|
||||
* false will be returned if either argument is not a scalar as defined by Type.isScalar().
|
||||
* If both are scalars the return value is true if any of the following are true.
|
||||
* <ul>
|
||||
* <li>Both arguments are numeric.</li>
|
||||
* <li>Both arguments have the same type.</li>
|
||||
* <li>Either argument is a string.</li>
|
||||
* </ul>
|
||||
* @param from The introspection interface for the from data.
|
||||
* @param to The introspection interface for the to data..
|
||||
* @return (false,true) If the arguments (are not, are) compatible.
|
||||
*/
|
||||
bool isCopyScalarCompatible(
|
||||
ScalarConstPtr const & from,
|
||||
ScalarConstPtr const & to);
|
||||
/**
|
||||
* Copy from a scalar pv to another scalar pv.
|
||||
* @param from the source.
|
||||
* @param to the destination.
|
||||
* @throws std::invalid_argument if the arguments are not compatible.
|
||||
*/
|
||||
void copyScalar(PVScalarPtr const & from, PVScalarPtr const & to);
|
||||
/**
|
||||
* Are from and to valid arguments to copyArray.
|
||||
* The results are like isCopyScalarCompatible except that the tests are made on the elementType.
|
||||
* @param from The from array.
|
||||
* @param to The to array.
|
||||
* @return (false,true) If the arguments (are not, are) compatible.
|
||||
*/
|
||||
bool isCopyScalarArrayCompatible(
|
||||
ScalarArrayConstPtr const & from,
|
||||
ScalarArrayConstPtr const & to);
|
||||
/**
|
||||
* Convert from a source PV array to a destination PV array.
|
||||
* @param from The source array.
|
||||
* @param offset Starting element in the source.
|
||||
* @param to The destination array.
|
||||
* @param toOffset Starting element in the array.
|
||||
* @param length Number of elements to transfer.
|
||||
* @return Number of elements converted.
|
||||
* @throws std::invalid_argument if the arguments are not compatible.
|
||||
*/
|
||||
std::size_t copyScalarArray(
|
||||
PVScalarArrayPtr const & from,
|
||||
std::size_t offset,
|
||||
PVScalarArrayPtr const & to,
|
||||
std::size_t toOffset,
|
||||
std::size_t length);
|
||||
/**
|
||||
* Are from and to valid arguments for copyStructure.
|
||||
* They are only compatible if they have the same Structure description.
|
||||
* @param from from structure.
|
||||
* @param to structure.
|
||||
* @return (false,true) If the arguments (are not, are) compatible.
|
||||
*/
|
||||
bool isCopyStructureCompatible(
|
||||
StructureConstPtr const & from, StructureConstPtr const & to);
|
||||
/**
|
||||
* Copy from a structure pv to another structure pv.
|
||||
* NOTE: Only compatible nodes are copied. This means:
|
||||
* <ul>
|
||||
* <li>For scalar nodes this means that isCopyScalarCompatible is true.</li>
|
||||
* <li>For array nodes this means that isCopyArrayCompatible is true.</li>
|
||||
* <li>For structure nodes this means that isCopyStructureCompatible is true.</li>
|
||||
* <li>Link nodes are not copied.</li>
|
||||
* </ul>
|
||||
* @param from The source.
|
||||
* @param to The destination.
|
||||
* @throws std::invalid_argument if the arguments are not compatible.
|
||||
*/
|
||||
void copyStructure(PVStructurePtr const & from, PVStructurePtr const & to);
|
||||
/**
|
||||
* Are from and to valid for copyStructureArray.
|
||||
* @param from The from StructureArray.
|
||||
* @param to The to StructureArray.
|
||||
* @return (false,true) If the arguments (are not, are) compatible.
|
||||
*/
|
||||
bool isCopyStructureArrayCompatible(
|
||||
StructureArrayConstPtr const & from, StructureArrayConstPtr const & to);
|
||||
/**
|
||||
* Copy from a structure array to another structure array.
|
||||
* @param from The source array.
|
||||
* @param to The destination array.
|
||||
*/
|
||||
void copyStructureArray(
|
||||
PVStructureArrayPtr const & from, PVStructureArrayPtr const & to);
|
||||
/**
|
||||
* Convert a PV to a <byte>.
|
||||
* @param pv a PV
|
||||
* @return converted value
|
||||
*/
|
||||
int8 toByte(PVScalarPtr const & pv);
|
||||
/**
|
||||
* Convert a PV to a short.
|
||||
* @param pv a PV
|
||||
* @return converted value
|
||||
* @throws std::invalid_argument if the Type is not a numeric scalar
|
||||
*/
|
||||
int16 toShort(PVScalarPtr const & pv);
|
||||
/**
|
||||
* Convert a PV to a int.
|
||||
* @param pv a PV
|
||||
* @return converted value
|
||||
* @throws std::invalid_argument if the Type is not a numeric scalar
|
||||
*/
|
||||
int32 toInt(PVScalarPtr const & pv);
|
||||
/**
|
||||
* Convert a PV to an long
|
||||
* @param pv a PV
|
||||
* @return converted value
|
||||
* @throws std::invalid_argument if the Type is not a numeric scalar
|
||||
*/
|
||||
int64 toLong(PVScalarPtr const & pv);
|
||||
/**
|
||||
* Convert a PV to a ubyte.
|
||||
* @param pv a PV
|
||||
* @return converted value
|
||||
*/
|
||||
uint8 toUByte(PVScalarPtr const & pv);
|
||||
/**
|
||||
* Convert a PV to a ushort.
|
||||
* @param pv a PV
|
||||
* @return converted value
|
||||
* @throws std::invalid_argument if the Type is not a numeric scalar
|
||||
*/
|
||||
uint16 toUShort(PVScalarPtr const & pv);
|
||||
/**
|
||||
* Convert a PV to a uint.
|
||||
* @param pv a PV
|
||||
* @return converted value
|
||||
* @throws std::invalid_argument if the Type is not a numeric scalar
|
||||
*/
|
||||
uint32 toUInt(PVScalarPtr const & pv);
|
||||
/**
|
||||
* Convert a PV to an ulong
|
||||
* @param pv a PV
|
||||
* @return converted value
|
||||
* @throws std::invalid_argument if the Type is not a numeric scalar
|
||||
*/
|
||||
uint64 toULong(PVScalarPtr const & pv);
|
||||
/**
|
||||
* Convert a PV to a float
|
||||
* @param pv a PV
|
||||
* @return converted value
|
||||
* @throws std::invalid_argument if the Type is not a numeric scalar
|
||||
*/
|
||||
float toFloat(PVScalarPtr const & pv);
|
||||
/**
|
||||
* Convert a PV to a double
|
||||
* @param pv a PV
|
||||
* @return converted value
|
||||
* @throws std::invalid_argument if the Type is not a numeric scalar
|
||||
*/
|
||||
double toDouble(PVScalarPtr const & pv);
|
||||
/**
|
||||
* Convert a PV to a String
|
||||
* @param pv a PV
|
||||
* @return converted value
|
||||
*/
|
||||
String toString(PVScalarPtr const & pv);
|
||||
/**
|
||||
* Convert a PV from a byte
|
||||
* @param pv a PV
|
||||
* @param from value to put into PV
|
||||
* @throws std::invalid_argument if the Type is not a numeric scalar
|
||||
*/
|
||||
void fromByte(PVScalarPtr const & pv,int8 from);
|
||||
/**
|
||||
* Convert a PV from a short
|
||||
* @param pv a PV
|
||||
* @param from value to put into PV
|
||||
* @throws std::invalid_argument if the Type is not a numeric scalar
|
||||
*/
|
||||
void fromShort(PVScalarPtr const & pv,int16 from);
|
||||
/**
|
||||
* Convert a PV from an int
|
||||
* @param pv a PV
|
||||
* @param from value to put into PV
|
||||
* @throws std::invalid_argument if the Type is not a numeric scalar
|
||||
*/
|
||||
void fromInt(PVScalarPtr const & pv, int32 from);
|
||||
/**
|
||||
* Convert a PV from a long
|
||||
* @param pv a PV
|
||||
* @param from value to put into PV
|
||||
* @throws std::invalid_argument if the Type is not a numeric scalar
|
||||
*/
|
||||
void fromLong(PVScalarPtr const & pv, int64 from);
|
||||
/**
|
||||
* Convert a PV from a ubyte
|
||||
* @param pv a PV
|
||||
* @param from value to put into PV
|
||||
* @throws std::invalid_argument if the Type is not a numeric scalar
|
||||
*/
|
||||
void fromUByte(PVScalarPtr const & pv,uint8 from);
|
||||
/**
|
||||
* Convert a PV from a ushort
|
||||
* @param pv a PV
|
||||
* @param from value to put into PV
|
||||
* @throws std::invalid_argument if the Type is not a numeric scalar
|
||||
*/
|
||||
void fromUShort(PVScalarPtr const & pv,uint16 from);
|
||||
/**
|
||||
* Convert a PV from an uint
|
||||
* @param pv a PV
|
||||
* @param from value to put into PV
|
||||
* @throws std::invalid_argument if the Type is not a numeric scalar
|
||||
*/
|
||||
void fromUInt(PVScalarPtr const & pv, uint32 from);
|
||||
/**
|
||||
* Convert a PV from a ulong
|
||||
* @param pv a PV
|
||||
* @param from value to put into PV
|
||||
* @throws std::invalid_argument if the Type is not a numeric scalar
|
||||
*/
|
||||
void fromULong(PVScalarPtr const & pv, uint64 from);
|
||||
/**
|
||||
* Convert a PV from a float
|
||||
* @param pv a PV
|
||||
* @param from value to put into PV
|
||||
* @throws std::invalid_argument if the Type is not a numeric scalar
|
||||
*/
|
||||
void fromFloat(PVScalarPtr const & pv, float from);
|
||||
/**
|
||||
* Convert a PV from a double
|
||||
* @param pv a PV
|
||||
* @param from value to put into PV
|
||||
* @throws std::invalid_argument if the Type is not a numeric scalar
|
||||
*/
|
||||
void fromDouble(PVScalarPtr const & pv, double from);
|
||||
/**
|
||||
* Convert a PV array to a byte array.
|
||||
* @param pv a PV
|
||||
* @param offset starting element in a PV
|
||||
* @param length number of elements to transfer
|
||||
* @param to where to put the PV data
|
||||
* @param toOffset starting element in the array
|
||||
* @return number of elements converted
|
||||
* @throws std::invalid_argument if the element type is not numeric
|
||||
*/
|
||||
std::size_t toByteArray(PVScalarArrayPtr const & pv,
|
||||
std::size_t offset,
|
||||
std::size_t length,
|
||||
int8* to,
|
||||
std::size_t toOffset);
|
||||
/**
|
||||
* Convert a PV array to a short array.
|
||||
* @param pv a PV
|
||||
* @param offset starting element in a PV
|
||||
* @param length number of elements to transfer
|
||||
* @param to where to put the PV data
|
||||
* @param toOffset starting element in the array
|
||||
* @return number of elements converted
|
||||
* @throws std::invalid_argument if the element type is not numeric
|
||||
*/
|
||||
std::size_t toShortArray(PVScalarArrayPtr const & pv,
|
||||
std::size_t offset,
|
||||
std::size_t length,
|
||||
int16* to,
|
||||
std::size_t toOffset);
|
||||
/**
|
||||
* Convert a PV array to an int array.
|
||||
* @param pv a PV
|
||||
* @param offset starting element in a PV
|
||||
* @param length number of elements to transfer
|
||||
* @param to where to put the PV data
|
||||
* @param toOffset starting element in the array
|
||||
* @return number of elements converted
|
||||
* @throws std::invalid_argument if the element type is not numeric
|
||||
*/
|
||||
std::size_t toIntArray(PVScalarArrayPtr const & pv,
|
||||
std::size_t offset,
|
||||
std::size_t length,
|
||||
int32* to,
|
||||
std::size_t toOffset);
|
||||
/**
|
||||
* Convert a PV array to a long array.
|
||||
* @param pv a PV
|
||||
* @param offset starting element in a PV
|
||||
* @param length number of elements to transfer
|
||||
* @param to where to put the PV data
|
||||
* @param toOffset starting element in the array
|
||||
* @return number of elements converted
|
||||
* @throws std::invalid_argument if the element type is not numeric
|
||||
*/
|
||||
std::size_t toLongArray(PVScalarArrayPtr const & pv,
|
||||
std::size_t offset,
|
||||
std::size_t length,
|
||||
int64* to,
|
||||
std::size_t toOffset);
|
||||
/**
|
||||
* Convert a PV array to a ubyte array.
|
||||
* @param pv a PV
|
||||
* @param offset starting element in a PV
|
||||
* @param length number of elements to transfer
|
||||
* @param to where to put the PV data
|
||||
* @param toOffset starting element in the array
|
||||
* @return number of elements converted
|
||||
* @throws std::invalid_argument if the element type is not numeric
|
||||
*/
|
||||
std::size_t toUByteArray(PVScalarArrayPtr const & pv,
|
||||
std::size_t offset,
|
||||
std::size_t length,
|
||||
uint8* to,
|
||||
std::size_t toOffset);
|
||||
/**
|
||||
* Convert a PV array to a ushort array.
|
||||
* @param pv a PV
|
||||
* @param offset starting element in a PV
|
||||
* @param length number of elements to transfer
|
||||
* @param to where to put the PV data
|
||||
* @param toOffset starting element in the array
|
||||
* @return number of elements converted
|
||||
* @throws std::invalid_argument if the element type is not numeric
|
||||
*/
|
||||
std::size_t toUShortArray(PVScalarArrayPtr const & pv,
|
||||
std::size_t offset,
|
||||
std::size_t length,
|
||||
uint16* to,
|
||||
std::size_t toOffset);
|
||||
/**
|
||||
* Convert a PV array to an uint array.
|
||||
* @param pv a PV
|
||||
* @param offset starting element in a PV
|
||||
* @param length number of elements to transfer
|
||||
* @param to where to put the PV data
|
||||
* @param toOffset starting element in the array
|
||||
* @return number of elements converted
|
||||
* @throws std::invalid_argument if the element type is not numeric
|
||||
*/
|
||||
std::size_t toUIntArray(
|
||||
PVScalarArrayPtr const & pv,
|
||||
std::size_t offset,
|
||||
std::size_t length,
|
||||
uint32* to,
|
||||
std::size_t toOffset);
|
||||
/**
|
||||
* Convert a PV array to a ulong array.
|
||||
* @param pv a PV
|
||||
* @param offset starting element in a PV
|
||||
* @param length number of elements to transfer
|
||||
* @param to where to put the PV data
|
||||
* @param toOffset starting element in the array
|
||||
* @return number of elements converted
|
||||
* @throws std::invalid_argument if the element type is not numeric
|
||||
*/
|
||||
std::size_t toULongArray(
|
||||
PVScalarArrayPtr const & pv,
|
||||
std::size_t offset,
|
||||
std::size_t length,
|
||||
uint64* to,
|
||||
std::size_t toOffset);
|
||||
/**
|
||||
* Convert a PV array to a float array.
|
||||
* @param pv a PV
|
||||
* @param offset starting element in a PV
|
||||
* @param length number of elements to transfer
|
||||
* @param to where to put the PV data
|
||||
* @param toOffset starting element in the array
|
||||
* @return number of elements converted
|
||||
* @throws std::invalid_argument if the element type is not numeric
|
||||
*/
|
||||
std::size_t toFloatArray(
|
||||
PVScalarArrayPtr const & pv,
|
||||
std::size_t offset,
|
||||
std::size_t length,
|
||||
float* to,
|
||||
std::size_t toOffset);
|
||||
/**
|
||||
* Convert a PV array to a double array.
|
||||
* @param pv a PV
|
||||
* @param offset starting element in a PV
|
||||
* @param length number of elements to transfer
|
||||
* @param to where to put the PV data
|
||||
* @param toOffset starting element in the array
|
||||
* @return number of elements converted
|
||||
* @throws std::invalid_argument if the element type is not numeric
|
||||
*/
|
||||
std::size_t toDoubleArray(
|
||||
PVScalarArrayPtr const & pv,
|
||||
std::size_t offset,
|
||||
std::size_t length,
|
||||
double* to, std::size_t
|
||||
toOffset);
|
||||
/**
|
||||
* Convert a PV array from a byte array.
|
||||
* @param pv a PV
|
||||
* @param offset starting element in a PV
|
||||
* @param length number of elements to transfer
|
||||
* @param from value to put into PV
|
||||
* @param fromOffset
|
||||
* @return number of elements converted
|
||||
* @throws std::invalid_argument if the element type is not numeric
|
||||
*/
|
||||
std::size_t fromByteArray(
|
||||
PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
|
||||
const int8* from, std::size_t fromOffset);
|
||||
std::size_t fromByteArray(
|
||||
PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
|
||||
const ByteArray & from, std::size_t fromOffset);
|
||||
/**
|
||||
* Convert a PV array from a short array.
|
||||
* @param pv a PV
|
||||
* @param offset starting element in a PV
|
||||
* @param length number of elements to transfer
|
||||
* @param from value to put into PV
|
||||
* @param fromOffset starting element in the source array
|
||||
* @return number of elements converted
|
||||
* @throws std::invalid_argument if the element type is not numeric
|
||||
*/
|
||||
std::size_t fromShortArray(
|
||||
PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
|
||||
const int16* from, std::size_t fromOffset);
|
||||
std::size_t fromShortArray(
|
||||
PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
|
||||
const ShortArray & from, std::size_t fromOffset);
|
||||
/**
|
||||
* Convert a PV array from an int array.
|
||||
* @param pv a PV
|
||||
* @param offset starting element in a PV
|
||||
* @param length number of elements to transfer
|
||||
* @param from value to put into PV
|
||||
* @param fromOffset starting element in the source array
|
||||
* @return number of elements converted
|
||||
* @throws std::invalid_argument if the element type is not numeric
|
||||
*/
|
||||
std::size_t fromIntArray(
|
||||
PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
|
||||
const int32* from, std::size_t fromOffset);
|
||||
std::size_t fromIntArray(
|
||||
PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
|
||||
const IntArray & from, std::size_t fromOffset);
|
||||
/**
|
||||
* Convert a PV array from a long array.
|
||||
* @param pv a PV
|
||||
* @param offset starting element in a PV
|
||||
* @param length number of elements to transfer
|
||||
* @param from value to put into PV
|
||||
* @param fromOffset starting element in the source array
|
||||
* @return number of elements converted
|
||||
* @throws std::invalid_argument if the element type is not numeric
|
||||
*/
|
||||
std::size_t fromLongArray(
|
||||
PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
|
||||
const int64* from, std::size_t fromOffset);
|
||||
std::size_t fromLongArray(
|
||||
PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
|
||||
const LongArray & from, std::size_t fromOffset);
|
||||
/**
|
||||
* Convert a PV array from a ubyte array.
|
||||
* @param pv a PV
|
||||
* @param offset starting element in a PV
|
||||
* @param length number of elements to transfer
|
||||
* @param from value to put into PV
|
||||
* @param fromOffset
|
||||
* @return number of elements converted
|
||||
* @throws std::invalid_argument if the element type is not numeric
|
||||
*/
|
||||
std::size_t fromUByteArray(
|
||||
PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
|
||||
const uint8* from, std::size_t fromOffset);
|
||||
std::size_t fromUByteArray(
|
||||
PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
|
||||
const UByteArray & from, std::size_t fromOffset);
|
||||
/**
|
||||
* Convert a PV array from a ushort array.
|
||||
* @param pv a PV
|
||||
* @param offset starting element in a PV
|
||||
* @param length number of elements to transfer
|
||||
* @param from value to put into PV
|
||||
* @param fromOffset starting element in the source array
|
||||
* @return number of elements converted
|
||||
* @throws std::invalid_argument if the element type is not numeric
|
||||
*/
|
||||
std::size_t fromUShortArray(
|
||||
PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
|
||||
const uint16* from, std::size_t fromOffset);
|
||||
std::size_t fromUShortArray(
|
||||
PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
|
||||
const UShortArray & from, std::size_t fromOffset);
|
||||
/**
|
||||
* Convert a PV array from an uint array.
|
||||
* @param pv a PV
|
||||
* @param offset starting element in a PV
|
||||
* @param length number of elements to transfer
|
||||
* @param from value to put into PV
|
||||
* @param fromOffset starting element in the source array
|
||||
* @return number of elements converted
|
||||
* @throws std::invalid_argument if the element type is not numeric
|
||||
*/
|
||||
std::size_t fromUIntArray(
|
||||
PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
|
||||
const uint32* from, std::size_t fromOffset);
|
||||
std::size_t fromUIntArray(
|
||||
PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
|
||||
const UIntArray & from, std::size_t fromOffset);
|
||||
/**
|
||||
* Convert a PV array from a ulong array.
|
||||
* @param pv a PV
|
||||
* @param offset starting element in a PV
|
||||
* @param length number of elements to transfer
|
||||
* @param from value to put into PV
|
||||
* @param fromOffset starting element in the source array
|
||||
* @return number of elements converted
|
||||
* @throws std::invalid_argument if the element type is not numeric
|
||||
*/
|
||||
std::size_t fromULongArray(
|
||||
PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
|
||||
const uint64* from, std::size_t fromOffset);
|
||||
std::size_t fromULongArray(
|
||||
PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
|
||||
const ULongArray & from, std::size_t fromOffset);
|
||||
/**
|
||||
* Convert a PV array from a float array.
|
||||
* @param pv a PV
|
||||
* @param offset starting element in a PV
|
||||
* @param length number of elements to transfer
|
||||
* @param from value to put into PV
|
||||
* @param fromOffset starting element in the source array
|
||||
* @return number of elements converted
|
||||
* @throws std::invalid_argument if the element type is not numeric
|
||||
*/
|
||||
std::size_t fromFloatArray(
|
||||
PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
|
||||
const float* from, std::size_t fromOffset);
|
||||
std::size_t fromFloatArray(
|
||||
PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
|
||||
const FloatArray & from, std::size_t fromOffset);
|
||||
/**
|
||||
* Convert a PV array from a double array.
|
||||
* @param pv a PV
|
||||
* @param offset starting element in a PV
|
||||
* @param length number of elements to transfer
|
||||
* @param from value to put into PV
|
||||
* @param fromOffset starting element in the source array
|
||||
* @return number of elements converted
|
||||
* @throws std::invalid_argument if the element type is not numeric
|
||||
*/
|
||||
std::size_t fromDoubleArray(
|
||||
PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
|
||||
const double* from, std::size_t fromOffset);
|
||||
std::size_t fromDoubleArray(
|
||||
PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
|
||||
const DoubleArray & from, std::size_t fromOffset);
|
||||
/**
|
||||
* Convenience method for implementing toString.
|
||||
* It generates a newline and inserts blanks at the beginning of the newline.
|
||||
* @param builder The StringBuilder being constructed.
|
||||
* @param indentLevel Indent level, Each level is four spaces.
|
||||
*/
|
||||
void newLine(StringBuilder buf, int indentLevel);
|
||||
private:
|
||||
Convert();
|
||||
PVDataCreatePtr pvDataCreate;
|
||||
String trueString;
|
||||
String falseString;
|
||||
String illegalScalarType;
|
||||
};
|
||||
|
||||
extern ConvertPtr getConvert();
|
||||
|
||||
}}
|
||||
#endif /* CONVERT_H */
|
||||
23
src/Makefile
Normal file
23
src/Makefile
Normal file
@@ -0,0 +1,23 @@
|
||||
# Makefile for the pvData library
|
||||
|
||||
TOP = ..
|
||||
include $(TOP)/configure/CONFIG
|
||||
|
||||
INSTALL_INCLUDE = $(INSTALL_LOCATION)/include/pv
|
||||
USR_INCLUDES += -I$(INSTALL_LOCATION)/include
|
||||
|
||||
PVDATA_SRC = $(TOP)/src
|
||||
|
||||
include $(PVDATA_SRC)/misc/Makefile
|
||||
include $(PVDATA_SRC)/pv/Makefile
|
||||
include $(PVDATA_SRC)/factory/Makefile
|
||||
include $(PVDATA_SRC)/property/Makefile
|
||||
include $(PVDATA_SRC)/pvMisc/Makefile
|
||||
include $(PVDATA_SRC)/monitor/Makefile
|
||||
|
||||
LIBRARY = pvData
|
||||
|
||||
pvData_LIBS += Com
|
||||
|
||||
include $(TOP)/configure/RULES
|
||||
|
||||
328
src/factory/Compare.cpp
Normal file
328
src/factory/Compare.cpp
Normal file
@@ -0,0 +1,328 @@
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mes
|
||||
*/
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/convert.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <sstream>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
// Introspection object comparision
|
||||
|
||||
/** Field equality conditions:
|
||||
* 1) same instance
|
||||
* 2) same type (field and scalar/element), same name, same subfields (if any)
|
||||
*/
|
||||
bool operator==(const Field& a, const Field& b)
|
||||
{
|
||||
if(&a==&b)
|
||||
return true;
|
||||
if(a.getType()!=b.getType())
|
||||
return false;
|
||||
switch(a.getType()) {
|
||||
case scalar: {
|
||||
const Scalar &A=static_cast<const Scalar&>(a);
|
||||
const Scalar &B=static_cast<const Scalar&>(b);
|
||||
return A==B;
|
||||
}
|
||||
case scalarArray: {
|
||||
const ScalarArray &A=static_cast<const ScalarArray&>(a);
|
||||
const ScalarArray &B=static_cast<const ScalarArray&>(b);
|
||||
return A==B;
|
||||
}
|
||||
case structure: {
|
||||
const Structure &A=static_cast<const Structure&>(a);
|
||||
const Structure &B=static_cast<const Structure&>(b);
|
||||
return A==B;
|
||||
}
|
||||
case structureArray: {
|
||||
const StructureArray &A=static_cast<const StructureArray&>(a);
|
||||
const StructureArray &B=static_cast<const StructureArray&>(b);
|
||||
return A==B;
|
||||
}
|
||||
case union_: {
|
||||
const Union &A=static_cast<const Union&>(a);
|
||||
const Union &B=static_cast<const Union&>(b);
|
||||
return A==B;
|
||||
}
|
||||
case unionArray: {
|
||||
const UnionArray &A=static_cast<const UnionArray&>(a);
|
||||
const UnionArray &B=static_cast<const UnionArray&>(b);
|
||||
return A==B;
|
||||
}
|
||||
default:
|
||||
throw std::logic_error("Invalid Field type in comparision");
|
||||
}
|
||||
}
|
||||
|
||||
bool operator==(const Scalar& a, const Scalar& b)
|
||||
{
|
||||
if(&a==&b)
|
||||
return true;
|
||||
return a.getScalarType()==b.getScalarType();
|
||||
}
|
||||
|
||||
bool operator==(const ScalarArray& a, const ScalarArray& b)
|
||||
{
|
||||
if(&a==&b)
|
||||
return true;
|
||||
return a.getElementType()==b.getElementType();
|
||||
}
|
||||
|
||||
bool operator==(const Structure& a, const Structure& b)
|
||||
{
|
||||
if(&a==&b)
|
||||
return true;
|
||||
if (a.getID()!=b.getID())
|
||||
return false;
|
||||
size_t nflds=a.getNumberFields();
|
||||
if (b.getNumberFields()!=nflds)
|
||||
return false;
|
||||
|
||||
// std::equals does not work, since FieldConstPtrArray is an array of shared_pointers
|
||||
FieldConstPtrArray af = a.getFields();
|
||||
FieldConstPtrArray bf = b.getFields();
|
||||
for (size_t i = 0; i < nflds; i++)
|
||||
if (*(af[i].get()) != *(bf[i].get()))
|
||||
return false;
|
||||
|
||||
StringArray an = a.getFieldNames();
|
||||
StringArray bn = b.getFieldNames();
|
||||
return std::equal( an.begin(), an.end(), bn.begin() );
|
||||
}
|
||||
|
||||
bool operator==(const StructureArray& a, const StructureArray& b)
|
||||
{
|
||||
return *(a.getStructure().get())==*(b.getStructure().get());
|
||||
}
|
||||
|
||||
bool operator==(const Union& a, const Union& b)
|
||||
{
|
||||
if(&a==&b)
|
||||
return true;
|
||||
if (a.getID()!=b.getID())
|
||||
return false;
|
||||
size_t nflds=a.getNumberFields();
|
||||
if (b.getNumberFields()!=nflds)
|
||||
return false;
|
||||
|
||||
// std::equals does not work, since FieldConstPtrArray is an array of shared_pointers
|
||||
FieldConstPtrArray af = a.getFields();
|
||||
FieldConstPtrArray bf = b.getFields();
|
||||
for (size_t i = 0; i < nflds; i++)
|
||||
if (*(af[i].get()) != *(bf[i].get()))
|
||||
return false;
|
||||
|
||||
StringArray an = a.getFieldNames();
|
||||
StringArray bn = b.getFieldNames();
|
||||
return std::equal( an.begin(), an.end(), bn.begin() );
|
||||
}
|
||||
|
||||
bool operator==(const UnionArray& a, const UnionArray& b)
|
||||
{
|
||||
return *(a.getUnion().get())==*(b.getUnion().get());
|
||||
}
|
||||
|
||||
// PVXXX object comparison
|
||||
|
||||
namespace {
|
||||
|
||||
// fully typed comparisons
|
||||
|
||||
template<typename T>
|
||||
bool compareScalar(const PVScalarValue<T>* left, const PVScalarValue<T>* right)
|
||||
{
|
||||
return left->get()==right->get();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool compareArray(const PVValueArray<T>* left, const PVValueArray<T>* right)
|
||||
{
|
||||
typename PVValueArray<T>::const_svector lhs(left->view()), rhs(right->view());
|
||||
return std::equal(lhs.begin(), lhs.end(), rhs.begin());
|
||||
}
|
||||
|
||||
// partially typed comparisons
|
||||
|
||||
bool compareField(const PVScalar* left, const PVScalar* right)
|
||||
{
|
||||
ScalarType lht = left->getScalar()->getScalarType();
|
||||
if(lht != right->getScalar()->getScalarType())
|
||||
return false;
|
||||
switch(lht) {
|
||||
#define OP(ENUM, TYPE) case ENUM: return compareScalar(static_cast<const PVScalarValue<TYPE>*>(left), static_cast<const PVScalarValue<TYPE>*>(right))
|
||||
OP(pvBoolean, uint8);
|
||||
OP(pvUByte, uint8);
|
||||
OP(pvByte, int8);
|
||||
OP(pvUShort, uint16);
|
||||
OP(pvShort, int16);
|
||||
OP(pvUInt, uint32);
|
||||
OP(pvInt, int32);
|
||||
OP(pvULong, uint64);
|
||||
OP(pvLong, int64);
|
||||
OP(pvFloat, float);
|
||||
OP(pvDouble, double);
|
||||
#undef OP
|
||||
case pvString: {
|
||||
const PVString *a=static_cast<const PVString*>(left), *b=static_cast<const PVString*>(right);
|
||||
return a->get()==b->get();
|
||||
}
|
||||
}
|
||||
throw std::logic_error("PVScalar with invalid scalar type!");
|
||||
}
|
||||
|
||||
bool compareField(const PVScalarArray* left, const PVScalarArray* right)
|
||||
{
|
||||
ScalarType lht = left->getScalarArray()->getElementType();
|
||||
if(lht != right->getScalarArray()->getElementType())
|
||||
return false;
|
||||
|
||||
if(left->getLength()!=right->getLength())
|
||||
return false;
|
||||
|
||||
switch(lht) {
|
||||
#define OP(ENUM, TYPE) case ENUM: return compareArray(static_cast<const PVValueArray<TYPE>*>(left), static_cast<const PVValueArray<TYPE>*>(right))
|
||||
OP(pvBoolean, uint8);
|
||||
OP(pvUByte, uint8);
|
||||
OP(pvByte, int8);
|
||||
OP(pvUShort, uint16);
|
||||
OP(pvShort, int16);
|
||||
OP(pvUInt, uint32);
|
||||
OP(pvInt, int32);
|
||||
OP(pvULong, uint64);
|
||||
OP(pvLong, int64);
|
||||
OP(pvFloat, float);
|
||||
OP(pvDouble, double);
|
||||
OP(pvString, String);
|
||||
#undef OP
|
||||
}
|
||||
throw std::logic_error("PVScalarArray with invalid element type!");
|
||||
}
|
||||
|
||||
bool compareField(const PVStructure* left, const PVStructure* right)
|
||||
{
|
||||
StructureConstPtr ls = left->getStructure();
|
||||
|
||||
if(*ls!=*right->getStructure())
|
||||
return false;
|
||||
|
||||
const PVFieldPtrArray& lf = left->getPVFields();
|
||||
const PVFieldPtrArray& rf = right->getPVFields();
|
||||
|
||||
for(size_t i=0, nfld=ls->getNumberFields(); i<nfld; i++) {
|
||||
if(*lf[i]!=*rf[i])
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool compareField(const PVStructureArray* left, const PVStructureArray* right)
|
||||
{
|
||||
if(*left->getStructureArray()->getStructure()
|
||||
!= *right->getStructureArray()->getStructure())
|
||||
return false;
|
||||
|
||||
PVStructureArray::const_svector ld=left->view(), rd=right->view();
|
||||
|
||||
if(ld.size()!=rd.size())
|
||||
return false;
|
||||
|
||||
PVStructureArray::const_svector::const_iterator lit, lend, rit;
|
||||
|
||||
for(lit=ld.begin(), lend=ld.end(), rit=rd.begin();
|
||||
lit!=lend;
|
||||
++lit, ++rit)
|
||||
{
|
||||
if(**lit != **rit)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool compareField(const PVUnion* left, const PVUnion* right)
|
||||
{
|
||||
UnionConstPtr ls = left->getUnion();
|
||||
|
||||
if(*ls!=*right->getUnion())
|
||||
return false;
|
||||
|
||||
if (ls->isVariant())
|
||||
{
|
||||
PVFieldPtr lval = left->get();
|
||||
if (lval.get() == 0)
|
||||
return right->get().get() == 0;
|
||||
else
|
||||
return *(lval.get()) == *(right->get().get());
|
||||
}
|
||||
else
|
||||
{
|
||||
int32 lix = left->getSelectedIndex();
|
||||
if (lix == right->getSelectedIndex())
|
||||
{
|
||||
if (lix == PVUnion::UNDEFINED_INDEX || *(left->get()) == *(right->get().get()))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool compareField(const PVUnionArray* left, const PVUnionArray* right)
|
||||
{
|
||||
if(*left->getUnionArray()->getUnion()
|
||||
!= *right->getUnionArray()->getUnion())
|
||||
return false;
|
||||
|
||||
PVUnionArray::const_svector ld=left->view(), rd=right->view();
|
||||
|
||||
if(ld.size()!=rd.size())
|
||||
return false;
|
||||
|
||||
PVUnionArray::const_svector::const_iterator lit, lend, rit;
|
||||
|
||||
for(lit=ld.begin(), lend=ld.end(), rit=rd.begin();
|
||||
lit!=lend;
|
||||
++lit, ++rit)
|
||||
{
|
||||
if(**lit != **rit)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // end namespace
|
||||
|
||||
// untyped comparison
|
||||
|
||||
bool operator==(const PVField& left, const PVField& right)
|
||||
{
|
||||
if(&left == &right)
|
||||
return true;
|
||||
|
||||
Type lht = left.getField()->getType();
|
||||
if(lht != right.getField()->getType())
|
||||
return false;
|
||||
|
||||
switch(lht) {
|
||||
case scalar: return compareField(static_cast<const PVScalar*>(&left), static_cast<const PVScalar*>(&right));
|
||||
case scalarArray: return compareField(static_cast<const PVScalarArray*>(&left), static_cast<const PVScalarArray*>(&right));
|
||||
case structure: return compareField(static_cast<const PVStructure*>(&left), static_cast<const PVStructure*>(&right));
|
||||
case structureArray: return compareField(static_cast<const PVStructureArray*>(&left), static_cast<const PVStructureArray*>(&right));
|
||||
case union_: return compareField(static_cast<const PVUnion*>(&left), static_cast<const PVUnion*>(&right));
|
||||
case unionArray: return compareField(static_cast<const PVUnionArray*>(&left), static_cast<const PVUnionArray*>(&right));
|
||||
}
|
||||
throw std::logic_error("PVField with invalid type!");
|
||||
}
|
||||
|
||||
}} // namespace epics::pvData
|
||||
533
src/factory/Convert.cpp
Normal file
533
src/factory/Convert.cpp
Normal file
@@ -0,0 +1,533 @@
|
||||
/* Convert.cpp */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
*/
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <stdexcept>
|
||||
#include <typeinfo>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/lock.h>
|
||||
#include <pv/pvIntrospect.h>
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/convert.h>
|
||||
#include <pv/printer.h>
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using std::size_t;
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
|
||||
static std::vector<String> split(String commaSeparatedList) {
|
||||
String::size_type numValues = 1;
|
||||
String::size_type index=0;
|
||||
while(true) {
|
||||
String::size_type pos = commaSeparatedList.find(',',index);
|
||||
if(pos==String::npos) break;
|
||||
numValues++;
|
||||
index = pos +1;
|
||||
}
|
||||
std::vector<String> valueList(numValues,"");
|
||||
index=0;
|
||||
for(size_t i=0; i<numValues; i++) {
|
||||
size_t pos = commaSeparatedList.find(',',index);
|
||||
String value = commaSeparatedList.substr(index,pos);
|
||||
valueList[i] = value;
|
||||
index = pos +1;
|
||||
}
|
||||
return valueList;
|
||||
}
|
||||
|
||||
void Convert::getString(StringBuilder buf,PVField const *pvField,int /*indentLevel*/)
|
||||
{
|
||||
// TODO indextLevel ignored
|
||||
std::ostringstream strm;
|
||||
PrinterPlain p;
|
||||
p.setStream(strm);
|
||||
p.print(*pvField);
|
||||
strm.str().swap(*buf);
|
||||
}
|
||||
|
||||
|
||||
size_t Convert::fromString(PVStructurePtr const &pvStructure, StringArray const & from, size_t fromStartIndex)
|
||||
{
|
||||
size_t processed = 0;
|
||||
|
||||
PVFieldPtrArray const & fieldsData = pvStructure->getPVFields();
|
||||
if (fieldsData.size() != 0) {
|
||||
size_t length = pvStructure->getStructure()->getNumberFields();
|
||||
for(size_t i=0; i<length; i++) {
|
||||
PVFieldPtr fieldField = fieldsData[i];
|
||||
|
||||
Type type = fieldField->getField()->getType();
|
||||
if(type==structure) {
|
||||
PVStructurePtr pv = static_pointer_cast<PVStructure>(fieldField);
|
||||
size_t count = fromString(pv, from, fromStartIndex);
|
||||
processed += count;
|
||||
fromStartIndex += count;
|
||||
}
|
||||
else if(type==scalarArray) {
|
||||
PVScalarArrayPtr pv = static_pointer_cast<PVScalarArray>(fieldField);
|
||||
size_t count = fromString(pv, from[fromStartIndex]);
|
||||
processed += count;
|
||||
fromStartIndex += count;
|
||||
}
|
||||
else if(type==scalar) {
|
||||
PVScalarPtr pv = static_pointer_cast<PVScalar>(fieldField);
|
||||
fromString(pv, from[fromStartIndex++]);
|
||||
processed++;
|
||||
}
|
||||
else {
|
||||
// union, structureArray, unionArray not supported
|
||||
String message("Convert::fromString unsupported fieldType ");
|
||||
TypeFunc::toString(&message,type);
|
||||
throw std::logic_error(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return processed;
|
||||
}
|
||||
|
||||
size_t Convert::fromString(PVScalarArrayPtr const &pv, String from)
|
||||
{
|
||||
if(from[0]=='[' && from[from.length()]==']') {
|
||||
size_t offset = from.rfind(']');
|
||||
from = from.substr(1, offset);
|
||||
}
|
||||
std::vector<String> valueList(split(from));
|
||||
size_t length = valueList.size();
|
||||
size_t num = fromStringArray(pv,0,length,valueList,0);
|
||||
if(num<length) length = num;
|
||||
pv->setLength(length);
|
||||
return length;
|
||||
}
|
||||
|
||||
size_t Convert::fromStringArray(PVScalarArrayPtr const &pv,
|
||||
size_t offset, size_t length,
|
||||
StringArray const & from,
|
||||
size_t fromOffset)
|
||||
{
|
||||
size_t alen = pv->getLength();
|
||||
|
||||
if(offset==0 && length>=alen) {
|
||||
// replace all existing elements
|
||||
assert(from.size()>=fromOffset+length);
|
||||
|
||||
PVStringArray::svector data(length);
|
||||
std::copy(from.begin()+fromOffset,
|
||||
from.begin()+fromOffset+length,
|
||||
data.begin());
|
||||
|
||||
PVStringArray::const_svector temp(freeze(data));
|
||||
pv->putFrom<String>(temp);
|
||||
return length;
|
||||
|
||||
} else {
|
||||
// partial update.
|
||||
throw std::runtime_error("fromStringArray: partial update not implemented");
|
||||
}
|
||||
}
|
||||
|
||||
size_t Convert::toStringArray(PVScalarArrayPtr const & pv,
|
||||
size_t offset, size_t length,
|
||||
StringArray &to, size_t toOffset)
|
||||
{
|
||||
PVStringArray::const_svector data;
|
||||
pv->getAs<String>(data);
|
||||
data.slice(offset, length);
|
||||
if(toOffset+data.size() > to.size())
|
||||
to.resize(toOffset+data.size());
|
||||
std::copy(data.begin()+toOffset, data.end(), to.begin());
|
||||
return data.size();
|
||||
}
|
||||
|
||||
bool Convert::isCopyCompatible(FieldConstPtr const &from, FieldConstPtr const &to)
|
||||
{
|
||||
if(from->getType()!=to->getType()) return false;
|
||||
switch(from->getType()) {
|
||||
case scalar:
|
||||
{
|
||||
ScalarConstPtr xxx = static_pointer_cast<const Scalar>(from);
|
||||
ScalarConstPtr yyy = static_pointer_cast<const Scalar>(to);
|
||||
return isCopyScalarCompatible(xxx,yyy);
|
||||
}
|
||||
case scalarArray:
|
||||
{
|
||||
ScalarArrayConstPtr xxx = static_pointer_cast<const ScalarArray>(from);
|
||||
ScalarArrayConstPtr yyy = static_pointer_cast<const ScalarArray>(to);
|
||||
return isCopyScalarArrayCompatible(xxx,yyy);
|
||||
}
|
||||
case structure:
|
||||
{
|
||||
StructureConstPtr xxx = static_pointer_cast<const Structure>(from);
|
||||
StructureConstPtr yyy = static_pointer_cast<const Structure>(to);
|
||||
return isCopyStructureCompatible(xxx,yyy);
|
||||
}
|
||||
case structureArray:
|
||||
{
|
||||
StructureArrayConstPtr xxx = static_pointer_cast<const StructureArray>(from);
|
||||
StructureArrayConstPtr yyy = static_pointer_cast<const StructureArray>(to);
|
||||
return isCopyStructureArrayCompatible(xxx,yyy);
|
||||
}
|
||||
case union_:
|
||||
{
|
||||
UnionConstPtr xxx = static_pointer_cast<const Union>(from);
|
||||
UnionConstPtr yyy = static_pointer_cast<const Union>(to);
|
||||
return isCopyUnionCompatible(xxx,yyy);
|
||||
}
|
||||
case unionArray:
|
||||
{
|
||||
UnionArrayConstPtr xxx = static_pointer_cast<const UnionArray>(from);
|
||||
UnionArrayConstPtr yyy = static_pointer_cast<const UnionArray>(to);
|
||||
return isCopyUnionArrayCompatible(xxx,yyy);
|
||||
}
|
||||
}
|
||||
String message("Convert::isCopyCompatible should never get here");
|
||||
throw std::logic_error(message);
|
||||
}
|
||||
|
||||
void Convert::copy(PVFieldPtr const & from, PVFieldPtr const & to)
|
||||
{
|
||||
switch(from->getField()->getType()) {
|
||||
case scalar:
|
||||
{
|
||||
PVScalarPtr xxx = static_pointer_cast<PVScalar>(from);
|
||||
PVScalarPtr yyy = static_pointer_cast<PVScalar>(to);
|
||||
copyScalar(xxx,yyy);
|
||||
return;
|
||||
}
|
||||
case scalarArray:
|
||||
{
|
||||
PVScalarArrayPtr fromArray = static_pointer_cast<PVScalarArray>(from);
|
||||
PVScalarArrayPtr toArray = static_pointer_cast<PVScalarArray>(to);
|
||||
toArray->assign(*fromArray.get());
|
||||
return;
|
||||
}
|
||||
case structure:
|
||||
{
|
||||
PVStructurePtr xxx = static_pointer_cast<PVStructure>(from);
|
||||
PVStructurePtr yyy = static_pointer_cast<PVStructure>(to);
|
||||
copyStructure(xxx,yyy);
|
||||
return;
|
||||
}
|
||||
case structureArray: {
|
||||
PVStructureArrayPtr fromArray = static_pointer_cast<PVStructureArray>(from);
|
||||
PVStructureArrayPtr toArray = static_pointer_cast<PVStructureArray>(to);
|
||||
copyStructureArray(fromArray,toArray);
|
||||
return;
|
||||
}
|
||||
case union_:
|
||||
{
|
||||
PVUnionPtr xxx = static_pointer_cast<PVUnion>(from);
|
||||
PVUnionPtr yyy = static_pointer_cast<PVUnion>(to);
|
||||
copyUnion(xxx,yyy);
|
||||
return;
|
||||
}
|
||||
case unionArray: {
|
||||
PVUnionArrayPtr fromArray = static_pointer_cast<PVUnionArray>(from);
|
||||
PVUnionArrayPtr toArray = static_pointer_cast<PVUnionArray>(to);
|
||||
copyUnionArray(fromArray,toArray);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Convert::isCopyScalarCompatible(
|
||||
ScalarConstPtr const & fromField, ScalarConstPtr const & toField)
|
||||
{
|
||||
ScalarType fromScalarType = fromField->getScalarType();
|
||||
ScalarType toScalarType = toField->getScalarType();
|
||||
if(fromScalarType==toScalarType) return true;
|
||||
if(ScalarTypeFunc::isNumeric(fromScalarType)
|
||||
&& ScalarTypeFunc::isNumeric(toScalarType)) return true;
|
||||
if(fromScalarType==pvString) return true;
|
||||
if(toScalarType==pvString) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void Convert::copyScalar(PVScalarPtr const & from, PVScalarPtr const & to)
|
||||
{
|
||||
if(to->isImmutable()) {
|
||||
if(from==to) return;
|
||||
String message("Convert.copyScalar destination is immutable");
|
||||
throw std::invalid_argument(message);
|
||||
}
|
||||
to->assign(*from.get());
|
||||
}
|
||||
|
||||
bool Convert::isCopyScalarArrayCompatible(ScalarArrayConstPtr const &fromArray,
|
||||
ScalarArrayConstPtr const &toArray)
|
||||
{
|
||||
ScalarType fromType = fromArray->getElementType();
|
||||
ScalarType toType = toArray->getElementType();
|
||||
if(fromType==toType) return true;
|
||||
if(ScalarTypeFunc::isNumeric(fromType)
|
||||
&& ScalarTypeFunc::isNumeric(toType)) return true;
|
||||
if(toType==pvString) return true;
|
||||
if(fromType==pvString) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Convert::isCopyStructureCompatible(
|
||||
StructureConstPtr const &fromStruct, StructureConstPtr const &toStruct)
|
||||
{
|
||||
FieldConstPtrArray fromFields = fromStruct->getFields();
|
||||
FieldConstPtrArray toFields = toStruct->getFields();
|
||||
size_t length = fromStruct->getNumberFields();
|
||||
if(length!=toStruct->getNumberFields()) return false;
|
||||
for(size_t i=0; i<length; i++) {
|
||||
FieldConstPtr from = fromFields[i];
|
||||
FieldConstPtr to = toFields[i];
|
||||
Type fromType = from->getType();
|
||||
Type toType = to->getType();
|
||||
if(fromType!=toType) return false;
|
||||
switch(fromType) {
|
||||
case scalar:
|
||||
{
|
||||
ScalarConstPtr xxx = static_pointer_cast<const Scalar>(from);
|
||||
ScalarConstPtr yyy = static_pointer_cast<const Scalar>(to);
|
||||
if(!isCopyScalarCompatible(xxx,yyy)) return false;
|
||||
}
|
||||
break;
|
||||
case scalarArray:
|
||||
{
|
||||
ScalarArrayConstPtr xxx = static_pointer_cast<const ScalarArray>(from);
|
||||
ScalarArrayConstPtr yyy = static_pointer_cast<const ScalarArray>(to);
|
||||
if(!isCopyScalarArrayCompatible(xxx,yyy)) return false;
|
||||
}
|
||||
break;
|
||||
case structure:
|
||||
{
|
||||
StructureConstPtr xxx = static_pointer_cast<const Structure>(from);
|
||||
StructureConstPtr yyy = static_pointer_cast<const Structure>(to);
|
||||
if(!isCopyStructureCompatible(xxx,yyy)) return false;
|
||||
}
|
||||
break;
|
||||
case structureArray:
|
||||
{
|
||||
StructureArrayConstPtr xxx = static_pointer_cast<const StructureArray>(from);
|
||||
StructureArrayConstPtr yyy = static_pointer_cast<const StructureArray>(to);
|
||||
if(!isCopyStructureArrayCompatible(xxx,yyy)) return false;
|
||||
}
|
||||
case union_:
|
||||
{
|
||||
UnionConstPtr xxx = static_pointer_cast<const Union>(from);
|
||||
UnionConstPtr yyy = static_pointer_cast<const Union>(to);
|
||||
if(!isCopyUnionCompatible(xxx,yyy)) return false;
|
||||
}
|
||||
break;
|
||||
case unionArray:
|
||||
{
|
||||
UnionArrayConstPtr xxx = static_pointer_cast<const UnionArray>(from);
|
||||
UnionArrayConstPtr yyy = static_pointer_cast<const UnionArray>(to);
|
||||
if(!isCopyUnionArrayCompatible(xxx,yyy)) return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Convert::copyStructure(PVStructurePtr const & from, PVStructurePtr const & to)
|
||||
{
|
||||
if(to->isImmutable()) {
|
||||
if(from==to) return;
|
||||
throw std::invalid_argument("Convert.copyStructure destination is immutable");
|
||||
}
|
||||
if(from==to) return;
|
||||
PVFieldPtrArray const & fromDatas = from->getPVFields();
|
||||
PVFieldPtrArray const & toDatas = to->getPVFields();
|
||||
if(from->getStructure()->getNumberFields()
|
||||
!= to->getStructure()->getNumberFields()) {
|
||||
String message("Convert.copyStructure Illegal copyStructure");
|
||||
throw std::invalid_argument(message);
|
||||
}
|
||||
size_t numberFields = from->getStructure()->getNumberFields();
|
||||
if(numberFields>=2) {
|
||||
String name0 = fromDatas[0]->getFieldName();
|
||||
String name1 = fromDatas[1]->getFieldName();
|
||||
// look for enumerated structure and copy choices first
|
||||
if(name0.compare("index")==0 && name1.compare("choices")==0) {
|
||||
FieldConstPtr fieldIndex = fromDatas[0]->getField();
|
||||
FieldConstPtr fieldChoices = fromDatas[1]->getField();
|
||||
if(fieldIndex->getType()==scalar
|
||||
&& fieldChoices->getType()==scalarArray) {
|
||||
PVScalarPtr pvScalar = static_pointer_cast<PVScalar>(fromDatas[0]);
|
||||
PVScalarArrayPtr pvArray =
|
||||
static_pointer_cast<PVScalarArray>(fromDatas[1]);
|
||||
if((pvScalar->getScalar()->getScalarType()==pvInt)
|
||||
&& (pvArray->getScalarArray()->getElementType()==pvString)) {
|
||||
PVScalarArrayPtr toArray =
|
||||
static_pointer_cast<PVScalarArray>(toDatas[1]);
|
||||
toArray->assign(*pvArray.get());
|
||||
PVScalarPtr toScalar = static_pointer_cast<PVScalar>(toDatas[0]);
|
||||
copyScalar(pvScalar,toScalar);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for(size_t i=0; i < numberFields; i++) {
|
||||
PVFieldPtr fromData = fromDatas[i];
|
||||
PVFieldPtr toData = toDatas[i];
|
||||
Type fromType = fromData->getField()->getType();
|
||||
Type toType = toData->getField()->getType();
|
||||
if(fromType!=toType) {
|
||||
String message("Convert.copyStructure Illegal copyStructure");
|
||||
throw std::invalid_argument(message);
|
||||
}
|
||||
if(toData->isImmutable()) {
|
||||
if(fromData==toData) return;
|
||||
throw std::invalid_argument("Convert.copyStructure destination is immutable");
|
||||
}
|
||||
switch(fromType) {
|
||||
case scalar:
|
||||
{
|
||||
PVScalarPtr xxx = static_pointer_cast<PVScalar>(fromData);
|
||||
PVScalarPtr yyy = static_pointer_cast<PVScalar>(toData);
|
||||
copyScalar(xxx,yyy);
|
||||
break;
|
||||
}
|
||||
case scalarArray:
|
||||
{
|
||||
PVScalarArrayPtr fromArray = static_pointer_cast<PVScalarArray>(fromData);
|
||||
PVScalarArrayPtr toArray = static_pointer_cast<PVScalarArray>(toData);
|
||||
toArray->assign(*fromArray.get());
|
||||
break;
|
||||
}
|
||||
case structure:
|
||||
{
|
||||
PVStructurePtr xxx = static_pointer_cast<PVStructure>(fromData);
|
||||
PVStructurePtr yyy = static_pointer_cast<PVStructure>(toData);
|
||||
copyStructure(xxx,yyy);
|
||||
break;
|
||||
}
|
||||
case structureArray:
|
||||
{
|
||||
PVStructureArrayPtr fromArray =
|
||||
static_pointer_cast<PVStructureArray>(fromData);
|
||||
PVStructureArrayPtr toArray =
|
||||
static_pointer_cast<PVStructureArray>(toData);
|
||||
copyStructureArray(fromArray,toArray);
|
||||
break;
|
||||
}
|
||||
case union_:
|
||||
{
|
||||
PVUnionPtr xxx = static_pointer_cast<PVUnion>(fromData);
|
||||
PVUnionPtr yyy = static_pointer_cast<PVUnion>(toData);
|
||||
copyUnion(xxx,yyy);
|
||||
break;
|
||||
}
|
||||
case unionArray:
|
||||
{
|
||||
PVUnionArrayPtr fromArray =
|
||||
static_pointer_cast<PVUnionArray>(fromData);
|
||||
PVUnionArrayPtr toArray =
|
||||
static_pointer_cast<PVUnionArray>(toData);
|
||||
copyUnionArray(fromArray,toArray);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Convert::isCopyUnionCompatible(
|
||||
UnionConstPtr const &from, UnionConstPtr const &to)
|
||||
{
|
||||
return *(from.get()) == *(to.get());
|
||||
}
|
||||
|
||||
void Convert::copyUnion(PVUnionPtr const & from, PVUnionPtr const & to)
|
||||
{
|
||||
if(to->isImmutable()) {
|
||||
if(from==to) return;
|
||||
throw std::invalid_argument("Convert.copyUnion destination is immutable");
|
||||
}
|
||||
if(from==to) return;
|
||||
if(!isCopyUnionCompatible(from->getUnion(), to->getUnion())) {
|
||||
throw std::invalid_argument("Illegal copyUnion");
|
||||
}
|
||||
|
||||
PVFieldPtr fromValue = from->get();
|
||||
if (from->getUnion()->isVariant())
|
||||
{
|
||||
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
|
||||
copy(fromValue, to->select(from->getSelectedIndex()));
|
||||
}
|
||||
}
|
||||
|
||||
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(StringBuilder buffer, int indentLevel)
|
||||
{
|
||||
*buffer += "\n";
|
||||
*buffer += String(indentLevel*4, ' ');
|
||||
}
|
||||
|
||||
ConvertPtr Convert::getConvert()
|
||||
{
|
||||
static ConvertPtr convert;
|
||||
static Mutex mutex;
|
||||
Lock xx(mutex);
|
||||
|
||||
if(convert.get()==0) {
|
||||
convert = ConvertPtr(new Convert());
|
||||
}
|
||||
return convert;
|
||||
}
|
||||
|
||||
}}
|
||||
1036
src/factory/FieldCreateFactory.cpp
Normal file
1036
src/factory/FieldCreateFactory.cpp
Normal file
File diff suppressed because it is too large
Load Diff
24
src/factory/Makefile
Normal file
24
src/factory/Makefile
Normal file
@@ -0,0 +1,24 @@
|
||||
# This is a Makefile fragment, see ../Makefile
|
||||
|
||||
SRC_DIRS += $(PVDATA_SRC)/factory
|
||||
|
||||
INC += factory.h
|
||||
LIBSRCS += TypeFunc.cpp
|
||||
LIBSRCS += FieldCreateFactory.cpp
|
||||
LIBSRCS += PVAuxInfoImpl.cpp
|
||||
LIBSRCS += PVField.cpp
|
||||
LIBSRCS += PVScalar.cpp
|
||||
LIBSRCS += PVArray.cpp
|
||||
LIBSRCS += PVScalarArray.cpp
|
||||
LIBSRCS += PVStructure.cpp
|
||||
LIBSRCS += PVStructureArray.cpp
|
||||
LIBSRCS += PVUnion.cpp
|
||||
LIBSRCS += PVUnionArray.cpp
|
||||
LIBSRCS += PVDataCreateFactory.cpp
|
||||
LIBSRCS += Convert.cpp
|
||||
LIBSRCS += pvSubArrayCopy.cpp
|
||||
LIBSRCS += Compare.cpp
|
||||
LIBSRCS += StandardField.cpp
|
||||
LIBSRCS += StandardPVField.cpp
|
||||
LIBSRCS += printer.cpp
|
||||
|
||||
56
src/factory/PVArray.cpp
Normal file
56
src/factory/PVArray.cpp
Normal file
@@ -0,0 +1,56 @@
|
||||
/*PVArray.cpp*/
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
*/
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/factory.h>
|
||||
|
||||
using std::size_t;
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
PVArray::PVArray(FieldConstPtr const & field)
|
||||
: PVField(field),capacityMutable(true)
|
||||
{ }
|
||||
|
||||
void PVArray::setImmutable()
|
||||
{
|
||||
capacityMutable = false;
|
||||
PVField::setImmutable();
|
||||
}
|
||||
|
||||
bool PVArray::isCapacityMutable() const
|
||||
{
|
||||
if(PVField::isImmutable()) {
|
||||
return false;
|
||||
}
|
||||
return capacityMutable;
|
||||
}
|
||||
|
||||
void PVArray::setCapacityMutable(bool isMutable)
|
||||
{
|
||||
if(isMutable && PVField::isImmutable()) {
|
||||
throw std::runtime_error("field is immutable");
|
||||
}
|
||||
capacityMutable = isMutable;
|
||||
}
|
||||
|
||||
|
||||
std::ostream& operator<<(format::array_at_internal const& manip, const PVArray& array)
|
||||
{
|
||||
return array.dumpValue(manip.stream, manip.index);
|
||||
}
|
||||
|
||||
}}
|
||||
@@ -11,6 +11,8 @@
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/noDefaultMethods.h>
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/convert.h>
|
||||
@@ -7,13 +7,17 @@
|
||||
/**
|
||||
* @author mrk
|
||||
*/
|
||||
|
||||
#ifdef _WIN32
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/lock.h>
|
||||
#include <pv/pvIntrospect.h>
|
||||
#include <pv/pvData.h>
|
||||
@@ -28,6 +32,32 @@ using std::min;
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
|
||||
template<> const ScalarType PVBoolean::typeCode = pvBoolean;
|
||||
template<> const ScalarType PVByte::typeCode = pvByte;
|
||||
template<> const ScalarType PVShort::typeCode = pvShort;
|
||||
template<> const ScalarType PVInt::typeCode = pvInt;
|
||||
template<> const ScalarType PVLong::typeCode = pvLong;
|
||||
template<> const ScalarType PVUByte::typeCode = pvUByte;
|
||||
template<> const ScalarType PVUShort::typeCode = pvUShort;
|
||||
template<> const ScalarType PVUInt::typeCode = pvUInt;
|
||||
template<> const ScalarType PVULong::typeCode = pvULong;
|
||||
template<> const ScalarType PVFloat::typeCode = pvFloat;
|
||||
template<> const ScalarType PVDouble::typeCode = pvDouble;
|
||||
template<> const ScalarType PVScalarValue<String>::typeCode = pvString;
|
||||
|
||||
template<> const ScalarType PVBooleanArray::typeCode = pvBoolean;
|
||||
template<> const ScalarType PVByteArray::typeCode = pvByte;
|
||||
template<> const ScalarType PVShortArray::typeCode = pvShort;
|
||||
template<> const ScalarType PVIntArray::typeCode = pvInt;
|
||||
template<> const ScalarType PVLongArray::typeCode = pvLong;
|
||||
template<> const ScalarType PVUByteArray::typeCode = pvUByte;
|
||||
template<> const ScalarType PVUShortArray::typeCode = pvUShort;
|
||||
template<> const ScalarType PVUIntArray::typeCode = pvUInt;
|
||||
template<> const ScalarType PVULongArray::typeCode = pvULong;
|
||||
template<> const ScalarType PVFloatArray::typeCode = pvFloat;
|
||||
template<> const ScalarType PVDoubleArray::typeCode = pvDouble;
|
||||
template<> const ScalarType PVStringArray::typeCode = pvString;
|
||||
|
||||
/** Default storage for scalar values
|
||||
*/
|
||||
template<typename T>
|
||||
@@ -170,157 +200,79 @@ public:
|
||||
typedef const std::vector<T> const_vector;
|
||||
typedef std::tr1::shared_ptr<vector> shared_vector;
|
||||
|
||||
typedef ::epics::pvData::shared_vector<T> svector;
|
||||
typedef ::epics::pvData::shared_vector<const T> const_svector;
|
||||
|
||||
DefaultPVArray(ScalarArrayConstPtr const & scalarArray);
|
||||
virtual ~DefaultPVArray();
|
||||
|
||||
virtual size_t getLength() const {return value.size();}
|
||||
virtual size_t getCapacity() const {return value.capacity();}
|
||||
|
||||
virtual void setCapacity(size_t capacity);
|
||||
virtual void setLength(size_t length);
|
||||
virtual size_t get(size_t offset, size_t length, PVArrayData<T> &data) ;
|
||||
virtual size_t put(size_t offset,size_t length, const_pointer from,
|
||||
size_t fromOffset);
|
||||
virtual void shareData(
|
||||
std::tr1::shared_ptr<std::vector<T> > const & value,
|
||||
std::size_t capacity,
|
||||
std::size_t length);
|
||||
virtual pointer get() ;
|
||||
virtual pointer get() const ;
|
||||
virtual vector const & getVector() { return *value.get(); }
|
||||
virtual shared_vector const & getSharedVector(){return value;};
|
||||
|
||||
virtual const_svector view() const {return value;}
|
||||
virtual void swap(const_svector &other);
|
||||
virtual void replace(const const_svector& next);
|
||||
|
||||
// from Serializable
|
||||
virtual void serialize(ByteBuffer *pbuffer,SerializableControl *pflusher) const;
|
||||
virtual void deserialize(ByteBuffer *pbuffer,DeserializableControl *pflusher);
|
||||
virtual void serialize(ByteBuffer *pbuffer,
|
||||
SerializableControl *pflusher, size_t offset, size_t count) const;
|
||||
private:
|
||||
shared_vector value;
|
||||
const_svector value;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
T *DefaultPVArray<T>::get()
|
||||
{
|
||||
std::vector<T> *vec = value.get();
|
||||
T *praw = &((*vec)[0]);
|
||||
return praw;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T *DefaultPVArray<T>::get() const
|
||||
{
|
||||
std::vector<T> *vec = value.get();
|
||||
T *praw = &((*vec)[0]);
|
||||
return praw;
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
DefaultPVArray<T>::DefaultPVArray(ScalarArrayConstPtr const & scalarArray)
|
||||
: PVValueArray<T>(scalarArray),
|
||||
value(std::tr1::shared_ptr<std::vector<T> >(new std::vector<T>()))
|
||||
value()
|
||||
|
||||
{ }
|
||||
|
||||
template<typename T>
|
||||
DefaultPVArray<T>::~DefaultPVArray()
|
||||
{ }
|
||||
|
||||
template<typename T>
|
||||
void DefaultPVArray<T>::setCapacity(size_t capacity)
|
||||
{
|
||||
if(PVArray::getCapacity()==capacity) return;
|
||||
if(!PVArray::isCapacityMutable()) {
|
||||
std::string message("not capacityMutable");
|
||||
PVField::message(message, errorMessage);
|
||||
return;
|
||||
if(this->isCapacityMutable()) {
|
||||
value.reserve(capacity);
|
||||
}
|
||||
size_t length = PVArray::getLength();
|
||||
if(length>capacity) length = capacity;
|
||||
size_t oldCapacity = PVArray::getCapacity();
|
||||
if(oldCapacity>capacity) {
|
||||
std::vector<T> array;
|
||||
array.reserve(capacity);
|
||||
array.resize(length);
|
||||
T * from = get();
|
||||
for (size_t i=0; i<length; i++) array[i] = from[i];
|
||||
value->swap(array);
|
||||
} else {
|
||||
value->reserve(capacity);
|
||||
}
|
||||
PVArray::setCapacityLength(capacity,length);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void DefaultPVArray<T>::setLength(size_t length)
|
||||
{
|
||||
if(PVArray::getLength()==length) return;
|
||||
size_t capacity = PVArray::getCapacity();
|
||||
if(length>capacity) {
|
||||
if(!PVArray::isCapacityMutable()) {
|
||||
std::string message("not capacityMutable");
|
||||
PVField::message(message, errorMessage);
|
||||
return;
|
||||
}
|
||||
setCapacity(length);
|
||||
}
|
||||
value->resize(length);
|
||||
PVArray::setCapacityLength(capacity,length);
|
||||
if(this->isImmutable())
|
||||
THROW_EXCEPTION2(std::logic_error,"Immutable");
|
||||
if(length == value.size())
|
||||
return;
|
||||
else if(length < value.size())
|
||||
value.slice(0, length);
|
||||
else
|
||||
value.resize(length);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
size_t DefaultPVArray<T>::get(size_t offset, size_t len, PVArrayData<T> &data)
|
||||
void DefaultPVArray<T>::replace(const const_svector& next)
|
||||
{
|
||||
size_t n = len;
|
||||
size_t length = this->getLength();
|
||||
if(offset+len > length) {
|
||||
n = length-offset;
|
||||
//if(n<0) n = 0;
|
||||
}
|
||||
data.data = *value.get();
|
||||
data.offset = offset;
|
||||
return n;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
size_t DefaultPVArray<T>::put(size_t offset,size_t len,
|
||||
const_pointer from,size_t fromOffset)
|
||||
{
|
||||
if(PVField::isImmutable()) {
|
||||
PVField::message("field is immutable",errorMessage);
|
||||
return 0;
|
||||
}
|
||||
T * pvalue = get();
|
||||
if(from==pvalue) return len;
|
||||
if(len<1) return 0;
|
||||
size_t length = this->getLength();
|
||||
size_t capacity = this->getCapacity();
|
||||
if(offset+len > length) {
|
||||
size_t newlength = offset + len;
|
||||
if(newlength>capacity) {
|
||||
setCapacity(newlength);
|
||||
newlength = this->getCapacity();
|
||||
len = newlength - offset;
|
||||
if(len<=0) return 0;
|
||||
}
|
||||
length = newlength;
|
||||
setLength(length);
|
||||
}
|
||||
pvalue = get();
|
||||
for(size_t i=0;i<len;i++) {
|
||||
pvalue[i+offset] = from[i+fromOffset];
|
||||
}
|
||||
this->setLength(length);
|
||||
value = next;
|
||||
this->postPut();
|
||||
return len;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void DefaultPVArray<T>::shareData(
|
||||
std::tr1::shared_ptr<std::vector<T> > const & sharedValue,
|
||||
std::size_t capacity,
|
||||
std::size_t length)
|
||||
void DefaultPVArray<T>::swap(const_svector &other)
|
||||
{
|
||||
value = sharedValue;
|
||||
PVArray::setCapacityLength(capacity,length);
|
||||
if(this->isImmutable())
|
||||
THROW_EXCEPTION2(std::logic_error,"Immutable");
|
||||
|
||||
value.swap(other);
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
void DefaultPVArray<T>::serialize(ByteBuffer *pbuffer,
|
||||
SerializableControl *pflusher) const {
|
||||
@@ -331,92 +283,82 @@ template<typename T>
|
||||
void DefaultPVArray<T>::deserialize(ByteBuffer *pbuffer,
|
||||
DeserializableControl *pcontrol) {
|
||||
size_t size = SerializeHelper::readSize(pbuffer, pcontrol);
|
||||
// alignment if (size>0) { pcontrol->ensureData(sizeof(T)-1); pbuffer->align(sizeof(T)); }
|
||||
//if(size>=0) {
|
||||
// prepare array, if necessary
|
||||
if(size>this->getCapacity()) this->setCapacity(size);
|
||||
// set new length
|
||||
this->setLength(size);
|
||||
|
||||
// try to avoid deserializing from the buffer
|
||||
// this is only possible if we do not need to do endian-swapping
|
||||
if (!pbuffer->reverse<T>())
|
||||
if (pcontrol->directDeserialize(pbuffer, (char*)(get()), size, sizeof(T)))
|
||||
{
|
||||
// inform about the change?
|
||||
PVField::postPut();
|
||||
return;
|
||||
}
|
||||
svector nextvalue(thaw(value));
|
||||
nextvalue.resize(size); // TODO: avoid copy of stuff we will then overwrite
|
||||
|
||||
// retrieve value from the buffer
|
||||
size_t i = 0;
|
||||
T * pvalue = get();
|
||||
while(true) {
|
||||
/*
|
||||
size_t maxIndex = min(size-i, (int)(pbuffer->getRemaining()/sizeof(T)))+i;
|
||||
for(; i<maxIndex; i++)
|
||||
value[i] = pbuffer->get<T>();
|
||||
*/
|
||||
size_t maxCount = min(size-i, (pbuffer->getRemaining()/sizeof(T)));
|
||||
pbuffer->getArray(pvalue+i, maxCount);
|
||||
i += maxCount;
|
||||
|
||||
if(i<size)
|
||||
pcontrol->ensureData(sizeof(T)); // this is not OK since can exceen max local buffer (size-i)*sizeof(T));
|
||||
else
|
||||
break;
|
||||
}
|
||||
T* cur = nextvalue.data();
|
||||
|
||||
// try to avoid deserializing from the buffer
|
||||
// this is only possible if we do not need to do endian-swapping
|
||||
if (!pbuffer->reverse<T>())
|
||||
if (pcontrol->directDeserialize(pbuffer, (char*)cur, size, sizeof(T)))
|
||||
{
|
||||
// inform about the change?
|
||||
PVField::postPut();
|
||||
//}
|
||||
// TODO null arrays (size == -1) not supported
|
||||
return;
|
||||
}
|
||||
|
||||
// retrieve value from the buffer
|
||||
size_t remaining = size;
|
||||
while(remaining) {
|
||||
const size_t have_bytes = pbuffer->getRemaining();
|
||||
|
||||
// correctly rounds down in an element is partially received
|
||||
const size_t available = have_bytes/sizeof(T);
|
||||
|
||||
if(available == 0) {
|
||||
// get at least one element
|
||||
pcontrol->ensureData(sizeof(T));
|
||||
continue;
|
||||
}
|
||||
|
||||
const size_t n2read = std::min(remaining, available);
|
||||
|
||||
pbuffer->getArray(cur, n2read);
|
||||
cur += n2read;
|
||||
remaining -= n2read;
|
||||
}
|
||||
value = freeze(nextvalue);
|
||||
// inform about the change?
|
||||
PVField::postPut();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void DefaultPVArray<T>::serialize(ByteBuffer *pbuffer,
|
||||
SerializableControl *pflusher, size_t offset, size_t count) const {
|
||||
// cache
|
||||
size_t length = this->getLength();
|
||||
SerializableControl *pflusher, size_t offset, size_t count) const
|
||||
{
|
||||
//TODO: avoid incrementing the ref counter...
|
||||
const_svector temp(value);
|
||||
temp.slice(offset, count);
|
||||
count = temp.size();
|
||||
|
||||
// check bounds
|
||||
/*if(offset<0)
|
||||
offset = 0;
|
||||
else*/ if(offset>length) offset = length;
|
||||
//if(count<0) count = length;
|
||||
|
||||
size_t maxCount = length-offset;
|
||||
if(count>maxCount) count = maxCount;
|
||||
|
||||
// write
|
||||
SerializeHelper::writeSize(count, pbuffer, pflusher);
|
||||
//if (count == 0) return; pcontrol->ensureData(sizeof(T)-1); pbuffer->align(sizeof(T));
|
||||
SerializeHelper::writeSize(temp.size(), pbuffer, pflusher);
|
||||
|
||||
const T* cur = temp.data();
|
||||
|
||||
// try to avoid copying into the buffer
|
||||
// this is only possible if we do not need to do endian-swapping
|
||||
if (!pbuffer->reverse<T>())
|
||||
if (pflusher->directSerialize(pbuffer, (const char*)(get()+offset), count, sizeof(T)))
|
||||
if (pflusher->directSerialize(pbuffer, (const char*)cur, count, sizeof(T)))
|
||||
return;
|
||||
|
||||
size_t end = offset+count;
|
||||
size_t i = offset;
|
||||
T * pvalue = const_cast<T *>(get());
|
||||
while(true) {
|
||||
|
||||
/*
|
||||
size_t maxIndex = min<int>(end-i, (int)(pbuffer->getRemaining()/sizeof(T)))+i;
|
||||
for(; i<maxIndex; i++)
|
||||
pbuffer->put<T>(value[i]);
|
||||
*/
|
||||
|
||||
size_t maxCount = min<int>(end-i, (int)(pbuffer->getRemaining()/sizeof(T)));
|
||||
pbuffer->putArray(pvalue+i, maxCount);
|
||||
i += maxCount;
|
||||
|
||||
if(i<end)
|
||||
while(count) {
|
||||
const size_t empty = pbuffer->getRemaining();
|
||||
const size_t space_for = empty/sizeof(T);
|
||||
|
||||
if(space_for==0) {
|
||||
pflusher->flushSerializeBuffer();
|
||||
else
|
||||
break;
|
||||
// Can we be certain that more space is now free???
|
||||
// If not then we spinnnnnnnnn
|
||||
continue;
|
||||
}
|
||||
|
||||
const size_t n2send = std::min(count, space_for);
|
||||
|
||||
pbuffer->putArray(cur, n2send);
|
||||
cur += n2send;
|
||||
count -= n2send;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -426,42 +368,37 @@ template<>
|
||||
void DefaultPVArray<String>::deserialize(ByteBuffer *pbuffer,
|
||||
DeserializableControl *pcontrol) {
|
||||
size_t size = SerializeHelper::readSize(pbuffer, pcontrol);
|
||||
//if(size>=0) {
|
||||
// prepare array, if necessary
|
||||
if(size>getCapacity()) setCapacity(size);
|
||||
// set new length
|
||||
setLength(size);
|
||||
// retrieve value from the buffer
|
||||
String * pvalue = get();
|
||||
for(size_t i = 0; i<size; i++) {
|
||||
pvalue[i] = SerializeHelper::deserializeString(pbuffer,
|
||||
pcontrol);
|
||||
}
|
||||
// inform about the change?
|
||||
postPut();
|
||||
//}
|
||||
// TODO null arrays (size == -1) not supported
|
||||
|
||||
svector nextvalue(thaw(value));
|
||||
|
||||
// Decide if we must re-allocate
|
||||
if(size > nextvalue.size() || !nextvalue.unique())
|
||||
nextvalue.resize(size);
|
||||
else if(size < nextvalue.size())
|
||||
nextvalue.slice(0, size);
|
||||
|
||||
|
||||
String * pvalue = nextvalue.data();
|
||||
for(size_t i = 0; i<size; i++) {
|
||||
pvalue[i] = SerializeHelper::deserializeString(pbuffer,
|
||||
pcontrol);
|
||||
}
|
||||
value = freeze(nextvalue);
|
||||
// inform about the change?
|
||||
postPut();
|
||||
}
|
||||
|
||||
template<>
|
||||
void DefaultPVArray<String>::serialize(ByteBuffer *pbuffer,
|
||||
SerializableControl *pflusher, size_t offset, size_t count) const {
|
||||
size_t length = getLength();
|
||||
|
||||
// check bounds
|
||||
/*if(offset<0)
|
||||
offset = 0;
|
||||
else*/ if(offset>length) offset = length;
|
||||
//if(count<0) count = length;
|
||||
const_svector temp(value);
|
||||
temp.slice(offset, count);
|
||||
|
||||
size_t maxCount = length-offset;
|
||||
if(count>maxCount) count = maxCount;
|
||||
SerializeHelper::writeSize(temp.size(), pbuffer, pflusher);
|
||||
|
||||
// write
|
||||
SerializeHelper::writeSize(count, pbuffer, pflusher);
|
||||
size_t end = offset+count;
|
||||
String * pvalue = get();
|
||||
for(size_t i = offset; i<end; i++) {
|
||||
const String * pvalue = temp.data();
|
||||
for(size_t i = 0; i<temp.size(); i++) {
|
||||
SerializeHelper::serializeString(pvalue[i], pbuffer, pflusher);
|
||||
}
|
||||
}
|
||||
@@ -504,6 +441,14 @@ PVFieldPtr PVDataCreate::createPVField(FieldConstPtr const & field)
|
||||
StructureArrayConstPtr xx = static_pointer_cast<const StructureArray>(field);
|
||||
return createPVStructureArray(xx);
|
||||
}
|
||||
case union_: {
|
||||
UnionConstPtr xx = static_pointer_cast<const Union>(field);
|
||||
return createPVUnion(xx);
|
||||
}
|
||||
case unionArray: {
|
||||
UnionArrayConstPtr xx = static_pointer_cast<const UnionArray>(field);
|
||||
return createPVUnionArray(xx);
|
||||
}
|
||||
}
|
||||
throw std::logic_error("PVDataCreate::createPVField should never get here");
|
||||
}
|
||||
@@ -540,6 +485,21 @@ PVFieldPtr PVDataCreate::createPVField(PVFieldPtr const & fieldToClone)
|
||||
getConvert()->copyStructureArray(from, to);
|
||||
return to;
|
||||
}
|
||||
case union_:
|
||||
{
|
||||
PVUnionPtr pvUnion
|
||||
= static_pointer_cast<PVUnion>(fieldToClone);
|
||||
return createPVUnion(pvUnion);
|
||||
}
|
||||
case unionArray:
|
||||
{
|
||||
PVUnionArrayPtr from
|
||||
= static_pointer_cast<PVUnionArray>(fieldToClone);
|
||||
UnionArrayConstPtr unionArray = from->getUnionArray();
|
||||
PVUnionArrayPtr to = createPVUnionArray(unionArray);
|
||||
getConvert()->copyUnionArray(from, to);
|
||||
return to;
|
||||
}
|
||||
}
|
||||
throw std::logic_error("PVDataCreate::createPVField should never get here");
|
||||
}
|
||||
@@ -646,7 +606,7 @@ PVScalarArrayPtr PVDataCreate::createPVScalarArray(
|
||||
{
|
||||
PVScalarArrayPtr pvArray = createPVScalarArray(
|
||||
arrayToClone->getScalarArray()->getElementType());
|
||||
getConvert()->copyScalarArray(arrayToClone,0, pvArray,0,arrayToClone->getLength());
|
||||
pvArray->assign(*arrayToClone.get());
|
||||
PVAuxInfoPtr from = arrayToClone->getPVAuxInfo();
|
||||
PVAuxInfoPtr to = pvArray->getPVAuxInfo();
|
||||
PVAuxInfo::PVInfoMap & map = from->getInfoMap();
|
||||
@@ -672,6 +632,28 @@ PVStructurePtr PVDataCreate::createPVStructure(
|
||||
return PVStructurePtr(new PVStructure(structure));
|
||||
}
|
||||
|
||||
PVUnionArrayPtr PVDataCreate::createPVUnionArray(
|
||||
UnionArrayConstPtr const & unionArray)
|
||||
{
|
||||
return PVUnionArrayPtr(new PVUnionArray(unionArray));
|
||||
}
|
||||
|
||||
PVUnionPtr PVDataCreate::createPVUnion(
|
||||
UnionConstPtr const & punion)
|
||||
{
|
||||
return PVUnionPtr(new PVUnion(punion));
|
||||
}
|
||||
|
||||
PVUnionPtr PVDataCreate::createPVVariantUnion()
|
||||
{
|
||||
return PVUnionPtr(new PVUnion(fieldCreate->createVariantUnion()));
|
||||
}
|
||||
|
||||
PVUnionArrayPtr PVDataCreate::createPVVariantUnionArray()
|
||||
{
|
||||
return PVUnionArrayPtr(new PVUnionArray(fieldCreate->createVariantUnionArray()));
|
||||
}
|
||||
|
||||
PVStructurePtr PVDataCreate::createPVStructure(
|
||||
StringArray const & fieldNames,PVFieldPtrArray const & pvFields)
|
||||
{
|
||||
@@ -687,6 +669,7 @@ PVStructurePtr PVDataCreate::createPVStructure(PVStructurePtr const & structToCl
|
||||
{
|
||||
FieldConstPtrArray field;
|
||||
if(structToClone==0) {
|
||||
// is this correct?!
|
||||
FieldConstPtrArray fields(0);
|
||||
StringArray fieldNames(0);
|
||||
StructureConstPtr structure = fieldCreate->createStructure(fieldNames,fields);
|
||||
@@ -698,6 +681,16 @@ PVStructurePtr PVDataCreate::createPVStructure(PVStructurePtr const & structToCl
|
||||
return pvStructure;
|
||||
}
|
||||
|
||||
PVUnionPtr PVDataCreate::createPVUnion(PVUnionPtr const & unionToClone)
|
||||
{
|
||||
PVUnionPtr punion(new PVUnion(unionToClone->getUnion()));
|
||||
// set cloned value
|
||||
punion->set(unionToClone->getSelectedIndex(), createPVField(unionToClone->get()));
|
||||
return punion;
|
||||
}
|
||||
|
||||
// TODO not thread-safe (local static initializers)
|
||||
// TODO replace with non-locking singleton pattern
|
||||
PVDataCreatePtr PVDataCreate::getPVDataCreate()
|
||||
{
|
||||
static PVDataCreatePtr pvDataCreate;
|
||||
@@ -11,6 +11,8 @@
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/lock.h>
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/factory.h>
|
||||
@@ -26,8 +28,7 @@ PVField::PVField(FieldConstPtr field)
|
||||
: notImplemented("not implemented"),
|
||||
parent(NULL),field(field),
|
||||
fieldOffset(0), nextFieldOffset(0),
|
||||
immutable(false),
|
||||
convert(getConvert())
|
||||
immutable(false)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -64,11 +65,6 @@ void PVField::message(String message,MessageType messageType)
|
||||
PVField::message(message,messageType,"");
|
||||
}
|
||||
|
||||
String PVField::getFieldName() const
|
||||
{
|
||||
return fieldName;
|
||||
}
|
||||
|
||||
void PVField::setRequester(RequesterPtr const &req)
|
||||
{
|
||||
if(parent!=NULL) {
|
||||
@@ -180,7 +176,7 @@ void PVField::setParentAndName(PVStructure * xxx,String const & name)
|
||||
|
||||
bool PVField::equals(PVField &pv)
|
||||
{
|
||||
return convert->equals(*this,pv);
|
||||
return pv==*this;
|
||||
}
|
||||
|
||||
void PVField::toString(StringBuilder buf)
|
||||
@@ -190,7 +186,7 @@ void PVField::toString(StringBuilder buf)
|
||||
|
||||
void PVField::toString(StringBuilder buf,int indentLevel)
|
||||
{
|
||||
convert->getString(buf,this,indentLevel);
|
||||
Convert().getString(buf,this,indentLevel);
|
||||
if(pvAuxInfo.get()!=NULL) pvAuxInfo->toString(buf,indentLevel);
|
||||
}
|
||||
|
||||
@@ -223,6 +219,31 @@ namespace format
|
||||
}
|
||||
};
|
||||
|
||||
String PVField::getFullName() const
|
||||
{
|
||||
size_t size=fieldName.size();
|
||||
|
||||
for(PVField *fld=getParent(); fld; fld=fld->getParent())
|
||||
{
|
||||
size+=fld->fieldName.size()+1;
|
||||
}
|
||||
|
||||
String ret(size, '.');
|
||||
size_t pos=size - fieldName.size();
|
||||
|
||||
ret.replace(pos, String::npos, fieldName);
|
||||
|
||||
for(PVField *fld=getParent(); fld; fld=fld->getParent())
|
||||
{
|
||||
const String& nref = fld->fieldName;
|
||||
assert(pos >= nref.size()+1);
|
||||
pos -= nref.size()+1;
|
||||
ret.replace(pos, String::npos, nref);
|
||||
}
|
||||
assert(pos==0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void PVField::computeOffset(const PVField * pvField) {
|
||||
const PVStructure * pvTop = pvField->getParent();
|
||||
if(pvTop==NULL) {
|
||||
@@ -236,8 +257,8 @@ void PVField::computeOffset(const PVField * pvField) {
|
||||
} else {
|
||||
while(pvTop->getParent()!=NULL) pvTop = pvTop->getParent();
|
||||
}
|
||||
int offset = 0;
|
||||
int nextOffset = 1;
|
||||
size_t offset = 0;
|
||||
size_t nextOffset = 1;
|
||||
PVFieldPtrArray pvFields = pvTop->getPVFields();
|
||||
for(size_t i=0; i < pvTop->getStructure()->getNumberFields(); i++) {
|
||||
offset = nextOffset;
|
||||
@@ -246,7 +267,9 @@ void PVField::computeOffset(const PVField * pvField) {
|
||||
switch(field->getType()) {
|
||||
case scalar:
|
||||
case scalarArray:
|
||||
case structureArray:{
|
||||
case structureArray:
|
||||
case union_:
|
||||
case unionArray: {
|
||||
nextOffset++;
|
||||
pvField->fieldOffset = offset;
|
||||
pvField->nextFieldOffset = nextOffset;
|
||||
@@ -265,8 +288,8 @@ void PVField::computeOffset(const PVField * pvField) {
|
||||
}
|
||||
|
||||
void PVField::computeOffset(const PVField * pvField,size_t offset) {
|
||||
int beginOffset = offset;
|
||||
int nextOffset = offset + 1;
|
||||
size_t beginOffset = offset;
|
||||
size_t nextOffset = offset + 1;
|
||||
const PVStructure *pvStructure = static_cast<const PVStructure *>(pvField);
|
||||
const PVFieldPtrArray pvFields = pvStructure->getPVFields();
|
||||
for(size_t i=0; i < pvStructure->getStructure()->getNumberFields(); i++) {
|
||||
@@ -276,7 +299,9 @@ void PVField::computeOffset(const PVField * pvField,size_t offset) {
|
||||
switch(field->getType()) {
|
||||
case scalar:
|
||||
case scalarArray:
|
||||
case structureArray: {
|
||||
case structureArray:
|
||||
case union_:
|
||||
case unionArray: {
|
||||
nextOffset++;
|
||||
pvSubField->fieldOffset = offset;
|
||||
pvSubField->nextFieldOffset = nextOffset;
|
||||
@@ -11,6 +11,8 @@
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/factory.h>
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/factory.h>
|
||||
|
||||
@@ -28,16 +30,4 @@ namespace epics { namespace pvData {
|
||||
return static_pointer_cast<const ScalarArray>(PVField::getField());
|
||||
}
|
||||
|
||||
template<>
|
||||
std::ostream& PVValueArray<int8>::dumpValue(std::ostream& o, size_t index) const
|
||||
{
|
||||
return o << static_cast<int>(*(get() + index));
|
||||
}
|
||||
|
||||
template<>
|
||||
std::ostream& PVValueArray<uint8>::dumpValue(std::ostream& o, size_t index) const
|
||||
{
|
||||
return o << static_cast<unsigned int>(*(get() + index));
|
||||
}
|
||||
|
||||
}}
|
||||
@@ -12,6 +12,8 @@
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <vector>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/pvIntrospect.h>
|
||||
#include <pv/convert.h>
|
||||
@@ -38,6 +40,8 @@ PVDoublePtr PVStructure::nullPVDouble;
|
||||
PVStringPtr PVStructure::nullPVString;
|
||||
PVStructurePtr PVStructure::nullPVStructure;
|
||||
PVStructureArrayPtr PVStructure::nullPVStructureArray;
|
||||
PVUnionPtr PVStructure::nullPVUnion;
|
||||
PVUnionArrayPtr PVStructure::nullPVUnionArray;
|
||||
PVScalarArrayPtr PVStructure::nullPVScalarArray;
|
||||
|
||||
static PVFieldPtr findSubField(
|
||||
@@ -204,9 +208,6 @@ void PVStructure::removePVField(String const &fieldName)
|
||||
{
|
||||
PVFieldPtr pvField = getSubField(fieldName);
|
||||
if(pvField.get()==NULL) {
|
||||
String message("removePVField ");
|
||||
message += fieldName + " does not exist";
|
||||
this->message(message, errorMessage);
|
||||
return;
|
||||
}
|
||||
size_t origLength = pvFields.size();
|
||||
@@ -240,284 +241,72 @@ void PVStructure::removePVField(String const &fieldName)
|
||||
|
||||
PVBooleanPtr PVStructure::getBooleanField(String const &fieldName)
|
||||
{
|
||||
PVFieldPtr pvField = findSubField(fieldName,this);
|
||||
if(pvField.get()==NULL) {
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not exist";
|
||||
this->message(message, errorMessage);
|
||||
return nullPVBoolean;
|
||||
}
|
||||
if(pvField->getField()->getType()==scalar) {
|
||||
ScalarConstPtr pscalar = static_pointer_cast<const Scalar>(
|
||||
pvField->getField());
|
||||
if(pscalar->getScalarType()==pvBoolean) {
|
||||
return std::tr1::static_pointer_cast<PVBoolean>(pvField);
|
||||
}
|
||||
}
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not have type boolean ";
|
||||
this->message(message, errorMessage);
|
||||
return nullPVBoolean;
|
||||
return getSubField<PVBoolean>(fieldName);
|
||||
}
|
||||
|
||||
PVBytePtr PVStructure::getByteField(String const &fieldName)
|
||||
{
|
||||
PVFieldPtr pvField = findSubField(fieldName,this);
|
||||
if(pvField.get()==NULL) {
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not exist";
|
||||
this->message(message, errorMessage);
|
||||
return nullPVByte;
|
||||
}
|
||||
if(pvField->getField()->getType()==scalar) {
|
||||
ScalarConstPtr pscalar = static_pointer_cast<const Scalar>(
|
||||
pvField->getField());
|
||||
if(pscalar->getScalarType()==pvByte) {
|
||||
return std::tr1::static_pointer_cast<PVByte>(pvField);
|
||||
}
|
||||
}
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not have type byte ";
|
||||
this->message(message, errorMessage);
|
||||
return nullPVByte;
|
||||
return getSubField<PVByte>(fieldName);
|
||||
}
|
||||
|
||||
PVShortPtr PVStructure::getShortField(String const &fieldName)
|
||||
{
|
||||
PVFieldPtr pvField = findSubField(fieldName,this);
|
||||
if(pvField.get()==NULL) {
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not exist";
|
||||
this->message(message, errorMessage);
|
||||
return nullPVShort;
|
||||
}
|
||||
if(pvField->getField()->getType()==scalar) {
|
||||
ScalarConstPtr pscalar = static_pointer_cast<const Scalar>(
|
||||
pvField->getField());
|
||||
if(pscalar->getScalarType()==pvShort) {
|
||||
return std::tr1::static_pointer_cast<PVShort>(pvField);
|
||||
}
|
||||
}
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not have type short ";
|
||||
this->message(message, errorMessage);
|
||||
return nullPVShort;
|
||||
return getSubField<PVShort>(fieldName);
|
||||
}
|
||||
|
||||
PVIntPtr PVStructure::getIntField(String const &fieldName)
|
||||
{
|
||||
PVFieldPtr pvField = findSubField(fieldName,this);
|
||||
if(pvField.get()==NULL) {
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not exist";
|
||||
this->message(message, errorMessage);
|
||||
return nullPVInt;
|
||||
}
|
||||
if(pvField->getField()->getType()==scalar) {
|
||||
ScalarConstPtr pscalar = static_pointer_cast<const Scalar>(
|
||||
pvField->getField());
|
||||
if(pscalar->getScalarType()==pvInt) {
|
||||
return std::tr1::static_pointer_cast<PVInt>(pvField);
|
||||
}
|
||||
}
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not have type int ";
|
||||
this->message(message, errorMessage);
|
||||
return nullPVInt;
|
||||
return getSubField<PVInt>(fieldName);
|
||||
}
|
||||
|
||||
PVLongPtr PVStructure::getLongField(String const &fieldName)
|
||||
{
|
||||
PVFieldPtr pvField = findSubField(fieldName,this);
|
||||
if(pvField.get()==NULL) {
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not exist";
|
||||
this->message(message, errorMessage);
|
||||
return nullPVLong;
|
||||
}
|
||||
if(pvField->getField()->getType()==scalar) {
|
||||
ScalarConstPtr pscalar = static_pointer_cast<const Scalar>(
|
||||
pvField->getField());
|
||||
if(pscalar->getScalarType()==pvLong) {
|
||||
return std::tr1::static_pointer_cast<PVLong>(pvField);
|
||||
}
|
||||
}
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not have type long ";
|
||||
this->message(message, errorMessage);
|
||||
return nullPVLong;
|
||||
return getSubField<PVLong>(fieldName);
|
||||
}
|
||||
|
||||
PVUBytePtr PVStructure::getUByteField(String const &fieldName)
|
||||
{
|
||||
PVFieldPtr pvField = findSubField(fieldName,this);
|
||||
if(pvField.get()==NULL) {
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not exist";
|
||||
this->message(message, errorMessage);
|
||||
return nullPVUByte;
|
||||
}
|
||||
if(pvField->getField()->getType()==scalar) {
|
||||
ScalarConstPtr pscalar = static_pointer_cast<const Scalar>(
|
||||
pvField->getField());
|
||||
if(pscalar->getScalarType()==pvUByte) {
|
||||
return std::tr1::static_pointer_cast<PVUByte>(pvField);
|
||||
}
|
||||
}
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not have type byte ";
|
||||
this->message(message, errorMessage);
|
||||
return nullPVUByte;
|
||||
return getSubField<PVUByte>(fieldName);
|
||||
}
|
||||
|
||||
PVUShortPtr PVStructure::getUShortField(String const &fieldName)
|
||||
{
|
||||
PVFieldPtr pvField = findSubField(fieldName,this);
|
||||
if(pvField.get()==NULL) {
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not exist";
|
||||
this->message(message, errorMessage);
|
||||
return nullPVUShort;
|
||||
}
|
||||
if(pvField->getField()->getType()==scalar) {
|
||||
ScalarConstPtr pscalar = static_pointer_cast<const Scalar>(
|
||||
pvField->getField());
|
||||
if(pscalar->getScalarType()==pvUShort) {
|
||||
return std::tr1::static_pointer_cast<PVUShort>(pvField);
|
||||
}
|
||||
}
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not have type short ";
|
||||
this->message(message, errorMessage);
|
||||
return nullPVUShort;
|
||||
return getSubField<PVUShort>(fieldName);
|
||||
}
|
||||
|
||||
PVUIntPtr PVStructure::getUIntField(String const &fieldName)
|
||||
{
|
||||
PVFieldPtr pvField = findSubField(fieldName,this);
|
||||
if(pvField.get()==NULL) {
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not exist";
|
||||
this->message(message, errorMessage);
|
||||
return nullPVUInt;
|
||||
}
|
||||
if(pvField->getField()->getType()==scalar) {
|
||||
ScalarConstPtr pscalar = static_pointer_cast<const Scalar>(
|
||||
pvField->getField());
|
||||
if(pscalar->getScalarType()==pvUInt) {
|
||||
return std::tr1::static_pointer_cast<PVUInt>(pvField);
|
||||
}
|
||||
}
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not have type int ";
|
||||
this->message(message, errorMessage);
|
||||
return nullPVUInt;
|
||||
return getSubField<PVUInt>(fieldName);
|
||||
}
|
||||
|
||||
PVULongPtr PVStructure::getULongField(String const &fieldName)
|
||||
{
|
||||
PVFieldPtr pvField = findSubField(fieldName,this);
|
||||
if(pvField.get()==NULL) {
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not exist";
|
||||
this->message(message, errorMessage);
|
||||
return nullPVULong;
|
||||
}
|
||||
if(pvField->getField()->getType()==scalar) {
|
||||
ScalarConstPtr pscalar = static_pointer_cast<const Scalar>(
|
||||
pvField->getField());
|
||||
if(pscalar->getScalarType()==pvULong) {
|
||||
return std::tr1::static_pointer_cast<PVULong>(pvField);
|
||||
}
|
||||
}
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not have type long ";
|
||||
this->message(message, errorMessage);
|
||||
return nullPVULong;
|
||||
return getSubField<PVULong>(fieldName);
|
||||
}
|
||||
|
||||
PVFloatPtr PVStructure::getFloatField(String const &fieldName)
|
||||
{
|
||||
PVFieldPtr pvField = findSubField(fieldName,this);
|
||||
if(pvField.get()==NULL) {
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not exist";
|
||||
this->message(message, errorMessage);
|
||||
return nullPVFloat;
|
||||
}
|
||||
if(pvField->getField()->getType()==scalar) {
|
||||
ScalarConstPtr pscalar = static_pointer_cast<const Scalar>(
|
||||
pvField->getField());
|
||||
if(pscalar->getScalarType()==pvFloat) {
|
||||
return std::tr1::static_pointer_cast<PVFloat>(pvField);
|
||||
}
|
||||
}
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not have type float ";
|
||||
this->message(message, errorMessage);
|
||||
return nullPVFloat;
|
||||
return getSubField<PVFloat>(fieldName);
|
||||
}
|
||||
|
||||
PVDoublePtr PVStructure::getDoubleField(String const &fieldName)
|
||||
{
|
||||
PVFieldPtr pvField = findSubField(fieldName,this);
|
||||
if(pvField.get()==NULL) {
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not exist";
|
||||
this->message(message, errorMessage);
|
||||
return nullPVDouble;
|
||||
}
|
||||
if(pvField->getField()->getType()==scalar) {
|
||||
ScalarConstPtr pscalar = static_pointer_cast<const Scalar>(
|
||||
pvField->getField());
|
||||
if(pscalar->getScalarType()==pvDouble) {
|
||||
return std::tr1::static_pointer_cast<PVDouble>(pvField);
|
||||
}
|
||||
}
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not have type double ";
|
||||
this->message(message, errorMessage);
|
||||
return nullPVDouble;
|
||||
return getSubField<PVDouble>(fieldName);
|
||||
}
|
||||
|
||||
PVStringPtr PVStructure::getStringField(String const &fieldName)
|
||||
{
|
||||
PVFieldPtr pvField = findSubField(fieldName,this);
|
||||
if(pvField.get()==NULL) {
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not exist";
|
||||
this->message(message, errorMessage);
|
||||
return nullPVString;
|
||||
}
|
||||
if(pvField->getField()->getType()==scalar) {
|
||||
ScalarConstPtr pscalar = static_pointer_cast<const Scalar>(
|
||||
pvField->getField());
|
||||
if(pscalar->getScalarType()==pvString) {
|
||||
return std::tr1::static_pointer_cast<PVString>(pvField);
|
||||
}
|
||||
}
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not have type string ";
|
||||
this->message(message, errorMessage);
|
||||
return nullPVString;
|
||||
return getSubField<PVString>(fieldName);
|
||||
}
|
||||
|
||||
PVStructurePtr PVStructure::getStructureField(String const &fieldName)
|
||||
{
|
||||
PVFieldPtr pvField = findSubField(fieldName,this);
|
||||
if(pvField.get()==NULL) {
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not exist";
|
||||
this->message(message, errorMessage);
|
||||
return nullPVStructure;
|
||||
}
|
||||
if(pvField->getField()->getType()==structure) {
|
||||
return std::tr1::static_pointer_cast<PVStructure>(pvField);
|
||||
}
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not have type structure ";
|
||||
this->message(message, errorMessage);
|
||||
return nullPVStructure;
|
||||
return getSubField<PVStructure>(fieldName);
|
||||
}
|
||||
|
||||
PVUnionPtr PVStructure::getUnionField(String const &fieldName)
|
||||
{
|
||||
return getSubField<PVUnion>(fieldName);
|
||||
}
|
||||
|
||||
PVScalarArrayPtr PVStructure::getScalarArrayField(
|
||||
@@ -525,26 +314,16 @@ PVScalarArrayPtr PVStructure::getScalarArrayField(
|
||||
{
|
||||
PVFieldPtr pvField = findSubField(fieldName,this);
|
||||
if(pvField.get()==NULL) {
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not exist";
|
||||
this->message(message, errorMessage);
|
||||
return nullPVScalarArray;
|
||||
}
|
||||
FieldConstPtr field = pvField->getField();
|
||||
Type type = field->getType();
|
||||
if(type!=scalarArray) {
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not have type array ";
|
||||
this->message(message, errorMessage);
|
||||
return nullPVScalarArray;
|
||||
}
|
||||
ScalarArrayConstPtr pscalarArray
|
||||
= static_pointer_cast<const ScalarArray>(pvField->getField());
|
||||
if(pscalarArray->getElementType()!=elementType) {
|
||||
String message("fieldName ");
|
||||
message += fieldName + " is array but does not have elementType ";
|
||||
ScalarTypeFunc::toString(&message,elementType);
|
||||
this->message(message, errorMessage);
|
||||
return nullPVScalarArray;
|
||||
}
|
||||
return std::tr1::static_pointer_cast<PVScalarArray>(pvField);
|
||||
@@ -553,20 +332,13 @@ PVScalarArrayPtr PVStructure::getScalarArrayField(
|
||||
PVStructureArrayPtr PVStructure::getStructureArrayField(
|
||||
String const &fieldName)
|
||||
{
|
||||
PVFieldPtr pvField = findSubField(fieldName,this);
|
||||
if(pvField.get()==NULL) {
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not exist";
|
||||
this->message(message, errorMessage);
|
||||
return nullPVStructureArray;
|
||||
}
|
||||
if(pvField->getField()->getType()==structureArray) {
|
||||
return std::tr1::static_pointer_cast<PVStructureArray>(pvField);
|
||||
}
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not have type structureArray ";
|
||||
this->message(message, errorMessage);
|
||||
return nullPVStructureArray;
|
||||
return getSubField<PVStructureArray>(fieldName);
|
||||
}
|
||||
|
||||
PVUnionArrayPtr PVStructure::getUnionArrayField(
|
||||
String const &fieldName)
|
||||
{
|
||||
return getSubField<PVUnionArray>(fieldName);
|
||||
}
|
||||
|
||||
String PVStructure::getExtendsStructureName() const
|
||||
@@ -602,7 +374,7 @@ void PVStructure::serialize(ByteBuffer *pbuffer,
|
||||
PVStructure* nonConstThis = const_cast<PVStructure*>(this);
|
||||
size_t numberFields = nonConstThis->getNumberFields();
|
||||
size_t offset = nonConstThis->getFieldOffset();
|
||||
int32 next = pbitSet->nextSetBit(offset);
|
||||
int32 next = pbitSet->nextSetBit(static_cast<uint32>(offset));
|
||||
|
||||
// no more changes or no changes in this structure
|
||||
if(next<0||next>=static_cast<int32>(offset+numberFields)) return;
|
||||
@@ -617,8 +389,8 @@ void PVStructure::serialize(ByteBuffer *pbuffer,
|
||||
for(size_t i = 0; i<fieldsSize; i++) {
|
||||
PVFieldPtr pvField = pvFields[i];
|
||||
offset = pvField->getFieldOffset();
|
||||
int32 inumberFields = pvField->getNumberFields();
|
||||
next = pbitSet->nextSetBit(offset);
|
||||
int32 inumberFields = static_cast<int32>(pvField->getNumberFields());
|
||||
next = pbitSet->nextSetBit(static_cast<uint32>(offset));
|
||||
|
||||
// no more changes
|
||||
if(next<0) return;
|
||||
@@ -639,7 +411,7 @@ void PVStructure::deserialize(ByteBuffer *pbuffer,
|
||||
DeserializableControl *pcontrol, BitSet *pbitSet) {
|
||||
size_t offset = getFieldOffset();
|
||||
size_t numberFields = getNumberFields();
|
||||
int32 next = pbitSet->nextSetBit(offset);
|
||||
int32 next = pbitSet->nextSetBit(static_cast<uint32>(offset));
|
||||
|
||||
// no more changes or no changes in this structure
|
||||
if(next<0||next>=static_cast<int32>(offset+numberFields)) return;
|
||||
@@ -654,8 +426,8 @@ void PVStructure::deserialize(ByteBuffer *pbuffer,
|
||||
for(size_t i = 0; i<fieldsSize; i++) {
|
||||
PVFieldPtr pvField = pvFields[i];
|
||||
offset = pvField->getFieldOffset();
|
||||
int32 inumberFields = pvField->getNumberFields();
|
||||
next = pbitSet->nextSetBit(offset);
|
||||
int32 inumberFields = static_cast<int32>(pvField->getNumberFields());
|
||||
next = pbitSet->nextSetBit(static_cast<uint32>(offset));
|
||||
// no more changes
|
||||
if(next<0) return;
|
||||
// no change in this pvField
|
||||
217
src/factory/PVStructureArray.cpp
Normal file
217
src/factory/PVStructureArray.cpp
Normal file
@@ -0,0 +1,217 @@
|
||||
/*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.
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
*/
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/convert.h>
|
||||
#include <pv/factory.h>
|
||||
#include <pv/serializeHelper.h>
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using std::size_t;
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
size_t PVStructureArray::append(size_t number)
|
||||
{
|
||||
svector data(reuse());
|
||||
data.resize(data.size()+number);
|
||||
|
||||
StructureConstPtr structure = structureArray->getStructure();
|
||||
|
||||
PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
||||
for(svector::reverse_iterator it = data.rbegin(); number; ++it, --number)
|
||||
*it = pvDataCreate->createPVStructure(structure);
|
||||
|
||||
size_t newLength = data.size();
|
||||
|
||||
const_svector cdata(freeze(data));
|
||||
swap(cdata);
|
||||
|
||||
return newLength;
|
||||
}
|
||||
|
||||
bool PVStructureArray::remove(size_t offset,size_t number)
|
||||
{
|
||||
if(number==0)
|
||||
return true;
|
||||
else if(offset+number>getLength())
|
||||
return false;
|
||||
|
||||
svector vec(reuse());
|
||||
|
||||
size_t length = vec.size();
|
||||
|
||||
for(size_t i = offset; i+number < length; i++) {
|
||||
vec[i].swap(vec[i + number]);
|
||||
}
|
||||
|
||||
vec.resize(length - number);
|
||||
const_svector cdata(freeze(vec));
|
||||
swap(cdata);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PVStructureArray::compress() {
|
||||
svector vec(reuse()); // TODO: check for first NULL before realloc
|
||||
|
||||
size_t length = vec.size();
|
||||
size_t newLength = 0;
|
||||
|
||||
for(size_t i=0; i<length; i++) {
|
||||
if(vec[i].get()!=NULL) {
|
||||
newLength++;
|
||||
continue;
|
||||
}
|
||||
// find first non 0
|
||||
size_t notNull = 0;
|
||||
for(size_t j=i+1;j<length;j++) {
|
||||
if(vec[j].get()!=NULL) {
|
||||
notNull = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(notNull!=0) {
|
||||
vec[i] = vec[notNull];
|
||||
vec[notNull].reset();
|
||||
newLength++;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
vec.resize(newLength);
|
||||
const_svector cdata(freeze(vec));
|
||||
swap(cdata);
|
||||
}
|
||||
|
||||
void PVStructureArray::setCapacity(size_t capacity)
|
||||
{
|
||||
if(this->isCapacityMutable()) {
|
||||
const_svector value;
|
||||
swap(value);
|
||||
if(value.capacity()<capacity) {
|
||||
svector mvalue(thaw(value));
|
||||
mvalue.reserve(capacity);
|
||||
value = freeze(mvalue);
|
||||
}
|
||||
swap(value);
|
||||
}
|
||||
}
|
||||
|
||||
void PVStructureArray::setLength(size_t length)
|
||||
{
|
||||
if(this->isImmutable())
|
||||
THROW_EXCEPTION2(std::logic_error,"Immutable");
|
||||
const_svector value;
|
||||
swap(value);
|
||||
if(length == value.size()) {
|
||||
// nothing
|
||||
} else if(length < value.size()) {
|
||||
value.slice(0, length);
|
||||
} else {
|
||||
svector mvalue(thaw(value));
|
||||
mvalue.resize(length);
|
||||
value = freeze(mvalue);
|
||||
}
|
||||
swap(value);
|
||||
}
|
||||
|
||||
void PVStructureArray::swap(const_svector &other)
|
||||
{
|
||||
if(this->isImmutable())
|
||||
THROW_EXCEPTION2(std::logic_error,"Immutable");
|
||||
|
||||
value.swap(other);
|
||||
}
|
||||
|
||||
void PVStructureArray::serialize(ByteBuffer *pbuffer,
|
||||
SerializableControl *pflusher) const {
|
||||
serialize(pbuffer, pflusher, 0, getLength());
|
||||
}
|
||||
|
||||
void PVStructureArray::deserialize(ByteBuffer *pbuffer,
|
||||
DeserializableControl *pcontrol) {
|
||||
svector data(reuse());
|
||||
|
||||
size_t size = SerializeHelper::readSize(pbuffer, pcontrol);
|
||||
data.resize(size);
|
||||
|
||||
StructureConstPtr structure = structureArray->getStructure();
|
||||
|
||||
PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
||||
|
||||
for(size_t i = 0; i<size; i++) {
|
||||
pcontrol->ensureData(1);
|
||||
size_t temp = pbuffer->getByte();
|
||||
if(temp==0) {
|
||||
data[i].reset();
|
||||
}
|
||||
else {
|
||||
if(data[i].get()==NULL) {
|
||||
data[i] = pvDataCreate->createPVStructure(structure);
|
||||
}
|
||||
data[i]->deserialize(pbuffer, pcontrol);
|
||||
}
|
||||
}
|
||||
replace(freeze(data)); // calls postPut()
|
||||
}
|
||||
|
||||
void PVStructureArray::serialize(ByteBuffer *pbuffer,
|
||||
SerializableControl *pflusher, size_t offset, size_t count) const {
|
||||
|
||||
const_svector temp(view());
|
||||
temp.slice(offset, count);
|
||||
|
||||
SerializeHelper::writeSize(temp.size(), pbuffer, pflusher);
|
||||
|
||||
for(size_t i = 0; i<count; i++) {
|
||||
if(pbuffer->getRemaining()<1)
|
||||
pflusher->flushSerializeBuffer();
|
||||
|
||||
if(temp[i].get()==NULL) {
|
||||
pbuffer->putByte(0);
|
||||
}
|
||||
else {
|
||||
pbuffer->putByte(1);
|
||||
temp[i]->serialize(pbuffer, pflusher);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::ostream& PVStructureArray::dumpValue(std::ostream& o) const
|
||||
{
|
||||
o << format::indent() << getStructureArray()->getID() << ' ' << getFieldName() << std::endl;
|
||||
size_t length = getLength();
|
||||
if (length > 0)
|
||||
{
|
||||
format::indent_scope s(o);
|
||||
|
||||
for (size_t i = 0; i < length; i++)
|
||||
dumpValue(o, i);
|
||||
}
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
std::ostream& PVStructureArray::dumpValue(std::ostream& o, std::size_t index) const
|
||||
{
|
||||
const_svector temp(view());
|
||||
if(index<temp.size())
|
||||
o << *temp[index];
|
||||
return o;
|
||||
}
|
||||
|
||||
}}
|
||||
210
src/factory/PVUnion.cpp
Normal file
210
src/factory/PVUnion.cpp
Normal file
@@ -0,0 +1,210 @@
|
||||
/*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.
|
||||
*/
|
||||
/**
|
||||
* @author mse
|
||||
*/
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <vector>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/pvIntrospect.h>
|
||||
#include <pv/convert.h>
|
||||
#include <pv/factory.h>
|
||||
#include <pv/serializeHelper.h>
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using std::size_t;
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
#define PVUNION_UNDEFINED_INDEX -1
|
||||
int32 PVUnion::UNDEFINED_INDEX = PVUNION_UNDEFINED_INDEX;
|
||||
|
||||
PVUnion::PVUnion(UnionConstPtr const & unionPtr)
|
||||
: PVField(unionPtr),
|
||||
unionPtr(unionPtr),
|
||||
selector(PVUNION_UNDEFINED_INDEX), // to allow out-of-order static initialization
|
||||
value(),
|
||||
variant(unionPtr->isVariant())
|
||||
{
|
||||
}
|
||||
|
||||
#undef PVUNION_UNDEFINED_INDEX
|
||||
|
||||
PVUnion::~PVUnion()
|
||||
{
|
||||
}
|
||||
|
||||
UnionConstPtr PVUnion::getUnion() const
|
||||
{
|
||||
return unionPtr;
|
||||
}
|
||||
|
||||
PVFieldPtr PVUnion::get() const
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
int32 PVUnion::getSelectedIndex() const
|
||||
{
|
||||
return selector;
|
||||
}
|
||||
|
||||
String PVUnion::getSelectedFieldName() const
|
||||
{
|
||||
// no name for undefined and for variant unions
|
||||
if (selector == UNDEFINED_INDEX)
|
||||
return String();
|
||||
else
|
||||
return unionPtr->getFieldName(selector);
|
||||
}
|
||||
|
||||
PVFieldPtr PVUnion::select(int32 index)
|
||||
{
|
||||
// no change
|
||||
if (selector == index)
|
||||
return value;
|
||||
|
||||
if (index == UNDEFINED_INDEX)
|
||||
{
|
||||
selector = UNDEFINED_INDEX;
|
||||
value.reset();
|
||||
return value;
|
||||
}
|
||||
else if (variant)
|
||||
throw std::invalid_argument("index out of bounds");
|
||||
else if (index < 0 || index > static_cast<int32>(unionPtr->getFields().size()))
|
||||
throw std::invalid_argument("index out of bounds");
|
||||
|
||||
FieldConstPtr field = unionPtr->getField(index);
|
||||
selector = index;
|
||||
value = getPVDataCreate()->createPVField(field);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
PVFieldPtr PVUnion::select(String const & fieldName)
|
||||
{
|
||||
int32 index = variant ? -1 : static_cast<int32>(unionPtr->getFieldIndex(fieldName));
|
||||
if (index == -1)
|
||||
throw std::invalid_argument("no such fieldName");
|
||||
return select(index);
|
||||
}
|
||||
|
||||
void PVUnion::set(PVFieldPtr const & value)
|
||||
{
|
||||
set(selector, value);
|
||||
}
|
||||
|
||||
void PVUnion::set(int32 index, PVFieldPtr const & value)
|
||||
{
|
||||
if (variant && index != UNDEFINED_INDEX)
|
||||
throw std::invalid_argument("index out of bounds");
|
||||
else if (!variant)
|
||||
{
|
||||
if (index == UNDEFINED_INDEX)
|
||||
{
|
||||
// for undefined index we accept only null values
|
||||
if (value.get())
|
||||
throw std::invalid_argument("non-null value for index == UNDEFINED_INDEX");
|
||||
}
|
||||
else if (index < 0 || index > static_cast<int32>(unionPtr->getFields().size()))
|
||||
throw std::invalid_argument("index out of bounds");
|
||||
|
||||
// value type must match
|
||||
if (value->getField() != unionPtr->getField(index))
|
||||
throw std::invalid_argument("selected field and its introspection data do not match");
|
||||
}
|
||||
|
||||
selector = index;
|
||||
this->value = value;
|
||||
}
|
||||
|
||||
void PVUnion::set(String const & fieldName, PVFieldPtr const & value)
|
||||
{
|
||||
int32 index = variant ? -1 : static_cast<int32>(unionPtr->getFieldIndex(fieldName));
|
||||
if (index == -1)
|
||||
throw std::invalid_argument("no such fieldName");
|
||||
|
||||
set(index, value);
|
||||
}
|
||||
|
||||
void PVUnion::serialize(ByteBuffer *pbuffer, SerializableControl *pflusher) const
|
||||
{
|
||||
if (variant)
|
||||
{
|
||||
// write introspection data
|
||||
if (value.get() == 0)
|
||||
pbuffer->put((int8)-1);
|
||||
else
|
||||
{
|
||||
pflusher->cachedSerialize(value->getField(), pbuffer);
|
||||
value->serialize(pbuffer, pflusher);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// write selector value
|
||||
SerializeHelper::writeSize(selector, pbuffer, pflusher);
|
||||
// write value, no value for UNDEFINED_INDEX
|
||||
if (selector != UNDEFINED_INDEX)
|
||||
value->serialize(pbuffer, pflusher);
|
||||
}
|
||||
}
|
||||
|
||||
void PVUnion::deserialize(ByteBuffer *pbuffer, DeserializableControl *pcontrol)
|
||||
{
|
||||
if (variant)
|
||||
{
|
||||
FieldConstPtr field = pcontrol->cachedDeserialize(pbuffer);
|
||||
if (field.get())
|
||||
{
|
||||
value = getPVDataCreate()->createPVField(field);
|
||||
value->deserialize(pbuffer, pcontrol);
|
||||
}
|
||||
else
|
||||
value.reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
selector = static_cast<int32>(SerializeHelper::readSize(pbuffer, pcontrol));
|
||||
if (selector != UNDEFINED_INDEX)
|
||||
{
|
||||
FieldConstPtr field = unionPtr->getField(selector);
|
||||
value = getPVDataCreate()->createPVField(field);
|
||||
value->deserialize(pbuffer, pcontrol);
|
||||
}
|
||||
else
|
||||
value.reset();
|
||||
}
|
||||
}
|
||||
|
||||
std::ostream& PVUnion::dumpValue(std::ostream& o) const
|
||||
{
|
||||
o << format::indent() << getUnion()->getID() << ' ' << getFieldName() << std::endl;
|
||||
{
|
||||
format::indent_scope s(o);
|
||||
PVFieldPtr fieldField = get();
|
||||
if (fieldField.get() == NULL)
|
||||
o << format::indent() << "(none)" << std::endl;
|
||||
else
|
||||
{
|
||||
Type type = fieldField->getField()->getType();
|
||||
if (type == scalar || type == scalarArray)
|
||||
o << format::indent() << fieldField->getField()->getID() << ' ' << fieldField->getFieldName() << ' ' << *(fieldField.get()) << std::endl;
|
||||
else
|
||||
o << *(fieldField.get());
|
||||
}
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
}}
|
||||
217
src/factory/PVUnionArray.cpp
Normal file
217
src/factory/PVUnionArray.cpp
Normal file
@@ -0,0 +1,217 @@
|
||||
/*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.
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
*/
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/convert.h>
|
||||
#include <pv/factory.h>
|
||||
#include <pv/serializeHelper.h>
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using std::size_t;
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
size_t PVUnionArray::append(size_t number)
|
||||
{
|
||||
svector data(reuse());
|
||||
data.resize(data.size()+number);
|
||||
|
||||
UnionConstPtr punion = unionArray->getUnion();
|
||||
|
||||
PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
||||
for(svector::reverse_iterator it = data.rbegin(); number; ++it, --number)
|
||||
*it = pvDataCreate->createPVUnion(punion);
|
||||
|
||||
size_t newLength = data.size();
|
||||
|
||||
const_svector cdata(freeze(data));
|
||||
swap(cdata);
|
||||
|
||||
return newLength;
|
||||
}
|
||||
|
||||
bool PVUnionArray::remove(size_t offset,size_t number)
|
||||
{
|
||||
if(number==0)
|
||||
return true;
|
||||
else if(offset+number>getLength())
|
||||
return false;
|
||||
|
||||
svector vec(reuse());
|
||||
|
||||
size_t length = vec.size();
|
||||
|
||||
for(size_t i = offset; i+number < length; i++) {
|
||||
vec[i].swap(vec[i + number]);
|
||||
}
|
||||
|
||||
vec.resize(length - number);
|
||||
const_svector cdata(freeze(vec));
|
||||
swap(cdata);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PVUnionArray::compress() {
|
||||
svector vec(reuse()); // TODO: check for first NULL before realloc
|
||||
|
||||
size_t length = vec.size();
|
||||
size_t newLength = 0;
|
||||
|
||||
for(size_t i=0; i<length; i++) {
|
||||
if(vec[i].get()!=NULL) {
|
||||
newLength++;
|
||||
continue;
|
||||
}
|
||||
// find first non 0
|
||||
size_t notNull = 0;
|
||||
for(size_t j=i+1;j<length;j++) {
|
||||
if(vec[j].get()!=NULL) {
|
||||
notNull = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(notNull!=0) {
|
||||
vec[i] = vec[notNull];
|
||||
vec[notNull].reset();
|
||||
newLength++;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
vec.resize(newLength);
|
||||
const_svector cdata(freeze(vec));
|
||||
swap(cdata);
|
||||
}
|
||||
|
||||
void PVUnionArray::setCapacity(size_t capacity)
|
||||
{
|
||||
if(this->isCapacityMutable()) {
|
||||
const_svector value;
|
||||
swap(value);
|
||||
if(value.capacity()<capacity) {
|
||||
svector mvalue(thaw(value));
|
||||
mvalue.reserve(capacity);
|
||||
value = freeze(mvalue);
|
||||
}
|
||||
swap(value);
|
||||
}
|
||||
}
|
||||
|
||||
void PVUnionArray::setLength(size_t length)
|
||||
{
|
||||
if(this->isImmutable())
|
||||
THROW_EXCEPTION2(std::logic_error,"Immutable");
|
||||
const_svector value;
|
||||
swap(value);
|
||||
if(length == value.size()) {
|
||||
// nothing
|
||||
} else if(length < value.size()) {
|
||||
value.slice(0, length);
|
||||
} else {
|
||||
svector mvalue(thaw(value));
|
||||
mvalue.resize(length);
|
||||
value = freeze(mvalue);
|
||||
}
|
||||
swap(value);
|
||||
}
|
||||
|
||||
void PVUnionArray::swap(const_svector &other)
|
||||
{
|
||||
if(this->isImmutable())
|
||||
THROW_EXCEPTION2(std::logic_error,"Immutable");
|
||||
|
||||
value.swap(other);
|
||||
}
|
||||
|
||||
void PVUnionArray::serialize(ByteBuffer *pbuffer,
|
||||
SerializableControl *pflusher) const {
|
||||
serialize(pbuffer, pflusher, 0, getLength());
|
||||
}
|
||||
|
||||
void PVUnionArray::deserialize(ByteBuffer *pbuffer,
|
||||
DeserializableControl *pcontrol) {
|
||||
svector data(reuse());
|
||||
|
||||
size_t size = SerializeHelper::readSize(pbuffer, pcontrol);
|
||||
data.resize(size);
|
||||
|
||||
UnionConstPtr punion = unionArray->getUnion();
|
||||
|
||||
PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
||||
|
||||
for(size_t i = 0; i<size; i++) {
|
||||
pcontrol->ensureData(1);
|
||||
size_t temp = pbuffer->getByte();
|
||||
if(temp==0) {
|
||||
data[i].reset();
|
||||
}
|
||||
else {
|
||||
if(data[i].get()==NULL) {
|
||||
data[i] = pvDataCreate->createPVUnion(punion);
|
||||
}
|
||||
data[i]->deserialize(pbuffer, pcontrol);
|
||||
}
|
||||
}
|
||||
replace(freeze(data)); // calls postPut()
|
||||
}
|
||||
|
||||
void PVUnionArray::serialize(ByteBuffer *pbuffer,
|
||||
SerializableControl *pflusher, size_t offset, size_t count) const {
|
||||
|
||||
const_svector temp(view());
|
||||
temp.slice(offset, count);
|
||||
|
||||
SerializeHelper::writeSize(temp.size(), pbuffer, pflusher);
|
||||
|
||||
for(size_t i = 0; i<count; i++) {
|
||||
if(pbuffer->getRemaining()<1)
|
||||
pflusher->flushSerializeBuffer();
|
||||
|
||||
if(temp[i].get()==NULL) {
|
||||
pbuffer->putByte(0);
|
||||
}
|
||||
else {
|
||||
pbuffer->putByte(1);
|
||||
temp[i]->serialize(pbuffer, pflusher);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::ostream& PVUnionArray::dumpValue(std::ostream& o) const
|
||||
{
|
||||
o << format::indent() << getUnionArray()->getID() << ' ' << getFieldName() << std::endl;
|
||||
size_t length = getLength();
|
||||
if (length > 0)
|
||||
{
|
||||
format::indent_scope s(o);
|
||||
|
||||
for (size_t i = 0; i < length; i++)
|
||||
dumpValue(o, i);
|
||||
}
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
std::ostream& PVUnionArray::dumpValue(std::ostream& o, std::size_t index) const
|
||||
{
|
||||
const_svector temp(view());
|
||||
if(index<temp.size())
|
||||
o << *temp[index];
|
||||
return o;
|
||||
}
|
||||
|
||||
}}
|
||||
@@ -10,8 +10,8 @@
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <stdexcept>
|
||||
#include <epicsThread.h>
|
||||
#include <epicsExit.h>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/lock.h>
|
||||
#include <pv/pvIntrospect.h>
|
||||
#include <pv/standardField.h>
|
||||
@@ -9,8 +9,8 @@
|
||||
*/
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <epicsThread.h>
|
||||
#include <epicsExit.h>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/lock.h>
|
||||
#include <pv/pvIntrospect.h>
|
||||
#include <pv/pvData.h>
|
||||
@@ -59,11 +59,9 @@ PVStructurePtr StandardPVField::enumerated(StringArray const &choices)
|
||||
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(field);
|
||||
PVScalarArrayPtr pvScalarArray = pvStructure->getScalarArrayField(
|
||||
"choices",pvString);
|
||||
if(pvScalarArray.get()==NULL) {
|
||||
throw std::logic_error(String("StandardPVField::enumerated"));
|
||||
}
|
||||
PVStringArray * pvChoices = static_cast<PVStringArray *>(pvScalarArray.get());
|
||||
pvChoices->put(0,choices.size(),get(choices),0);
|
||||
PVStringArray::svector cdata(choices.size());
|
||||
std::copy(choices.begin(), choices.end(), cdata.begin());
|
||||
static_cast<PVStringArray&>(*pvScalarArray).replace(freeze(cdata));
|
||||
return pvStructure;
|
||||
}
|
||||
|
||||
@@ -74,11 +72,9 @@ PVStructurePtr StandardPVField::enumerated(
|
||||
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(field);
|
||||
PVScalarArrayPtr pvScalarArray = pvStructure->getScalarArrayField(
|
||||
"value.choices",pvString);
|
||||
if(pvScalarArray.get()==NULL) {
|
||||
throw std::logic_error(String("StandardPVField::enumerated"));
|
||||
}
|
||||
PVStringArray * pvChoices = static_cast<PVStringArray *>(pvScalarArray.get());
|
||||
pvChoices->put(0,choices.size(),get(choices),0);
|
||||
PVStringArray::svector cdata(choices.size());
|
||||
std::copy(choices.begin(), choices.end(), cdata.begin());
|
||||
static_cast<PVStringArray&>(*pvScalarArray).replace(freeze(cdata));
|
||||
return pvStructure;
|
||||
}
|
||||
|
||||
@@ -12,8 +12,10 @@
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/pvIntrospect.h>
|
||||
#include <pv/epicsException.h>
|
||||
#include <pv/sharedVector.h>
|
||||
|
||||
#include "dbDefs.h" // for NELEMENTS
|
||||
|
||||
@@ -21,10 +23,10 @@ namespace epics { namespace pvData {
|
||||
|
||||
namespace TypeFunc {
|
||||
static const char* names[] = {
|
||||
"scalar", "scalarArray", "structure", "structureArray",
|
||||
"scalar", "scalarArray", "structure", "structureArray", "union", "unionArray"
|
||||
};
|
||||
const char* name(Type t) {
|
||||
if (t<int(pvBoolean) || t>int(pvString))
|
||||
if (t<int(scalar) || t>int(unionArray))
|
||||
THROW_EXCEPTION2(std::invalid_argument, "logic error unknown Type");
|
||||
return names[t];
|
||||
}
|
||||
@@ -61,7 +63,7 @@ namespace ScalarTypeFunc {
|
||||
"ubyte", "ushort", "uint", "ulong",
|
||||
"float", "double", "string",
|
||||
};
|
||||
ScalarType getScalarType(String pvalue) {
|
||||
ScalarType getScalarType(const String& pvalue) {
|
||||
for(size_t i=0; i<NELEMENTS(names); i++)
|
||||
if(pvalue==names[i])
|
||||
return ScalarType(i);
|
||||
@@ -78,6 +80,50 @@ namespace ScalarTypeFunc {
|
||||
*buf += name(scalarType);
|
||||
}
|
||||
|
||||
size_t elementSize(ScalarType id)
|
||||
{
|
||||
switch(id) {
|
||||
#define OP(ENUM, TYPE) case ENUM: return sizeof(TYPE)
|
||||
OP(pvBoolean, boolean);
|
||||
OP(pvUByte, uint8);
|
||||
OP(pvByte, int8);
|
||||
OP(pvUShort, uint16);
|
||||
OP(pvShort, int16);
|
||||
OP(pvUInt, uint32);
|
||||
OP(pvInt, int32);
|
||||
OP(pvULong, uint64);
|
||||
OP(pvLong, int64);
|
||||
OP(pvFloat, float);
|
||||
OP(pvDouble, double);
|
||||
OP(pvString, String);
|
||||
#undef OP
|
||||
default:
|
||||
THROW_EXCEPTION2(std::invalid_argument, "error unknown ScalarType");
|
||||
}
|
||||
}
|
||||
|
||||
shared_vector<void> allocArray(ScalarType id, size_t len)
|
||||
{
|
||||
switch(id) {
|
||||
#define OP(ENUM, TYPE) case ENUM: return static_shared_vector_cast<void>(shared_vector<TYPE>(len))
|
||||
OP(pvBoolean, boolean);
|
||||
OP(pvUByte, uint8);
|
||||
OP(pvByte, int8);
|
||||
OP(pvUShort, uint16);
|
||||
OP(pvShort, int16);
|
||||
OP(pvUInt, uint32);
|
||||
OP(pvInt, int32);
|
||||
OP(pvULong, uint64);
|
||||
OP(pvLong, int64);
|
||||
OP(pvFloat, float);
|
||||
OP(pvDouble, double);
|
||||
OP(pvString, String);
|
||||
#undef OP
|
||||
default:
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ScalarTypeFunc
|
||||
|
||||
}}
|
||||
270
src/factory/printer.cpp
Normal file
270
src/factory/printer.cpp
Normal file
@@ -0,0 +1,270 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
#include <deque>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/printer.h>
|
||||
|
||||
namespace {
|
||||
|
||||
void indentN(std::ostream& strm, size_t N)
|
||||
{
|
||||
while(N--)
|
||||
strm.put(' ');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
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*)▮
|
||||
|
||||
/* 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();
|
||||
String ename(pv.getExtendsStructureName());
|
||||
if(!ename.empty())
|
||||
S() << " extends " << ename;
|
||||
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;
|
||||
}
|
||||
|
||||
}}
|
||||
204
src/factory/pvSubArrayCopy.cpp
Normal file
204
src/factory/pvSubArrayCopy.cpp
Normal file
@@ -0,0 +1,204 @@
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author Marty Kraimer
|
||||
* @date 2013.07
|
||||
*/
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <memory>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/pvSubArrayCopy.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
template<typename T>
|
||||
void copy(
|
||||
PVValueArray<T> & pvFrom,
|
||||
size_t fromOffset,
|
||||
PVValueArray<T> & pvTo,
|
||||
size_t toOffset,
|
||||
size_t len)
|
||||
{
|
||||
if(pvTo.isImmutable()) {
|
||||
throw std::logic_error("pvSubArrayCopy to is immutable");
|
||||
}
|
||||
size_t fromLength = pvFrom.getLength();
|
||||
if(fromOffset+len>fromLength) {
|
||||
throw std::length_error("pvSubArrayCopy from length error");
|
||||
}
|
||||
size_t capacity = pvTo.getCapacity();
|
||||
if(toOffset+len>capacity) capacity = toOffset + len;
|
||||
shared_vector<T> temp(capacity);
|
||||
typename PVValueArray<T>::const_svector vecFrom = pvFrom.view();
|
||||
typename PVValueArray<T>::const_svector vecTo = pvTo.view();
|
||||
for(size_t i=0; i<toOffset; ++i) temp[i] = vecTo[i];
|
||||
for(size_t i=0; i<len; ++i) temp[i + toOffset] = vecFrom[i + fromOffset];
|
||||
for(size_t i=len + toOffset; i<capacity; ++i) temp[i] = vecTo[i];
|
||||
shared_vector<const T> temp2(freeze(temp));
|
||||
pvTo.replace(temp2);
|
||||
}
|
||||
|
||||
void copy(
|
||||
PVScalarArray & from,
|
||||
size_t fromOffset,
|
||||
PVScalarArray & to,
|
||||
size_t toOffset,
|
||||
size_t len)
|
||||
{
|
||||
ScalarType scalarType = from.getScalarArray()->getElementType();
|
||||
ScalarType otherType = to.getScalarArray()->getElementType();
|
||||
if(scalarType!=otherType) {
|
||||
throw std::invalid_argument("pvSubArrayCopy element types do not match");
|
||||
}
|
||||
switch(scalarType)
|
||||
{
|
||||
case pvBoolean:
|
||||
{
|
||||
copy(dynamic_cast<PVValueArray<boolean> &>(from),fromOffset,
|
||||
dynamic_cast<PVValueArray<boolean>& >(to),
|
||||
toOffset,len);
|
||||
}
|
||||
break;
|
||||
case pvByte:
|
||||
{
|
||||
copy(dynamic_cast<PVValueArray<int8> &>(from),fromOffset,
|
||||
dynamic_cast<PVValueArray<int8>& >(to),
|
||||
toOffset,len);
|
||||
}
|
||||
break;
|
||||
case pvShort:
|
||||
{
|
||||
copy(dynamic_cast<PVValueArray<int16> &>(from),fromOffset,
|
||||
dynamic_cast<PVValueArray<int16>& >(to),
|
||||
toOffset,len);
|
||||
}
|
||||
break;
|
||||
case pvInt:
|
||||
{
|
||||
copy(dynamic_cast<PVValueArray<int32> &>(from),fromOffset,
|
||||
dynamic_cast<PVValueArray<int32>& >(to),
|
||||
toOffset,len);
|
||||
}
|
||||
break;
|
||||
case pvLong:
|
||||
{
|
||||
copy(dynamic_cast<PVValueArray<int64> &>(from),fromOffset,
|
||||
dynamic_cast<PVValueArray<int64>& >(to),
|
||||
toOffset,len);
|
||||
}
|
||||
break;
|
||||
case pvUByte:
|
||||
{
|
||||
copy(dynamic_cast<PVValueArray<uint8> &>(from),fromOffset,
|
||||
dynamic_cast<PVValueArray<uint8>& >(to),
|
||||
toOffset,len);
|
||||
}
|
||||
break;
|
||||
case pvUShort:
|
||||
{
|
||||
copy(dynamic_cast<PVValueArray<uint16> &>(from),fromOffset,
|
||||
dynamic_cast<PVValueArray<uint16>& >(to),
|
||||
toOffset,len);
|
||||
}
|
||||
break;
|
||||
case pvUInt:
|
||||
{
|
||||
copy(dynamic_cast<PVValueArray<uint32> &>(from),fromOffset,
|
||||
dynamic_cast<PVValueArray<uint32>& >(to),
|
||||
toOffset,len);
|
||||
}
|
||||
break;
|
||||
case pvULong:
|
||||
{
|
||||
copy(dynamic_cast<PVValueArray<uint64> &>(from),fromOffset,
|
||||
dynamic_cast<PVValueArray<uint64>& >(to),
|
||||
toOffset,len);
|
||||
}
|
||||
break;
|
||||
case pvFloat:
|
||||
{
|
||||
copy(dynamic_cast<PVValueArray<float> &>(from),fromOffset,
|
||||
dynamic_cast<PVValueArray<float>& >(to),
|
||||
toOffset,len);
|
||||
}
|
||||
break;
|
||||
case pvDouble:
|
||||
{
|
||||
copy(dynamic_cast<PVValueArray<double> &>(from),fromOffset,
|
||||
dynamic_cast<PVValueArray<double>& >(to),
|
||||
toOffset,len);
|
||||
}
|
||||
break;
|
||||
case pvString:
|
||||
{
|
||||
copy(dynamic_cast<PVValueArray<String> &>(from),fromOffset,
|
||||
dynamic_cast<PVValueArray<String>& >(to),
|
||||
toOffset,len);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void copy(
|
||||
PVStructureArray & from,
|
||||
size_t fromOffset,
|
||||
PVStructureArray & to,
|
||||
size_t toOffset,
|
||||
size_t len)
|
||||
{
|
||||
if(to.isImmutable()) {
|
||||
throw std::logic_error("pvSubArrayCopy to is immutable");
|
||||
}
|
||||
StructureArrayConstPtr fromStructure = from.getStructureArray();
|
||||
StructureArrayConstPtr toStructure = to.getStructureArray();
|
||||
if(fromStructure!=toStructure) {
|
||||
throw std::invalid_argument(
|
||||
"pvSubArrayCopy structureArray to and from have different structures");
|
||||
}
|
||||
size_t fromLength = from.getLength();
|
||||
if(fromOffset+len>fromLength) {
|
||||
throw std::length_error("pvSubArrayCopy from length error");
|
||||
}
|
||||
size_t capacity = to.getCapacity();
|
||||
if(toOffset+len>capacity) capacity = toOffset+len;
|
||||
shared_vector<PVStructurePtr> temp(capacity);
|
||||
PVValueArray<PVStructurePtr>::const_svector vecFrom = from.view();
|
||||
PVValueArray<PVStructurePtr>::const_svector vecTo = to.view();
|
||||
for(size_t i=0; i<toOffset; ++i) temp[i] = vecTo[i];
|
||||
for(size_t i=0; i<len; ++i) temp[i + toOffset] = vecFrom[i + fromOffset];
|
||||
for(size_t i=len + toOffset; i<capacity; ++i) temp[i] = vecTo[i];
|
||||
shared_vector<const PVStructurePtr> temp2(freeze(temp));
|
||||
to.replace(temp2);
|
||||
}
|
||||
|
||||
void copy(
|
||||
PVArray & from,
|
||||
size_t fromOffset,
|
||||
PVArray & to,
|
||||
size_t toOffset,
|
||||
size_t len)
|
||||
{
|
||||
Type type = from.getField()->getType();
|
||||
Type otherType = to.getField()->getType();
|
||||
if(type!=otherType) {
|
||||
throw std::invalid_argument("pvSubArrayCopy types do not match");
|
||||
}
|
||||
if(type==scalarArray) {
|
||||
copy(dynamic_cast<PVScalarArray &>(from) ,fromOffset,
|
||||
dynamic_cast<PVScalarArray&>(to),
|
||||
toOffset,len);
|
||||
}
|
||||
if(type==structureArray) {
|
||||
copy(dynamic_cast<PVStructureArray &>(from) ,fromOffset,
|
||||
dynamic_cast<PVStructureArray&>(to),
|
||||
toOffset,len);
|
||||
}
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
44
src/misc/Makefile
Normal file
44
src/misc/Makefile
Normal file
@@ -0,0 +1,44 @@
|
||||
# This is a Makefile fragment, see ../Makefile
|
||||
|
||||
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
|
||||
|
||||
LIBSRCS += byteBuffer.cpp
|
||||
LIBSRCS += bitSet.cpp
|
||||
LIBSRCS += epicsException.cpp
|
||||
LIBSRCS += requester.cpp
|
||||
LIBSRCS += serializeHelper.cpp
|
||||
LIBSRCS += event.cpp
|
||||
LIBSRCS += executor.cpp
|
||||
LIBSRCS += timeFunction.cpp
|
||||
LIBSRCS += timer.cpp
|
||||
LIBSRCS += status.cpp
|
||||
LIBSRCS += messageQueue.cpp
|
||||
LIBSRCS += localStaticLock.cpp
|
||||
LIBSRCS += typeCast.cpp
|
||||
LIBSRCS += parseToPOD.cpp
|
||||
|
||||
@@ -7,11 +7,14 @@
|
||||
/**
|
||||
* @author mes
|
||||
*/
|
||||
#include "string.h"
|
||||
#include "stdio.h"
|
||||
#include <pv/bitSet.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/lock.h>
|
||||
#include <pv/serializeHelper.h>
|
||||
#include <pv/bitSet.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
@@ -199,6 +202,8 @@ namespace epics { namespace pvData {
|
||||
}
|
||||
|
||||
BitSet& BitSet::operator&=(const BitSet& set) {
|
||||
// Check for self-assignment!
|
||||
if (this == &set) return *this;
|
||||
|
||||
while (wordsInUse > set.wordsInUse)
|
||||
words[--wordsInUse] = 0;
|
||||
@@ -213,76 +218,49 @@ namespace epics { namespace pvData {
|
||||
}
|
||||
|
||||
BitSet& BitSet::operator|=(const BitSet& set) {
|
||||
|
||||
uint32 wordsInCommon;
|
||||
// Check for self-assignment!
|
||||
if (this == &set) return *this;
|
||||
uint32 wordsInCommon = wordsInUse;
|
||||
if(wordsInUse>set.wordsInUse) wordsInCommon = set.wordsInUse;
|
||||
if (wordsInUse < set.wordsInUse) {
|
||||
wordsInCommon = wordsInUse;
|
||||
//ensureCapacity(set.wordsInUse);
|
||||
//wordsInUse = set.wordsInUse;
|
||||
ensureCapacity(set.wordsInUse);
|
||||
wordsInUse = set.wordsInUse;
|
||||
}
|
||||
else
|
||||
wordsInCommon = set.wordsInUse;
|
||||
|
||||
// Perform logical OR on words in common
|
||||
uint32 i = 0;
|
||||
for (; i < wordsInCommon; i++)
|
||||
for (uint32 i =0; i < wordsInCommon; i++) {
|
||||
words[i] |= set.words[i];
|
||||
|
||||
// TODO what to do if BitSets are not the same size !!!
|
||||
|
||||
}
|
||||
// Copy any remaining words
|
||||
for(uint32 i=wordsInCommon; i<set.wordsInUse; ++i) {
|
||||
words[i] = set.words[i];
|
||||
}
|
||||
// recalculateWordsInUse() is not needed
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
BitSet& BitSet::operator^=(const BitSet& set) {
|
||||
|
||||
uint32 wordsInCommon;
|
||||
uint32 wordsInCommon = wordsInUse;
|
||||
if(wordsInUse>set.wordsInUse) wordsInCommon = set.wordsInUse;
|
||||
if (wordsInUse < set.wordsInUse) {
|
||||
wordsInCommon = wordsInUse;
|
||||
//ensureCapacity(set.wordsInUse);
|
||||
//wordsInUse = set.wordsInUse;
|
||||
ensureCapacity(set.wordsInUse);
|
||||
wordsInUse = set.wordsInUse;
|
||||
}
|
||||
else
|
||||
wordsInCommon = set.wordsInUse;
|
||||
|
||||
// Perform logical XOR on words in common
|
||||
uint32 i = 0;
|
||||
for (; i < wordsInCommon; i++)
|
||||
// Perform logical OR on words in common
|
||||
for (uint32 i =0; i < wordsInCommon; i++) {
|
||||
words[i] ^= set.words[i];
|
||||
|
||||
// TODO what to do if BitSets are not the same size !!!
|
||||
|
||||
recalculateWordsInUse();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
BitSet& BitSet::operator-=(const BitSet& set) {
|
||||
|
||||
uint32 wordsInCommon;
|
||||
if (wordsInUse < set.wordsInUse) {
|
||||
wordsInCommon = wordsInUse;
|
||||
//ensureCapacity(set.wordsInUse);
|
||||
//wordsInUse = set.wordsInUse;
|
||||
}
|
||||
// Copy any remaining words
|
||||
for(uint32 i=wordsInCommon; i<set.wordsInUse; ++i) {
|
||||
words[i] = set.words[i];
|
||||
}
|
||||
else
|
||||
wordsInCommon = set.wordsInUse;
|
||||
|
||||
// Perform logical (a & !b) on words in common
|
||||
uint32 i = 0;
|
||||
for (; i < wordsInCommon; i++)
|
||||
words[i] &= ~set.words[i];
|
||||
|
||||
recalculateWordsInUse();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
BitSet& BitSet::operator=(const BitSet &set) {
|
||||
// Check for self-assignment!
|
||||
if (this == &set)
|
||||
return *this;
|
||||
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)
|
||||
@@ -369,7 +347,7 @@ namespace epics { namespace pvData {
|
||||
|
||||
void BitSet::deserialize(ByteBuffer* buffer, DeserializableControl* control) {
|
||||
|
||||
uint32 bytes = SerializeHelper::readSize(buffer, control); // in bytes
|
||||
uint32 bytes = static_cast<uint32>(SerializeHelper::readSize(buffer, control)); // in bytes
|
||||
|
||||
wordsInUse = (bytes + 7) / 8;
|
||||
if (wordsInUse > wordsLength)
|
||||
@@ -9,11 +9,15 @@
|
||||
*/
|
||||
#ifndef BITSET_H
|
||||
#define BITSET_H
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include <pv/pvType.h>
|
||||
#include <pv/serialize.h>
|
||||
#include <pv/sharedPtr.h>
|
||||
|
||||
#include <shareLib.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
class BitSet;
|
||||
@@ -42,10 +46,10 @@ namespace epics { namespace pvData {
|
||||
*
|
||||
* Based on Java implementation.
|
||||
*/
|
||||
class BitSet : public Serializable {
|
||||
class epicsShareClass BitSet : public Serializable {
|
||||
public:
|
||||
POINTER_DEFINITIONS(BitSet);
|
||||
static BitSet::shared_pointer create(uint32 nbits);
|
||||
static BitSetPtr create(uint32 nbits);
|
||||
/**
|
||||
* Creates a new bit set. All bits are initially {@code false}.
|
||||
*/
|
||||
@@ -201,15 +205,6 @@ namespace epics { namespace pvData {
|
||||
*/
|
||||
BitSet& operator^=(const BitSet& set);
|
||||
|
||||
/**
|
||||
* Clears all of the bits in this {@code BitSet} whose corresponding
|
||||
* bit is set in the specified {@code BitSet}.
|
||||
*
|
||||
* @param set the {@code BitSet} with which to mask this
|
||||
* {@code BitSet}
|
||||
*/
|
||||
BitSet& operator-=(const BitSet& set);
|
||||
|
||||
/**
|
||||
* Assigment operator.
|
||||
*/
|
||||
@@ -4,5 +4,5 @@
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mes
|
||||
* @author mse
|
||||
*/
|
||||
@@ -11,12 +11,25 @@
|
||||
#define BYTEBUFFER_H
|
||||
|
||||
#include <string>
|
||||
#include <pv/pvType.h>
|
||||
#include <epicsEndian.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef epicsExportSharedSymbols
|
||||
#define byteBufferepicsExportSharedSymbols
|
||||
#undef epicsExportSharedSymbols
|
||||
#endif
|
||||
|
||||
#include <epicsEndian.h>
|
||||
|
||||
#ifdef byteBufferepicsExportSharedSymbols
|
||||
#define epicsExportSharedSymbols
|
||||
#undef byteBufferepicsExportSharedSymbols
|
||||
#endif
|
||||
|
||||
#include <pv/pvType.h>
|
||||
#include <pv/epicsException.h>
|
||||
|
||||
#include <shareLib.h>
|
||||
|
||||
namespace epics {
|
||||
namespace pvData {
|
||||
|
||||
@@ -189,22 +202,40 @@ public:
|
||||
*
|
||||
* @param size The number of bytes.
|
||||
* @param byteOrder The byte order.
|
||||
* Must be one of EPICS_BYTE_ORDER,EPICS_ENDIAN_LITTLE,EPICS_ENDIAN_BIG,
|
||||
* 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),
|
||||
_reverseEndianess(byteOrder != EPICS_BYTE_ORDER),
|
||||
_reverseFloatEndianess(byteOrder != EPICS_FLOAT_WORD_ORDER)
|
||||
_reverseFloatEndianess(byteOrder != EPICS_FLOAT_WORD_ORDER),
|
||||
_wrapped(false)
|
||||
{
|
||||
_buffer = (char*)malloc(size);
|
||||
clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for wrapping existing buffers.
|
||||
* Given buffer will not be released by the ByteBuffer instance.
|
||||
* @param buffer Existing buffer.
|
||||
* @param size The number of bytes.
|
||||
* @param byteOrder The byte order.
|
||||
* Must be one of EPICS_BYTE_ORDER,EPICS_ENDIAN_LITTLE,EPICS_ENDIAN_BIG.
|
||||
*/
|
||||
ByteBuffer(char* buffer, std::size_t size, int byteOrder = EPICS_BYTE_ORDER) :
|
||||
_buffer(buffer), _size(size),
|
||||
_reverseEndianess(byteOrder != EPICS_BYTE_ORDER),
|
||||
_reverseFloatEndianess(byteOrder != EPICS_FLOAT_WORD_ORDER),
|
||||
_wrapped(true)
|
||||
{
|
||||
clear();
|
||||
}
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~ByteBuffer()
|
||||
{
|
||||
if (_buffer) free(_buffer);
|
||||
if (_buffer && !_wrapped) free(_buffer);
|
||||
}
|
||||
/**
|
||||
* Set the byte order.
|
||||
@@ -379,7 +410,7 @@ public:
|
||||
* @param count The number of elements.
|
||||
*/
|
||||
template<typename T>
|
||||
inline void putArray(T* values, std::size_t count);
|
||||
inline void putArray(const T* values, std::size_t count);
|
||||
/**
|
||||
* Get an array of type {@code T} from the byte buffer.
|
||||
* The position is adjusted.
|
||||
@@ -605,7 +636,8 @@ private:
|
||||
char* _limit;
|
||||
std::size_t _size;
|
||||
bool _reverseEndianess;
|
||||
bool _reverseFloatEndianess;
|
||||
bool _reverseFloatEndianess;
|
||||
bool _wrapped;
|
||||
};
|
||||
|
||||
template<>
|
||||
@@ -842,7 +874,7 @@ private:
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline void ByteBuffer::putArray(T* values, std::size_t count)
|
||||
inline void ByteBuffer::putArray(const T* values, std::size_t count)
|
||||
{
|
||||
// this avoids int8 specialization, compiler will take care if optimization, -O2 or more
|
||||
if (sizeof(T) == 1)
|
||||
42
src/misc/current_function.h
Executable file
42
src/misc/current_function.h
Executable file
@@ -0,0 +1,42 @@
|
||||
#ifndef CURRENT_FUNCTION_HPP_INCLUDED
|
||||
#define CURRENT_FUNCTION_HPP_INCLUDED
|
||||
|
||||
// MS compatible compilers support #pragma once
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(__GNUC__) || (defined(__MWERKS__) && (__MWERKS__ >= 0x3000)) || (defined(__ICC) && (__ICC >= 600)) || defined(__ghs__)
|
||||
|
||||
# define CURRENT_FUNCTION __PRETTY_FUNCTION__
|
||||
|
||||
#elif defined(__DMC__) && (__DMC__ >= 0x810)
|
||||
|
||||
# define CURRENT_FUNCTION __PRETTY_FUNCTION__
|
||||
|
||||
#elif defined(__FUNCSIG__)
|
||||
|
||||
# define CURRENT_FUNCTION __FUNCSIG__
|
||||
|
||||
#elif (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 600)) || (defined(__IBMCPP__) && (__IBMCPP__ >= 500))
|
||||
|
||||
# define CURRENT_FUNCTION __FUNCTION__
|
||||
|
||||
#elif defined(__BORLANDC__) && (__BORLANDC__ >= 0x550)
|
||||
|
||||
# define CURRENT_FUNCTION __FUNC__
|
||||
|
||||
#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901)
|
||||
|
||||
# define CURRENT_FUNCTION __func__
|
||||
|
||||
#else
|
||||
|
||||
# define CURRENT_FUNCTION "(unknown)"
|
||||
|
||||
#endif
|
||||
|
||||
#endif // #ifndef BOOST_CURRENT_FUNCTION_HPP_INCLUDED
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
|
||||
#include <pv/sharedPtr.h>
|
||||
|
||||
#include <shareLib.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
|
||||
@@ -19,7 +21,7 @@ namespace epics { namespace pvData {
|
||||
* Instance declaring destroy method.
|
||||
* @author mse
|
||||
*/
|
||||
class Destroyable {
|
||||
class epicsShareClass Destroyable {
|
||||
public:
|
||||
POINTER_DEFINITIONS(Destroyable);
|
||||
/**
|
||||
@@ -7,14 +7,15 @@
|
||||
* @author mes
|
||||
*/
|
||||
|
||||
#include <pv/epicsException.h>
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
||||
namespace epics{namespace pvData{
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/epicsException.h>
|
||||
|
||||
|
||||
namespace epics{ namespace pvData {
|
||||
|
||||
void
|
||||
ExceptionMixin::print(FILE *fp) const
|
||||
@@ -34,6 +34,10 @@
|
||||
#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)
|
||||
#endif
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
@@ -43,6 +47,8 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <shareLib.h>
|
||||
|
||||
// Users may redefine this for a large size if desired
|
||||
#ifndef EXCEPT_DEPTH
|
||||
# define EXCEPT_DEPTH 20
|
||||
@@ -67,7 +73,7 @@ namespace epics { namespace pvData {
|
||||
/* Stores file and line number given, and when possible the call stack
|
||||
* at the point where it was constructed
|
||||
*/
|
||||
class ExceptionMixin {
|
||||
class epicsShareClass ExceptionMixin {
|
||||
const char *m_file;
|
||||
int m_line;
|
||||
#ifndef EXCEPT_USE_NONE
|
||||
@@ -103,7 +109,7 @@ namespace detail {
|
||||
*
|
||||
* Takes advantage of the requirement that all exception classes
|
||||
* must be copy constructable. Of course this also requires
|
||||
* the and extra copy be constructed...
|
||||
* that an extra copy be constructed...
|
||||
*/
|
||||
template<typename E>
|
||||
class ExceptionMixed : public E, public ExceptionMixin {
|
||||
@@ -197,7 +203,7 @@ do { \
|
||||
|
||||
#endif // THROW_EXCEPTION_COMPAT
|
||||
|
||||
class BaseException : public std::logic_error {
|
||||
class epicsShareClass BaseException : public std::logic_error {
|
||||
public:
|
||||
explicit BaseException(const std::string msg) : std::logic_error(msg) {}
|
||||
|
||||
@@ -209,6 +215,10 @@ private:
|
||||
mutable std::string base_msg;
|
||||
};
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma warning( pop )
|
||||
#endif
|
||||
|
||||
#define THROW_BASE_EXCEPTION(msg) THROW_EXCEPTION2(::epics::pvData::BaseException, msg)
|
||||
#define THROW_BASE_EXCEPTION_CAUSE(msg, cause) THROW_EXCEPTION2(::epics::pvData::BaseException, msg)
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
#include <epicsThread.h>
|
||||
#include <epicsMutex.h>
|
||||
#include <epicsEvent.h>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/noDefaultMethods.h>
|
||||
#include <pv/pvType.h>
|
||||
#include <pv/lock.h>
|
||||
@@ -9,18 +9,33 @@
|
||||
*/
|
||||
#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 Event {
|
||||
class epicsShareClass Event {
|
||||
public:
|
||||
POINTER_DEFINITIONS(Event);
|
||||
explicit Event(bool = false);
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/executor.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
@@ -57,6 +58,7 @@ void Executor::run()
|
||||
xx.lock();
|
||||
}
|
||||
CommandPtr command = head;
|
||||
head = command->next;
|
||||
if(command.get()==NULL) continue;
|
||||
if(command.get()==shutdown.get()) break;
|
||||
xx.unlock();
|
||||
@@ -83,7 +85,8 @@ void Executor::execute(CommandPtr const & command)
|
||||
moreWork.signal();
|
||||
return;
|
||||
}
|
||||
if(tail.get()==NULL) return;
|
||||
CommandPtr tail = head;
|
||||
while(tail->next!=NULL) tail = tail->next;
|
||||
tail->next = command;
|
||||
}
|
||||
|
||||
@@ -9,13 +9,17 @@
|
||||
*/
|
||||
#ifndef EXECUTOR_H
|
||||
#define EXECUTOR_H
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <pv/pvType.h>
|
||||
#include <pv/lock.h>
|
||||
#include <pv/event.h>
|
||||
#include <pv/thread.h>
|
||||
#include <pv/sharedPtr.h>
|
||||
|
||||
#include <shareLib.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
class Command;
|
||||
@@ -23,7 +27,7 @@ class Executor;
|
||||
typedef std::tr1::shared_ptr<Command> CommandPtr;
|
||||
typedef std::tr1::shared_ptr<Executor> ExecutorPtr;
|
||||
|
||||
class Command {
|
||||
class epicsShareClass Command {
|
||||
public:
|
||||
POINTER_DEFINITIONS(Command);
|
||||
virtual ~Command(){}
|
||||
@@ -33,7 +37,7 @@ private:
|
||||
friend class Executor;
|
||||
};
|
||||
|
||||
class Executor : public Runnable{
|
||||
class epicsShareClass Executor : public Runnable{
|
||||
public:
|
||||
POINTER_DEFINITIONS(Executor);
|
||||
Executor(String threadName,ThreadPriority priority);
|
||||
@@ -8,6 +8,7 @@
|
||||
* @author mse
|
||||
*/
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/localStaticLock.h>
|
||||
|
||||
static int nifty_counter;
|
||||
@@ -12,7 +12,9 @@
|
||||
|
||||
#include <pv/lock.h>
|
||||
|
||||
extern epics::pvData::Mutex& getLocalStaticInitMutex();
|
||||
#include <shareLib.h>
|
||||
|
||||
epicsShareExtern epics::pvData::Mutex& getLocalStaticInitMutex();
|
||||
|
||||
#if defined(__GNUC__) && __GNUC__ >= 4
|
||||
// noop
|
||||
@@ -21,7 +23,7 @@ extern epics::pvData::Mutex& getLocalStaticInitMutex();
|
||||
#define LOCAL_STATIC_LOCK epics::pvData::Lock localStaticInitMutexLock(getLocalStaticInitMutex());
|
||||
#endif
|
||||
|
||||
static class MutexInitializer {
|
||||
static class epicsShareClass MutexInitializer {
|
||||
public:
|
||||
MutexInitializer ();
|
||||
~MutexInitializer ();
|
||||
@@ -9,9 +9,25 @@
|
||||
*/
|
||||
#ifndef LOCK_H
|
||||
#define LOCK_H
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#ifdef epicsExportSharedSymbols
|
||||
#define lockepicsExportSharedSymbols
|
||||
#undef epicsExportSharedSymbols
|
||||
#endif
|
||||
|
||||
#include <epicsMutex.h>
|
||||
|
||||
#ifdef lockepicsExportSharedSymbols
|
||||
#define epicsExportSharedSymbols
|
||||
#undef lockepicsExportSharedSymbols
|
||||
#endif
|
||||
|
||||
#include <pv/noDefaultMethods.h>
|
||||
|
||||
#include <shareLib.h>
|
||||
|
||||
/* This is based on item 14 of
|
||||
* Effective C++, Third Edition, Scott Meyers
|
||||
*/
|
||||
@@ -22,7 +38,7 @@ namespace epics { namespace pvData {
|
||||
|
||||
typedef epicsMutex Mutex;
|
||||
|
||||
class Lock : private NoDefaultMethods {
|
||||
class epicsShareClass Lock : private NoDefaultMethods {
|
||||
public:
|
||||
explicit Lock(Mutex &m)
|
||||
: mutexPtr(m), locked(true)
|
||||
@@ -8,7 +8,10 @@
|
||||
* @author mrk
|
||||
*/
|
||||
#include <string>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/messageQueue.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
MessageNode::MessageNode()
|
||||
@@ -18,6 +18,8 @@
|
||||
#include <pv/requester.h>
|
||||
#include <pv/queue.h>
|
||||
|
||||
#include <shareLib.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
class MessageNode;
|
||||
@@ -26,7 +28,7 @@ typedef std::tr1::shared_ptr<MessageNode> MessageNodePtr;
|
||||
typedef std::vector<MessageNodePtr> MessageNodePtrArray;
|
||||
typedef std::tr1::shared_ptr<MessageQueue> MessageQueuePtr;
|
||||
|
||||
class MessageNode {
|
||||
class epicsShareClass MessageNode {
|
||||
public:
|
||||
MessageNode();
|
||||
String getMessage() const;
|
||||
@@ -37,7 +39,7 @@ private:
|
||||
friend class MessageQueue;
|
||||
};
|
||||
|
||||
class MessageQueue : public Queue<MessageNode> {
|
||||
class epicsShareClass MessageQueue : public Queue<MessageNode> {
|
||||
public:
|
||||
POINTER_DEFINITIONS(MessageQueue);
|
||||
static MessageQueuePtr create(int size);
|
||||
@@ -9,13 +9,16 @@
|
||||
*/
|
||||
#ifndef NO_DEFAULT_METHODS_H
|
||||
#define NO_DEFAULT_METHODS_H
|
||||
|
||||
#include <shareLib.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
/* This is based on Item 6 of
|
||||
* Effective C++, Third Edition, Scott Meyers
|
||||
*/
|
||||
|
||||
|
||||
class NoDefaultMethods {
|
||||
class epicsShareClass NoDefaultMethods {
|
||||
protected:
|
||||
// allow by derived objects
|
||||
NoDefaultMethods(){};
|
||||
478
src/misc/parseToPOD.cpp
Normal file
478
src/misc/parseToPOD.cpp
Normal file
@@ -0,0 +1,478 @@
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <float.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include <epicsVersion.h>
|
||||
|
||||
#include <epicsMath.h>
|
||||
#include <epicsStdlib.h>
|
||||
#include <epicsString.h>
|
||||
#include <epicsConvert.h>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include "typeCast.h"
|
||||
|
||||
// need to use "long long" when sizeof(int)==sizeof(long)
|
||||
#if (ULONG_MAX == 0xfffffffful) || defined(_WIN32) || defined(__rtems__)
|
||||
#define NEED_LONGLONG
|
||||
#endif
|
||||
|
||||
#ifndef EPICS_VERSION_INT
|
||||
#define VERSION_INT(V,R,M,P) ( ((V)<<24) | ((R)<<16) | ((M)<<8) | (P))
|
||||
#define EPICS_VERSION_INT VERSION_INT(EPICS_VERSION, EPICS_REVISION, EPICS_MODIFICATION, EPICS_PATCH_LEVEL)
|
||||
#endif
|
||||
|
||||
#if EPICS_VERSION_INT < VERSION_INT(3,15,0,1)
|
||||
/* integer conversion primatives 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 */
|
||||
#define S_stdlib_underflow 3 /* Too small to represent */
|
||||
#define S_stdlib_overflow 4 /* Too large to represent */
|
||||
#define S_stdlib_badBase 5 /* Number base not supported */
|
||||
|
||||
static int
|
||||
epicsParseLong(const char *str, long *to, int base, char **units)
|
||||
{
|
||||
int c;
|
||||
char *endp;
|
||||
long value;
|
||||
|
||||
while ((c = *str) && isspace(c))
|
||||
++str;
|
||||
|
||||
errno = 0;
|
||||
value = strtol(str, &endp, base);
|
||||
|
||||
if (endp == str)
|
||||
return S_stdlib_noConversion;
|
||||
if (errno == EINVAL) /* Not universally supported */
|
||||
return S_stdlib_badBase;
|
||||
if (errno == ERANGE)
|
||||
return S_stdlib_overflow;
|
||||
|
||||
while ((c = *endp) && isspace(c))
|
||||
++endp;
|
||||
if (c && !units)
|
||||
return S_stdlib_extraneous;
|
||||
|
||||
*to = value;
|
||||
if (units)
|
||||
*units = endp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
epicsParseULong(const char *str, unsigned long *to, int base, char **units)
|
||||
{
|
||||
int c;
|
||||
char *endp;
|
||||
unsigned long value;
|
||||
|
||||
while ((c = *str) && isspace(c))
|
||||
++str;
|
||||
|
||||
errno = 0;
|
||||
value = strtoul(str, &endp, base);
|
||||
|
||||
if (endp == str)
|
||||
return S_stdlib_noConversion;
|
||||
if (errno == EINVAL) /* Not universally supported */
|
||||
return S_stdlib_badBase;
|
||||
if (errno == ERANGE)
|
||||
return S_stdlib_overflow;
|
||||
|
||||
while ((c = *endp) && isspace(c))
|
||||
++endp;
|
||||
if (c && !units)
|
||||
return S_stdlib_extraneous;
|
||||
|
||||
*to = value;
|
||||
if (units)
|
||||
*units = endp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
epicsParseDouble(const char *str, double *to, char **units)
|
||||
{
|
||||
int c;
|
||||
char *endp;
|
||||
double value;
|
||||
|
||||
while ((c = *str) && isspace(c))
|
||||
++str;
|
||||
|
||||
errno = 0;
|
||||
value = epicsStrtod(str, &endp);
|
||||
|
||||
if (endp == str)
|
||||
return S_stdlib_noConversion;
|
||||
if (errno == ERANGE)
|
||||
return (value == 0) ? S_stdlib_underflow : S_stdlib_overflow;
|
||||
|
||||
while ((c = *endp) && isspace(c))
|
||||
++endp;
|
||||
if (c && !units)
|
||||
return S_stdlib_extraneous;
|
||||
|
||||
*to = value;
|
||||
if (units)
|
||||
*units = endp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* These call the primitives */
|
||||
|
||||
static int
|
||||
epicsParseInt8(const char *str, epicsInt8 *to, int base, char **units)
|
||||
{
|
||||
long value;
|
||||
int status = epicsParseLong(str, &value, base, units);
|
||||
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
if (value < -0x80 || value > 0x7f)
|
||||
return S_stdlib_overflow;
|
||||
|
||||
*to = (epicsInt8)value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
epicsParseUInt8(const char *str, epicsUInt8 *to, int base, char **units)
|
||||
{
|
||||
unsigned long value;
|
||||
int status = epicsParseULong(str, &value, base, units);
|
||||
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
if (value > 0xff && value <= ~0xffUL)
|
||||
return S_stdlib_overflow;
|
||||
|
||||
*to = (epicsUInt8)value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
epicsParseInt16(const char *str, epicsInt16 *to, int base, char **units)
|
||||
{
|
||||
long value;
|
||||
int status = epicsParseLong(str, &value, base, units);
|
||||
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
if (value < -0x8000 || value > 0x7fff)
|
||||
return S_stdlib_overflow;
|
||||
|
||||
*to = (epicsInt16)value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
epicsParseUInt16(const char *str, epicsUInt16 *to, int base, char **units)
|
||||
{
|
||||
unsigned long value;
|
||||
int status = epicsParseULong(str, &value, base, units);
|
||||
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
if (value > 0xffff && value <= ~0xffffUL)
|
||||
return S_stdlib_overflow;
|
||||
|
||||
*to = (epicsUInt16)value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
epicsParseInt32(const char *str, epicsInt32 *to, int base, char **units)
|
||||
{
|
||||
long value;
|
||||
int status = epicsParseLong(str, &value, base, units);
|
||||
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
#if (LONG_MAX > 0x7fffffff)
|
||||
if (value < -0x80000000L || value > 0x7fffffffL)
|
||||
return S_stdlib_overflow;
|
||||
#endif
|
||||
|
||||
*to = (epicsInt32)value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
epicsParseUInt32(const char *str, epicsUInt32 *to, int base, char **units)
|
||||
{
|
||||
unsigned long value;
|
||||
int status = epicsParseULong(str, &value, base, units);
|
||||
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
#if (ULONG_MAX > 0xffffffff)
|
||||
if (value > 0xffffffffUL && value <= ~0xffffffffUL)
|
||||
return S_stdlib_overflow;
|
||||
#endif
|
||||
|
||||
*to = (epicsUInt32)value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
epicsParseFloat(const char *str, float *to, char **units)
|
||||
{
|
||||
double value, abs;
|
||||
int status = epicsParseDouble(str, &value, units);
|
||||
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
abs = fabs(value);
|
||||
if (value > 0 && abs <= FLT_MIN)
|
||||
return S_stdlib_underflow;
|
||||
if (finite(value) && abs >= FLT_MAX)
|
||||
return S_stdlib_overflow;
|
||||
|
||||
*to = (float)value;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(NEED_LONGLONG) && (defined(__vxworks) || defined (_WIN32))
|
||||
static
|
||||
long long strtoll(const char *ptr, char ** endp, int base)
|
||||
{
|
||||
size_t inlen = strlen(ptr);
|
||||
long long result;
|
||||
unsigned char offset=0;
|
||||
|
||||
assert(base==0);
|
||||
|
||||
if(ptr[0]=='-')
|
||||
offset=1;
|
||||
|
||||
try {
|
||||
std::istringstream strm(ptr);
|
||||
|
||||
assert(strm.rdbuf()->in_avail()>=0
|
||||
&& inlen==(size_t)strm.rdbuf()->in_avail());
|
||||
|
||||
if(ptr[offset]=='0') {
|
||||
if(ptr[offset+1]=='x')
|
||||
strm >> std::hex;
|
||||
else
|
||||
strm >> std::oct;
|
||||
}
|
||||
|
||||
strm >> result;
|
||||
if(strm.fail())
|
||||
goto noconvert;
|
||||
|
||||
assert(strm.rdbuf()->in_avail()>=0
|
||||
&& inlen>=(size_t)strm.rdbuf()->in_avail());
|
||||
|
||||
size_t consumed = inlen - strm.rdbuf()->in_avail();
|
||||
*endp = (char*)ptr + consumed;
|
||||
|
||||
return result;
|
||||
|
||||
} catch(...) {
|
||||
goto noconvert;
|
||||
}
|
||||
|
||||
return result;
|
||||
noconvert:
|
||||
*endp = (char*)ptr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
unsigned long long strtoull(const char *ptr, char ** endp, int base)
|
||||
{
|
||||
size_t inlen = strlen(ptr);
|
||||
unsigned long long result;
|
||||
|
||||
assert(base==0);
|
||||
|
||||
try {
|
||||
std::istringstream strm(ptr);
|
||||
|
||||
assert(strm.rdbuf()->in_avail()>=0
|
||||
&& inlen==(size_t)strm.rdbuf()->in_avail());
|
||||
|
||||
if(ptr[0]=='0') {
|
||||
if(ptr[1]=='x')
|
||||
strm >> std::hex;
|
||||
else
|
||||
strm >> std::oct;
|
||||
}
|
||||
|
||||
strm >> result;
|
||||
if(strm.fail())
|
||||
goto noconvert;
|
||||
|
||||
assert(strm.rdbuf()->in_avail()>=0
|
||||
&& inlen>=(size_t)strm.rdbuf()->in_avail());
|
||||
|
||||
size_t consumed = inlen - strm.rdbuf()->in_avail();
|
||||
*endp = (char*)ptr + consumed;
|
||||
|
||||
return result;
|
||||
|
||||
} catch(...) {
|
||||
goto noconvert;
|
||||
}
|
||||
|
||||
return result;
|
||||
noconvert:
|
||||
*endp = (char*)ptr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* do we need long long? */
|
||||
#ifdef NEED_LONGLONG
|
||||
static int
|
||||
epicsParseLongLong(const char *str, long long *to, int base, char **units)
|
||||
{
|
||||
int c;
|
||||
char *endp;
|
||||
long long value;
|
||||
|
||||
while ((c = *str) && isspace(c))
|
||||
++str;
|
||||
|
||||
errno = 0;
|
||||
value = strtoll(str, &endp, base);
|
||||
|
||||
if (endp == str)
|
||||
return S_stdlib_noConversion;
|
||||
if (errno == EINVAL) /* Not universally supported */
|
||||
return S_stdlib_badBase;
|
||||
if (errno == ERANGE)
|
||||
return S_stdlib_overflow;
|
||||
|
||||
while ((c = *endp) && isspace(c))
|
||||
++endp;
|
||||
if (c && !units)
|
||||
return S_stdlib_extraneous;
|
||||
|
||||
*to = value;
|
||||
if (units)
|
||||
*units = endp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
epicsParseULongLong(const char *str, unsigned long long *to, int base, char **units)
|
||||
{
|
||||
int c;
|
||||
char *endp;
|
||||
unsigned long long value;
|
||||
|
||||
while ((c = *str) && isspace(c))
|
||||
++str;
|
||||
|
||||
errno = 0;
|
||||
value = strtoull(str, &endp, base);
|
||||
|
||||
if (endp == str)
|
||||
return S_stdlib_noConversion;
|
||||
if (errno == EINVAL) /* Not universally supported */
|
||||
return S_stdlib_badBase;
|
||||
if (errno == ERANGE)
|
||||
return S_stdlib_overflow;
|
||||
|
||||
while ((c = *endp) && isspace(c))
|
||||
++endp;
|
||||
if (c && !units)
|
||||
return S_stdlib_extraneous;
|
||||
|
||||
*to = value;
|
||||
if (units)
|
||||
*units = endp;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static
|
||||
void handleParseError(int err)
|
||||
{
|
||||
switch(err) {
|
||||
case 0: break;
|
||||
case S_stdlib_noConversion: throw std::runtime_error("parseToPOD: No digits to convert");
|
||||
case S_stdlib_extraneous: throw std::runtime_error("parseToPOD: Extraneous characters");
|
||||
case S_stdlib_underflow: throw std::runtime_error("parseToPOD: Too small to represent");
|
||||
case S_stdlib_overflow: throw std::runtime_error("parseToPOD: Too large to represent");
|
||||
case S_stdlib_badBase: throw std::runtime_error("parseToPOD: Number base not supported");
|
||||
default:
|
||||
throw std::runtime_error("parseToPOD: unknown error");
|
||||
}
|
||||
}
|
||||
|
||||
namespace epics { namespace pvData { namespace detail {
|
||||
|
||||
void parseToPOD(const std::string & in, boolean *out)
|
||||
{
|
||||
if(epicsStrCaseCmp(in.c_str(),"true")==0)
|
||||
*out = 1;
|
||||
else if(epicsStrCaseCmp(in.c_str(),"false")==0)
|
||||
*out = 0;
|
||||
else
|
||||
throw std::runtime_error("parseToPOD: String no match true/false");
|
||||
}
|
||||
|
||||
#define INTFN(T, S) \
|
||||
void parseToPOD(const std::string& in, T *out) { \
|
||||
epics ## S temp; \
|
||||
int err = epicsParse ## S (in.c_str(), &temp, 0, NULL); \
|
||||
if(err) handleParseError(err); \
|
||||
else *out = temp; \
|
||||
}
|
||||
|
||||
INTFN(int8, Int8);
|
||||
INTFN(uint8, UInt8);
|
||||
INTFN(int16_t, Int16);
|
||||
INTFN(uint16_t, UInt16);
|
||||
INTFN(int32_t, Int32);
|
||||
INTFN(uint32_t, UInt32);
|
||||
|
||||
void parseToPOD(const std::string& in, int64_t *out) {
|
||||
#ifdef NEED_LONGLONG
|
||||
int err = epicsParseLongLong(in.c_str(), out, 0, NULL);
|
||||
#else
|
||||
int err = epicsParseLong(in.c_str(), out, 0, NULL);
|
||||
#endif
|
||||
if(err) handleParseError(err);
|
||||
}
|
||||
|
||||
void parseToPOD(const std::string& in, uint64_t *out) {
|
||||
#ifdef NEED_LONGLONG
|
||||
int err = epicsParseULongLong(in.c_str(), out, 0, NULL);
|
||||
#else
|
||||
int err = epicsParseULong(in.c_str(), out, 0, NULL);
|
||||
#endif
|
||||
if(err) handleParseError(err);
|
||||
}
|
||||
|
||||
void parseToPOD(const std::string& in, float *out) {
|
||||
int err = epicsParseFloat(in.c_str(), out, NULL);
|
||||
if(err) handleParseError(err);
|
||||
}
|
||||
|
||||
void parseToPOD(const std::string& in, double *out) {
|
||||
int err = epicsParseDouble(in.c_str(), out, NULL);
|
||||
if(err) handleParseError(err);
|
||||
}
|
||||
|
||||
}}}
|
||||
@@ -7,12 +7,15 @@
|
||||
/**
|
||||
* @author mrk
|
||||
*/
|
||||
#ifndef QUEUE_H
|
||||
#define QUEUE_H
|
||||
|
||||
#include <vector>
|
||||
#include <cstddef>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <pv/sharedPtr.h>
|
||||
#ifndef QUEUE_H
|
||||
#define QUEUE_H
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
template <typename T>
|
||||
@@ -35,6 +38,7 @@ public:
|
||||
private:
|
||||
queueElementPtr nullElement;
|
||||
queueElementPtrArray elements;
|
||||
// TODO use size_t instead
|
||||
int size;
|
||||
int numberFree;
|
||||
int numberUsed;
|
||||
@@ -46,7 +50,7 @@ private:
|
||||
|
||||
template <typename T>
|
||||
Queue<T>::Queue(std::vector<queueElementPtr> &xxx)
|
||||
: size(xxx.size()),
|
||||
: size(static_cast<int>(xxx.size())),
|
||||
numberFree(size),
|
||||
numberUsed(0),
|
||||
nextGetFree(0),
|
||||
@@ -9,15 +9,18 @@
|
||||
*/
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/lock.h>
|
||||
#include <pv/requester.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
const size_t messageTypeCount = 4;
|
||||
static StringArray messageTypeName(messageTypeCount);
|
||||
static StringArray messageTypeName(MESSAGE_TYPE_COUNT);
|
||||
|
||||
String getMessageTypeName(MessageType messageType)
|
||||
{
|
||||
// TODO not thread-safe
|
||||
static Mutex mutex;
|
||||
Lock xx(mutex);
|
||||
if(messageTypeName[0].size()==0) {
|
||||
@@ -10,9 +10,12 @@
|
||||
#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;
|
||||
@@ -21,10 +24,11 @@ typedef std::tr1::shared_ptr<Requester> RequesterPtr;
|
||||
enum MessageType {
|
||||
infoMessage,warningMessage,errorMessage,fatalErrorMessage
|
||||
};
|
||||
#define MESSAGE_TYPE_COUNT 4
|
||||
|
||||
extern String getMessageTypeName(MessageType messageType);
|
||||
extern const size_t messageTypeCount;
|
||||
class Requester {
|
||||
epicsShareExtern String getMessageTypeName(MessageType messageType);
|
||||
|
||||
class epicsShareClass Requester {
|
||||
public:
|
||||
POINTER_DEFINITIONS(Requester);
|
||||
virtual ~Requester(){}
|
||||
@@ -9,8 +9,12 @@
|
||||
*/
|
||||
#ifndef SERIALIZE_H
|
||||
#define SERIALIZE_H
|
||||
|
||||
#include <pv/byteBuffer.h>
|
||||
#include <pv/sharedPtr.h>
|
||||
|
||||
#include <shareLib.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
class SerializableControl;
|
||||
@@ -21,7 +25,7 @@ namespace epics { namespace pvData {
|
||||
class BitSet;
|
||||
class Field;
|
||||
|
||||
class SerializableControl {
|
||||
class epicsShareClass SerializableControl {
|
||||
public:
|
||||
virtual ~SerializableControl(){}
|
||||
virtual void flushSerializeBuffer() =0;
|
||||
@@ -32,7 +36,7 @@ namespace epics { namespace pvData {
|
||||
virtual void cachedSerialize(std::tr1::shared_ptr<const Field> const & field, ByteBuffer* buffer) = 0;
|
||||
};
|
||||
|
||||
class DeserializableControl {
|
||||
class epicsShareClass DeserializableControl {
|
||||
public:
|
||||
virtual ~DeserializableControl(){}
|
||||
virtual void ensureData(std::size_t size) =0;
|
||||
@@ -42,7 +46,7 @@ namespace epics { namespace pvData {
|
||||
virtual std::tr1::shared_ptr<const Field> cachedDeserialize(ByteBuffer* buffer) = 0;
|
||||
};
|
||||
|
||||
class Serializable {
|
||||
class epicsShareClass Serializable {
|
||||
public:
|
||||
virtual ~Serializable(){}
|
||||
virtual void serialize(ByteBuffer *buffer,
|
||||
@@ -51,7 +55,7 @@ namespace epics { namespace pvData {
|
||||
DeserializableControl *flusher) = 0;
|
||||
};
|
||||
|
||||
class BitSetSerializable {
|
||||
class epicsShareClass BitSetSerializable {
|
||||
public:
|
||||
virtual ~BitSetSerializable(){}
|
||||
virtual void serialize(ByteBuffer *buffer,
|
||||
@@ -61,7 +65,7 @@ namespace epics { namespace pvData {
|
||||
};
|
||||
|
||||
|
||||
class SerializableArray : virtual public Serializable {
|
||||
class epicsShareClass SerializableArray : virtual public Serializable {
|
||||
public:
|
||||
virtual ~SerializableArray(){}
|
||||
virtual void serialize(ByteBuffer *buffer,
|
||||
@@ -11,13 +11,13 @@
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <pv/pvType.h>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/pvType.h>
|
||||
#include <pv/epicsException.h>
|
||||
#include <pv/byteBuffer.h>
|
||||
#include <pv/serializeHelper.h>
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace epics {
|
||||
@@ -33,11 +33,11 @@ namespace epics {
|
||||
if(s==(std::size_t)-1) // null // TODO remove
|
||||
buffer->putByte(-1);
|
||||
else if(s<254)
|
||||
buffer->putByte(s);
|
||||
buffer->putByte(static_cast<int8>(s));
|
||||
else
|
||||
{
|
||||
buffer->putByte(-2);
|
||||
buffer->putInt(s); // (byte)-2 + size
|
||||
buffer->putInt(static_cast<uint32>(s)); // (byte)-2 + size
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,10 +18,12 @@
|
||||
#include <pv/noDefaultMethods.h>
|
||||
#include <pv/pvIntrospect.h>
|
||||
|
||||
#include <shareLib.h>
|
||||
|
||||
namespace epics {
|
||||
namespace pvData {
|
||||
|
||||
class SerializeHelper : public NoDefaultMethods {
|
||||
class epicsShareClass SerializeHelper : public NoDefaultMethods {
|
||||
public:
|
||||
|
||||
/**
|
||||
@@ -4,7 +4,7 @@
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author Michael DavidSaver
|
||||
* @author Michael Davidsaver
|
||||
*/
|
||||
|
||||
#ifndef SHAREDPTR_H
|
||||
@@ -77,6 +77,6 @@
|
||||
typedef std::tr1::shared_ptr<clazz> shared_pointer; \
|
||||
typedef std::tr1::shared_ptr<const clazz> const_shared_pointer; \
|
||||
typedef std::tr1::weak_ptr<clazz> weak_pointer; \
|
||||
typedef std::tr1::weak_ptr<const clazz> const_weak_pointer;
|
||||
typedef std::tr1::weak_ptr<const clazz> const_weak_pointer
|
||||
|
||||
#endif // SHAREDPTR_H
|
||||
1015
src/misc/sharedVector.h
Normal file
1015
src/misc/sharedVector.h
Normal file
File diff suppressed because it is too large
Load Diff
@@ -7,9 +7,10 @@
|
||||
/**
|
||||
* @author mrk
|
||||
*/
|
||||
#include <pv/status.h>
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/epicsException.h>
|
||||
#include <pv/serializeHelper.h>
|
||||
#include <pv/status.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
@@ -14,13 +14,15 @@
|
||||
#include <pv/byteBuffer.h>
|
||||
#include <pv/sharedPtr.h>
|
||||
|
||||
#include <shareLib.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
/**
|
||||
* Status.
|
||||
* @author mse
|
||||
*/
|
||||
class Status : public epics::pvData::Serializable {
|
||||
class epicsShareClass Status : public epics::pvData::Serializable {
|
||||
public:
|
||||
POINTER_DEFINITIONS(Status);
|
||||
/**
|
||||
120
src/misc/templateMeta.h
Normal file
120
src/misc/templateMeta.h
Normal file
@@ -0,0 +1,120 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
/** C++ Template meta programming helpers
|
||||
*/
|
||||
#ifndef TEMPLATEMETA_H
|
||||
#define TEMPLATEMETA_H
|
||||
|
||||
// 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
|
||||
# define FORCE_INLINE __attribute__((always_inline)) inline
|
||||
#elif defined(_MSC_VER)
|
||||
# define FORCE_INLINE __forceinline
|
||||
#else
|
||||
# define FORCE_INLINE inline
|
||||
#endif
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
namespace meta {
|
||||
|
||||
/** If needed, add the 'const' qualifier to the provided type.
|
||||
*
|
||||
* Avoids adding the const qualifier twice (aka 'const const int')
|
||||
@code
|
||||
assert(typeid(decorate_const<int>::type)==typeid(const int));
|
||||
assert(typeid(decorate_const<const int>::type)==typeid(const int));
|
||||
@endcode
|
||||
*/
|
||||
template<typename T> struct decorate_const { typedef const T type; };
|
||||
template<typename T> struct decorate_const<const T> { typedef const T type; };
|
||||
|
||||
/** Remove the 'const' qualifier if present
|
||||
@code
|
||||
assert(typeid(strip_const<int>::type)==typeid(int));
|
||||
assert(typeid(strip_const<const int>::type)==typeid(int));
|
||||
@endcode
|
||||
*/
|
||||
template<typename T> struct strip_const { typedef T type; };
|
||||
template<typename T> struct strip_const<const T> { typedef T type; };
|
||||
|
||||
/** test to allow specialization only when A!=B
|
||||
*
|
||||
@code
|
||||
template<typename A, typename B, class Enable = void>
|
||||
struct myTemp {...};
|
||||
|
||||
// specialization when A==B
|
||||
template<typename T>
|
||||
struct myTemp<T,T> {...};
|
||||
|
||||
// specialization for A is 'int',
|
||||
// enabler needed to remove ambiguity when B is 'int'.
|
||||
template<typename B>
|
||||
struct myTemp<int, B, typename meta::not_same_type<int,B>::type>
|
||||
{...};
|
||||
@endcode
|
||||
*/
|
||||
template<typename A, typename B, typename R = void>
|
||||
struct not_same_type {typedef R type;};
|
||||
template<typename A>
|
||||
struct not_same_type<A,A> {};
|
||||
|
||||
//! Select if both A and B have the same root type (excluding const qualifier)
|
||||
template<typename A, typename B, class R = void> struct same_root {};
|
||||
template<typename T, class R> struct same_root<T,T,R> { typedef R type; };
|
||||
template<typename T, class R> struct same_root<const T,T,R> { typedef R type; };
|
||||
template<typename T, class R> struct same_root<T,const T,R> { typedef R type; };
|
||||
|
||||
namespace detail {
|
||||
struct _const_yes {};
|
||||
struct _const_no {};
|
||||
template<typename T> struct _has_const { typedef _const_no type; };
|
||||
template<typename T> struct _has_const<const T> { typedef _const_yes type; };
|
||||
|
||||
template<typename A, typename B, class R = void> struct _same_type {};
|
||||
template<typename T, class R> struct _same_type<T,T,R> { typedef R type; };
|
||||
} // namespace detail
|
||||
|
||||
//! Check if both A and B are either const or non-const.
|
||||
template<typename A, typename B, class R = void>
|
||||
struct same_const :
|
||||
public detail::_same_type<typename detail::_has_const<A>::type,
|
||||
typename detail::_has_const<B>::type,
|
||||
R>
|
||||
{};
|
||||
|
||||
/** test if provided type is 'void' or 'const void'
|
||||
*
|
||||
* Avoid having to explicitly specialize for both
|
||||
@code
|
||||
template<typename A, class Enable = void>
|
||||
struct myTemp {...};
|
||||
|
||||
// specialization when A is 'void' or 'const void'
|
||||
template<typename A>
|
||||
struct myTemp<A, typename meta::is_void<A>::type> {...};
|
||||
@endcode
|
||||
*/
|
||||
template<typename T, class R = void> struct is_void {};
|
||||
template<class R> struct is_void<void,R> { typedef R type; };
|
||||
template<class R> struct is_void<const void,R> { typedef R type; };
|
||||
|
||||
//! Inverse of is_void<T>
|
||||
template<typename T, class R = void> struct is_not_void { typedef R type; };
|
||||
template<> struct is_not_void<void> {};
|
||||
template<> struct is_not_void<const void> {};
|
||||
|
||||
//! Enabler to ensure that both conditions A and B are true
|
||||
template<typename A, typename B, class EnableA = void, class EnableB = void, class R = void>
|
||||
struct _and {};
|
||||
template<typename A, typename B, class R>
|
||||
struct _and<A,B, typename A::type, typename B::type, R> { typedef R type; };
|
||||
|
||||
}}}
|
||||
|
||||
#endif // TEMPLATEMETA_H
|
||||
@@ -9,11 +9,25 @@
|
||||
*/
|
||||
#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 <epicsThread.h>
|
||||
#include <shareLib.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
@@ -27,9 +41,13 @@ enum ThreadPriority {
|
||||
highestPriority =epicsThreadPriorityHigh
|
||||
};
|
||||
|
||||
class Thread;
|
||||
typedef std::tr1::shared_ptr<Thread> ThreadPtr;
|
||||
typedef std::tr1::shared_ptr<epicsThread> EpicsThreadPtr;
|
||||
|
||||
typedef epicsThreadRunable Runnable;
|
||||
|
||||
class Thread : public epicsThread, private NoDefaultMethods {
|
||||
class epicsShareClass Thread : public epicsThread, private NoDefaultMethods {
|
||||
public:
|
||||
|
||||
Thread(String name,
|
||||
@@ -62,5 +80,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}}
|
||||
#endif /* THREAD_H */
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/pvType.h>
|
||||
#include <pv/timeStamp.h>
|
||||
#include <pv/timeFunction.h>
|
||||
@@ -9,8 +9,11 @@
|
||||
*/
|
||||
#ifndef TIMEFUNCTION_H
|
||||
#define TIMEFUNCTION_H
|
||||
|
||||
#include <pv/sharedPtr.h>
|
||||
|
||||
#include <shareLib.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
class TimeFunctionRequester;
|
||||
@@ -18,7 +21,7 @@ class TimeFunction;
|
||||
typedef std::tr1::shared_ptr<TimeFunctionRequester> TimeFunctionRequesterPtr;
|
||||
typedef std::tr1::shared_ptr<TimeFunction> TimeFunctionPtr;
|
||||
|
||||
class TimeFunctionRequester {
|
||||
class epicsShareClass TimeFunctionRequester {
|
||||
public:
|
||||
POINTER_DEFINITIONS(TimeFunctionRequester);
|
||||
virtual ~TimeFunctionRequester(){}
|
||||
@@ -26,7 +29,7 @@ public:
|
||||
};
|
||||
|
||||
|
||||
class TimeFunction {
|
||||
class epicsShareClass TimeFunction {
|
||||
public:
|
||||
POINTER_DEFINITIONS(TimeFunction);
|
||||
TimeFunction(TimeFunctionRequesterPtr const & requester);
|
||||
@@ -7,15 +7,16 @@
|
||||
/**
|
||||
* @author mrk
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include <pv/timer.h>
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/convert.h>
|
||||
#include <pv/timer.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
#include <pv/lock.h>
|
||||
#include <pv/sharedPtr.h>
|
||||
|
||||
#include <shareLib.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
class TimerCallback;
|
||||
@@ -30,7 +32,7 @@ class Timer;
|
||||
typedef std::tr1::shared_ptr<TimerCallback> TimerCallbackPtr;
|
||||
typedef std::tr1::shared_ptr<Timer> TimerPtr;
|
||||
|
||||
class TimerCallback {
|
||||
class epicsShareClass TimerCallback {
|
||||
public:
|
||||
POINTER_DEFINITIONS(TimerCallback);
|
||||
TimerCallback();
|
||||
@@ -45,7 +47,7 @@ private:
|
||||
friend class Timer;
|
||||
};
|
||||
|
||||
class Timer : public Runnable {
|
||||
class epicsShareClass Timer : public Runnable {
|
||||
public:
|
||||
POINTER_DEFINITIONS(Timer);
|
||||
Timer(String threadName, ThreadPriority priority);
|
||||
252
src/misc/typeCast.cpp
Normal file
252
src/misc/typeCast.cpp
Normal file
@@ -0,0 +1,252 @@
|
||||
/**
|
||||
* 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: Michael Davidsaver */
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include "typeCast.h"
|
||||
|
||||
using epics::pvData::castUnsafe;
|
||||
using epics::pvData::String;
|
||||
using epics::pvData::ScalarType;
|
||||
using epics::pvData::pvString;
|
||||
|
||||
namespace {
|
||||
|
||||
static void noconvert(size_t, void*, const void*)
|
||||
{
|
||||
throw std::runtime_error("castUnsafeV: Conversion not supported");
|
||||
}
|
||||
|
||||
template<typename TO, typename FROM>
|
||||
static void castVTyped(size_t count, void *draw, const void *sraw)
|
||||
{
|
||||
TO *dest=(TO*)draw;
|
||||
const FROM *src=(FROM*)sraw;
|
||||
|
||||
//std::transform(src, src+count, dest, castUnsafe<TO,FROM>);
|
||||
|
||||
const FROM *last = src+count;
|
||||
try {
|
||||
while (src != last) {
|
||||
*dest = castUnsafe<TO,FROM>(*src);
|
||||
++dest; ++src;
|
||||
}
|
||||
} catch (std::exception& ex) {
|
||||
// do not report index for scalars (or arrays with one element)
|
||||
if (count > 1)
|
||||
{
|
||||
std::ostringstream os;
|
||||
os << "failed to parse element at index " << (src - (FROM*)sraw);
|
||||
os << ": " << ex.what();
|
||||
throw std::runtime_error(os.str());
|
||||
}
|
||||
else
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static void copyV(size_t count, void *draw, const void *sraw)
|
||||
{
|
||||
T *dest=(T*)draw;
|
||||
const T *src=(T*)sraw;
|
||||
std::copy(src, src+count, dest);
|
||||
}
|
||||
|
||||
typedef void (*convertfn)(size_t, void*, const void*);
|
||||
|
||||
/* lookup table of converter functions.
|
||||
* first dimension is TO, second is FROM
|
||||
*/
|
||||
static convertfn converters[pvString+1][pvString+1] =
|
||||
{
|
||||
// to pvBoolean
|
||||
{ ©V<epics::pvData::boolean>,
|
||||
&noconvert,
|
||||
&noconvert,
|
||||
&noconvert,
|
||||
&noconvert,
|
||||
&noconvert,
|
||||
&noconvert,
|
||||
&noconvert,
|
||||
&noconvert,
|
||||
&noconvert,
|
||||
&noconvert,
|
||||
&castVTyped<epics::pvData::boolean, String>,
|
||||
},
|
||||
// to pvByte
|
||||
{&noconvert,
|
||||
©V<int8_t>,
|
||||
&castVTyped<int8_t, int16_t>,
|
||||
&castVTyped<int8_t, int32_t>,
|
||||
&castVTyped<int8_t, int64_t>,
|
||||
&castVTyped<int8_t, uint8_t>,
|
||||
&castVTyped<int8_t, uint16_t>,
|
||||
&castVTyped<int8_t, uint32_t>,
|
||||
&castVTyped<int8_t, uint64_t>,
|
||||
&castVTyped<int8_t, float>,
|
||||
&castVTyped<int8_t, double>,
|
||||
&castVTyped<int8_t, String>,
|
||||
},
|
||||
// to pvShort
|
||||
{&noconvert,
|
||||
&castVTyped<int16_t, int8_t>,
|
||||
©V<int16_t>,
|
||||
&castVTyped<int16_t, int32_t>,
|
||||
&castVTyped<int16_t, int64_t>,
|
||||
&castVTyped<int16_t, uint8_t>,
|
||||
&castVTyped<int16_t, uint16_t>,
|
||||
&castVTyped<int16_t, uint32_t>,
|
||||
&castVTyped<int16_t, uint64_t>,
|
||||
&castVTyped<int16_t, float>,
|
||||
&castVTyped<int16_t, double>,
|
||||
&castVTyped<int16_t, String>,
|
||||
},
|
||||
// to pvInt
|
||||
{&noconvert,
|
||||
&castVTyped<int32_t, int8_t>,
|
||||
&castVTyped<int32_t, int16_t>,
|
||||
©V<int32_t>,
|
||||
&castVTyped<int32_t, int64_t>,
|
||||
&castVTyped<int32_t, uint8_t>,
|
||||
&castVTyped<int32_t, uint16_t>,
|
||||
&castVTyped<int32_t, uint32_t>,
|
||||
&castVTyped<int32_t, uint64_t>,
|
||||
&castVTyped<int32_t, float>,
|
||||
&castVTyped<int32_t, double>,
|
||||
&castVTyped<int32_t, String>,
|
||||
},
|
||||
// to pvLong
|
||||
{&noconvert,
|
||||
&castVTyped<int64_t, int8_t>,
|
||||
&castVTyped<int64_t, int16_t>,
|
||||
&castVTyped<int64_t, int32_t>,
|
||||
©V<int64_t>,
|
||||
&castVTyped<int64_t, uint8_t>,
|
||||
&castVTyped<int64_t, uint16_t>,
|
||||
&castVTyped<int64_t, uint32_t>,
|
||||
&castVTyped<int64_t, uint64_t>,
|
||||
&castVTyped<int64_t, float>,
|
||||
&castVTyped<int64_t, double>,
|
||||
&castVTyped<int64_t, String>,
|
||||
},
|
||||
// to pvUByte
|
||||
{&noconvert,
|
||||
&castVTyped<uint8_t, int8_t>,
|
||||
&castVTyped<uint8_t, int16_t>,
|
||||
&castVTyped<uint8_t, int32_t>,
|
||||
&castVTyped<uint8_t, uint64_t>,
|
||||
©V<uint8_t>,
|
||||
&castVTyped<uint8_t, uint16_t>,
|
||||
&castVTyped<uint8_t, uint32_t>,
|
||||
&castVTyped<uint8_t, uint64_t>,
|
||||
&castVTyped<uint8_t, float>,
|
||||
&castVTyped<uint8_t, double>,
|
||||
&castVTyped<uint8_t, String>,
|
||||
},
|
||||
// to pvUShort
|
||||
{&noconvert,
|
||||
&castVTyped<uint16_t, int8_t>,
|
||||
&castVTyped<uint16_t, int16_t>,
|
||||
&castVTyped<uint16_t, int32_t>,
|
||||
&castVTyped<uint16_t, uint64_t>,
|
||||
&castVTyped<uint16_t, uint8_t>,
|
||||
©V<uint16_t>,
|
||||
&castVTyped<uint16_t, uint32_t>,
|
||||
&castVTyped<uint16_t, uint64_t>,
|
||||
&castVTyped<uint16_t, float>,
|
||||
&castVTyped<uint16_t, double>,
|
||||
&castVTyped<uint16_t, String>,
|
||||
},
|
||||
// to pvUInt
|
||||
{&noconvert,
|
||||
&castVTyped<uint32_t, int8_t>,
|
||||
&castVTyped<uint32_t, int16_t>,
|
||||
&castVTyped<uint32_t, int32_t>,
|
||||
&castVTyped<uint32_t, uint64_t>,
|
||||
&castVTyped<uint32_t, uint8_t>,
|
||||
&castVTyped<uint32_t, uint16_t>,
|
||||
©V<uint32_t>,
|
||||
&castVTyped<uint32_t, uint64_t>,
|
||||
&castVTyped<uint32_t, float>,
|
||||
&castVTyped<uint32_t, double>,
|
||||
&castVTyped<uint32_t, String>,
|
||||
},
|
||||
// to pvULong
|
||||
{&noconvert,
|
||||
&castVTyped<uint64_t, int8_t>,
|
||||
&castVTyped<uint64_t, int16_t>,
|
||||
&castVTyped<uint64_t, int32_t>,
|
||||
&castVTyped<uint64_t, uint64_t>,
|
||||
&castVTyped<uint64_t, uint8_t>,
|
||||
&castVTyped<uint64_t, uint16_t>,
|
||||
&castVTyped<uint64_t, uint32_t>,
|
||||
©V<uint64_t>,
|
||||
&castVTyped<uint64_t, float>,
|
||||
&castVTyped<uint64_t, double>,
|
||||
&castVTyped<uint64_t, String>,
|
||||
},
|
||||
// to pvFloat
|
||||
{&noconvert,
|
||||
&castVTyped<float, int8_t>,
|
||||
&castVTyped<float, int16_t>,
|
||||
&castVTyped<float, int32_t>,
|
||||
&castVTyped<float, uint64_t>,
|
||||
&castVTyped<float, uint8_t>,
|
||||
&castVTyped<float, uint16_t>,
|
||||
&castVTyped<float, uint32_t>,
|
||||
&castVTyped<float, uint64_t>,
|
||||
©V<float>,
|
||||
&castVTyped<float, double>,
|
||||
&castVTyped<float, String>,
|
||||
},
|
||||
// to pvDouble
|
||||
{&noconvert,
|
||||
&castVTyped<double, int8_t>,
|
||||
&castVTyped<double, int16_t>,
|
||||
&castVTyped<double, int32_t>,
|
||||
&castVTyped<double, uint64_t>,
|
||||
&castVTyped<double, uint8_t>,
|
||||
&castVTyped<double, uint16_t>,
|
||||
&castVTyped<double, uint32_t>,
|
||||
&castVTyped<double, uint64_t>,
|
||||
&castVTyped<double, float>,
|
||||
©V<double>,
|
||||
&castVTyped<double, String>,
|
||||
},
|
||||
// to pvString
|
||||
{&castVTyped<String, epics::pvData::boolean>,
|
||||
&castVTyped<String, int8_t>,
|
||||
&castVTyped<String, int16_t>,
|
||||
&castVTyped<String, int32_t>,
|
||||
&castVTyped<String, uint64_t>,
|
||||
&castVTyped<String, uint8_t>,
|
||||
&castVTyped<String, uint16_t>,
|
||||
&castVTyped<String, uint32_t>,
|
||||
&castVTyped<String, uint64_t>,
|
||||
&castVTyped<String, float>,
|
||||
&castVTyped<String, double>,
|
||||
©V<String>,
|
||||
},
|
||||
};
|
||||
|
||||
} // end namespace
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
void castUnsafeV(size_t count, ScalarType to, void *dest, ScalarType from, const void *src)
|
||||
{
|
||||
unsigned int ito=to, ifrom=from;
|
||||
|
||||
if(ito>pvString || ifrom>pvString)
|
||||
throw std::runtime_error("castUnsafeV: Invalid types");
|
||||
|
||||
converters[ito][ifrom](count, dest, src);
|
||||
}
|
||||
|
||||
}}
|
||||
199
src/misc/typeCast.h
Normal file
199
src/misc/typeCast.h
Normal file
@@ -0,0 +1,199 @@
|
||||
/**
|
||||
* 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: Michael Davidsaver */
|
||||
#ifndef PVTYPECAST_H
|
||||
#define PVTYPECAST_H
|
||||
|
||||
#include <stdexcept>
|
||||
#include <sstream>
|
||||
|
||||
#ifdef epicsExportSharedSymbols
|
||||
#define typeCastepicsExportSharedSymbols
|
||||
#undef epicsExportSharedSymbols
|
||||
#endif
|
||||
|
||||
#include <epicsConvert.h>
|
||||
|
||||
#ifdef typeCastepicsExportSharedSymbols
|
||||
#define epicsExportSharedSymbols
|
||||
#undef typeCastepicsExportSharedSymbols
|
||||
#endif
|
||||
|
||||
#include <pv/pvType.h>
|
||||
#include <pv/pvIntrospect.h>
|
||||
#include <pv/templateMeta.h>
|
||||
|
||||
#include <shareLib.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
typedef std::string String;
|
||||
|
||||
namespace detail {
|
||||
// parseToPOD wraps the epicsParse*() functions in one name
|
||||
// and throws exceptions
|
||||
epicsShareExtern void parseToPOD(const std::string&, boolean *out);
|
||||
epicsShareExtern void parseToPOD(const std::string&, int8 *out);
|
||||
epicsShareExtern void parseToPOD(const std::string&, uint8 *out);
|
||||
epicsShareExtern void parseToPOD(const std::string&, int16_t *out);
|
||||
epicsShareExtern void parseToPOD(const std::string&, uint16_t *out);
|
||||
epicsShareExtern void parseToPOD(const std::string&, int32_t *out);
|
||||
epicsShareExtern void parseToPOD(const std::string&, uint32_t *out);
|
||||
epicsShareExtern void parseToPOD(const std::string&, int64_t *out);
|
||||
epicsShareExtern void parseToPOD(const std::string&, uint64_t *out);
|
||||
epicsShareExtern void parseToPOD(const std::string&, float *out);
|
||||
epicsShareExtern void parseToPOD(const std::string&, double *out);
|
||||
|
||||
/* want to pass POD types by value,
|
||||
* and String by const reference
|
||||
*/
|
||||
template<typename ARG>
|
||||
struct cast_arg { typedef ARG arg; };
|
||||
template<>
|
||||
struct cast_arg<String> { typedef const String& arg; };
|
||||
|
||||
// Handle mangling of type/value when printing
|
||||
template<typename T>
|
||||
struct print_convolute {
|
||||
typedef T return_t;
|
||||
static FORCE_INLINE return_t op(const T& i) { return i; }
|
||||
};
|
||||
// trick std::ostream into treating char's as numbers
|
||||
// by promoting char to int
|
||||
template<>
|
||||
struct print_convolute<int8> {
|
||||
typedef signed int return_t;
|
||||
static FORCE_INLINE return_t op(int8 i) { return i; }
|
||||
};
|
||||
template<>
|
||||
struct print_convolute<uint8> {
|
||||
typedef unsigned int return_t;
|
||||
static FORCE_INLINE return_t op(uint8 i) { return i; }
|
||||
};
|
||||
// Turn boolean into a string
|
||||
template<>
|
||||
struct print_convolute<boolean> {
|
||||
typedef const char* return_t;
|
||||
static FORCE_INLINE return_t op(boolean i) { return i ? "true" : "false"; }
|
||||
};
|
||||
|
||||
|
||||
// default to C++ type casting
|
||||
template<typename TO, typename FROM, class Enable = void>
|
||||
struct cast_helper {
|
||||
static FORCE_INLINE TO op(FROM from) {
|
||||
return static_cast<TO>(from);
|
||||
}
|
||||
};
|
||||
|
||||
// special handling when down-casting double to float
|
||||
template<>
|
||||
struct cast_helper<float, double> {
|
||||
static FORCE_INLINE float op(double from) {
|
||||
return epicsConvertDoubleToFloat(from);
|
||||
}
|
||||
};
|
||||
|
||||
// print POD to string
|
||||
// when String!=FROM
|
||||
template<typename FROM>
|
||||
struct cast_helper<String, FROM, typename meta::not_same_type<String,FROM>::type> {
|
||||
static String op(FROM from) {
|
||||
std::ostringstream strm;
|
||||
strm << print_convolute<FROM>::op(from);
|
||||
if(strm.fail())
|
||||
throw std::runtime_error("Cast to string failed");
|
||||
return strm.str();
|
||||
}
|
||||
};
|
||||
|
||||
// parse POD from string
|
||||
// TO!=String
|
||||
template<typename TO>
|
||||
struct cast_helper<TO, String, typename meta::not_same_type<TO,String>::type> {
|
||||
static FORCE_INLINE TO op(const String& from) {
|
||||
TO ret;
|
||||
parseToPOD(from, &ret);
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
} // end detail
|
||||
|
||||
/** @brief Casting/converting between supported scalar types.
|
||||
*
|
||||
* Supported types: uint8_t, int8_t, uint16_t, int16_t,
|
||||
* uint32_t, int32_t, uint64_t, int64_t,
|
||||
* float, double, String
|
||||
*
|
||||
* As defined in pvType.h
|
||||
*
|
||||
@throws std::runtime_error when the cast is not possible.
|
||||
@throws std::bad_alloc when the cast is not possible.
|
||||
*
|
||||
@section convertg Conversion Guarantees
|
||||
*
|
||||
* Conversions which always produce a correct result.
|
||||
*
|
||||
* - signed integer -> larger signed integer
|
||||
* - unsigned integer -> larger unsigned integer
|
||||
* - integer -> float or double (where sizeof(integer)<sizeof(floating))
|
||||
* - float -> double
|
||||
*
|
||||
* Conversions where out of range inputs always produce
|
||||
* a defined result, but may not be reversable.
|
||||
*
|
||||
* - double -> float. When abs(value) is outside the range
|
||||
* [FLT_MIN, FLT_MAX] the value is clipped to FLT_MIN or FLT_MAX
|
||||
* with the sign preserved.
|
||||
*
|
||||
* Conversions where invalid or out of range inputs result
|
||||
* in an exception.
|
||||
*
|
||||
* - non-String -> String
|
||||
* - String -> non-String
|
||||
* - String -> String (throws only std::bad_alloc)
|
||||
*
|
||||
* Conversions where out of range inputs produce undefined
|
||||
* results.
|
||||
*
|
||||
* - signed integer -> smaller signed integer
|
||||
* - unsigned integer -> smaller unsigned integer
|
||||
* - signed integer <-> unsigned integer
|
||||
* - integer -> float or double (where sizeof(integer)>=sizeof(floating))
|
||||
* - float or double -> integer. The floating point value
|
||||
* is rounded towards zero. However, the result for values
|
||||
* too large to be represented by the integer type
|
||||
* is not defined.
|
||||
*
|
||||
@section stringf String formats
|
||||
*
|
||||
* - Numbers beginning with 1-9 are parsed as base-10.
|
||||
* - Numbers beginning with '0x' are parsed as base-16
|
||||
* - Numbers beginning with '0' are parsed as base-8.
|
||||
* - Hex numbers are case insensitive.
|
||||
* - Exponential numbers may use either 'e' or 'E'.
|
||||
*/
|
||||
template<typename TO, typename FROM>
|
||||
static FORCE_INLINE TO castUnsafe(const FROM& from)
|
||||
{
|
||||
return detail::cast_helper<TO,FROM>::op(from);
|
||||
}
|
||||
|
||||
epicsShareExtern void castUnsafeV(size_t count, ScalarType to, void *dest, ScalarType from, const void *src);
|
||||
|
||||
//! Cast value to printable type
|
||||
//! A no-op except for int8 and uint8, which are cast to int
|
||||
//! so that they are printed as numbers std::ostream operators,
|
||||
//! and boolean which is transformed into a const char*
|
||||
template<typename T>
|
||||
static FORCE_INLINE
|
||||
typename detail::print_convolute<T>::return_t
|
||||
print_cast(const T& v) { return detail::print_convolute<T>::op(v); }
|
||||
|
||||
}} // end namespace
|
||||
|
||||
#endif // PVTYPECAST_H
|
||||
8
src/monitor/Makefile
Normal file
8
src/monitor/Makefile
Normal file
@@ -0,0 +1,8 @@
|
||||
# This is a Makefile fragment, see ../Makefile
|
||||
|
||||
SRC_DIRS += $(PVDATA_SRC)/monitor
|
||||
|
||||
INC += monitor.h
|
||||
|
||||
LIBSRCS += monitor.cpp
|
||||
|
||||
14
src/monitor/monitor.cpp
Normal file
14
src/monitor/monitor.cpp
Normal file
@@ -0,0 +1,14 @@
|
||||
/*monitor.cpp*/
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mse
|
||||
*/
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
|
||||
// needed to get interfaces exported
|
||||
#include <pv/monitor.h>
|
||||
@@ -16,6 +16,8 @@
|
||||
#include <pv/sharedPtr.h>
|
||||
#include <pv/bitSet.h>
|
||||
|
||||
#include <shareLib.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
class MonitorElement;
|
||||
@@ -30,14 +32,14 @@ typedef std::tr1::shared_ptr<Monitor> MonitorPtr;
|
||||
* Class instance representing monitor element.
|
||||
* @author mrk
|
||||
*/
|
||||
class MonitorElement {
|
||||
class epicsShareClass MonitorElement {
|
||||
public:
|
||||
POINTER_DEFINITIONS(MonitorElement);
|
||||
MonitorElement(){}
|
||||
MonitorElement(PVStructurePtr const & pvStructurePtr)
|
||||
: pvStructurePtr(pvStructurePtr),
|
||||
changedBitSet(BitSet::create(pvStructurePtr->getNumberFields())),
|
||||
overrunBitSet(BitSet::create(pvStructurePtr->getNumberFields()))
|
||||
changedBitSet(BitSet::create(static_cast<uint32>(pvStructurePtr->getNumberFields()))),
|
||||
overrunBitSet(BitSet::create(static_cast<uint32>(pvStructurePtr->getNumberFields())))
|
||||
{}
|
||||
PVStructurePtr pvStructurePtr;
|
||||
BitSet::shared_pointer changedBitSet;
|
||||
@@ -48,7 +50,7 @@ class MonitorElement {
|
||||
* Interface for Monitor.
|
||||
* @author mrk
|
||||
*/
|
||||
class Monitor : public Destroyable{
|
||||
class epicsShareClass Monitor : public Destroyable{
|
||||
public:
|
||||
POINTER_DEFINITIONS(Monitor);
|
||||
virtual ~Monitor(){}
|
||||
@@ -80,7 +82,7 @@ class Monitor : public Destroyable{
|
||||
* Requester for ChannelMonitor.
|
||||
* @author mrk
|
||||
*/
|
||||
class MonitorRequester : public virtual Requester {
|
||||
class epicsShareClass MonitorRequester : public virtual Requester {
|
||||
public:
|
||||
POINTER_DEFINITIONS(MonitorRequester);
|
||||
virtual ~MonitorRequester(){}
|
||||
22
src/property/Makefile
Normal file
22
src/property/Makefile
Normal file
@@ -0,0 +1,22 @@
|
||||
# This is a Makefile fragment, see ../Makefile
|
||||
|
||||
SRC_DIRS += $(PVDATA_SRC)/property
|
||||
|
||||
INC += alarm.h
|
||||
INC += pvAlarm.h
|
||||
INC += control.h
|
||||
INC += pvControl.h
|
||||
INC += display.h
|
||||
INC += pvDisplay.h
|
||||
INC += pvEnumerated.h
|
||||
INC += timeStamp.h
|
||||
INC += pvTimeStamp.h
|
||||
|
||||
LIBSRCS += alarm.cpp
|
||||
LIBSRCS += pvAlarm.cpp
|
||||
LIBSRCS += pvControl.cpp
|
||||
LIBSRCS += pvDisplay.cpp
|
||||
LIBSRCS += pvEnumerated.cpp
|
||||
LIBSRCS += timeStamp.cpp
|
||||
LIBSRCS += pvTimeStamp.cpp
|
||||
|
||||
@@ -9,13 +9,15 @@
|
||||
*/
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/lock.h>
|
||||
#include <pv/pvType.h>
|
||||
#include <pv/pvIntrospect.h>
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/alarm.h>
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
AlarmSeverity AlarmSeverityFunc::getSeverity(int value)
|
||||
{
|
||||
@@ -34,7 +36,7 @@ AlarmSeverity AlarmSeverityFunc::getSeverity(int value)
|
||||
|
||||
StringArrayPtr AlarmSeverityFunc::getSeverityNames()
|
||||
{
|
||||
static size_t severityCount = 5;
|
||||
static size_t severityCount = 5;
|
||||
static StringArrayPtr severityNames;
|
||||
static Mutex mutex;
|
||||
Lock xx(mutex);
|
||||
@@ -82,7 +84,7 @@ AlarmStatus AlarmStatusFunc::getStatus(int value)
|
||||
|
||||
StringArrayPtr AlarmStatusFunc::getStatusNames()
|
||||
{
|
||||
static size_t statusCount = 8;
|
||||
static size_t statusCount = 8;
|
||||
static StringArrayPtr statusNames;
|
||||
static Mutex mutex;
|
||||
Lock xx(mutex);
|
||||
@@ -7,10 +7,15 @@
|
||||
/**
|
||||
* @author mrk
|
||||
*/
|
||||
#include <string>
|
||||
#include <pv/pvType.h>
|
||||
#ifndef ALARM_H
|
||||
#define ALARM_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <pv/pvType.h>
|
||||
|
||||
#include <shareLib.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
enum AlarmSeverity {
|
||||
@@ -23,21 +28,19 @@ enum AlarmStatus {
|
||||
};
|
||||
|
||||
|
||||
extern const size_t severityCount;
|
||||
class AlarmSeverityFunc {
|
||||
class epicsShareClass AlarmSeverityFunc {
|
||||
public:
|
||||
static AlarmSeverity getSeverity(int value);
|
||||
static StringArrayPtr getSeverityNames();
|
||||
};
|
||||
|
||||
extern const size_t statusCount;
|
||||
class AlarmStatusFunc {
|
||||
class epicsShareClass AlarmStatusFunc {
|
||||
public:
|
||||
static AlarmStatus getStatus(int value);
|
||||
static StringArrayPtr getStatusNames();
|
||||
};
|
||||
|
||||
class Alarm {
|
||||
class epicsShareClass Alarm {
|
||||
public:
|
||||
Alarm() : severity(0),status(0), message(String("")) {}
|
||||
//default constructors and destructor are OK
|
||||
@@ -9,9 +9,12 @@
|
||||
*/
|
||||
#ifndef CONTROL_H
|
||||
#define CONTROL_H
|
||||
|
||||
#include <shareLib.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
class Control {
|
||||
class epicsShareClass Control {
|
||||
public:
|
||||
Control() : low(0.0), high(0.0) {}
|
||||
//default constructors and destructor are OK
|
||||
@@ -7,14 +7,19 @@
|
||||
/**
|
||||
* @author mrk
|
||||
*/
|
||||
#include <string>
|
||||
#include <pv/pvType.h>
|
||||
#include <pv/pvData.h>
|
||||
#ifndef DISPLAY_H
|
||||
#define DISPLAY_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <pv/pvType.h>
|
||||
#include <pv/pvData.h>
|
||||
|
||||
#include <shareLib.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
class Display {
|
||||
class epicsShareClass Display {
|
||||
public:
|
||||
Display()
|
||||
: description(String("")),format(String("")),units(String("")),
|
||||
@@ -9,10 +9,13 @@
|
||||
*/
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/pvType.h>
|
||||
#include <pv/pvIntrospect.h>
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/pvAlarm.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
@@ -9,14 +9,18 @@
|
||||
*/
|
||||
#ifndef PVALARM_H
|
||||
#define PVALARM_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <pv/pvType.h>
|
||||
#include <pv/alarm.h>
|
||||
#include <pv/pvData.h>
|
||||
|
||||
#include <shareLib.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
class PVAlarm {
|
||||
class epicsShareClass PVAlarm {
|
||||
public:
|
||||
PVAlarm() {}
|
||||
//default constructors and destructor are OK
|
||||
@@ -9,10 +9,13 @@
|
||||
*/
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/pvType.h>
|
||||
#include <pv/pvIntrospect.h>
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/pvControl.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
@@ -7,13 +7,17 @@
|
||||
/**
|
||||
* @author mrk
|
||||
*/
|
||||
#include <pv/control.h>
|
||||
#include <pv/pvData.h>
|
||||
#ifndef PVCONTROL_H
|
||||
#define PVCONTROL_H
|
||||
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/control.h>
|
||||
|
||||
#include <shareLib.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
class PVControl {
|
||||
class epicsShareClass PVControl {
|
||||
public:
|
||||
PVControl(){}
|
||||
//default constructors and destructor are OK
|
||||
@@ -9,10 +9,13 @@
|
||||
*/
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/pvType.h>
|
||||
#include <pv/pvIntrospect.h>
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/pvDisplay.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
@@ -7,15 +7,20 @@
|
||||
/**
|
||||
* @author mrk
|
||||
*/
|
||||
#ifndef PVDISPLAY_H
|
||||
#define PVDISPLAY_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <pv/pvType.h>
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/display.h>
|
||||
#ifndef PVDISPLAY_H
|
||||
#define PVDISPLAY_H
|
||||
|
||||
#include <shareLib.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
class PVDisplay {
|
||||
class epicsShareClass PVDisplay {
|
||||
public:
|
||||
PVDisplay() {}
|
||||
//default constructors and destructor are OK
|
||||
@@ -9,10 +9,13 @@
|
||||
*/
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/pvType.h>
|
||||
#include <pv/pvIntrospect.h>
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/pvEnumerated.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
@@ -78,9 +81,8 @@ String PVEnumerated::getChoice()
|
||||
throw std::logic_error(notAttached);
|
||||
}
|
||||
int index = pvIndex->get();
|
||||
StringArrayData data;
|
||||
pvChoices->get(0,pvChoices->getLength(),data);
|
||||
return data.data[index];
|
||||
const PVStringArray::const_svector& data(pvChoices->view());
|
||||
return data[index];
|
||||
}
|
||||
|
||||
bool PVEnumerated::choicesMutable()
|
||||
@@ -91,30 +93,23 @@ bool PVEnumerated::choicesMutable()
|
||||
return pvChoices->isImmutable();
|
||||
}
|
||||
|
||||
StringArrayPtr const & PVEnumerated:: getChoices()
|
||||
{
|
||||
if(pvIndex.get()==NULL ) {
|
||||
throw std::logic_error(notAttached);
|
||||
}
|
||||
StringArrayData data;
|
||||
return pvChoices->getSharedVector();
|
||||
}
|
||||
|
||||
int32 PVEnumerated::getNumberChoices()
|
||||
{
|
||||
if(pvIndex.get()==NULL ) {
|
||||
throw std::logic_error(notAttached);
|
||||
}
|
||||
return pvChoices->getLength();
|
||||
return static_cast<int32>(pvChoices->getLength());
|
||||
}
|
||||
|
||||
bool PVEnumerated:: setChoices(StringArray & choices)
|
||||
bool PVEnumerated:: setChoices(const StringArray & choices)
|
||||
{
|
||||
if(pvIndex.get()==NULL ) {
|
||||
throw std::logic_error(notAttached);
|
||||
}
|
||||
if(pvChoices->isImmutable()) return false;
|
||||
pvChoices->put(0,choices.size(),get(choices),0);
|
||||
PVStringArray::svector data(choices.size());
|
||||
std::copy(choices.begin(), choices.end(), data.begin());
|
||||
pvChoices->replace(freeze(data));
|
||||
return true;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user