aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/serd/env.h28
-rw-r--r--src/env.c51
-rw-r--r--src/env.h24
-rw-r--r--src/writer.c4
-rw-r--r--test/test_env.c85
5 files changed, 117 insertions, 75 deletions
diff --git a/include/serd/env.h b/include/serd/env.h
index ca02523b..2b2982f3 100644
--- a/include/serd/env.h
+++ b/include/serd/env.h
@@ -10,8 +10,6 @@
#include "serd/status.h"
#include "serd/string_view.h"
-#include <stdbool.h>
-
SERD_BEGIN_DECLS
/**
@@ -51,24 +49,24 @@ 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_NULLABLE env,
- const SerdNode* SERD_NONNULL uri,
- const SerdNode* SERD_NULLABLE* SERD_NONNULL prefix,
- SerdStringView* SERD_NONNULL suffix);
+/**
+ Qualify `uri` into a CURIE if possible.
+
+ Returns null if `uri` can not be qualified (usually because no corresponding
+ prefix is defined).
+*/
+SERD_API SerdNode* SERD_ALLOCATED
+serd_env_qualify(const SerdEnv* SERD_NULLABLE env,
+ const SerdNode* SERD_NULLABLE uri);
/**
- Expand `curie`.
+ Expand `node`, which must be a CURIE or URI, to a full URI.
- Errors: SERD_BAD_ARG if `curie` is not valid, or SERD_BAD_CURIE if prefix is
- not defined in `env`.
+ Returns null if `node` can not be expanded.
*/
-SERD_API SerdStatus
+SERD_API SerdNode* SERD_ALLOCATED
serd_env_expand(const SerdEnv* SERD_NULLABLE env,
- const SerdNode* SERD_NULLABLE curie,
- SerdStringView* SERD_NONNULL uri_prefix,
- SerdStringView* SERD_NONNULL uri_suffix);
+ const SerdNode* SERD_NULLABLE node);
/**
Expand `node`, which must be a CURIE or URI, to a full URI.
diff --git a/src/env.c b/src/env.c
index 4ce0add4..9bf307fd 100644
--- a/src/env.c
+++ b/src/env.c
@@ -151,15 +151,11 @@ serd_env_set_prefix(SerdEnv* const env,
}
bool
-serd_env_qualify(const SerdEnv* const env,
- const SerdNode* const uri,
- const SerdNode** const prefix,
- SerdStringView* const suffix)
+serd_env_qualify_in_place(const SerdEnv* const env,
+ const SerdNode* const uri,
+ const SerdNode** const prefix,
+ SerdStringView* const suffix)
{
- if (!env) {
- return false;
- }
-
for (size_t i = 0; i < env->n_prefixes; ++i) {
const SerdNode* const prefix_uri = env->prefixes[i].uri;
if (uri->length >= prefix_uri->length) {
@@ -177,16 +173,35 @@ serd_env_qualify(const SerdEnv* const env,
return false;
}
-SerdStatus
-serd_env_expand(const SerdEnv* const env,
- const SerdNode* const curie,
- SerdStringView* const uri_prefix,
- SerdStringView* const uri_suffix)
+SerdNode*
+serd_env_qualify(const SerdEnv* const env, const SerdNode* const uri)
{
- if (!env || !curie) {
- return SERD_BAD_CURIE;
+ if (!env || !uri) {
+ return NULL;
+ }
+
+ 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 length = prefix_len + 1 + suffix.length;
+ SerdNode* node = serd_node_malloc(length, 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.data, suffix.length);
+ node->length = length;
+ return node;
}
+ return NULL;
+}
+
+SerdStatus
+serd_env_expand_in_place(const SerdEnv* const env,
+ const SerdNode* const curie,
+ SerdStringView* const uri_prefix,
+ SerdStringView* const uri_suffix)
+{
const char* const str = serd_node_string(curie);
const char* const colon = (const char*)memchr(str, ':', curie->length + 1);
if (curie->type != SERD_CURIE || !colon) {
@@ -206,9 +221,9 @@ serd_env_expand(const SerdEnv* const env,
}
SerdNode*
-serd_env_expand_node(const SerdEnv* const env, const SerdNode* const node)
+serd_env_expand(const SerdEnv* const env, const SerdNode* const node)
{
- if (!env) {
+ if (!env || !node) {
return NULL;
}
@@ -220,7 +235,7 @@ serd_env_expand_node(const SerdEnv* const env, const SerdNode* const 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;
}
diff --git a/src/env.h b/src/env.h
index ed3fbfd9..934b9879 100644
--- a/src/env.h
+++ b/src/env.h
@@ -6,8 +6,32 @@
#include "serd/attributes.h"
#include "serd/env.h"
+#include "serd/node.h"
+#include "serd/status.h"
+#include "serd/string_view.h"
#include "serd/uri.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_BAD_ARG if `curie` is not valid, or SERD_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_PURE_FUNC SerdURIView
serd_env_base_uri_view(const SerdEnv* env);
diff --git a/src/writer.c b/src/writer.c
index 0ba90c0b..42a6ded0 100644
--- a/src/writer.c
+++ b/src/writer.c
@@ -852,7 +852,7 @@ write_uri_node(SerdWriter* const writer,
}
if (has_scheme && !(writer->flags & SERD_WRITE_UNQUALIFIED) &&
- serd_env_qualify(writer->env, node, &prefix, &suffix) &&
+ serd_env_qualify_in_place(writer->env, node, &prefix, &suffix) &&
is_name(serd_node_string(prefix), serd_node_length(prefix)) &&
is_name(suffix.data, suffix.length)) {
TRY(st, write_uri_from_node(writer, prefix));
@@ -885,7 +885,7 @@ write_curie(SerdWriter* const writer, const SerdNode* const node)
(writer->flags & (SERD_WRITE_UNQUALIFIED | SERD_WRITE_UNRESOLVED));
if (!supports_abbrev(writer) || !fast) {
- if ((st = serd_env_expand(writer->env, node, &prefix, &suffix))) {
+ if ((st = serd_env_expand_in_place(writer->env, node, &prefix, &suffix))) {
return w_err(writer, st, "undefined namespace prefix '%s'\n", node_str);
}
}
diff --git a/test/test_env.c b/test/test_env.c
index 31446f69..4f947246 100644
--- a/test/test_env.c
+++ b/test/test_env.c
@@ -26,25 +26,30 @@ count_prefixes(void* handle, const SerdEvent* event)
static void
test_env(void)
{
- SerdNode* u = serd_new_uri(serd_string("http://example.org/foo"));
- SerdNode* b = serd_new_curie(serd_string("invalid"));
- SerdNode* e = serd_new_uri(serd_empty_string());
- SerdNode* c = serd_new_curie(serd_string("eg.2:b"));
- SerdNode* s = serd_new_string(serd_string("hello"));
- SerdEnv* env = serd_env_new(serd_empty_string());
+ const SerdStringView prefix = serd_string("eg.2");
+ const SerdStringView eg = serd_string("http://example.org/");
- const SerdNode* prefix_node = NULL;
- SerdStringView prefix = serd_empty_string();
- SerdStringView suffix = serd_empty_string();
+ SerdNode* hello = serd_new_string(serd_string("hello\""));
+ SerdNode* rel = serd_new_uri(serd_string("rel"));
+ SerdNode* foo_u = serd_new_uri(serd_string("http://example.org/foo"));
+ SerdNode* foo_c = serd_new_curie(serd_string("eg.2:foo"));
+ SerdNode* b = serd_new_curie(serd_string("invalid"));
- assert(!serd_env_qualify(NULL, u, &prefix_node, &suffix));
+ SerdEnv* env = serd_env_new(serd_empty_string());
- assert(serd_env_expand(env, NULL, &prefix, &suffix) == SERD_BAD_CURIE);
+ serd_env_set_prefix(env, prefix, eg);
+
+ assert(!serd_env_base_uri(NULL));
+ assert(!serd_env_expand(NULL, NULL));
+ assert(!serd_env_expand(NULL, foo_c));
+ assert(!serd_env_expand(env, NULL));
+ assert(!serd_env_qualify(NULL, NULL));
+ assert(!serd_env_qualify(env, NULL));
+ assert(!serd_env_qualify(NULL, foo_u));
assert(!serd_env_base_uri(env));
assert(!serd_env_set_base_uri(env, serd_empty_string()));
assert(!serd_env_base_uri(env));
- assert(!serd_env_base_uri(env));
serd_env_set_prefix(
env, serd_string("eg.2"), serd_string("http://example.org/"));
@@ -52,61 +57,61 @@ test_env(void)
assert(serd_env_set_prefix(env, serd_string("eg.3"), serd_string("rel")) ==
SERD_BAD_ARG);
- assert(!serd_env_expand_node(NULL, u));
- assert(!serd_env_expand_node(env, b));
- assert(!serd_env_expand_node(env, s));
- assert(!serd_env_expand_node(env, e));
+ SerdNode* xnode = serd_env_expand(env, hello);
+ assert(!xnode);
+
+ 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);
+ 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_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_string("b1"));
- assert(!serd_env_expand_node(env, blank));
+ assert(!serd_env_expand(env, blank));
serd_node_free(blank);
size_t n_prefixes = 0;
SerdSink* const count_prefixes_sink =
serd_sink_new(&n_prefixes, count_prefixes, NULL);
- serd_env_set_prefix(
- env, serd_string("eg.2"), serd_string("http://example.org/"));
+ serd_env_set_prefix(env, prefix, eg);
serd_env_write_prefixes(env, count_prefixes_sink);
assert(n_prefixes == 1);
- SerdNode* shorter_uri = serd_new_uri(serd_string("urn:foo"));
- assert(!serd_env_qualify(env, shorter_uri, &prefix_node, &suffix));
+ SerdNode* qualified = serd_env_qualify(env, foo_u);
+ assert(serd_node_equals(qualified, foo_c));
+ serd_node_free(qualified);
- assert(!serd_env_set_base_uri(env, serd_node_string_view(u)));
- assert(serd_node_equals(serd_env_base_uri(env), u));
+ SerdNode* unqualifiable = serd_new_uri(serd_string("http://drobilla.net/"));
+ assert(!serd_env_qualify(env, unqualifiable));
+ serd_node_free(unqualifiable);
- SerdNode* xe = serd_env_expand_node(env, e);
- assert(xe);
- assert(!strcmp(serd_node_string(xe), "http://example.org/foo"));
- serd_node_free(xe);
+ assert(!serd_env_expand(env, rel));
+ serd_env_set_base_uri(env, serd_string("http://example.org/base/"));
- assert(!serd_env_set_base_uri(env, serd_empty_string()));
- assert(!serd_env_base_uri(env));
+ SerdNode* xrel = serd_env_expand(env, rel);
+ assert(xrel);
+ assert(!strcmp(serd_node_string(xrel), "http://example.org/base/rel"));
+ serd_node_free(xrel);
serd_sink_free(count_prefixes_sink);
- serd_node_free(shorter_uri);
- serd_node_free(badpre);
- serd_node_free(s);
- serd_node_free(c);
- serd_node_free(e);
serd_node_free(b);
- serd_node_free(u);
-
+ serd_node_free(foo_c);
+ serd_node_free(foo_u);
+ serd_node_free(rel);
+ serd_node_free(hello);
serd_env_free(env);
}