/** Signal meta data. * * @author Steffen Vogel * @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . *********************************************************************************/ #include #include #include #include using namespace villas; using namespace villas::utils; int signal_init(struct signal *s) { s->enabled = true; s->name = nullptr; s->unit = nullptr; s->type = SignalType::INVALID; s->init = signal_data::nan(); s->refcnt = ATOMIC_VAR_INIT(1); return 0; } int signal_init_from_mapping(struct signal *s, const struct mapping_entry *me, unsigned index) { int ret; ret = signal_init(s); if (ret) return ret; ret = mapping_to_str(me, index, &s->name); if (ret) return ret; switch (me->type) { case MappingType::STATS: s->type = Stats::types[me->stats.type].signal_type; break; case MappingType::HEADER: switch (me->header.type) { case MappingHeaderType::LENGTH: case MappingHeaderType::SEQUENCE: s->type = SignalType::INTEGER; break; } break; case MappingType::TIMESTAMP: s->type = SignalType::INTEGER; break; case MappingType::DATA: s->type = me->data.signal->type; s->init = me->data.signal->init; s->enabled = me->data.signal->enabled; if (me->data.signal->name) s->name = strdup(me->data.signal->name); if (me->data.signal->unit) s->name = strdup(me->data.signal->unit); break; } return 0; } int signal_destroy(struct signal *s) { if (s->name) free(s->name); if (s->unit) free(s->unit); return 0; } struct signal * signal_create(const char *name, const char *unit, enum SignalType fmt) { int ret; struct signal *sig; sig = new struct signal; if (!sig) throw MemoryAllocationError(); ret = signal_init(sig); if (ret) return nullptr; if (name) sig->name = strdup(name); if (unit) sig->unit = strdup(unit); sig->type = fmt; return sig; } int signal_free(struct signal *s) { int ret; ret = signal_destroy(s); if (ret) return ret; delete s; return 0; } int signal_incref(struct signal *s) { return atomic_fetch_add(&s->refcnt, 1) + 1; } int signal_decref(struct signal *s) { int prev = atomic_fetch_sub(&s->refcnt, 1); /* Did we had the last reference? */ if (prev == 1) signal_free(s); return prev - 1; } struct signal * signal_copy(struct signal *s) { struct signal *ns; ns = new struct signal; if (!ns) throw MemoryAllocationError(); signal_init(ns); ns->type = s->type; ns->init = s->init; ns->enabled = s->enabled; if (s->name) ns->name = strdup(s->name); if (s->unit) ns->name = strdup(s->unit); return ns; } int signal_parse(struct signal *s, json_t *cfg) { int ret; json_error_t err; json_t *json_init = nullptr; const char *name = nullptr; const char *unit = nullptr; const char *type = nullptr; ret = json_unpack_ex(cfg, &err, 0, "{ s?: s, s?: s, s?: s, s?: o, s?: b }", "name", &name, "unit", &unit, "type", &type, "init", &json_init, "enabled", &s->enabled ); if (ret) return -1; if (name) s->name = strdup(name); if (unit) s->unit = strdup(unit); if (type) { s->type = signal_type_from_str(type); if (s->type == SignalType::INVALID) return -1; } if (json_init) { ret = signal_data_parse_json(&s->init, s, json_init); if (ret) return ret; } else signal_data_set(&s->init, s, 0); return 0; }