aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2022-12-20 09:47:26 -0500
committerDavid Robillard <d@drobilla.net>2023-12-02 18:49:08 -0500
commit530edb265fbbed20e6d3a6fd7a36461ff83d9b46 (patch)
tree0f67206d7631bcff366c02cbedcd7f20b405dcb7
parent0f9816d67bc67a396607291f845ca2a33c2285a7 (diff)
downloadserd-530edb265fbbed20e6d3a6fd7a36461ff83d9b46.tar.gz
serd-530edb265fbbed20e6d3a6fd7a36461ff83d9b46.tar.bz2
serd-530edb265fbbed20e6d3a6fd7a36461ff83d9b46.zip
Add serd_env_unset_prefix()
-rw-r--r--include/serd/env.h12
-rw-r--r--src/env.c37
-rw-r--r--test/test_env.c61
3 files changed, 110 insertions, 0 deletions
diff --git a/include/serd/env.h b/include/serd/env.h
index 9ec2ef6a..a894ee4f 100644
--- a/include/serd/env.h
+++ b/include/serd/env.h
@@ -73,6 +73,18 @@ serd_env_set_prefix(SerdEnv* ZIX_NONNULL env,
ZixStringView uri);
/**
+ Unset a namespace prefix.
+
+ This removes the namespace prefix with the given name, if present. No such
+ prefix being found is not considered an error, that is, the call is
+ successful as long as the prefix is not set in the env upon return.
+
+ @return #SERD_SUCCESS if the prefix was removed or not present, or an error.
+*/
+SERD_API SerdStatus
+serd_env_unset_prefix(SerdEnv* ZIX_NONNULL env, ZixStringView name);
+
+/**
Qualify `uri` into a prefix and suffix (like a CURIE) if possible.
@param env Environment with prefixes to use.
diff --git a/src/env.c b/src/env.c
index a63f2126..0a1d0d5b 100644
--- a/src/env.c
+++ b/src/env.c
@@ -315,6 +315,43 @@ serd_env_set_prefix(SerdEnv* const env,
}
SerdStatus
+serd_env_unset_prefix(SerdEnv* const env, const ZixStringView name)
+{
+ // Find matching prefix
+ SerdPrefix* const prefix = serd_env_find(env, name.data, name.length);
+ if (!prefix) {
+ return SERD_SUCCESS;
+ }
+
+ // Drop prefix's URI node and clear if it's the only one
+ serd_nodes_deref(env->nodes, prefix->uri);
+ if (env->n_prefixes == 1U) {
+ zix_free(env->allocator, env->prefixes);
+ env->prefixes = NULL;
+ env->n_prefixes = 0U;
+ return SERD_SUCCESS;
+ }
+
+ // Replace the prefix entry with the last one (if applicable)
+ const size_t index = (size_t)(prefix - env->prefixes);
+ const size_t new_n_prefixes = env->n_prefixes - 1U;
+ if (index < new_n_prefixes) {
+ env->prefixes[index] = env->prefixes[new_n_prefixes];
+ }
+
+ // Shrink prefixes array
+ SerdPrefix* const new_prefixes = (SerdPrefix*)zix_realloc(
+ env->allocator, env->prefixes, new_n_prefixes * sizeof(SerdPrefix));
+
+ if (new_prefixes) {
+ env->prefixes = new_prefixes;
+ env->n_prefixes = new_n_prefixes;
+ }
+
+ return new_prefixes ? SERD_SUCCESS : SERD_BAD_ALLOC;
+}
+
+SerdStatus
serd_env_qualify(const SerdEnv* const env,
const ZixStringView uri,
ZixStringView* const prefix,
diff --git a/test/test_env.c b/test/test_env.c
index 9539798d..2cd05249 100644
--- a/test/test_env.c
+++ b/test/test_env.c
@@ -11,6 +11,8 @@
#include "serd/nodes.h"
#include "serd/sink.h"
#include "serd/status.h"
+#include "serd/world.h"
+#include "zix/allocator.h"
#include "zix/string_view.h"
#include <assert.h>
@@ -263,6 +265,64 @@ test_set_prefix(void)
}
static void
+test_unset_prefix(void)
+{
+ static const ZixStringView name1 = ZIX_STATIC_STRING("name1");
+ static const ZixStringView uri1 = ZIX_STATIC_STRING(NS_EG "uri1");
+ static const ZixStringView name2 = ZIX_STATIC_STRING("name2");
+ static const ZixStringView uri2 = ZIX_STATIC_STRING(NS_EG "uri2");
+ static const ZixStringView name3 = ZIX_STATIC_STRING("name3");
+ const ZixStringView uri3 = uri2;
+ static const ZixStringView base = ZIX_STATIC_STRING("base ");
+
+ SerdWorld* const world = serd_world_new(NULL);
+ ZixAllocator* const alloc = serd_world_allocator(world);
+ SerdEnv* const env = serd_env_new(alloc, base);
+ size_t count = 0;
+ SerdSink* const sink = serd_sink_new(alloc, &count, count_prefixes, NULL);
+
+ // Test "successfully" unsetting an unknown prefix
+ assert(!serd_env_unset_prefix(env, zix_string("unknown")));
+
+ // Set three initial prefixes
+ assert(!serd_env_set_prefix(env, name1, uri1));
+ assert(!serd_env_set_prefix(env, name2, uri2));
+ assert(!serd_env_set_prefix(env, name3, uri3));
+ serd_env_write_prefixes(env, sink);
+ assert(count == 3U);
+
+ // Unset the middle one
+ assert(!serd_env_unset_prefix(env, name2));
+ count = 0;
+ serd_env_write_prefixes(env, sink);
+ assert(count == 2U);
+
+ // Unset the last one
+ assert(!serd_env_unset_prefix(env, name3));
+ count = 0;
+ serd_env_write_prefixes(env, sink);
+ assert(count == 1U);
+
+ // Unset the first (and final) one
+ assert(!serd_env_unset_prefix(env, name1));
+ count = 0;
+ serd_env_write_prefixes(env, sink);
+ assert(count == 0U);
+
+ // Test re-adding to an empty env (and a different unsetting order)
+ assert(!serd_env_set_prefix(env, name1, uri1));
+ assert(!serd_env_set_prefix(env, name2, uri2));
+ assert(!serd_env_set_prefix(env, name3, uri3));
+ assert(!serd_env_unset_prefix(env, name1));
+ assert(!serd_env_unset_prefix(env, name2));
+ assert(!serd_env_unset_prefix(env, name3));
+
+ serd_sink_free(sink);
+ serd_env_free(env);
+ serd_world_free(world);
+}
+
+static void
test_expand_untyped_literal(void)
{
SerdNodes* const nodes = serd_nodes_new(NULL);
@@ -442,6 +502,7 @@ main(void)
test_null();
test_base_uri();
test_set_prefix();
+ test_unset_prefix();
test_expand_untyped_literal();
test_expand_bad_uri_datatype();
test_expand_uri();