Merge branch 'master' into PSI

This commit is contained in:
zimoch committed 2026-09-25 15:23:11 +02:00
commit 8a5a6fcd27
19 files changed
+333 -130

No files matched your search

+27 -3
View File
@@ -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 {
+3
View File
@@ -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);
+3
View File
@@ -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
View File
@@ -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();
}
}
+3
View File
@@ -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 ?
+14
View File
@@ -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
View File
@@ -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';