Merge branch 'master' into PSI
This commit is contained in:
commit
8a5a6fcd27
19 files changed
+333
-130
No files matched your search
@@ -28,6 +28,8 @@
|
||||
#include <pv/thread.h>
|
||||
#include <pv/pvData.h>
|
||||
|
||||
#include "factoryPvt.h"
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using std::size_t;
|
||||
using std::string;
|
||||
@@ -36,7 +38,6 @@ namespace epics { namespace pvData {
|
||||
|
||||
size_t Field::num_instances;
|
||||
|
||||
|
||||
struct Field::Helper {
|
||||
static unsigned hash(Field *fld) {
|
||||
std::ostringstream key;
|
||||
@@ -1488,6 +1489,7 @@ static int decodeScalar(int8 code)
|
||||
|
||||
FieldConstPtr FieldCreate::deserialize(ByteBuffer* buffer, DeserializableControl* control) const
|
||||
{
|
||||
RecurseGuard RG;
|
||||
control->ensureData(1);
|
||||
int8 code = buffer->getByte();
|
||||
if (code == -1)
|
||||
@@ -1576,7 +1578,9 @@ FieldConstPtr FieldCreate::deserialize(ByteBuffer* buffer, DeserializableControl
|
||||
throw std::invalid_argument("fixed and bounded structure array not supported");
|
||||
|
||||
// Type type = Type.structureArray;
|
||||
StructureConstPtr elementStructure = std::tr1::static_pointer_cast<const Structure>(control->cachedDeserialize(buffer));
|
||||
StructureConstPtr elementStructure = std::tr1::dynamic_pointer_cast<const Structure>(control->cachedDeserialize(buffer));
|
||||
if(!elementStructure)
|
||||
throw std::invalid_argument("Expected Structure");
|
||||
// TODO use std::make_shared
|
||||
std::tr1::shared_ptr<Field> sp(new StructureArray(elementStructure));
|
||||
Helper::cache(this, sp);
|
||||
@@ -1589,7 +1593,9 @@ FieldConstPtr FieldCreate::deserialize(ByteBuffer* buffer, DeserializableControl
|
||||
throw std::invalid_argument("fixed and bounded structure array not supported");
|
||||
|
||||
// Type type = Type.unionArray;
|
||||
UnionConstPtr elementUnion = std::tr1::static_pointer_cast<const Union>(control->cachedDeserialize(buffer));
|
||||
UnionConstPtr elementUnion = std::tr1::dynamic_pointer_cast<const Union>(control->cachedDeserialize(buffer));
|
||||
if(!elementUnion)
|
||||
throw std::invalid_argument("Expected Union");
|
||||
// TODO use std::make_shared
|
||||
std::tr1::shared_ptr<Field> sp(new UnionArray(elementUnion));
|
||||
Helper::cache(this, sp);
|
||||
@@ -1612,6 +1618,7 @@ FieldConstPtr FieldCreate::deserialize(ByteBuffer* buffer, DeserializableControl
|
||||
namespace detail {
|
||||
struct field_factory {
|
||||
FieldCreatePtr fieldCreate;
|
||||
epicsThreadPrivate<unsigned> deserDepth;
|
||||
field_factory() :fieldCreate(new FieldCreate()) {
|
||||
registerRefCounter("Field", &Field::num_instances);
|
||||
registerRefCounter("Thread", &Thread::num_instances);
|
||||
@@ -1622,6 +1629,23 @@ struct field_factory {
|
||||
static detail::field_factory* field_factory_s;
|
||||
static epicsThreadOnceId field_factory_once = EPICS_THREAD_ONCE_INIT;
|
||||
|
||||
#if defined(__rtems__) || defined(vxWorks)
|
||||
// lower limit on embedded targets
|
||||
const unsigned maxDepth = 10;
|
||||
#else
|
||||
const unsigned maxDepth = 20;
|
||||
#endif
|
||||
RecurseGuard::RecurseGuard() {
|
||||
size_t current = (size_t)field_factory_s->deserDepth.get();
|
||||
if(current>=maxDepth)
|
||||
throw std::logic_error("FieldCreateFactory recursion depth exceeded");
|
||||
field_factory_s->deserDepth.set((unsigned*)(current+1));
|
||||
}
|
||||
RecurseGuard::~RecurseGuard() {
|
||||
size_t current = (size_t)field_factory_s->deserDepth.get();
|
||||
field_factory_s->deserDepth.set((unsigned*)(current-1));
|
||||
}
|
||||
|
||||
static void field_factory_init(void*)
|
||||
{
|
||||
try {
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
#include <pv/factory.h>
|
||||
#include <pv/bitSet.h>
|
||||
|
||||
#include "factoryPvt.h"
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using std::size_t;
|
||||
using std::string;
|
||||
@@ -224,6 +226,7 @@ void PVStructure::serialize(ByteBuffer *pbuffer,
|
||||
|
||||
void PVStructure::deserialize(ByteBuffer *pbuffer,
|
||||
DeserializableControl *pcontrol) {
|
||||
RecurseGuard G;
|
||||
size_t fieldsSize = pvFields.size();
|
||||
for(size_t i = 0; i<fieldsSize; i++)
|
||||
pvFields[i]->deserialize(pbuffer, pcontrol);
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
#include <pv/factory.h>
|
||||
#include <pv/serializeHelper.h>
|
||||
|
||||
#include "factoryPvt.h"
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using std::size_t;
|
||||
|
||||
@@ -158,6 +160,7 @@ void PVStructureArray::serialize(ByteBuffer *pbuffer,
|
||||
|
||||
void PVStructureArray::deserialize(ByteBuffer *pbuffer,
|
||||
DeserializableControl *pcontrol) {
|
||||
RecurseGuard G;
|
||||
svector data(reuse());
|
||||
|
||||
size_t size = this->getArray()->getArraySizeType() == Array::fixed ?
|
||||
|
||||
+15
-7
@@ -18,6 +18,8 @@
|
||||
#include <pv/factory.h>
|
||||
#include <pv/serializeHelper.h>
|
||||
|
||||
#include "factoryPvt.h"
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using std::size_t;
|
||||
using std::string;
|
||||
@@ -143,6 +145,7 @@ void PVUnion::serialize(ByteBuffer *pbuffer, SerializableControl *pflusher) cons
|
||||
|
||||
void PVUnion::deserialize(ByteBuffer *pbuffer, DeserializableControl *pcontrol)
|
||||
{
|
||||
RecurseGuard G;
|
||||
if (variant)
|
||||
{
|
||||
FieldConstPtr field = pcontrol->cachedDeserialize(pbuffer);
|
||||
@@ -158,21 +161,26 @@ void PVUnion::deserialize(ByteBuffer *pbuffer, DeserializableControl *pcontrol)
|
||||
}
|
||||
else
|
||||
{
|
||||
int32 previousSelector = selector;
|
||||
selector = static_cast<int32>(SerializeHelper::readSize(pbuffer, pcontrol));
|
||||
if (selector != UNDEFINED_INDEX)
|
||||
int32 index = static_cast<int32>(SerializeHelper::readSize(pbuffer, pcontrol));
|
||||
if (index == UNDEFINED_INDEX)
|
||||
{
|
||||
if (selector != previousSelector)
|
||||
selector = index;
|
||||
value.reset();
|
||||
}
|
||||
else if (index < 0 || size_t(index) >= unionPtr->getFields().size())
|
||||
throw std::runtime_error("union index out of bounds");
|
||||
else
|
||||
{
|
||||
if (selector != index)
|
||||
{
|
||||
FieldConstPtr field = unionPtr->getField(selector);
|
||||
selector = index;
|
||||
FieldConstPtr field = unionPtr->getField(index);
|
||||
// try to reuse existing field instance
|
||||
if (!value.get() || *value->getField() != *field)
|
||||
value = pvDataCreate->createPVField(field);
|
||||
}
|
||||
value->deserialize(pbuffer, pcontrol);
|
||||
}
|
||||
else
|
||||
value.reset();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
#include <pv/factory.h>
|
||||
#include <pv/serializeHelper.h>
|
||||
|
||||
#include "factoryPvt.h"
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using std::size_t;
|
||||
|
||||
@@ -157,6 +159,7 @@ void PVUnionArray::serialize(ByteBuffer *pbuffer,
|
||||
|
||||
void PVUnionArray::deserialize(ByteBuffer *pbuffer,
|
||||
DeserializableControl *pcontrol) {
|
||||
RecurseGuard G;
|
||||
svector data(reuse());
|
||||
|
||||
size_t size = this->getArray()->getArraySizeType() == Array::fixed ?
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
#ifndef FACTORYPVT_H
|
||||
#define FACTORYPVT_H
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
// use to bound recursion in FieldCreate and PVDataCreator singletons
|
||||
struct RecurseGuard {
|
||||
RecurseGuard();
|
||||
~RecurseGuard();
|
||||
};
|
||||
|
||||
}} // namespace epics::pvData
|
||||
|
||||
#endif // FACTORYPVT_H
|
||||
+23
-2
@@ -434,12 +434,33 @@ std::ostream& operator<<(std::ostream& strm, const PVStructure::Formatter& forma
|
||||
return strm;
|
||||
|
||||
case scalarArray:
|
||||
{
|
||||
strm<<format::indent();
|
||||
printTimeT(strm, format.xtop);
|
||||
printAlarmT(strm, format.xtop);
|
||||
strm<<std::setprecision(6)<<*static_cast<const PVScalarArray*>(value.get())<<'\n';
|
||||
return strm;
|
||||
|
||||
const PVScalarArray* pvArray = static_cast<const PVScalarArray*>(value.get());
|
||||
ScalarArrayConstPtr scalarArray = pvArray->getScalarArray();
|
||||
|
||||
// Stringify byte arrays if requested
|
||||
if (format.xarrAsStr && scalarArray && scalarArray->getElementType() == pvByte) {
|
||||
shared_vector<const int8_t> byteArray;
|
||||
pvArray->getAs(byteArray);
|
||||
|
||||
if (!byteArray.empty()) {
|
||||
const char* data = reinterpret_cast<const char*>(byteArray.data());
|
||||
size_t slen = byteArray.size();
|
||||
if (!data[slen-1])
|
||||
--slen; // Trim trailing null so we don't end up with "mystring\0"
|
||||
strm<<escape(std::string(data, slen));
|
||||
}
|
||||
} else {
|
||||
strm<<std::setprecision(6);
|
||||
strm<<*pvArray;
|
||||
}
|
||||
strm<<'\n';
|
||||
return strm;
|
||||
}
|
||||
case structure:
|
||||
if(printEnumT(strm, format.xtop, true)) {
|
||||
strm<<'\n';
|
||||
|
||||
Reference in new issue
Block a user