Files
2026-08-11 06:46:06 +00:00

399 lines
13 KiB
C

#include <jansson.h>
#include "schema.h"
static int mqtt_schema_parse(json_t *root, mqtt_schema_vt_t **vts,
size_t *vts_len, int deep)
{
*vts_len = 0;
*vts = NULL;
const char *key = NULL;
json_t * value = NULL;
json_object_foreach(root, key, value)
{
if (json_is_string(value)) {
const char *str_val = json_string_value(value);
if (str_val == NULL) {
return -1;
}
*vts_len += 1;
*vts = realloc(*vts, *vts_len * sizeof(mqtt_schema_vt_t));
mqtt_schema_vt_t *vt = &(*vts)[*vts_len - 1];
memset(vt, 0, sizeof(mqtt_schema_vt_t));
strncpy(vt->name, key, sizeof(vt->name) - 1);
if (strcmp(str_val, "${timestamp}") == 0) {
vt->vt = MQTT_SCHEMA_TIMESTAMP;
} else if (strcmp(str_val, "${node}") == 0) {
vt->vt = MQTT_SCHEMA_NODE_NAME;
} else if (strcmp(str_val, "${group}") == 0) {
vt->vt = MQTT_SCHEMA_GROUP_NAME;
} else if (strcmp(str_val, "${tags}") == 0) {
vt->vt = MQTT_SCHEMA_TAGS;
} else if (strcmp(str_val, "${static_tags}") == 0) {
vt->vt = MQTT_SCHEMA_STATIC_TAGS;
} else if (strcmp(str_val, "${tag_values}") == 0) {
vt->vt = MQTT_SCHEMA_TAGVALUES;
} else if (strcmp(str_val, "${static_tag_values}") == 0) {
vt->vt = MQTT_SCHEMA_STATIC_TAGVALUES;
} else if (strcmp(str_val, "${tag_error_values}") == 0) {
vt->vt = MQTT_SCHEMA_TAG_ERROR_VALUES;
} else if (strcmp(str_val, "${tag_errors}") == 0) {
vt->vt = MQTT_SCHEMA_TAG_ERRORS;
} else {
if (str_val[0] == '$' && str_val[1] == '{' &&
str_val[strlen(str_val) - 1] == '}') {
return -1;
} else {
vt->vt = MQTT_SCHEMA_UD;
vt->jtype = NEU_JSON_STR;
strncpy(vt->ud, str_val, sizeof(vt->ud) - 1);
}
}
} else if (json_is_integer(value) || json_is_real(value) ||
json_is_boolean(value)) {
*vts_len += 1;
*vts = realloc(*vts, *vts_len * sizeof(mqtt_schema_vt_t));
mqtt_schema_vt_t *vt = &(*vts)[*vts_len - 1];
memset(vt, 0, sizeof(mqtt_schema_vt_t));
strncpy(vt->name, key, sizeof(vt->name) - 1);
vt->vt = MQTT_SCHEMA_UD;
if (json_is_integer(value)) {
vt->jtype = NEU_JSON_INT;
vt->jvalue.val_int = json_integer_value(value);
} else if (json_is_real(value)) {
vt->jtype = NEU_JSON_DOUBLE;
vt->jvalue.val_double = json_real_value(value);
} else {
vt->jtype = NEU_JSON_BOOL;
vt->jvalue.val_bool = json_boolean_value(value);
}
} else if (json_is_object(value)) {
if (deep >= 3) {
return -1;
}
*vts_len += 1;
*vts = realloc(*vts, *vts_len * sizeof(mqtt_schema_vt_t));
mqtt_schema_vt_t *vt = &(*vts)[*vts_len - 1];
memset(vt, 0, sizeof(mqtt_schema_vt_t));
strncpy(vt->name, key, sizeof(vt->name) - 1);
vt->vt = MQTT_SCHEMA_OBJECT;
return mqtt_schema_parse(value, &vt->sub_vts, &vt->n_sub_vts,
deep + 1);
} else {
return -1;
}
}
return 0;
}
int mqtt_schema_validate(const char *schema, mqtt_schema_vt_t **vts,
size_t *vts_len)
{
json_t *root = json_loads(schema, 0, NULL);
if (root == NULL) {
return -1;
}
int ret = mqtt_schema_parse(root, vts, vts_len, 1);
if (ret != 0) {
if (*vts != NULL) {
free(*vts);
*vts = NULL;
}
json_decref(root);
return -1;
}
json_decref(root);
return 0;
}
static void *schema_encode(char *driver, char *group,
neu_json_read_resp_t *tags, mqtt_schema_vt_t *vts,
size_t n_vts, mqtt_static_vt_t *s_tags,
size_t n_s_tags)
{
void *root = neu_json_encode_new();
for (size_t i = 0; i < n_vts; i++) {
neu_json_elem_t elem = {
.name = vts[i].name,
};
switch (vts[i].vt) {
case MQTT_SCHEMA_TIMESTAMP:
elem.t = NEU_JSON_INT;
elem.v.val_int = global_timestamp;
break;
case MQTT_SCHEMA_NODE_NAME:
elem.t = NEU_JSON_STR;
elem.v.val_str = driver;
break;
case MQTT_SCHEMA_GROUP_NAME:
elem.t = NEU_JSON_STR;
elem.v.val_str = group;
break;
case MQTT_SCHEMA_TAGS: {
void *values_array = neu_json_array();
neu_json_read_resp_tag_t *p_tag = tags->tags;
for (int j = 0; j < tags->n_tag; j++) {
neu_json_elem_t tag_elems[2 + NEU_TAG_META_SIZE] = { 0 };
if (p_tag->error == 0) {
tag_elems[0].name = "name";
tag_elems[0].t = NEU_JSON_STR;
tag_elems[0].v.val_str = p_tag->name;
tag_elems[1].name = "value";
tag_elems[1].t = p_tag->t;
tag_elems[1].v = p_tag->value;
tag_elems[1].precision = p_tag->precision;
for (int k = 0; k < p_tag->n_meta; k++) {
tag_elems[2 + k].name = p_tag->metas[k].name;
tag_elems[2 + k].t = p_tag->metas[k].t;
tag_elems[2 + k].v = p_tag->metas[k].value;
}
values_array = neu_json_encode_array(
values_array, tag_elems, 2 + p_tag->n_meta);
}
p_tag++;
}
elem.t = NEU_JSON_OBJECT;
elem.v.val_object = values_array;
break;
}
case MQTT_SCHEMA_TAGVALUES: {
void *values_array = neu_json_encode_new();
neu_json_read_resp_tag_t *p_tag = tags->tags;
for (int j = 0; j < tags->n_tag; j++) {
neu_json_elem_t tag_elems[1 + NEU_TAG_META_SIZE] = { 0 };
if (p_tag->error == 0) {
tag_elems[0].name = p_tag->name;
tag_elems[0].t = p_tag->t;
tag_elems[0].v = p_tag->value;
for (int k = 0; k < p_tag->n_meta; k++) {
tag_elems[1 + k].name = p_tag->metas[k].name;
tag_elems[1 + k].t = p_tag->metas[k].t;
tag_elems[1 + k].v = p_tag->metas[k].value;
}
neu_json_encode_field(values_array, tag_elems,
1 + p_tag->n_meta);
}
p_tag++;
}
elem.t = NEU_JSON_OBJECT;
elem.v.val_object = values_array;
break;
}
case MQTT_SCHEMA_STATIC_TAGS: {
void *static_array = neu_json_array();
for (size_t k = 0; k < n_s_tags; k++) {
neu_json_elem_t tag_elems[2 + NEU_TAG_META_SIZE] = { 0 };
tag_elems[0].name = "name";
tag_elems[0].t = NEU_JSON_STR;
tag_elems[0].v.val_str = s_tags[k].name;
tag_elems[1].name = "value";
tag_elems[1].t = s_tags[k].jtype;
tag_elems[1].v = s_tags[k].jvalue;
static_array =
neu_json_encode_array(static_array, tag_elems, 2);
}
elem.t = NEU_JSON_OBJECT;
elem.v.val_object = static_array;
break;
}
case MQTT_SCHEMA_STATIC_TAGVALUES: {
void *static_array = neu_json_encode_new();
for (size_t k = 0; k < n_s_tags; k++) {
neu_json_elem_t tag_elems[1 + NEU_TAG_META_SIZE] = { 0 };
tag_elems[0].name = s_tags[k].name;
tag_elems[0].t = s_tags[k].jtype;
tag_elems[0].v = s_tags[k].jvalue;
neu_json_encode_field(static_array, tag_elems, 1);
}
elem.t = NEU_JSON_OBJECT;
elem.v.val_object = static_array;
break;
}
case MQTT_SCHEMA_TAG_ERRORS: {
void *errors_array = neu_json_array();
neu_json_read_resp_tag_t *p_tag = tags->tags;
for (int k = 0; k < tags->n_tag; k++) {
neu_json_elem_t tag_elems[2 + NEU_TAG_META_SIZE] = { 0 };
if (p_tag->error != 0) {
tag_elems[0].name = "name";
tag_elems[0].t = NEU_JSON_STR;
tag_elems[0].v.val_str = p_tag->name;
tag_elems[1].name = "error";
tag_elems[1].t = NEU_JSON_INT;
tag_elems[1].v.val_int = p_tag->error;
errors_array =
neu_json_encode_array(errors_array, tag_elems, 2);
}
p_tag++;
}
elem.t = NEU_JSON_OBJECT;
elem.v.val_object = errors_array;
break;
}
case MQTT_SCHEMA_TAG_ERROR_VALUES: {
void *errors_array = neu_json_encode_new();
neu_json_read_resp_tag_t *p_tag = tags->tags;
for (int k = 0; k < tags->n_tag; k++) {
neu_json_elem_t tag_elems[1 + NEU_TAG_META_SIZE] = { 0 };
if (p_tag->error != 0) {
tag_elems[0].name = p_tag->name;
tag_elems[0].t = NEU_JSON_INT;
tag_elems[0].v.val_int = p_tag->error;
neu_json_encode_field(errors_array, tag_elems, 1);
}
p_tag++;
}
elem.t = NEU_JSON_OBJECT;
elem.v.val_object = errors_array;
break;
}
case MQTT_SCHEMA_UD:
elem.t = vts[i].jtype;
if (vts[i].jtype == NEU_JSON_STR) {
elem.v.val_str = vts[i].ud;
} else {
elem.v = vts[i].jvalue;
}
break;
case MQTT_SCHEMA_OBJECT: {
void *sub_root = schema_encode(driver, group, tags, vts[i].sub_vts,
vts[i].n_sub_vts, s_tags, n_s_tags);
elem.t = NEU_JSON_OBJECT;
elem.v.val_object = sub_root;
break;
}
}
neu_json_encode_field(root, &elem, 1);
}
return root;
}
int mqtt_schema_encode(char *driver, char *group, neu_json_read_resp_t *tags,
mqtt_schema_vt_t *vts, size_t n_vts,
mqtt_static_vt_t *s_tags, size_t n_s_tags,
char **result_str)
{
void *root =
schema_encode(driver, group, tags, vts, n_vts, s_tags, n_s_tags);
int ret = neu_json_encode(root, result_str);
neu_json_decode_free(root);
return ret;
}
int mqtt_static_validate(const char *static_tags, mqtt_static_vt_t **vts,
size_t *vts_len)
{
json_t *root = json_loads(static_tags, 0, NULL);
if (root == NULL) {
return -1;
}
*vts_len = 0;
*vts = NULL;
const char *key = NULL;
json_t * value = NULL;
json_t *child = json_object_get(root, "static_tags");
if (child == NULL) {
json_decref(root);
return -1;
}
json_object_foreach(child, key, value)
{
*vts_len += 1;
*vts = realloc(*vts, *vts_len * sizeof(mqtt_static_vt_t));
mqtt_static_vt_t *vt = &(*vts)[*vts_len - 1];
memset(vt, 0, sizeof(mqtt_static_vt_t));
strncpy(vt->name, key, sizeof(vt->name) - 1);
if (json_is_string(value)) {
vt->jtype = NEU_JSON_STR;
vt->jvalue.val_str = strdup(json_string_value(value));
} else if (json_is_real(value)) {
vt->jtype = NEU_JSON_DOUBLE;
vt->jvalue.val_double = json_real_value(value);
} else if (json_is_integer(value)) {
vt->jtype = NEU_JSON_INT;
vt->jvalue.val_int = json_integer_value(value);
} else if (json_is_boolean(value)) {
vt->jtype = NEU_JSON_BOOL;
vt->jvalue.val_bool = json_boolean_value(value);
} else {
vt->jtype = NEU_JSON_STR;
vt->jvalue.val_str = json_dumps(value, JSON_ENCODE_ANY);
}
}
json_decref(root);
return 0;
}
void mqtt_static_free(mqtt_static_vt_t *vts, size_t vts_len)
{
for (size_t i = 0; i < vts_len; i++) {
if (vts[i].jtype == NEU_JSON_STR) {
free(vts[i].jvalue.val_str);
}
}
free(vts);
}