diff options
author | David Robillard <d@drobilla.net> | 2022-12-20 09:47:26 -0500 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2023-12-02 18:49:08 -0500 |
commit | 530edb265fbbed20e6d3a6fd7a36461ff83d9b46 (patch) | |
tree | 0f67206d7631bcff366c02cbedcd7f20b405dcb7 | |
parent | 0f9816d67bc67a396607291f845ca2a33c2285a7 (diff) | |
download | serd-530edb265fbbed20e6d3a6fd7a36461ff83d9b46.tar.gz serd-530edb265fbbed20e6d3a6fd7a36461ff83d9b46.tar.bz2 serd-530edb265fbbed20e6d3a6fd7a36461ff83d9b46.zip |
Add serd_env_unset_prefix()
-rw-r--r-- | include/serd/env.h | 12 | ||||
-rw-r--r-- | src/env.c | 37 | ||||
-rw-r--r-- | test/test_env.c | 61 |
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. @@ -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(); |