Files
pvData/src/factory/Convert.cpp
2016-07-22 15:56:43 +01:00

166 lines
4.8 KiB
C++

/* Convert.cpp */
/*
* Copyright information and license terms for this software can be
* found in the file LICENSE that is included with the distribution
*/
/**
* @author mrk
*/
#include <cstdio>
#include <string>
#include <vector>
#include <stdexcept>
#include <typeinfo>
#include <epicsMutex.h>
#define epicsExportSharedSymbols
#include <pv/lock.h>
#include <pv/pvIntrospect.h>
#include <pv/pvData.h>
#include <pv/convert.h>
using std::tr1::static_pointer_cast;
using std::size_t;
using std::string;
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(string *buf,PVField const *pvField,int /*indentLevel*/)
{
// TODO indextLevel ignored
std::ostringstream strm;
pvField->dumpValue(strm);
strm << std::endl;
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
std::ostringstream oss;
oss << "Convert::fromString unsupported fieldType " << type;
throw std::logic_error(oss.str());
}
}
}
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();
}
ConvertPtr Convert::getConvert()
{
static ConvertPtr convert;
static Mutex mutex;
Lock xx(mutex);
if(convert.get()==0) {
convert = ConvertPtr(new Convert());
}
return convert;
}
}}