This is Unofficial EPICS BASE Doxygen Site
dbf_copy.cpp
Go to the documentation of this file.
1 
2 #include <epicsStdio.h>
3 #include <dbAccess.h>
4 #include <dbChannel.h>
5 #include <dbStaticLib.h>
6 #include <dbLock.h>
7 #include <dbEvent.h>
8 #include <epicsString.h>
9 #include <epicsVersion.h>
10 
11 #include <pv/status.h>
12 #include <pv/bitSet.h>
13 #include <pv/pvData.h>
14 #include <pv/anyscalar.h>
15 
16 #include "pvif.h"
17 
18 namespace pvd = epics::pvData;
19 
20 // note that we handle DBF_ENUM differently than in pvif.cpp
21 static
22 pvd::ScalarType DBR2PVD(short dbr)
23 {
24  switch(dbr) {
25 #define CASE(BASETYPE, PVATYPE, DBFTYPE, PVACODE) case DBR_##DBFTYPE: return pvd::pv##PVACODE;
26 #define CASE_SKIP_BOOL
27 #define CASE_REAL_INT64
28 #include "pv/typemap.h"
29 #undef CASE_SKIP_BOOL
30 #undef CASE_REAL_INT64
31 #undef CASE
32  case DBF_ENUM: return pvd::pvUShort;
33  case DBF_STRING: return pvd::pvString;
34  }
35  throw std::invalid_argument("Unsupported DBR code");
36 }
37 
38 long copyPVD2DBF(const pvd::PVField::const_shared_pointer& inraw,
39  void *outbuf, short outdbf, long *outnReq)
40 {
41  long nreq = outnReq ? *outnReq : 1;
42  if(!inraw || nreq <= 0 || INVALID_DB_REQ(outdbf)) return S_db_errArg;
43 
44  pvd::ScalarType outpvd = DBR2PVD(outdbf);
45 
46  pvd::PVField::const_shared_pointer in(inraw);
47 
48  if(outdbf != DBF_STRING && in->getField()->getType() == pvd::structure) {
49  // assume NTEnum.
50  // index to string not requested, so attempt to treat .index as plain integer
51  in = static_cast<const pvd::PVStructure*>(in.get())->getSubField("index");
52  if(!in) return S_db_errArg;
53  }
54 
55  if(in->getField()->getType() == pvd::structure) {
56  assert(outdbf == DBF_STRING);
57  char *outsbuf = (char*)outbuf;
58 
59  // maybe NTEnum
60  // try index -> string
61  const pvd::PVStructure* sin = static_cast<const pvd::PVStructure*>(in.get());
62 
63  pvd::PVScalar::const_shared_pointer index(sin->getSubField<pvd::PVScalar>("index"));
64  if(!index) return S_db_badField; // Not NTEnum, don't know how to handle...
65 
66  // we will have an answer.
67  if(outnReq)
68  *outnReq = 1;
69 
70  pvd::uint16 ival = index->getAs<pvd::uint16>();
71 
72 
73  pvd::PVStringArray::const_shared_pointer choices(sin->getSubField<pvd::PVStringArray>("choices"));
74 
75  if(choices) {
76  pvd::PVStringArray::const_svector strs(choices->view());
77 
78  if(ival < strs.size()) {
79  // found it!
80 
81  const std::string& sval = strs[ival];
82  size_t slen = std::min(sval.size(), size_t(MAX_STRING_SIZE-1));
83  memcpy(outbuf, sval.c_str(), slen);
84  outsbuf[slen] = '\0';
85  return 0;
86  }
87  }
88  // didn't find it. either no choices or index is out of range
89 
90  // print numeric index
91  epicsSnprintf(outsbuf, MAX_STRING_SIZE, "%u", ival);
92  return 0;
93 
94  } else if(in->getField()->getType() == pvd::scalarArray) {
95  const pvd::PVScalarArray* sarr = static_cast<const pvd::PVScalarArray*>(in.get());
97  sarr->getAs(arr);
98  size_t elemsize = pvd::ScalarTypeFunc::elementSize(arr.original_type());
99 
100  arr.slice(0, nreq*elemsize);
101  nreq = arr.size()/elemsize;
102 
103  if(outdbf == DBF_STRING) {
104  char *outsbuf = (char*)outbuf;
105 
106  // allocate a temp buffer of string[], ick...
107  pvd::shared_vector<std::string> strs(nreq); // alloc
108 
109  pvd::castUnsafeV(nreq, pvd::pvString, strs.data(), arr.original_type(), arr.data());
110 
111  for(long i =0; i<nreq; i++, outsbuf += MAX_STRING_SIZE) {
112  size_t slen = std::min(strs[i].size(), size_t(MAX_STRING_SIZE-1));
113  memcpy(outsbuf, strs[i].c_str(), slen);
114  outsbuf[slen] = '\0';
115  }
116 
117  } else {
118  pvd::castUnsafeV(nreq, outpvd, outbuf, arr.original_type(), arr.data());
119  }
120 
121  if(outnReq)
122  *outnReq = nreq;
123  return 0;
124 
125  } else if(in->getField()->getType() == pvd::scalar) {
126  char *outsbuf = (char*)outbuf;
127  const pvd::PVScalar* sval = static_cast<const pvd::PVScalar*>(in.get());
128  pvd::AnyScalar val;
129  sval->getAs(val);
130 
131  if(outdbf == DBF_STRING && val.type()==pvd::pvString) {
132  // std::string to char*
133  size_t len = std::min(val.as<std::string>().size(), size_t(MAX_STRING_SIZE-1));
134 
135  memcpy(outbuf, val.as<std::string>().c_str(), len);
136  outsbuf[len] = '\0';
137 
138  } else if(outdbf == DBF_STRING) {
139  // non-string to char*
140  std::string temp;
141 
142  pvd::castUnsafeV(1, pvd::pvString, &temp, val.type(), val.unsafe());
143 
144  size_t len = std::min(temp.size(), size_t(MAX_STRING_SIZE-1));
145 
146  memcpy(outbuf, temp.c_str(), len);
147  outsbuf[len] = '\0';
148 
149  } else {
150  // non-string to any
151  pvd::castUnsafeV(1, outpvd, outbuf, val.type(), val.unsafe());
152  }
153 
154  if(outnReq)
155  *outnReq = 1;
156  return 0;
157 
158  } else {
159  // struct array or other strangeness which I don't know how to handle
160  return S_dbLib_badField;
161  }
162 }
163 
165  const pvd::PVField::shared_pointer& outraw,
166  pvd::BitSet& changed,
167  const pvd::PVStringArray::const_svector &choices)
168 {
169 
170  pvd::ScalarType inpvd = inbuf.original_type();
171  size_t incnt = inbuf.size()/pvd::ScalarTypeFunc::elementSize(inpvd);
172 
173  if(!outraw) return S_db_errArg;
174 
175  pvd::PVField::shared_pointer out(outraw);
176 
177  if(inpvd != pvd::pvString && out->getField()->getType() == pvd::structure) {
178  // assume NTEnum.
179  // string to index not requested, so attempt to treat .index as plain integer
180  out = static_cast<pvd::PVStructure*>(out.get())->getSubField("index");
181  if(!out) return S_db_errArg;
182  }
183 
184  if(out->getField()->getType() == pvd::structure) {
185  assert(inpvd == pvd::pvString);
186 
187  if(incnt==0)
188  return S_db_errArg; // Need at least one string
189 
190  const pvd::shared_vector<const std::string> insbuf(pvd::static_shared_vector_cast<const std::string>(inbuf));
191  const std::string& instr(insbuf[0]);
192 
193  // assume NTEnum
194  // try string to index, then parse
195  pvd::PVStructure* sout = static_cast<pvd::PVStructure*>(out.get());
196 
197  pvd::PVScalar::shared_pointer index(sout->getSubField<pvd::PVScalar>("index"));
198  if(!index) return S_db_badField; // Not NTEnum, don't know how to handle...
199 
201  bool match = false;
202 
203  for(size_t i=0, N=std::min(size_t(0xffff), choices.size()); i<N; i++) {
204  if(choices[i] == instr) {
205  match = true;
206  result = pvd::uint16(i);
207  }
208  }
209 
210  if(!match) {
211  // no choice string matched, so try to parse as integer
212 
213  try{
214  result = pvd::castUnsafe<pvd::uint16>(instr);
215  }catch(std::exception&){
216  return S_db_errArg;
217  }
218  }
219 
220  index->putFrom(result);
221 
222  out = index;
223 
224  } else if(out->getField()->getType() == pvd::scalarArray) {
225  pvd::PVScalarArray* sarr = static_cast<pvd::PVScalarArray*>(out.get());
226 
227  sarr->putFrom(inbuf);
228 
229  } else if(out->getField()->getType() == pvd::scalar) {
230  pvd::PVScalar* sval = static_cast<pvd::PVScalar*>(out.get());
231 
232  if(incnt==0) return S_db_errArg;
233 
234  pvd::AnyScalar val(inpvd, inbuf.data());
235 
236  sval->putFrom(val);
237 
238  } else {
239  // struct array or other strangeness which I don't know how to handle
240  return S_db_badField;
241  }
242 
243  changed.set(out->getFieldOffset());
244  return 0;
245 }
FORCE_INLINE std::tr1::shared_ptr< PVField > getSubField(A a)
Definition: pvData.h:744
PVScalar is the base class for each scalar field.
Definition: pvData.h:272
pvac::PutEvent result
Definition: clientSync.cpp:117
#define S_dbLib_badField
Definition: dbStaticLib.h:241
#define assert(exp)
Declare that a condition should be true.
Definition: epicsAssert.h:70
size_t elementSize(ScalarType id)
gives sizeof(T) where T depends on the scalar type id.
Definition: TypeFunc.cpp:82
pointer data() const
Return Base pointer.
Definition: sharedVector.h:616
uint16_t uint16
Definition: pvType.h:95
int i
Definition: scan.c:967
#define min(x, y)
Definition: flexdef.h:78
#define INVALID_DB_REQ(x)
Definition: db_access.h:115
long copyPVD2DBF(const pvd::PVField::const_shared_pointer &inraw, void *outbuf, short outdbf, long *outnReq)
Definition: dbf_copy.cpp:38
A vector of bits.
Definition: bitSet.h:56
void putFrom(T val)
Definition: pvData.h:324
ScalarType type() const
Type code of contained value. Or (ScalarType)-1 is empty.
Definition: anyscalar.h:158
void getAs(shared_vector< const T > &out) const
Definition: pvData.h:647
pvData
Definition: monitor.h:428
template class for all extensions of PVArray.
Definition: pvData.h:55
Base class for a scalarArray.
Definition: pvData.h:618
Data interface for a structure,.
Definition: pvData.h:712
size_t size() const
Number of elements visible through this vector.
Definition: sharedVector.h:220
epicsShareExtern void castUnsafeV(size_t count, ScalarType to, void *dest, ScalarType from, const void *src)
Definition: typeCast.cpp:72
#define MAX_STRING_SIZE
Definition: epicsTypes.h:65
void putFrom(const shared_vector< const T > &inp)
Definition: pvData.h:666
void slice(size_t offset, size_t length=(size_t)-1)
Reduce the view of this shared_vector.
Definition: sharedVector.h:244
long copyDBF2PVD(const pvd::shared_vector< const void > &inbuf, const pvd::PVField::shared_pointer &outraw, pvd::BitSet &changed, const pvd::PVStringArray::const_svector &choices)
Definition: dbf_copy.cpp:164
BitSet & set(uint32 bitIndex)
Definition: bitSet.cpp:103
T getAs() const
Definition: pvData.h:302
LIBCOM_API int epicsStdCall epicsSnprintf(char *str, size_t size, const char *format,...) EPICS_PRINTF_STYLE(3
::epics::pvData::shared_vector< const T > const_svector
Definition: pvData.h:1185