fixed possible SEGFAULT in ceateRequest; new stream operator for Field and PVField

This commit is contained in:
Marty Kraimer
2015-02-11 07:26:04 -05:00
parent a277a4fdd5
commit 6cb95c5cfc
10 changed files with 161 additions and 22 deletions

View File

@@ -1,4 +1,45 @@
<h1>Release 4.0 IN DEVELOPMENT</h1>
<h1>Release 4.1 IN DEVELOPMENT</h1>
<p>The main changes since release 4.0 are:</p>
<ul>
<li>Convert::copyUnion now always copies between subfields.</li>
<li>CreateRequest prevents a possible SEGFAULT.</li>
<li>New stream operators for Field and PVField are provided.</li>
</ul>
<h2>Convert::copyUnion</h2>
<p>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.</p>
<h2>CreateRequest change</h2>
<p>createRequest could cause a SEGFAULT if passed a bad argument.
This has been changed so the it returns a null pvStructure
and provies an error.</p>
<h2>New stream operators</h2>
<p>New steam operators are available for Field and PVField.
Before to print a Field (or any extension) or a PVField (or any extension)
it was necessary to have code like:</p>
<pre><code> void print(StructureConstPtr struct, PVStructurePtr pv)
{
if(struct) {
cout &lt;&lt; *struct &lt;&lt; endl;
} else {
cout &lt;&lt; "nullptr\n"
}
if(pv) {
cout &lt;&lt; *.struct &lt;&lt; endl;
} else {
cout &lt;&lt; "nullptr\n"
}
}
</code></pre>
<p>Now it can be done as follows:</p>
<pre><code> void print(StructureConstPtr struct, PVStructurePtr pv)
{
cout &lt;&lt; struct &lt;&lt; endl;
cout &lt;&lt; pv &lt;&lt; endl;
}
</code></pre>
<h1>Release 4.0</h1>
<p>The main changes since release 3.0.2 are:</p>
<ul>
<li>array semantics now enforce Copy On Write.</li>
@@ -55,4 +96,4 @@ only on pvData, i. e. it no longer has any knowledge of PVRecord.</p>
<p>This is for is for use by code that implements pvAccess monitors.
This is prototype and is subject to debate.</p>
<h1>Release 3.0.2</h1>
<p>This was the starting point for RELEASE_NOTES</p>
<p>This was the starting point for RELEASE_NOTES</p>

View File

@@ -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:

View File

@@ -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; i<optionList.size(); ++i) {
OptionPair pair = optionList[i];
string name = pair.name;
string value = pair.value;
PVStringPtr pvField = pvStructure->getSubField<PVString>(name);
if(!pvField) throw std::invalid_argument("bad request " + crequest);
pvField->put(value);
}
optionList.clear();

View File

@@ -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";
}
}

View File

@@ -741,3 +741,12 @@ PVDataCreatePtr getPVDataCreate() {
}
}}
namespace std{
std::ostream& operator<<(std::ostream& o, const epics::pvData::PVField *ptr)
{
if(ptr) return o << *ptr;
return o << "nullptr";
}
}

View File

@@ -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

View File

@@ -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 */

View File

@@ -31,7 +31,7 @@ static void testCreateRequestInternal() {
if(debug) { cout << "request " << request <<endl;}
PVStructurePtr pvRequest = createRequest->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 <<endl;}
pvRequest = createRequest->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 <<endl;}
pvRequest = createRequest->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<PVString>("record._options.a");
sval = pvString->get();
@@ -68,7 +68,7 @@ static void testCreateRequestInternal() {
if(debug) { cout << "request " << request <<endl;}
pvRequest = createRequest->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<PVString>("field.a.b._options.x");
sval = pvString->get();
@@ -79,7 +79,7 @@ static void testCreateRequestInternal() {
if(debug) { cout << "request " << request <<endl;}
pvRequest = createRequest->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 <<endl;}
pvRequest = createRequest->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<PVString>("field.a.b._options.x");
sval = pvString->get();
@@ -100,7 +100,7 @@ static void testCreateRequestInternal() {
if(debug) { cout << "request " << request <<endl;}
pvRequest = createRequest->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<PVString>("field.a.b._options.x");
sval = pvString->get();
@@ -114,7 +114,7 @@ static void testCreateRequestInternal() {
if(debug) { cout << "request " << request <<endl;}
pvRequest = createRequest->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<PVString>("field.a.a._options.a");
sval = pvString->get();
@@ -134,7 +134,7 @@ static void testCreateRequestInternal() {
if(debug) { cout << "request " << request <<endl;}
pvRequest = createRequest->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 <<endl;}
pvRequest = createRequest->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<PVString>("record._options.process");
sval = pvString->get();
@@ -159,7 +159,7 @@ static void testCreateRequestInternal() {
if(debug) { cout << "request " << request <<endl;}
pvRequest = createRequest->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<PVString>("record._options.process");
sval = pvString->get();
@@ -180,7 +180,7 @@ static void testCreateRequestInternal() {
if(debug) { cout << "request " << request <<endl;}
pvRequest = createRequest->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<PVString>("record._options.int");
sval = pvString->get();
@@ -202,7 +202,7 @@ static void testCreateRequestInternal() {
if(debug) { cout << "request " << request <<endl;}
pvRequest = createRequest->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 <<endl;}
pvRequest = createRequest->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 <<endl;}
pvRequest = createRequest->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 <<endl;}
pvRequest = createRequest->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 <<endl;}
cout << endl << "Error Expected for next call!!" << endl;
pvRequest = createRequest->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();
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}