8 #include "daq/slc/nsm/NSMData.h"
10 #include "daq/slc/nsm/NSMCommunicator.h"
11 #include "daq/slc/nsm/NSMCallback.h"
12 #include "daq/slc/nsm/NSMHandlerException.h"
14 #include <daq/slc/system/Time.h>
16 #include <daq/slc/base/ConfigFile.h>
17 #include <daq/slc/base/StringUtil.h>
18 #include <daq/slc/base/Writer.h>
19 #include <daq/slc/base/Reader.h>
21 #include <nsm2/belle2nsm.h>
23 #include <nsm2/nsmlib2.h>
33 NSMData::NSMData(
const std::string& dataname,
34 const std::string& format,
int revision)
36 m_pdata(NULL), m_size(0), m_offset(0)
40 setRevision(revision);
45 m_pdata(NULL), m_size(0), m_offset(0)
50 NSMData::NSMData(
const NSMData& data)
53 m_allocated = data.m_allocated;
55 setFormat(data.getFormat());
56 setRevision(data.getRevision());
57 setIndex(data.getIndex());
58 setName(data.getName());
61 m_pdata = malloc(m_size);
62 memcpy(m_pdata, data.m_pdata, m_size);
64 if (data.m_pdata != NULL) m_pdata = data.m_pdata;
66 const DBField::NameList& name_v(data.getFieldNames());
67 for (DBField::NameList::const_iterator it = name_v.begin();
68 it != name_v.end(); it++) {
69 const std::string& name(*it);
72 if (pro.getType() == DBField::OBJECT) {
73 NSMDataList data_v(data.getObjects(name));
74 for (
size_t i = 0; i < data_v.size(); i++) {
76 cdata.m_pdata = (
void*)((
char*)m_pdata +
77 pro.getOffset() + cdata.m_size * i);
79 m_data_v_m.insert(NSMDataListMap::value_type(name, data_v));
87 if (m_allocated && m_pdata != NULL) {
95 AbstractDBObject::reset();
96 if (m_allocated && m_pdata != NULL) {
102 void NSMData::addValue(
const std::string& name,
const void* data,
103 DBField::Type type,
int length)
106 if (length == 0) length = 1;
107 int size = pro.getTypeSize() * length;
108 if (size <= 0)
return;
109 if (!hasField(name)) {
114 memcpy((
char*)m_pdata + pro.getOffset(), data, size);
118 void NSMData::setValue(
const std::string& name,
const void* data,
122 if (length == 0) length = 1;
123 int size = pro.getTypeSize() * length;
124 if (data != NULL && hasField(name) && size > 0) {
125 memcpy((
char*)m_pdata + pro.getOffset(), data, size);
131 if (m_pdata == NULL) {
132 b2nsm_context(com.getContext());
133 if (getenv(
"NSM2_INCDIR") == NULL) {
135 setenv(
"NSM2_INCDIR", file.get(
"nsm.data.incpath").c_str(), 0);
137 if ((m_pdata = b2nsm_openmem(getName().c_str(), getFormat().c_str(),
138 getRevision())) == NULL) {
140 nsmlib_strerror(com.getContext()), getName().c_str(), getFormat().c_str(),
150 if (m_pdata == NULL) {
151 b2nsm_context(com.getContext());
152 if (getenv(
"NSM2_INCDIR") == NULL) {
154 setenv(
"NSM2_INCDIR", file.get(
"nsm.data.incpath").c_str(), 0);
156 if ((m_pdata = b2nsm_allocmem(getName().c_str(), getFormat().c_str(),
157 getRevision(), interval)) == NULL) {
159 nsmlib_strerror(com.getContext())));
162 memset(m_pdata, 0, m_size);
175 void* NSMData::parse(
const char* incpath,
bool malloc_new)
177 #if NSM_PACKAGE_VERSION >= 1914
178 if (getenv(
"NSM2_INCDIR") == NULL) {
180 setenv(
"NSM2_INCDIR", file.get(
"nsm.data.incpath").c_str(), 0);
185 if ((ptr = (
NSMparse*)nsmlib_parsefile(getFormat().c_str(), getRevision(),
186 incpath, fmtstr, &revision)) == NULL) {
188 getFormat().c_str(), getRevision(), nsmlib_parseerr(NULL)));
190 if (getRevision() != revision && revision > 0) {
191 setRevision(revision);
195 parse(ptr, length, name_in);
196 if (m_size > 0 && malloc_new) {
198 return (m_pdata = malloc(m_size));
201 throw (
NSMHandlerException(
"too old nsmlib (nsmparse) : version = %d", NSM_PACKAGE_VERSION));
206 void NSMData::flush()
208 #if NSM_PACKAGE_VERSION >= 1914
209 m_tstamp =
Time().getSecond();
211 m_com->getCallback().set(
"nsmdata.tstamp", m_tstamp);
215 #if NSM_PACKAGE_VERSION >= 1914
219 while (ptr != NULL) {
221 if (length < 0) length = 0;
222 int type = ptr->type;
223 std::string name = ptr->name;
224 int offset = ptr->offset;
226 if (type ==
'l') type = DBField::LONG;
227 else if (type ==
'i') type = DBField::INT;
228 else if (type ==
's') type = DBField::SHORT;
229 else if (type ==
'c') type = DBField::CHAR;
230 else if (type ==
'L') type = DBField::LONG;
231 else if (type ==
'I') type = DBField::INT;
232 else if (type ==
'S') type = DBField::SHORT;
233 else if (type ==
'C') type = DBField::CHAR;
234 else if (type ==
'd') type = DBField::DOUBLE;
235 else if (type ==
'f') type = DBField::FLOAT;
236 else if (type ==
'(') {
237 NSMData data(getName(), getFormat() +
"." + name, getRevision());
238 char* pdata = ((
char*)m_pdata + offset);
239 data.m_pdata = pdata;
240 ptr = data.parse(ptr->next, length, name);
241 data.setFormat(getFormat() +
"." + name);
242 int len = (length == 0) ? 1 : length;
244 for (
int i = 0; i < len; i++) {
246 data.m_pdata = (
void*)(pdata + i * data.getSize());
247 data_v.push_back(data);
249 m_data_v_m.insert(NSMDataListMap::value_type(name, data_v));
250 type = DBField::OBJECT;
251 m_size += data.m_size * length;
252 }
else if (type ==
')') {
258 int len = (length == 0) ? 1 : length;
259 m_size += pro.getTypeSize() * len;
260 if (ptr == NULL)
break;
267 void* NSMData::getValue(
const std::string& name)
269 if (!hasValue(name))
return NULL;
270 char* data = (
char*)get();
271 return (data + getProperty(name).getOffset());
274 const void* NSMData::getValue(
const std::string& name)
277 if (!hasValue(name))
return NULL;
278 char* data = (
char*)get();
279 return (data + getProperty(name).getOffset());
282 void NSMData::readObject(
Reader& reader)
284 setName(reader.readString());
285 setFormat(reader.readString());
286 setRevision(reader.readInt());
287 int size = reader.readInt();
288 if (m_size > 0 && m_size < size) {
291 m_pdata = malloc(size);
294 int npars = reader.readInt();
295 for (
int n = 0; n < npars; n++) {
296 std::string name = reader.readString();
297 DBField::Type type = (DBField::Type)reader.readInt();
298 size_t length = reader.readInt();
299 size_t offset = reader.readInt();
301 void* buf = getValue(name);
302 if (length == 0) length = 1;
303 if (type == DBField::OBJECT) {
305 for (
size_t i = 0; i < length; i++) {
307 data.m_pdata = (
char*)getValue(name) + length * i;
308 reader.readObject(data);
309 data_v.push_back(data);
311 m_data_v_m.insert(NSMDataListMap::value_type(name, data_v));
313 for (
size_t i = 0; i < length; i++) {
315 case DBField::CHAR: ((
char*)buf)[i] = reader.readChar();
break;
316 case DBField::SHORT: ((int16*)buf)[i] = reader.readShort();
break;
317 case DBField::INT: ((int32*)buf)[i] = reader.readInt();
break;
318 case DBField::LONG: ((int64*)buf)[i] = reader.readLong();
break;
319 case DBField::FLOAT: ((
float*)buf)[i] = reader.readFloat();
break;
320 case DBField::DOUBLE: ((
double*)buf)[i] = reader.readDouble();
break;
328 void NSMData::writeObject(
Writer& writer)
const
330 writer.writeString(getName());
331 writer.writeString(getFormat());
332 writer.writeInt(getRevision());
333 writer.writeInt(getSize());
334 const DBField::NameList& name_v(getFieldNames());
335 writer.writeInt(name_v.size());
336 for (DBField::NameList::const_iterator it = name_v.begin();
337 it != name_v.end(); it++) {
338 const std::string& name(*it);
339 writer.writeString(name);
341 writer.writeInt(pro.getType());
342 writer.writeInt(pro.getLength());
343 writer.writeInt(pro.getOffset());
344 size_t length = pro.getLength();
345 const void* buf = getValue(name);
346 if (length == 0) length = 1;
347 if (pro.getType() == DBField::OBJECT) {
348 const NSMDataList& data_v(getObjects(name));
349 for (
size_t i = 0; i < length; i++) {
350 writer.writeObject(data_v[i]);
353 for (
size_t i = 0; i < length; i++) {
354 switch (pro.getType()) {
355 case DBField::CHAR: writer.writeChar(((
char*)buf)[i]);
break;
356 case DBField::SHORT: writer.writeShort(((int16*)buf)[i]);
break;
357 case DBField::INT: writer.writeInt(((int64*)buf)[i]);
break;
358 case DBField::LONG: writer.writeLong(((int32*)buf)[i]);
break;
359 case DBField::FLOAT: writer.writeFloat(((
float*)buf)[i]);
break;
360 case DBField::DOUBLE: writer.writeDouble(((
double*)buf)[i]);
break;
368 void NSMData::print(
const std::string& name_in)
const
371 search(map, name_in);
373 for (NameValueList::iterator it = map.begin();
374 it != map.end(); it++) {
375 if (it->name.size() > length) length = it->name.size();
377 for (NameValueList::iterator it = map.begin();
378 it != map.end(); it++) {
379 printf(StringUtil::form(
"%%-%ds : %%s\n", length).c_str(),
380 it->name.c_str(), it->value.c_str());
384 void NSMData::search(NSMData::NameValueList& map,
385 const std::string& name_in)
const
387 const DBField::NameList& name_v(getFieldNames());
388 for (DBField::NameList::const_iterator it = name_v.begin();
389 it != name_v.end(); it++) {
390 const std::string& name(*it);
392 size_t length = pro.getLength();
393 std::string name_out = name_in;
394 if (name_in.size() > 0) name_out +=
".";
398 if (pro.getType() == DBField::OBJECT) {
399 const NSMDataList& data_v(getObjects(name));
400 for (
size_t i = 0; i < length; i++) {
401 data_v[i].search(map, StringUtil::form(
"%s[%d]", name_out.c_str(), i));
404 const void* buf = getValue(name);
405 if (pro.getType() == DBField::CHAR) {
408 nv.value = (
char*)buf;
411 const char* name_c = name_out.c_str();
412 for (
int i = 0; i < (int)length; i++) {
413 std::string vname = StringUtil::form(
"%s[%d]", name_c, i);
415 switch (pro.getType()) {
417 val = StringUtil::form(
"%d", ((int16*)buf)[i]);
break;
419 val = StringUtil::form(
"%d", ((int32*)buf)[i]);
break;
421 val = StringUtil::form(
"%ld", ((int64*)buf)[i]);
break;
423 val = StringUtil::form(
"%f", ((
float*)buf)[i]);
break;
424 case DBField::DOUBLE:
425 val = StringUtil::form(
"%d", ((
double*)buf)[i]);
break;
436 if (pro.getType() == DBField::OBJECT) {
437 const NSMDataList& data_v(getObjects(name));
438 data_v[0].search(map, name_out);
442 nv.value = getValueText(name);
449 void NSMData::printPV(
const std::string& name_in)
const
451 const DBField::NameList& name_v(getFieldNames());
452 for (DBField::NameList::const_iterator it = name_v.begin();
453 it != name_v.end(); it++) {
454 const std::string& name(*it);
456 size_t length = pro.getLength();
457 std::string name_out = name_in;
458 if (name_in.size() > 0) name_out +=
":";
460 name_out += (getName() +
":") + (getFormat() +
":");
464 switch (pro.getType()) {
468 case DBField::LONG: pvtype =
"longin";
break;
470 case DBField::DOUBLE: pvtype =
"ai";
break;
474 if (pro.getType() == DBField::OBJECT) {
475 const NSMDataList& data_v(getObjects(name));
476 for (
size_t i = 0; i < length; i++) {
477 data_v[i].printPV(StringUtil::form(
"%s[%d]", name_out.c_str(), i));
480 for (
size_t i = 0; i < length; i++) {
481 printf(
"record(%s, \"B2_nsm:%s[%d]\")\n"
483 " field(SCAN, \".1 second\")\n"
484 " field(DTYP, \"nsm2_data_%s\")\n"
485 "}\n\n", pvtype.c_str(), name_out.c_str(), (
int)i, pvtype.c_str());
489 if (pro.getType() == DBField::OBJECT) {
490 const NSMDataList& data_v(getObjects(name));
491 data_v[0].print(name_out);
493 printf(
"record(%s, \"B2_nsm2:%s\")\n"
495 " field(SCAN, \".1 second\")\n"
496 " field(DTYP, \"nsm2_data_%s\")\n"
497 "}\n\n", pvtype.c_str(), name_out.c_str(), pvtype.c_str());
503 const void* NSMData::find(
const std::string& name_in, DBField::Type& type,
int& length)
const
506 std::string name_out = name_in;
507 if ((pos = name_in.find(
".")) != std::string::npos) {
508 StringList str = StringUtil::split(name_out,
'.');
509 StringList sstr = StringUtil::split(str[0],
'[');
510 const NSMDataList& data_v(getObjects(sstr[0]));
512 if (sstr.size() > 1) {
513 index = atoi(sstr[1].c_str());
515 name_out = name_in.substr(pos + 1);
516 return data_v[index].find(name_out, type, length);
519 if ((pos = name_out.find(
"[")) != std::string::npos) {
520 StringList str = StringUtil::split(name_out,
'[');
522 index = atoi(str[1].c_str());
524 if (!hasValue(name_out))
return NULL;
526 length = pro.getLength();
527 type = pro.getType();
528 const void* buf = getValue(name_out);
530 case DBField::CHAR:
return (((
const char*)buf) + index);
531 case DBField::SHORT:
return (((
const int16*)buf) + index);
532 case DBField::INT:
return (((
const int32*)buf) + index);
533 case DBField::LONG:
return (((
const int64*)buf) + index);
534 case DBField::FLOAT:
return (((
const float*)buf) + index);
535 case DBField::DOUBLE:
return (((
const double*)buf) + index);
536 default:
return NULL;
541 int NSMData::getNObjects(
const std::string& name)
const
543 NSMDataListMap::const_iterator it = m_data_v_m.find(name);
544 if (it != m_data_v_m.end())
return it->second.size();
548 const NSMData& NSMData::getObject(
const std::string& name,
int index)
const
550 NSMDataListMap::const_iterator it = m_data_v_m.find(name);
551 if (it != m_data_v_m.end())
return it->second[index];
552 else throw (std::out_of_range(StringUtil::form(
"%s:%d", __FILE__, __LINE__)));
555 NSMData& NSMData::getObject(
const std::string& name,
int index)
557 NSMDataListMap::iterator it = m_data_v_m.find(name);
558 if (it != m_data_v_m.end())
return it->second[index];
559 else throw (std::out_of_range(StringUtil::form(
"%s:%d", __FILE__, __LINE__)));
562 const NSMData::NSMDataList& NSMData::getObjects(
const std::string& name)
const
564 NSMDataListMap::const_iterator it = m_data_v_m.find(name);
565 if (it != m_data_v_m.end())
return it->second;
566 else throw (std::out_of_range(StringUtil::form(
"%s:%d", __FILE__, __LINE__)));
569 NSMData::NSMDataList& NSMData::getObjects(
const std::string& name)
571 NSMDataListMap::iterator it = m_data_v_m.find(name);
572 if (it != m_data_v_m.end())
return it->second;
573 else throw (std::out_of_range(StringUtil::form(
"%s:%d", __FILE__, __LINE__)));
Abstract base class for different kinds of events.