diff options
-rw-r--r-- | include/serd/serd.h | 26 | ||||
-rw-r--r-- | src/env.c | 45 | ||||
-rw-r--r-- | src/env.h | 23 | ||||
-rw-r--r-- | src/writer.c | 4 | ||||
-rw-r--r-- | test/test_env.c | 60 |
5 files changed, 95 insertions, 63 deletions
diff --git a/include/serd/serd.h b/include/serd/serd.h index 3d08eb07..c2077f5c 100644 --- a/include/serd/serd.h +++ b/include/serd/serd.h @@ -931,26 +931,16 @@ serd_env_set_prefix(SerdEnv* SERD_NONNULL env, SerdStringView name, SerdStringView uri); -/// Qualify `uri` into a CURIE if possible -SERD_API -bool -serd_env_qualify(const SerdEnv* SERD_NONNULL env, - const SerdNode* SERD_NONNULL uri, - const SerdNode* SERD_NULLABLE* SERD_NONNULL prefix, - SerdStringView* SERD_NONNULL suffix); - /** - Expand `curie`. + Qualify `uri` into a CURIE if possible. - Errors: SERD_ERR_BAD_ARG if `curie` is not valid, or SERD_ERR_BAD_CURIE if - prefix is not defined in `env`. + Returns null if `uri` can not be qualified (usually because no corresponding + prefix is defined). */ SERD_API -SerdStatus -serd_env_expand(const SerdEnv* SERD_NONNULL env, - const SerdNode* SERD_NONNULL curie, - SerdStringView* SERD_NONNULL uri_prefix, - SerdStringView* SERD_NONNULL uri_suffix); +SerdNode* SERD_ALLOCATED +serd_env_qualify(const SerdEnv* SERD_NONNULL env, + const SerdNode* SERD_NONNULL uri); /** Expand `node`, transforming CURIEs into URIs. @@ -963,8 +953,8 @@ serd_env_expand(const SerdEnv* SERD_NONNULL env, */ SERD_API SerdNode* SERD_ALLOCATED -serd_env_expand_node(const SerdEnv* SERD_NONNULL env, - const SerdNode* SERD_NONNULL node); +serd_env_expand(const SerdEnv* SERD_NONNULL env, + const SerdNode* SERD_NONNULL node); /// Call `func` for each prefix defined in `env` SERD_API @@ -155,10 +155,10 @@ serd_env_set_prefix(SerdEnv* env, } bool -serd_env_qualify(const SerdEnv* env, - const SerdNode* uri, - const SerdNode** prefix, - SerdStringView* suffix) +serd_env_qualify_in_place(const SerdEnv* env, + const SerdNode* uri, + const SerdNode** prefix, + SerdStringView* suffix) { for (size_t i = 0; i < env->n_prefixes; ++i) { const SerdNode* const prefix_uri = env->prefixes[i].uri; @@ -177,11 +177,30 @@ serd_env_qualify(const SerdEnv* env, return false; } +SerdNode* +serd_env_qualify(const SerdEnv* env, const SerdNode* uri) +{ + const SerdNode* prefix = NULL; + SerdStringView suffix = {NULL, 0}; + if (serd_env_qualify_in_place(env, uri, &prefix, &suffix)) { + const size_t prefix_len = serd_node_length(prefix); + const size_t n_bytes = prefix_len + 1 + suffix.len; + SerdNode* node = serd_node_malloc(n_bytes, 0, SERD_CURIE); + memcpy(serd_node_buffer(node), serd_node_string(prefix), prefix_len); + serd_node_buffer(node)[prefix_len] = ':'; + memcpy(serd_node_buffer(node) + 1 + prefix_len, suffix.buf, suffix.len); + node->n_bytes = n_bytes; + return node; + } + + return NULL; +} + SerdStatus -serd_env_expand(const SerdEnv* env, - const SerdNode* curie, - SerdStringView* uri_prefix, - SerdStringView* uri_suffix) +serd_env_expand_in_place(const SerdEnv* env, + const SerdNode* curie, + SerdStringView* uri_prefix, + SerdStringView* uri_suffix) { const char* const str = serd_node_string(curie); const char* const colon = (const char*)memchr(str, ':', curie->n_bytes + 1); @@ -202,13 +221,17 @@ serd_env_expand(const SerdEnv* env, } SerdNode* -serd_env_expand_node(const SerdEnv* env, const SerdNode* node) +serd_env_expand(const SerdEnv* env, const SerdNode* node) { + if (!node) { + return NULL; + } + switch (node->type) { case SERD_LITERAL: { const SerdNode* const short_datatype = serd_node_datatype(node); if (short_datatype) { - SerdNode* const datatype = serd_env_expand_node(env, short_datatype); + SerdNode* const datatype = serd_env_expand(env, short_datatype); if (datatype) { SerdNode* ret = serd_new_typed_literal(serd_node_string_view(node), serd_node_string_view(datatype)); @@ -223,7 +246,7 @@ serd_env_expand_node(const SerdEnv* env, const SerdNode* node) case SERD_CURIE: { SerdStringView prefix; SerdStringView suffix; - if (serd_env_expand(env, node, &prefix, &suffix)) { + if (serd_env_expand_in_place(env, node, &prefix, &suffix)) { return NULL; } @@ -19,6 +19,29 @@ #include "serd/serd.h" +#include <stdbool.h> + +/** + Qualify `uri` into a CURIE if possible. +*/ +bool +serd_env_qualify_in_place(const SerdEnv* env, + const SerdNode* uri, + const SerdNode** prefix, + SerdStringView* suffix); + +/** + Expand `curie`. + + Errors: SERD_ERR_BAD_ARG if `curie` is not valid, or SERD_ERR_BAD_CURIE if + prefix is not defined in `env`. +*/ +SerdStatus +serd_env_expand_in_place(const SerdEnv* env, + const SerdNode* curie, + SerdStringView* uri_prefix, + SerdStringView* uri_suffix); + SERD_CONST_FUNC SerdURIView serd_env_base_uri_view(const SerdEnv* env); diff --git a/src/writer.c b/src/writer.c index d632c7af..be3f2469 100644 --- a/src/writer.c +++ b/src/writer.c @@ -588,7 +588,7 @@ write_uri_node(SerdWriter* const writer, } if (has_scheme && (writer->flags & SERD_WRITE_CURIED) && - serd_env_qualify(writer->env, node, &prefix, &suffix) && + serd_env_qualify_in_place(writer->env, node, &prefix, &suffix) && is_name(suffix.buf, suffix.len)) { write_uri_from_node(writer, prefix); sink(":", 1, writer); @@ -647,7 +647,7 @@ write_curie(SerdWriter* const writer, switch (writer->syntax) { case SERD_NTRIPLES: case SERD_NQUADS: - if ((st = serd_env_expand(writer->env, node, &prefix, &suffix))) { + if ((st = serd_env_expand_in_place(writer->env, node, &prefix, &suffix))) { serd_world_errorf( writer->world, st, "undefined namespace prefix `%s'\n", node_str); return false; diff --git a/test/test_env.c b/test/test_env.c index 9761a78c..3e38f71d 100644 --- a/test/test_env.c +++ b/test/test_env.c @@ -34,14 +34,16 @@ count_prefixes(void* handle, const SerdNode* name, const SerdNode* uri) static void test_env(void) { - SerdNode* u = serd_new_uri(SERD_STATIC_STRING("http://example.org/foo")); - SerdNode* b = serd_new_curie(SERD_STATIC_STRING("invalid")); - SerdNode* c = serd_new_curie(SERD_STATIC_STRING("eg.2:b")); - SerdNode* s = serd_new_string(SERD_STATIC_STRING("hello")); - SerdEnv* env = serd_env_new(SERD_EMPTY_STRING()); + SerdNode* hello = serd_new_string(SERD_STATIC_STRING("hello\"")); + SerdNode* eg = serd_new_uri(SERD_STATIC_STRING("http://example.org/")); + SerdNode* foo_u = serd_new_uri(SERD_STATIC_STRING("http://example.org/foo")); + SerdNode* foo_c = serd_new_curie(SERD_STATIC_STRING("eg.2:foo")); + SerdNode* b = serd_new_curie(SERD_STATIC_STRING("invalid")); - serd_env_set_prefix( - env, SERD_STATIC_STRING("eg.2"), SERD_STATIC_STRING("http://example.org/")); + const SerdStringView prefix = SERD_STATIC_STRING("eg.2"); + SerdEnv* env = serd_env_new(SERD_EMPTY_STRING()); + + serd_env_set_prefix(env, prefix, serd_node_string_view(eg)); assert(!serd_env_base_uri(env)); assert(!serd_env_set_base_uri(env, SERD_EMPTY_STRING())); @@ -52,52 +54,46 @@ test_env(void) SERD_STATIC_STRING("eg.3"), SERD_STATIC_STRING("rel")) == SERD_ERR_BAD_ARG); - SerdStringView prefix; - SerdStringView suffix; - assert(serd_env_expand(env, b, &prefix, &suffix)); + SerdNode* xnode = serd_env_expand(env, hello); + assert(!xnode); - assert(!serd_env_expand_node(env, b)); - assert(!serd_env_expand_node(env, s)); + assert(!serd_env_expand(env, b)); + assert(!serd_env_expand(env, hello)); assert(!serd_env_set_base_uri(env, SERD_EMPTY_STRING())); - SerdNode* xu = serd_env_expand_node(env, u); + serd_node_free(hello); + + SerdNode* xu = serd_env_expand(env, foo_c); assert(!strcmp(serd_node_string(xu), "http://example.org/foo")); serd_node_free(xu); SerdNode* badpre = serd_new_curie(SERD_STATIC_STRING("hm:what")); - SerdNode* xbadpre = serd_env_expand_node(env, badpre); + SerdNode* xbadpre = serd_env_expand(env, badpre); assert(!xbadpre); + serd_node_free(badpre); - SerdNode* xc = serd_env_expand_node(env, c); - assert(!strcmp(serd_node_string(xc), "http://example.org/b")); + SerdNode* xc = serd_env_expand(env, foo_c); + assert(serd_node_equals(xc, foo_u)); serd_node_free(xc); SerdNode* blank = serd_new_blank(SERD_STATIC_STRING("b1")); - assert(!serd_env_expand_node(env, blank)); + assert(!serd_env_expand(env, blank)); serd_node_free(blank); int n_prefixes = 0; - serd_env_set_prefix( - env, SERD_STATIC_STRING("eg.2"), SERD_STATIC_STRING("http://example.org/")); + serd_env_set_prefix(env, prefix, serd_node_string_view(eg)); serd_env_foreach(env, count_prefixes, &n_prefixes); assert(n_prefixes == 1); - SerdNode* shorter_uri = serd_new_uri(SERD_STATIC_STRING("urn:foo")); - const SerdNode* prefix_name = NULL; - assert(!serd_env_qualify(env, shorter_uri, &prefix_name, &suffix)); + SerdNode* qualified = serd_env_qualify(env, foo_u); + assert(serd_node_equals(qualified, foo_c)); - assert(!serd_env_set_base_uri(env, serd_node_string_view(u))); - assert(serd_node_equals(serd_env_base_uri(env), u)); - assert(!serd_env_set_base_uri(env, SERD_EMPTY_STRING())); - assert(!serd_env_base_uri(env)); - - serd_node_free(shorter_uri); - serd_node_free(badpre); - serd_node_free(s); - serd_node_free(c); + serd_node_free(qualified); + serd_node_free(foo_c); + serd_node_free(foo_u); serd_node_free(b); - serd_node_free(u); + serd_node_free(eg); serd_env_free(env); } |