mrfioc2  2.3.0
devlutstring.cpp
Go to the documentation of this file.
1 /*************************************************************************\
2 * Copyright (c) 2017 Michael Davidsaver
3 * mrfioc2 is distributed subject to a Software License Agreement found
4 * in file LICENSE that is included with this distribution.
5 \*************************************************************************/
16 #include <stdexcept>
17 #include <map>
18 #include <string>
19 #include <sstream>
20 
21 #include <stdio.h>
22 #include <errno.h>
23 
24 #include <epicsTypes.h>
25 #include <dbAccess.h>
26 #include <dbStaticLib.h>
27 #include <dbScan.h>
28 #include <link.h>
29 #include <devSup.h>
30 #include <recGbl.h>
31 #include <devLib.h> // For S_dev_*
32 #include <alarm.h>
33 #include <errlog.h>
34 
35 #include <stringinRecord.h>
36 
37 #include "mrfCommon.h"
38 #include "devObj.h"
39 
40 #include <epicsExport.h>
41 
42 namespace {
43 
44 std::string strip(const std::string& inp)
45 {
46  size_t S = inp.find_first_not_of(" \t"),
47  E = inp.find_last_not_of(" \t");
48  if(S==inp.npos)
49  return std::string(); // empty
50  else
51  return inp.substr(S, E-S+1);
52 }
53 
54 struct DBENT {
55  DBENTRY entry;
56  template<typename REC>
57  explicit DBENT(REC *prec)
58  {
59  dbInitEntry(pdbbase, &entry);
60  if(dbFindRecord(&entry, prec->name))
61  throw std::logic_error("Failed to lookup DBENTRY from dbCommon");
62  }
63  ~DBENT() {
64  dbFinishEntry(&entry);
65  }
66 };
67 
68 struct LUTPriv {
69  typedef std::map<epicsInt32, std::string> lut_t;
70  lut_t lut;
71  std::string unknown;
72 };
73 
74 static
75 long init_record_lut(stringinRecord *prec)
76 {
77  try {
78  mrf::auto_ptr<LUTPriv> priv(new LUTPriv);
79 
80  priv->unknown = "<unknown>";
81 
82  DBENT entry(prec);
83 
84  for(long status = dbFirstInfo(&entry.entry); status==0; status = dbNextInfo(&entry.entry))
85  {
86  const char * const name = dbGetInfoName(&entry.entry);
87 
88  std::string line(dbGetInfoString(&entry.entry));
89 
90  if(strcmp(name, "lutX")==0) {
91  priv->unknown = strip(line);
92  if(prec->tpro>1)
93  printf("%s : LUT <fallback> -> \"%s\"\n", prec->name, priv->unknown.c_str());
94  continue;
95 
96  } else if(strncmp(name, "lut", 3)!=0) {
97  continue;
98  }
99 
100  size_t eq = line.find_first_of('=');
101  if(eq==line.npos) {
102  fprintf(stderr, "%s : info %s value missing '=' : %s\n", prec->name, name, line.c_str());
103  return 0;
104  }
105 
106  epicsUInt32 raw;
107  {
108  std::string num(line.substr(0, eq));
109  if(epicsParseUInt32(num.c_str(), &raw, 0, 0)) {
110  fprintf(stderr, "%s : info %s index not number \"%s\"\n", prec->name, name, num.c_str());
111  throw std::runtime_error("Invalid LUT entry");
112  }
113  }
114 
115  std::pair<LUTPriv::lut_t::iterator, bool> ret =
116  priv->lut.insert(std::make_pair(raw, strip(line.substr(eq+1))));
117 
118  if(prec->tpro>1)
119  printf("%s : LUT %u -> \"%s\"\n", prec->name, ret.first->first, ret.first->second.c_str());
120  }
121 
122  /* initialize w/ unknown value */
123  strncpy(prec->val, priv->unknown.c_str(), sizeof(prec->val));
124  prec->val[sizeof(prec->val)-1] = '\0';
125 
126  prec->dpvt = priv.release();
127 
128  return 0;
129  }CATCH(-ENODEV)
130 }
131 
132 static
133 long read_lut(stringinRecord *prec)
134 {
135  const LUTPriv * const priv = static_cast<LUTPriv*>(prec->dpvt);
136  if(!priv) {
137  (void)recGblSetSevr(prec, COMM_ALARM, INVALID_ALARM);
138  return 0;
139  }
140  try {
141  const std::string *val = &priv->unknown;
142 
143  epicsUInt32 raw;
144  long status = dbGetLink(&prec->inp, DBR_LONG, &raw, 0, 0);
145 
146  if(status) {
147  (void)recGblSetSevr(prec, LINK_ALARM, INVALID_ALARM);
148 
149  } else {
150  LUTPriv::lut_t::const_iterator it = priv->lut.find(raw);
151  if(it==priv->lut.end()) {
152  (void)recGblSetSevr(prec, READ_ALARM, INVALID_ALARM);
153  } else {
154  val = &it->second;
155  }
156  }
157 
158  if(prec->tpro>2)
159  printf("%s : LUT status=%ld select=%u VAL=\"%s\"\n",
160  prec->name, status, (unsigned)raw, val->c_str());
161 
162  strncpy(prec->val, val->c_str(), sizeof(prec->val));
163  prec->val[sizeof(prec->val)-1] = '\0';
164 
165  return 0;
166  }CATCH(-ENODEV)
167 }
168 
169 common_dset devLUTSI = {
170  5,
171  0,
172  0,
173  (DEVSUPFUN)&init_record_lut,
174  0,
175  (DEVSUPFUN)&read_lut,
176  0
177 };
178 
179 } // namespace
180 
181 extern "C" {
182 epicsExportAddress(dset, devLUTSI);
183 }
int epicsParseUInt32(const char *str, epicsUInt32 *to, int base, char **units)
Definition: mrfCommon.cpp:113
#define CATCH(RET)
Definition: devObj.h:31
epicsExportAddress(dset, devLUTSI)