diff options
Diffstat (limited to 'src/env.c')
-rw-r--r-- | src/env.c | 155 |
1 files changed, 80 insertions, 75 deletions
@@ -8,6 +8,8 @@ #include "node.h" #include "serd/node.h" +#include "serd/nodes.h" +#include "serd/write_result.h" #include "zix/attributes.h" #include <assert.h> @@ -15,16 +17,17 @@ #include <string.h> typedef struct { - SerdNode* name; - SerdNode* uri; + const SerdNode* name; + const SerdNode* uri; } SerdPrefix; struct SerdEnvImpl { - SerdAllocator* allocator; - SerdPrefix* prefixes; - size_t n_prefixes; - SerdNode* base_uri_node; - SerdURIView base_uri; + SerdAllocator* allocator; + SerdNodes* nodes; + SerdPrefix* prefixes; + size_t n_prefixes; + const SerdNode* base_uri_node; + SerdURIView base_uri; }; SerdEnv* @@ -35,9 +38,14 @@ serd_env_new(SerdAllocator* const allocator, const SerdStringView base_uri) if (env) { env->allocator = allocator; + if (!(env->nodes = serd_nodes_new(allocator))) { + serd_afree(allocator, env); + return NULL; + } if (base_uri.length) { if (serd_env_set_base_uri(env, base_uri)) { + serd_nodes_free(env->nodes); serd_afree(allocator, env); return NULL; } @@ -54,55 +62,43 @@ serd_env_copy(SerdAllocator* const allocator, const SerdEnv* const env) return NULL; } - SerdEnv* const copy = - (SerdEnv*)serd_acalloc(allocator, 1, sizeof(struct SerdEnvImpl)); - + SerdEnv* const copy = (SerdEnv*)serd_acalloc(allocator, 1, sizeof(SerdEnv)); if (copy) { copy->allocator = allocator; copy->n_prefixes = env->n_prefixes; - if (!(copy->prefixes = (SerdPrefix*)serd_acalloc( - allocator, copy->n_prefixes, sizeof(SerdPrefix)))) { - serd_afree(allocator, copy); + // Allocate structure and set base URI + const SerdNode* const base = serd_env_base_uri(env); + if (!(copy->nodes = serd_nodes_new(allocator)) || + !(copy->prefixes = (SerdPrefix*)serd_acalloc( + allocator, copy->n_prefixes, sizeof(SerdPrefix))) || + (base && serd_env_set_base_uri(copy, serd_node_string_view(base)))) { + serd_env_free(copy); return NULL; } + // Copy each namespace prefix for (size_t i = 0; i < copy->n_prefixes; ++i) { if (!(copy->prefixes[i].name = - serd_node_copy(allocator, env->prefixes[i].name)) || + serd_nodes_intern(copy->nodes, env->prefixes[i].name)) || !(copy->prefixes[i].uri = - serd_node_copy(allocator, env->prefixes[i].uri))) { - serd_env_free(copy); - return NULL; - } - } - - const SerdNode* const base = serd_env_base_uri(env); - if (base) { - if (serd_env_set_base_uri(copy, serd_node_string_view(base))) { + serd_nodes_intern(copy->nodes, env->prefixes[i].uri))) { serd_env_free(copy); return NULL; } } } - return copy; } void serd_env_free(SerdEnv* const env) { - if (!env) { - return; - } - - for (size_t i = 0; i < env->n_prefixes; ++i) { - serd_node_free(env->allocator, env->prefixes[i].name); - serd_node_free(env->allocator, env->prefixes[i].uri); + if (env) { + serd_afree(env->allocator, env->prefixes); + serd_nodes_free(env->nodes); + serd_afree(env->allocator, env); } - serd_afree(env->allocator, env->prefixes); - serd_node_free(env->allocator, env->base_uri_node); - serd_afree(env->allocator, env); } bool @@ -145,13 +141,13 @@ serd_env_set_base_uri(SerdEnv* const env, const SerdStringView uri) assert(env); if (!uri.length) { - serd_node_free(env->allocator, env->base_uri_node); + serd_nodes_deref(env->nodes, env->base_uri_node); env->base_uri_node = NULL; env->base_uri = SERD_URI_NULL; return SERD_SUCCESS; } - SerdNode* const old_base_uri = env->base_uri_node; + const SerdNode* const old_base_uri = env->base_uri_node; // Resolve the new base against the current base in case it is relative const SerdURIView new_base_uri = @@ -159,13 +155,13 @@ serd_env_set_base_uri(SerdEnv* const env, const SerdStringView uri) // Replace the current base URI if ((env->base_uri_node = - serd_node_new(env->allocator, serd_a_parsed_uri(new_base_uri)))) { + serd_nodes_get(env->nodes, serd_a_parsed_uri(new_base_uri)))) { env->base_uri = serd_node_uri_view(env->base_uri_node); } else { return SERD_BAD_ALLOC; } - serd_node_free(env->allocator, old_base_uri); + serd_nodes_deref(env->nodes, old_base_uri); return SERD_SUCCESS; } @@ -201,38 +197,36 @@ serd_env_find(const SerdEnv* const env, } static SerdStatus -serd_env_add(SerdEnv* const env, - const SerdStringView name, - const SerdStringView uri) +serd_env_add(SerdEnv* const env, + const SerdStringView name, + const SerdNode* const uri) { SerdPrefix* const prefix = serd_env_find(env, name.data, name.length); if (prefix) { - if (!!strcmp(serd_node_string(prefix->uri), uri.data)) { - serd_node_free(env->allocator, prefix->uri); - prefix->uri = serd_node_new(env->allocator, serd_a_uri(uri)); + if (!!strcmp(serd_node_string(prefix->uri), serd_node_string(uri))) { + serd_nodes_deref(env->nodes, prefix->uri); + prefix->uri = uri; } } else { + const SerdNode* const name_node = + serd_nodes_get(env->nodes, serd_a_string_view(name)); + + if (!name_node) { + return SERD_BAD_ALLOC; + } + SerdPrefix* const new_prefixes = (SerdPrefix*)serd_arealloc(env->allocator, env->prefixes, (env->n_prefixes + 1) * sizeof(SerdPrefix)); - if (!new_prefixes) { - return SERD_BAD_ALLOC; - } - - env->prefixes = new_prefixes; - SerdNode* const name_node = - serd_node_new(env->allocator, serd_a_string_view(name)); - SerdNode* const uri_node = serd_node_new(env->allocator, serd_a_uri(uri)); - if (!name_node || !uri_node) { - serd_node_free(env->allocator, uri_node); - serd_node_free(env->allocator, name_node); + if (!new_prefixes) { return SERD_BAD_ALLOC; } new_prefixes[env->n_prefixes].name = name_node; - new_prefixes[env->n_prefixes].uri = uri_node; + new_prefixes[env->n_prefixes].uri = uri; + env->prefixes = new_prefixes; ++env->n_prefixes; } @@ -248,7 +242,12 @@ serd_env_set_prefix(SerdEnv* const env, if (serd_uri_string_has_scheme(uri.data)) { // Set prefix to absolute URI - return serd_env_add(env, name, uri); + const SerdNode* const abs_uri = serd_nodes_get(env->nodes, serd_a_uri(uri)); + if (!abs_uri) { + return SERD_BAD_ALLOC; + } + + return serd_env_add(env, name, abs_uri); } if (!env->base_uri_node) { @@ -261,8 +260,9 @@ serd_env_set_prefix(SerdEnv* const env, assert(abs_uri_view.scheme.length); // Create a new node for the absolute URI - SerdNode* const abs_uri = - serd_node_new(env->allocator, serd_a_parsed_uri(abs_uri_view)); + const SerdNode* const abs_uri = + serd_nodes_get(env->nodes, serd_a_parsed_uri(abs_uri_view)); + if (!abs_uri) { return SERD_BAD_ALLOC; } @@ -270,9 +270,7 @@ serd_env_set_prefix(SerdEnv* const env, assert(serd_uri_string_has_scheme(serd_node_string(abs_uri))); // Set prefix to resolved (absolute) URI - const SerdStatus st = serd_env_add(env, name, serd_node_string_view(abs_uri)); - serd_node_free(env->allocator, abs_uri); - return st; + return serd_env_add(env, name, abs_uri); } SerdStatus @@ -340,23 +338,21 @@ serd_env_expand_curie(const SerdEnv* const env, const SerdStringView curie) return NULL; } - const size_t len = prefix.length + suffix.length; - const size_t real_length = serd_node_pad_length(len); - const size_t node_size = sizeof(SerdNode) + real_length; - SerdNode* node = serd_node_malloc(env->allocator, node_size); + const size_t len = prefix.length + suffix.length; + SerdNode* ret = serd_node_malloc(env->allocator, sizeof(SerdNode) + len + 1); - if (node) { - node->length = len; - node->flags = 0U; - node->type = SERD_URI; + if (ret) { + ret->length = len; + ret->flags = 0U; + ret->type = SERD_URI; - char* const string = (char*)(node + 1U); + char* const string = serd_node_buffer(ret); assert(prefix.data); memcpy(string, prefix.data, prefix.length); memcpy(string + prefix.length, suffix.data, suffix.length); } - return node; + return ret; } SerdNode* @@ -368,10 +364,19 @@ serd_env_expand_node(const SerdEnv* const env, const SerdNode* const node) const SerdURIView uri = serd_node_uri_view(node); const SerdURIView abs_uri = serd_resolve_uri(uri, env->base_uri); + if (!abs_uri.scheme.length) { + return NULL; + } + + const SerdWriteResult r = + serd_node_construct(0U, NULL, serd_a_parsed_uri(abs_uri)); + + SerdNode* const expanded = serd_node_try_malloc(env->allocator, r); + if (expanded) { + serd_node_construct(r.count, expanded, serd_a_parsed_uri(abs_uri)); + } - return abs_uri.scheme.length - ? serd_node_new(env->allocator, serd_a_parsed_uri(abs_uri)) - : NULL; + return expanded; } SerdStatus |