8 #include <dbStaticLib.h>
12 #include <pv/pvIntrospect.h>
13 #include <pv/pvAccess.h>
14 #include <pv/configuration.h>
21 namespace pvd = epics::pvData;
22 using pvd::yajl::integer_arg;
23 using pvd::yajl::size_arg;
25 typedef std::map<std::string, pvd::AnyScalar> options_t;
26 typedef std::map<std::string, options_t> config_t;
29 const std::string chanprefix;
31 std::string group, field, key;
38 context(
const std::string& chanprefix,
GroupConfig& conf)
39 :chanprefix(chanprefix)
48 if(depth<2 || depth>3)
49 throw std::runtime_error(
"Can't assign value in this context");
52 void assign(
const pvd::AnyScalar& value) {
57 if(field==
"+atomic") {
58 grp.atomic = value.as<pvd::boolean>();
59 grp.atomic_set =
true;
61 }
else if(field==
"+id") {
62 grp.id = value.as<std::string>();
65 conf.warning +=
"Unknown group option ";
66 conf.warning += field;
74 fld.type = value.ref<std::string>();
76 }
else if(key==
"+channel") {
77 fld.channel = chanprefix + value.ref<std::string>();
79 }
else if(key==
"+id") {
80 fld.id = value.ref<std::string>();
82 }
else if(key==
"+trigger") {
83 fld.trigger = value.ref<std::string>();
85 }
else if(key==
"+putorder") {
86 fld.putorder = value.as<pvd::int32>();
89 conf.warning +=
"Unknown group field option ";
90 conf.warning += field;
97 #define TRY context *self = (context*)ctx; try
99 #define CATCH() catch(std::exception& e) { if(self->msg.empty()) self->msg = e.what(); return 0; }
101 int conf_null(
void * ctx)
104 self->assign(pvd::AnyScalar());
110 int conf_boolean(
void * ctx,
int boolVal)
113 self->assign(pvd::AnyScalar(pvd::boolean(boolVal)));
118 int conf_integer(
void * ctx, integer_arg integerVal)
121 self->assign(pvd::AnyScalar(pvd::int64(integerVal)));
126 int conf_double(
void * ctx,
double doubleVal)
129 self->assign(pvd::AnyScalar(doubleVal));
134 int conf_string(
void * ctx,
const unsigned char * stringVal,
138 std::string val((
const char*)stringVal, stringLen);
139 self->assign(pvd::AnyScalar(val));
144 int conf_start_map(
void * ctx)
149 throw std::runtime_error(
"Group field def. can't contain Object (too deep)");
154 int conf_map_key(
void * ctx,
const unsigned char * key,
158 if(stringLen==0 && self->depth!=2)
159 throw std::runtime_error(
"empty group or key name not allowed");
161 std::string name((
const char*)key, stringLen);
164 self->group.swap(name);
165 else if(self->depth==2)
166 self->field.swap(name);
167 else if(self->depth==3)
168 self->key.swap(name);
170 throw std::logic_error(
"Too deep!!");
176 int conf_end_map(
void * ctx)
179 assert(self->key.empty());
183 else if(self->depth==2)
185 else if(self->depth==1)
188 throw std::logic_error(
"Invalid depth");
195 yajl_callbacks conf_cbs = {
211 handler(yajl_handle handle) :handle(handle)
214 throw std::runtime_error(
"Failed to allocate yajl handle");
219 operator yajl_handle() {
return handle; }
224 void GroupConfig::parse(
const char *txt,
228 #ifndef EPICS_YAJL_VERSION
229 yajl_parser_config conf;
230 memset(&conf, 0,
sizeof(conf));
231 conf.allowComments = 1;
235 std::istringstream strm(txt);
237 std::string chanprefix;
239 chanprefix = recname;
242 context ctxt(chanprefix, result);
244 #ifndef EPICS_YAJL_VERSION
245 handler handle(yajl_alloc(&conf_cbs, &conf, NULL, &ctxt));
247 handler handle(yajl_alloc(&conf_cbs, NULL, &ctxt));
249 yajl_config(handle, yajl_allow_comments, 1);
252 if(!pvd::yajl_parse_helper(strm, handle))
253 throw std::runtime_error(ctxt.msg);