const char * transform_xml2json(struct ly_ctx *ctx, const char *expr, struct lyxml_elem *xml, int log) { const char *in, *id; char *out, *col, *prefix; size_t out_size, out_used, id_len, rc; const struct lys_module *mod; const struct lyxml_ns *ns; in = expr; out_size = strlen(in)+1; out = malloc(out_size); if (!out) { if (log) { LOGMEM; } return NULL; } out_used = 0; while (1) { col = strchr(in, ':'); /* we're finished, copy the remaining part */ if (!col) { strcpy(&out[out_used], in); out_used += strlen(in)+1; assert(out_size == out_used); return lydict_insert_zc(ctx, out); } id = strpbrk_backwards(col-1, "/ [\'\"", (col-in)-1); if ((id[0] == '/') || (id[0] == ' ') || (id[0] == '[') || (id[0] == '\'') || (id[0] == '\"')) { ++id; } id_len = col-id; rc = parse_identifier(id); if (rc < id_len) { if (log) { LOGVAL(LYE_XML_INCHAR, LY_VLOG_XML, xml, id[rc], &id[rc]); } free(out); return NULL; } /* get the module */ prefix = strndup(id, id_len); if (!prefix) { if (log) { LOGMEM; } free(out); return NULL; } ns = lyxml_get_ns(xml, prefix); free(prefix); if (!ns) { if (log) { LOGVAL(LYE_XML_INVAL, LY_VLOG_XML, xml, "namespace prexif"); LOGVAL(LYE_SPEC, LY_VLOG_XML, xml, "XML namespace with prefix \"%.*s\" not defined.", id_len, id); } free(out); return NULL; } mod = ly_ctx_get_module_by_ns(ctx, ns->value, NULL); if (!mod) { if (log) { LOGVAL(LYE_XML_INVAL, LY_VLOG_XML, xml, "module namespace"); LOGVAL(LYE_SPEC, LY_VLOG_XML, xml, "Module with the namespace \"%s\" could not be found.", ns->value); } free(out); return NULL; } /* adjust out size (it can even decrease in some strange cases) */ out_size += strlen(mod->name)-id_len; out = ly_realloc(out, out_size); if (!out) { if (log) { LOGMEM; } return NULL; } /* copy the data before prefix */ strncpy(&out[out_used], in, id-in); out_used += id-in; /* copy the model name */ strcpy(&out[out_used], mod->name); out_used += strlen(mod->name); /* copy ':' */ out[out_used] = ':'; ++out_used; /* finally adjust in pointer for next round */ in = col+1; } /* unreachable */ LOGINT; return NULL; }
static const char * instid_xml2json(struct ly_ctx *ctx, struct lyxml_elem *xml) { const char *in = xml->content; char *out, *aux, *prefix; size_t out_size, len, size, i = 0, o = 0; int start = 1, interior = 1; struct lys_module *mod, *mod_prev = NULL; struct lyxml_ns *ns; out_size = strlen(in); out = malloc((out_size + 1) * sizeof *out); while (in[i]) { /* skip whitespaces */ while (isspace(in[i])) { i++; } if (start) { /* leading '/' character */ if (start == 1 && in[i] != '/') { LOGVAL(LYE_INCHAR, LOGLINE(xml), in[i], &in[i]); free(out); return NULL; } /* check the output buffer size */ if (out_size == o) { out_size += 16; /* just add some size */ aux = realloc(out, out_size + 1); if (!aux) { free(out); LOGMEM; return NULL; } out = aux; } out[o++] = in[i++]; start = 0; continue; } else { /* translate the node identifier */ /* prefix */ aux = strchr(&in[i], ':'); if (aux) { /* interior segment */ len = aux - &in[i]; prefix = strndup(&in[i], len); i += len + 1; /* move after ':' */ } else { /* missing prefix -> invalid instance-identifier */ LOGVAL(LYE_INVAL, LOGLINE(xml), xml->content, xml->name); free(out); return NULL; } ns = lyxml_get_ns(xml, prefix); free(prefix); mod = ly_ctx_get_module_by_ns(ctx, ns->value, NULL); /* node name */ aux = strpbrk(&in[i], "/[="); if (aux) { /* interior segment */ len = aux - &in[i]; } else { /* end segment */ interior = 0; len = strlen(&in[i]); } /* check the output buffer size */ if (!mod_prev || (mod != mod_prev)) { /* prefix + ':' + name to print + '/' */ size = o + len + 1 + strlen(mod->name) + interior; } else { /* name to print + '/' */ size = o + len + interior; } if (out_size <= size) { /* extend to fit the needed size */ out_size = size; aux = realloc(out, out_size + 1); if (!aux) { free(out); LOGMEM; return NULL; } out = aux; } if (!mod_prev || (mod != mod_prev)) { mod_prev = mod; size = strlen(mod->name); memcpy(&out[o], mod->name, size); o += size; out[o++] = ':'; } memcpy(&out[o], &in[i], len); o += len; i += len; if (in[i] == '=') { /* we are in the predicate on the value, so just copy data */ aux = strchr(&in[i], ']'); if (aux) { len = aux - &in[i] + 1; /* include ] */ /* check the output buffer size */ size = o + len + 1; if (out_size <= size) { out_size = size; /* just add some size */ aux = realloc(out, out_size + 1); if (!aux) { free(out); LOGMEM; return NULL; } out = aux; } memcpy(&out[o], &in[i], len); o += len; i += len; } else { /* missing closing ] of predicate -> invalid instance-identifier */ LOGVAL(LYE_INVAL, LOGLINE(xml), xml->content, xml->name); free(out); return NULL; } } start = 2; } } /* terminating NULL byte */ /* check the output buffer size */ if (out_size < o) { out_size += 1; /* just add some size */ aux = realloc(out, out_size + 1); if (!aux) { free(out); LOGMEM; return NULL; } out = aux; } out[o] = '\0'; return lydict_insert_zc(ctx, out); }