aboutsummaryrefslogtreecommitdiffstats
path: root/src/env.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/env.c')
-rw-r--r--src/env.c155
1 files changed, 80 insertions, 75 deletions
diff --git a/src/env.c b/src/env.c
index dcffb98e..8d63c9c9 100644
--- a/src/env.c
+++ b/src/env.c
@@ -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