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>
33NSMData::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)
50NSMData::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) {
96 m_allocated = data.m_allocated;
97 m_pdata = data.m_pdata;
99 m_offset = data.m_offset;
100 m_format = data.m_format;
101 m_revision = data.m_revision;
102 m_data_v_m = data.m_data_v_m;
103 m_empty = data.m_empty;
105 m_tstamp = data.m_tstamp;
111 AbstractDBObject::reset();
112 if (m_allocated && m_pdata != NULL) {
118void NSMData::addValue(
const std::string& name,
const void* data,
119 DBField::Type type,
int length)
122 if (length == 0) length = 1;
123 int size = pro.getTypeSize() * length;
124 if (size <= 0)
return;
125 if (!hasField(name)) {
130 memcpy((
char*)m_pdata + pro.getOffset(), data, size);
134void NSMData::setValue(
const std::string& name,
const void* data,
138 if (length == 0) length = 1;
139 int size = pro.getTypeSize() * length;
140 if (data != NULL && hasField(name) && size > 0) {
141 memcpy((
char*)m_pdata + pro.getOffset(), data, size);
147 if (m_pdata == NULL) {
148 b2nsm_context(com.getContext());
149 if (getenv(
"NSM2_INCDIR") == NULL) {
151 setenv(
"NSM2_INCDIR", file.get(
"nsm.data.incpath").c_str(), 0);
153 if ((m_pdata = b2nsm_openmem(getName().c_str(), getFormat().c_str(),
154 getRevision())) == NULL) {
156 nsmlib_strerror(com.getContext()), getName().c_str(), getFormat().c_str(),
166 if (m_pdata == NULL) {
167 b2nsm_context(com.getContext());
168 if (getenv(
"NSM2_INCDIR") == NULL) {
170 setenv(
"NSM2_INCDIR", file.get(
"nsm.data.incpath").c_str(), 0);
172 if ((m_pdata = b2nsm_allocmem(getName().c_str(), getFormat().c_str(),
173 getRevision(), interval)) == NULL) {
175 nsmlib_strerror(com.getContext())));
178 memset(m_pdata, 0, m_size);
191void* NSMData::parse(
const char* incpath,
bool malloc_new)
193#if NSM_PACKAGE_VERSION >= 1914
194 if (getenv(
"NSM2_INCDIR") == NULL) {
196 setenv(
"NSM2_INCDIR", file.get(
"nsm.data.incpath").c_str(), 0);
201 if ((ptr = (
NSMparse*)nsmlib_parsefile(getFormat().c_str(), getRevision(),
202 incpath, fmtstr, &revision)) == NULL) {
204 getFormat().c_str(), getRevision(), nsmlib_parseerr(NULL)));
206 if (getRevision() != revision && revision > 0) {
207 setRevision(revision);
211 parse(ptr, length, name_in);
212 if (m_size > 0 && malloc_new) {
214 return (m_pdata = malloc(m_size));
217 throw (
NSMHandlerException(
"too old nsmlib (nsmparse) : version = %d", NSM_PACKAGE_VERSION));
224#if NSM_PACKAGE_VERSION >= 1914
225 m_tstamp =
Time().getSecond();
227 m_com->getCallback().set(
"nsmdata.tstamp", m_tstamp);
231#if NSM_PACKAGE_VERSION >= 1914
235 while (ptr != NULL) {
237 if (length < 0) length = 0;
238 int type = ptr->type;
239 std::string name = ptr->name;
240 int offset = ptr->offset;
242 if (type ==
'l') type = DBField::LONG;
243 else if (type ==
'i') type = DBField::INT;
244 else if (type ==
's') type = DBField::SHORT;
245 else if (type ==
'c') type = DBField::CHAR;
246 else if (type ==
'L') type = DBField::LONG;
247 else if (type ==
'I') type = DBField::INT;
248 else if (type ==
'S') type = DBField::SHORT;
249 else if (type ==
'C') type = DBField::CHAR;
250 else if (type ==
'd') type = DBField::DOUBLE;
251 else if (type ==
'f') type = DBField::FLOAT;
252 else if (type ==
'(') {
253 NSMData data(getName(), getFormat() +
"." + name, getRevision());
254 char* pdata = ((
char*)m_pdata + offset);
255 data.m_pdata = pdata;
256 ptr = data.parse(ptr->next, length, name);
257 data.setFormat(getFormat() +
"." + name);
258 int len = (length == 0) ? 1 : length;
260 for (
int i = 0; i < len; i++) {
262 data.m_pdata = (
void*)(pdata + i * data.getSize());
263 data_v.push_back(data);
265 m_data_v_m.insert(NSMDataListMap::value_type(name, data_v));
266 type = DBField::OBJECT;
267 m_size += data.m_size * length;
268 }
else if (type ==
')') {
274 int len = (length == 0) ? 1 : length;
275 m_size += pro.getTypeSize() * len;
276 if (ptr == NULL)
break;
283void* NSMData::getValue(
const std::string& name)
285 if (!hasValue(name))
return NULL;
286 char* data = (
char*)get();
287 return (data + getProperty(name).getOffset());
290const void* NSMData::getValue(
const std::string& name)
293 if (!hasValue(name))
return NULL;
294 char* data = (
char*)get();
295 return (data + getProperty(name).getOffset());
298void NSMData::readObject(
Reader& reader)
300 setName(reader.readString());
301 setFormat(reader.readString());
302 setRevision(reader.readInt());
303 int size = reader.readInt();
304 if (m_size > 0 && m_size < size) {
307 m_pdata = malloc(size);
310 int npars = reader.readInt();
311 for (
int n = 0; n < npars; n++) {
312 std::string name = reader.readString();
313 DBField::Type type = (DBField::Type)reader.readInt();
314 size_t length = reader.readInt();
315 size_t offset = reader.readInt();
317 void* buf = getValue(name);
318 if (length == 0) length = 1;
319 if (type == DBField::OBJECT) {
321 for (
size_t i = 0; i < length; i++) {
323 data.m_pdata = (
char*)getValue(name) + length * i;
324 reader.readObject(data);
325 data_v.push_back(data);
327 m_data_v_m.insert(NSMDataListMap::value_type(name, data_v));
329 for (
size_t i = 0; i < length; i++) {
331 case DBField::CHAR: ((
char*)buf)[i] = reader.readChar();
break;
332 case DBField::SHORT: ((int16*)buf)[i] = reader.readShort();
break;
333 case DBField::INT: ((int32*)buf)[i] = reader.readInt();
break;
334 case DBField::LONG: ((int64*)buf)[i] = reader.readLong();
break;
335 case DBField::FLOAT: ((
float*)buf)[i] = reader.readFloat();
break;
336 case DBField::DOUBLE: ((
double*)buf)[i] = reader.readDouble();
break;
344void NSMData::writeObject(
Writer& writer)
const
346 writer.writeString(getName());
347 writer.writeString(getFormat());
348 writer.writeInt(getRevision());
349 writer.writeInt(getSize());
350 const DBField::NameList& name_v(getFieldNames());
351 writer.writeInt(name_v.size());
352 for (DBField::NameList::const_iterator it = name_v.begin();
353 it != name_v.end(); ++it) {
354 const std::string& name(*it);
355 writer.writeString(name);
357 writer.writeInt(pro.getType());
358 writer.writeInt(pro.getLength());
359 writer.writeInt(pro.getOffset());
360 size_t length = pro.getLength();
361 const void* buf = getValue(name);
362 if (length == 0) length = 1;
363 if (pro.getType() == DBField::OBJECT) {
364 const NSMDataList& data_v(getObjects(name));
365 for (
size_t i = 0; i < length; i++) {
366 writer.writeObject(data_v[i]);
369 for (
size_t i = 0; i < length; i++) {
370 switch (pro.getType()) {
371 case DBField::CHAR: writer.writeChar(((
char*)buf)[i]);
break;
372 case DBField::SHORT: writer.writeShort(((int16*)buf)[i]);
break;
373 case DBField::INT: writer.writeInt(((int64*)buf)[i]);
break;
374 case DBField::LONG: writer.writeLong(((int32*)buf)[i]);
break;
375 case DBField::FLOAT: writer.writeFloat(((
float*)buf)[i]);
break;
376 case DBField::DOUBLE: writer.writeDouble(((
double*)buf)[i]);
break;
384void NSMData::print(
const std::string& name_in)
const
387 search(map, name_in);
389 for (NameValueList::iterator it = map.begin();
390 it != map.end(); ++it) {
391 if (it->name.size() > length) length = it->name.size();
393 for (NameValueList::iterator it = map.begin();
394 it != map.end(); ++it) {
395 printf(StringUtil::form(
"%%-%ds : %%s\n", length).c_str(),
396 it->name.c_str(), it->value.c_str());
400void NSMData::search(NSMData::NameValueList& map,
401 const std::string& name_in)
const
403 const DBField::NameList& name_v(getFieldNames());
404 for (DBField::NameList::const_iterator it = name_v.begin();
405 it != name_v.end(); ++it) {
406 const std::string& name(*it);
408 size_t length = pro.getLength();
409 std::string name_out = name_in;
410 if (name_in.size() > 0) name_out +=
".";
413 if (pro.getType() == DBField::OBJECT) {
414 const NSMDataList& data_v(getObjects(name));
415 for (
size_t i = 0; i < length; i++) {
416 data_v[i].search(map, StringUtil::form(
"%s[%d]", name_out.c_str(), i));
419 const void* buf = getValue(name);
420 if (pro.getType() == DBField::CHAR) {
423 nv.value = (
char*)buf;
426 const char* name_c = name_out.c_str();
427 for (
int i = 0; i < (int)length; i++) {
428 std::string vname = StringUtil::form(
"%s[%d]", name_c, i);
430 switch (pro.getType()) {
432 val = StringUtil::form(
"%d", ((int16*)buf)[i]);
break;
434 val = StringUtil::form(
"%d", ((int32*)buf)[i]);
break;
436 val = StringUtil::form(
"%ld", ((int64*)buf)[i]);
break;
438 val = StringUtil::form(
"%f", ((
float*)buf)[i]);
break;
439 case DBField::DOUBLE:
440 val = StringUtil::form(
"%d", ((
double*)buf)[i]);
break;
451 if (pro.getType() == DBField::OBJECT) {
452 const NSMDataList& data_v(getObjects(name));
453 data_v[0].search(map, name_out);
457 nv.value = getValueText(name);
464void NSMData::printPV(
const std::string& name_in)
const
466 const DBField::NameList& name_v(getFieldNames());
467 for (DBField::NameList::const_iterator it = name_v.begin();
468 it != name_v.end(); ++it) {
469 const std::string& name(*it);
471 size_t length = pro.getLength();
472 std::string name_out = name_in;
473 if (name_in.size() > 0) name_out +=
":";
475 name_out += (getName() +
":") + (getFormat() +
":");
479 switch (pro.getType()) {
483 case DBField::LONG: pvtype =
"longin";
break;
485 case DBField::DOUBLE: pvtype =
"ai";
break;
489 if (pro.getType() == DBField::OBJECT) {
490 const NSMDataList& data_v(getObjects(name));
491 for (
size_t i = 0; i < length; i++) {
492 data_v[i].printPV(StringUtil::form(
"%s[%d]", name_out.c_str(), i));
495 for (
size_t i = 0; i < length; i++) {
496 printf(
"record(%s, \"B2_nsm:%s[%d]\")\n"
498 " field(SCAN, \".1 second\")\n"
499 " field(DTYP, \"nsm2_data_%s\")\n"
500 "}\n\n", pvtype.c_str(), name_out.c_str(), (
int)i, pvtype.c_str());
504 if (pro.getType() == DBField::OBJECT) {
505 const NSMDataList& data_v(getObjects(name));
506 data_v[0].print(name_out);
508 printf(
"record(%s, \"B2_nsm2:%s\")\n"
510 " field(SCAN, \".1 second\")\n"
511 " field(DTYP, \"nsm2_data_%s\")\n"
512 "}\n\n", pvtype.c_str(), name_out.c_str(), pvtype.c_str());
518const void* NSMData::find(
const std::string& name_in, DBField::Type& type,
int& length)
const
521 std::string name_out = name_in;
522 if ((pos = name_in.find(
".")) != std::string::npos) {
523 StringList str = StringUtil::split(name_out,
'.');
524 StringList sstr = StringUtil::split(str[0],
'[');
525 const NSMDataList& data_v(getObjects(sstr[0]));
527 if (sstr.size() > 1) {
528 index = atoi(sstr[1].c_str());
530 name_out = name_in.substr(pos + 1);
531 return data_v[index].find(name_out, type, length);
534 if ((pos = name_out.find(
"[")) != std::string::npos) {
535 StringList str = StringUtil::split(name_out,
'[');
537 index = atoi(str[1].c_str());
539 if (!hasValue(name_out))
return NULL;
541 length = pro.getLength();
542 type = pro.getType();
543 const void* buf = getValue(name_out);
545 case DBField::CHAR:
return (((
const char*)buf) + index);
546 case DBField::SHORT:
return (((
const int16*)buf) + index);
547 case DBField::INT:
return (((
const int32*)buf) + index);
548 case DBField::LONG:
return (((
const int64*)buf) + index);
549 case DBField::FLOAT:
return (((
const float*)buf) + index);
550 case DBField::DOUBLE:
return (((
const double*)buf) + index);
551 default:
return NULL;
556int NSMData::getNObjects(
const std::string& name)
const
558 NSMDataListMap::const_iterator it = m_data_v_m.find(name);
559 if (it != m_data_v_m.end())
return it->second.size();
563const NSMData& NSMData::getObject(
const std::string& name,
int index)
const
565 NSMDataListMap::const_iterator it = m_data_v_m.find(name);
566 if (it != m_data_v_m.end())
return it->second[index];
567 else throw (std::out_of_range(StringUtil::form(
"%s:%d", __FILE__, __LINE__)));
570NSMData& NSMData::getObject(
const std::string& name,
int index)
572 NSMDataListMap::iterator it = m_data_v_m.find(name);
573 if (it != m_data_v_m.end())
return it->second[index];
574 else throw (std::out_of_range(StringUtil::form(
"%s:%d", __FILE__, __LINE__)));
577const NSMData::NSMDataList& NSMData::getObjects(
const std::string& name)
const
579 NSMDataListMap::const_iterator it = m_data_v_m.find(name);
580 if (it != m_data_v_m.end())
return it->second;
581 else throw (std::out_of_range(StringUtil::form(
"%s:%d", __FILE__, __LINE__)));
584NSMData::NSMDataList& NSMData::getObjects(
const std::string& name)
586 NSMDataListMap::iterator it = m_data_v_m.find(name);
587 if (it != m_data_v_m.end())
return it->second;
588 else throw (std::out_of_range(StringUtil::form(
"%s:%d", __FILE__, __LINE__)));
const AbstractDBObject & operator=(const AbstractDBObject &object)
Operator =.
const NSMData & operator=(const NSMData &data)
Operator =.
Abstract base class for different kinds of events.