diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.html
index 70a2f0f..a4d6997 100644
--- a/documentation/RELEASE_NOTES.html
+++ b/documentation/RELEASE_NOTES.html
@@ -1,4 +1,45 @@
-
Release 4.0 IN DEVELOPMENT
+Release 4.1 IN DEVELOPMENT
+The main changes since release 4.0 are:
+
+- Convert::copyUnion now always copies between subfields.
+- CreateRequest prevents a possible SEGFAULT.
+- New stream operators for Field and PVField are provided.
+
+Convert::copyUnion
+Before this method, depending on types for to and from,
+sometimes did a shallow cppy, i. e. just made to shared_ptr for to
+share the same data as from.
+Now it always copies between the subfield of to and from.
+CreateRequest change
+createRequest could cause a SEGFAULT if passed a bad argument.
+This has been changed so the it returns a null pvStructure
+and provies an error.
+New stream operators
+New steam operators are available for Field and PVField.
+Before to print a Field (or any extension) or a PVField (or any extension)
+it was necessary to have code like:
+ void print(StructureConstPtr struct, PVStructurePtr pv)
+ {
+ if(struct) {
+ cout << *struct << endl;
+ } else {
+ cout << "nullptr\n"
+ }
+ if(pv) {
+ cout << *.struct << endl;
+ } else {
+ cout << "nullptr\n"
+ }
+ }
+
+Now it can be done as follows:
+ void print(StructureConstPtr struct, PVStructurePtr pv)
+ {
+ cout << struct << endl;
+ cout << pv << endl;
+ }
+
+Release 4.0
The main changes since release 3.0.2 are:
- array semantics now enforce Copy On Write.
@@ -55,4 +96,4 @@ only on pvData, i. e. it no longer has any knowledge of PVRecord.
This is for is for use by code that implements pvAccess monitors.
This is prototype and is subject to debate.
Release 3.0.2
-This was the starting point for RELEASE_NOTES
+This was the starting point for RELEASE_NOTES
\ No newline at end of file
diff --git a/documentation/RELEASE_NOTES.md b/documentation/RELEASE_NOTES.md
index 760892c..d1caa32 100644
--- a/documentation/RELEASE_NOTES.md
+++ b/documentation/RELEASE_NOTES.md
@@ -1,4 +1,58 @@
-Release 4.0 IN DEVELOPMENT
+Release 4.1 IN DEVELOPMENT
+===========
+
+The main changes since release 4.0 are:
+
+* Convert::copyUnion now always copies between subfields.
+* CreateRequest prevents a possible SEGFAULT.
+* New stream operators for Field and PVField are provided.
+
+Convert::copyUnion
+-----------------
+
+Before this method, depending on types for to and from,
+sometimes did a shallow cppy, i. e. just made to shared_ptr for to
+share the same data as from.
+Now it always copies between the subfield of to and from.
+
+CreateRequest change
+--------------------
+
+createRequest could cause a SEGFAULT if passed a bad argument.
+This has been changed so the it returns a null pvStructure
+and provies an error.
+
+New stream operators
+--------------------
+
+New steam operators are available for Field and PVField.
+Before to print a Field (or any extension) or a PVField (or any extension)
+it was necessary to have code like:
+
+ void print(StructureConstPtr struct, PVStructurePtr pv)
+ {
+ if(struct) {
+ cout << *struct << endl;
+ } else {
+ cout << "nullptr\n"
+ }
+ if(pv) {
+ cout << *.struct << endl;
+ } else {
+ cout << "nullptr\n"
+ }
+ }
+
+Now it can be done as follows:
+
+ void print(StructureConstPtr struct, PVStructurePtr pv)
+ {
+ cout << struct << endl;
+ cout << pv << endl;
+ }
+
+
+Release 4.0
===========
The main changes since release 3.0.2 are:
diff --git a/src/copy/createRequest.cpp b/src/copy/createRequest.cpp
index 6260162..80e4f63 100644
--- a/src/copy/createRequest.cpp
+++ b/src/copy/createRequest.cpp
@@ -454,12 +454,14 @@ public:
}
}
StructureConstPtr structure = fieldCreate->createStructure(names, fields);
+ if(!structure) throw std::invalid_argument("bad request " + crequest);
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(structure);
for(size_t i=0; igetSubField(name);
+ if(!pvField) throw std::invalid_argument("bad request " + crequest);
pvField->put(value);
}
optionList.clear();
diff --git a/src/factory/FieldCreateFactory.cpp b/src/factory/FieldCreateFactory.cpp
index daaeaff..3f4c250 100644
--- a/src/factory/FieldCreateFactory.cpp
+++ b/src/factory/FieldCreateFactory.cpp
@@ -1230,3 +1230,12 @@ FieldCreatePtr getFieldCreate() {
}
}}
+
+namespace std{
+ std::ostream& operator<<(std::ostream& o, const epics::pvData::Field *ptr)
+ {
+ if(ptr) return o << *ptr;
+ return o << "nullptr";
+ }
+}
+
diff --git a/src/factory/PVDataCreateFactory.cpp b/src/factory/PVDataCreateFactory.cpp
index 3a5c714..e8eb148 100644
--- a/src/factory/PVDataCreateFactory.cpp
+++ b/src/factory/PVDataCreateFactory.cpp
@@ -741,3 +741,12 @@ PVDataCreatePtr getPVDataCreate() {
}
}}
+
+namespace std{
+ std::ostream& operator<<(std::ostream& o, const epics::pvData::PVField *ptr)
+ {
+ if(ptr) return o << *ptr;
+ return o << "nullptr";
+ }
+}
+
diff --git a/src/pv/pvData.h b/src/pv/pvData.h
index ad7de7c..7798aec 100644
--- a/src/pv/pvData.h
+++ b/src/pv/pvData.h
@@ -1565,6 +1565,14 @@ private:
epicsShareExtern PVDataCreatePtr getPVDataCreate();
}}
+
+/**
+ * stream support for pvField
+ */
+namespace std{
+ std::ostream& operator<<(std::ostream& o, const epics::pvData::PVField *ptr);
+}
+
#endif /* PVDATA_H */
/** @page Overview Documentation
diff --git a/src/pv/pvIntrospect.h b/src/pv/pvIntrospect.h
index 1c67db2..53d236f 100644
--- a/src/pv/pvIntrospect.h
+++ b/src/pv/pvIntrospect.h
@@ -1220,4 +1220,12 @@ struct StructureArrayHashFunction {
};
}}
+
+/**
+ * stream support for Field
+ */
+namespace std{
+ std::ostream& operator<<(std::ostream& o, const epics::pvData::Field *ptr);
+}
+
#endif /* PVINTROSPECT_H */
diff --git a/testApp/copy/testCreateRequest.cpp b/testApp/copy/testCreateRequest.cpp
index 4df1b89..d183bb1 100644
--- a/testApp/copy/testCreateRequest.cpp
+++ b/testApp/copy/testCreateRequest.cpp
@@ -31,7 +31,7 @@ static void testCreateRequestInternal() {
if(debug) { cout << "request " << request <createRequest(request);
if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
- if(debug) { cout << *pvRequest << endl;}
+ if(debug) { cout << pvRequest << endl;}
testOk1(pvRequest.get()!=NULL);
testOk1(pvRequest->getStructure()->getNumberFields()==0);
testPass("request %s",request.c_str());
@@ -40,7 +40,7 @@ static void testCreateRequestInternal() {
if(debug) { cout << "request " << request <createRequest(request);
if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
- if(debug) { cout << *pvRequest << endl;}
+ if(debug) { cout << pvRequest << endl;}
testOk1(pvRequest.get()!=NULL);
testOk1(pvRequest->getSubField("field").get()!=NULL);
testOk1(pvRequest->getSubField("putField").get()!=NULL);
@@ -51,7 +51,7 @@ static void testCreateRequestInternal() {
if(debug) { cout << "request " << request <createRequest(request);
if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
- if(debug) { cout << *pvRequest << endl;}
+ if(debug) { cout << pvRequest << endl;}
testOk1(pvRequest.get()!=NULL);
pvString = pvRequest->getSubField("record._options.a");
sval = pvString->get();
@@ -68,7 +68,7 @@ static void testCreateRequestInternal() {
if(debug) { cout << "request " << request <createRequest(request);
if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
- if(debug) { cout << *pvRequest << endl;}
+ if(debug) { cout << pvRequest << endl;}
testOk1(pvRequest.get()!=NULL);
pvString = pvRequest->getSubField("field.a.b._options.x");
sval = pvString->get();
@@ -79,7 +79,7 @@ static void testCreateRequestInternal() {
if(debug) { cout << "request " << request <createRequest(request);
if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
- if(debug) { cout << *pvRequest << endl;}
+ if(debug) { cout << pvRequest << endl;}
testOk1(pvRequest.get()!=NULL);
testOk1(pvRequest->getSubField("field.a.b.c.d").get()!=NULL);
testPass("request %s",request.c_str());
@@ -88,7 +88,7 @@ static void testCreateRequestInternal() {
if(debug) { cout << "request " << request <createRequest(request);
if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
- if(debug) { cout << *pvRequest << endl;}
+ if(debug) { cout << pvRequest << endl;}
testOk1(pvRequest.get()!=NULL);
pvString = pvRequest->getSubField("field.a.b._options.x");
sval = pvString->get();
@@ -100,7 +100,7 @@ static void testCreateRequestInternal() {
if(debug) { cout << "request " << request <createRequest(request);
if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
- if(debug) { cout << *pvRequest << endl;}
+ if(debug) { cout << pvRequest << endl;}
testOk1(pvRequest.get()!=NULL);
pvString = pvRequest->getSubField("field.a.b._options.x");
sval = pvString->get();
@@ -114,7 +114,7 @@ static void testCreateRequestInternal() {
if(debug) { cout << "request " << request <createRequest(request);
if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
- if(debug) { cout << *pvRequest << endl;}
+ if(debug) { cout << pvRequest << endl;}
testOk1(pvRequest.get()!=NULL);
pvString = pvRequest->getSubField("field.a.a._options.a");
sval = pvString->get();
@@ -134,7 +134,7 @@ static void testCreateRequestInternal() {
if(debug) { cout << "request " << request <createRequest(request);
if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
- if(debug) { cout << *pvRequest << endl;}
+ if(debug) { cout << pvRequest << endl;}
testOk1(pvRequest.get()!=NULL);
testOk1(pvRequest->getSubField("field.alarm").get()!=NULL);
testOk1(pvRequest->getSubField("field.timeStamp").get()!=NULL);
@@ -145,7 +145,7 @@ static void testCreateRequestInternal() {
if(debug) { cout << "request " << request <createRequest(request);
if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
- if(debug) { cout << *pvRequest << endl;}
+ if(debug) { cout << pvRequest << endl;}
testOk1(pvRequest.get()!=NULL);
pvString = pvRequest->getSubField("record._options.process");
sval = pvString->get();
@@ -159,7 +159,7 @@ static void testCreateRequestInternal() {
if(debug) { cout << "request " << request <createRequest(request);
if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
- if(debug) { cout << *pvRequest << endl;}
+ if(debug) { cout << pvRequest << endl;}
testOk1(pvRequest.get()!=NULL);
pvString = pvRequest->getSubField("record._options.process");
sval = pvString->get();
@@ -180,7 +180,7 @@ static void testCreateRequestInternal() {
if(debug) { cout << "request " << request <createRequest(request);
if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
- if(debug) { cout << *pvRequest << endl;}
+ if(debug) { cout << pvRequest << endl;}
testOk1(pvRequest.get()!=NULL);
pvString = pvRequest->getSubField("record._options.int");
sval = pvString->get();
@@ -202,7 +202,7 @@ static void testCreateRequestInternal() {
if(debug) { cout << "request " << request <createRequest(request);
if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
- if(debug) { cout << *pvRequest << endl;}
+ if(debug) { cout << pvRequest << endl;}
testOk1(pvRequest.get()!=NULL);
testOk1(pvRequest->getSubField("putField.power.value").get()!=NULL);
testOk1(pvRequest->getSubField("getField.alarm").get()!=NULL);
@@ -222,7 +222,7 @@ static void testCreateRequestInternal() {
if(debug) { cout << "request " << request <createRequest(request);
if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
- if(debug) { cout << *pvRequest << endl;}
+ if(debug) { cout << pvRequest << endl;}
testOk1(pvRequest.get()!=NULL);
testOk1(pvRequest->getSubField("field.alarm").get()!=NULL);
testOk1(pvRequest->getSubField("field.timeStamp").get()!=NULL);
@@ -244,7 +244,7 @@ static void testCreateRequestInternal() {
if(debug) { cout << "request " << request <createRequest(request);
if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
- if(debug) { cout << *pvRequest << endl;}
+ if(debug) { cout << pvRequest << endl;}
testOk1(pvRequest.get()!=NULL);
testOk1(pvRequest->getSubField("putField.power.value").get()!=NULL);
testOk1(pvRequest->getSubField("getField.alarm").get()!=NULL);
@@ -277,7 +277,7 @@ static void testCreateRequestInternal() {
if(debug) { cout << "request " << request <createRequest(request);
if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
- if(debug) { cout << *pvRequest << endl;}
+ if(debug) { cout << pvRequest << endl;}
testOk1(pvRequest.get()!=NULL);
testOk1(pvRequest->getSubField("field.a.b.c.d").get()!=NULL);
testPass("request %s",request.c_str());
@@ -310,11 +310,19 @@ static void testCreateRequestInternal() {
cout << "reason " << createRequest->getMessage() << endl;
testOk1(pvRequest.get()==NULL);
testPass("request %s",request.c_str());
+
+ request = ":field(record[process=false]power.value)";
+ if(debug) { cout << "request " << request <createRequest(request);
+ cout << "reason " << createRequest->getMessage() << endl;
+ testOk1(pvRequest.get()==NULL);
+ testPass("request %s",request.c_str());
}
MAIN(testCreateRequest)
{
- testPlan(119);
+ testPlan(121);
testCreateRequestInternal();
return testDone();
}
diff --git a/testApp/pv/testStandardField.cpp b/testApp/pv/testStandardField.cpp
index 3d5e434..de3f1cd 100644
--- a/testApp/pv/testStandardField.cpp
+++ b/testApp/pv/testStandardField.cpp
@@ -34,7 +34,7 @@ static StandardFieldPtr standardField = getStandardField();
static void print(const string& name, FieldConstPtr const & f)
{
if(debug) {
- std::cout << std::endl << name << std::endl << *f << std::endl;
+ std::cout << std::endl << name << std::endl << f << std::endl;
}
}
diff --git a/testApp/pv/testStandardPVField.cpp b/testApp/pv/testStandardPVField.cpp
index a22f9d1..28efc6d 100644
--- a/testApp/pv/testStandardPVField.cpp
+++ b/testApp/pv/testStandardPVField.cpp
@@ -36,7 +36,7 @@ static StandardPVFieldPtr standardPVField = getStandardPVField();
static void print(const string& name, PVFieldPtr const & f)
{
if(debug) {
- std::cout << std::endl << name << std::endl << *f << std::endl;
+ std::cout << std::endl << name << std::endl << f << std::endl;
}
}