data tree REFACTOR unify value prefix storing
Opaque nodes and attributes were using their own
format, which was unified with others.
diff --git a/src/tree_data_helpers.c b/src/tree_data_helpers.c
index 968dd87..2b1b5df 100644
--- a/src/tree_data_helpers.c
+++ b/src/tree_data_helpers.c
@@ -11,6 +11,8 @@
*
* https://opensource.org/licenses/BSD-3-Clause
*/
+#define _XOPEN_SOURCE 500 /* strdup */
+#define _POSIX_C_SOURCE 200809L /*strndup */
#include <assert.h>
#include <stdint.h>
@@ -18,6 +20,7 @@
#include <string.h>
#include "common.h"
+#include "compat.h"
#include "context.h"
#include "dict.h"
#include "hash_table.h"
@@ -400,3 +403,193 @@
return 0;
}
+
+void
+ly_free_prefix_data(LY_PREFIX_FORMAT format, void *prefix_data)
+{
+ struct ly_set *ns_list;
+ struct lysc_prefix *prefixes;
+ uint32_t i;
+ LY_ARRAY_COUNT_TYPE u;
+
+ if (!prefix_data) {
+ return;
+ }
+
+ switch (format) {
+ case LY_PREF_XML:
+ ns_list = prefix_data;
+ for (i = 0; i < ns_list->count; ++i) {
+ free(((struct lyxml_ns *)ns_list->objs[i])->prefix);
+ free(((struct lyxml_ns *)ns_list->objs[i])->uri);
+ }
+ ly_set_free(ns_list, free);
+ break;
+ case LY_PREF_SCHEMA_RESOLVED:
+ prefixes = prefix_data;
+ LY_ARRAY_FOR(prefixes, u) {
+ free(prefixes[u].prefix);
+ }
+ LY_ARRAY_FREE(prefixes);
+ break;
+ case LY_PREF_SCHEMA:
+ case LY_PREF_JSON:
+ break;
+ }
+}
+
+LY_ERR
+ly_dup_prefix_data(const struct ly_ctx *ctx, LY_PREFIX_FORMAT format, const void *prefix_data,
+ void **prefix_data_p)
+{
+ LY_ERR ret = LY_SUCCESS;
+ struct lyxml_ns *ns;
+ struct lysc_prefix *prefixes = NULL, *orig_pref;
+ struct ly_set *ns_list, *orig_ns;
+ uint32_t i;
+ LY_ARRAY_COUNT_TYPE u;
+
+ assert(!*prefix_data_p);
+
+ switch (format) {
+ case LY_PREF_SCHEMA:
+ *prefix_data_p = (void *)prefix_data;
+ break;
+ case LY_PREF_SCHEMA_RESOLVED:
+ /* copy all the value prefixes */
+ orig_pref = (struct lysc_prefix *)prefix_data;
+ LY_ARRAY_CREATE_GOTO(ctx, prefixes, LY_ARRAY_COUNT(orig_pref), ret, cleanup);
+ *prefix_data_p = prefixes;
+
+ LY_ARRAY_FOR(orig_pref, u) {
+ if (orig_pref[u].prefix) {
+ prefixes[u].prefix = strdup(orig_pref[u].prefix);
+ LY_CHECK_ERR_GOTO(!prefixes[u].prefix, LOGMEM(ctx); ret = LY_EMEM, cleanup);
+ }
+ prefixes[u].mod = orig_pref[u].mod;
+ LY_ARRAY_INCREMENT(prefixes);
+ }
+ break;
+ case LY_PREF_XML:
+ /* copy all the namespaces */
+ LY_CHECK_GOTO(ret = ly_set_new(&ns_list), cleanup);
+ *prefix_data_p = ns_list;
+
+ orig_ns = (struct ly_set *)prefix_data;
+ for (i = 0; i < orig_ns->count; ++i) {
+ ns = calloc(1, sizeof *ns);
+ LY_CHECK_ERR_GOTO(!ns, LOGMEM(ctx); ret = LY_EMEM, cleanup);
+ LY_CHECK_GOTO(ret = ly_set_add(ns_list, ns, 1, NULL), cleanup);
+
+ if (((struct lyxml_ns *)orig_ns->objs[i])->prefix) {
+ ns->prefix = strdup(((struct lyxml_ns *)orig_ns->objs[i])->prefix);
+ LY_CHECK_ERR_GOTO(!ns->prefix, LOGMEM(ctx); ret = LY_EMEM, cleanup);
+ }
+ ns->uri = strdup(((struct lyxml_ns *)orig_ns->objs[i])->uri);
+ LY_CHECK_ERR_GOTO(!ns->uri, LOGMEM(ctx); ret = LY_EMEM, cleanup);
+ }
+ break;
+ case LY_PREF_JSON:
+ assert(!prefix_data);
+ *prefix_data_p = NULL;
+ break;
+ }
+
+cleanup:
+ if (ret) {
+ ly_free_prefix_data(format, *prefix_data_p);
+ *prefix_data_p = NULL;
+ }
+ return ret;
+}
+
+LY_ERR
+ly_store_prefix_data(const struct ly_ctx *ctx, const char *value, size_t value_len, LY_PREFIX_FORMAT format,
+ void *prefix_data, LY_PREFIX_FORMAT *format_p, void **prefix_data_p)
+{
+ LY_ERR ret = LY_SUCCESS;
+ const char *start, *stop;
+ const struct lys_module *mod;
+ struct lyxml_ns *ns;
+ struct ly_set *ns_list;
+ struct lysc_prefix *prefixes = NULL, *val_pref;
+
+ switch (format) {
+ case LY_PREF_SCHEMA:
+ case LY_PREF_XML:
+ /* copy all referenced modules... */
+ if (format == LY_PREF_XML) {
+ /* ...as prefix - namespace pairs */
+ LY_CHECK_GOTO(ret = ly_set_new(&ns_list), cleanup);
+ *format_p = LY_PREF_XML;
+ *prefix_data_p = ns_list;
+ } else {
+ /* ...as prefix - module pairs */
+ assert(format == LY_PREF_SCHEMA);
+ LY_ARRAY_CREATE_GOTO(ctx, prefixes, 0, ret, cleanup);
+ *format_p = LY_PREF_SCHEMA_RESOLVED;
+ *prefix_data_p = prefixes;
+ }
+
+ /* add all used prefixes */
+ for (stop = start = value; (size_t)(stop - value) < value_len; start = stop) {
+ size_t bytes;
+ uint32_t c;
+
+ ly_getutf8(&stop, &c, &bytes);
+ if (is_xmlqnamestartchar(c)) {
+ for (ly_getutf8(&stop, &c, &bytes);
+ is_xmlqnamechar(c) && (size_t)(stop - value) < value_len;
+ ly_getutf8(&stop, &c, &bytes)) {}
+ stop = stop - bytes;
+ if (*stop == ':') {
+ /* we have a possible prefix */
+ size_t len = stop - start;
+
+ /* do we already have the prefix? */
+ mod = ly_type_store_resolve_prefix(ctx, start, len, *format_p, *prefix_data_p);
+ if (!mod) {
+ mod = ly_type_store_resolve_prefix(ctx, start, len, format, prefix_data);
+ if (mod) {
+ if (*format_p == LY_PREF_XML) {
+ /* store a new prefix - namespace pair */
+ ns = calloc(1, sizeof *ns);
+ LY_CHECK_ERR_GOTO(!ns, LOGMEM(ctx); ret = LY_EMEM, cleanup);
+ LY_CHECK_GOTO(ret = ly_set_add(ns_list, ns, 1, NULL), cleanup);
+
+ ns->prefix = strndup(start, len);
+ LY_CHECK_ERR_GOTO(!ns->prefix, LOGMEM(ctx); ret = LY_EMEM, cleanup);
+ ns->uri = strdup(mod->ns);
+ LY_CHECK_ERR_GOTO(!ns->uri, LOGMEM(ctx); ret = LY_EMEM, cleanup);
+ } else {
+ assert(*format_p == LY_PREF_SCHEMA_RESOLVED);
+ /* store a new prefix - module pair */
+ LY_ARRAY_NEW_GOTO(ctx, prefixes, val_pref, ret, cleanup);
+ *prefix_data_p = prefixes;
+
+ val_pref->prefix = strndup(start, len);
+ LY_CHECK_ERR_GOTO(!val_pref->prefix, LOGMEM(ctx); ret = LY_EMEM, cleanup);
+ val_pref->mod = mod;
+ }
+ } /* else it is not even defined */
+ } /* else the prefix is already present */
+ }
+ stop = stop + bytes;
+ }
+ }
+ break;
+ case LY_PREF_SCHEMA_RESOLVED:
+ case LY_PREF_JSON:
+ /* simply copy all the prefix data */
+ *format_p = format;
+ LY_CHECK_GOTO(ret = ly_dup_prefix_data(ctx, format, prefix_data, prefix_data_p), cleanup);
+ break;
+ }
+
+cleanup:
+ if (ret) {
+ ly_free_prefix_data(*format_p, *prefix_data_p);
+ *prefix_data_p = NULL;
+ }
+ return ret;
+}