aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2018-05-11 18:11:44 +0200
committerDavid Robillard <d@drobilla.net>2020-10-27 13:13:58 +0100
commit40c90e819d20d6933504ccb639896be223e10c3c (patch)
treefc9e0589c2fb4bb72eaf16fa06e7ce8263a6360a
parent36a418f0d8dfd10007e48d6e8cb796cfa8aa4d88 (diff)
downloadserd-40c90e819d20d6933504ccb639896be223e10c3c.tar.gz
serd-40c90e819d20d6933504ccb639896be223e10c3c.tar.bz2
serd-40c90e819d20d6933504ccb639896be223e10c3c.zip
Clean up node construction API
-rw-r--r--serd/serd.h102
-rw-r--r--src/env.c41
-rw-r--r--src/env.h24
-rw-r--r--src/node.c154
-rw-r--r--src/node.h1
-rw-r--r--src/serdi.c11
-rw-r--r--src/writer.c18
-rw-r--r--tests/env_test.c27
-rw-r--r--tests/serd_test.c176
9 files changed, 323 insertions, 231 deletions
diff --git a/serd/serd.h b/serd/serd.h
index 45e7ea56..b10d9ce9 100644
--- a/serd/serd.h
+++ b/serd/serd.h
@@ -463,18 +463,30 @@ serd_uri_serialise_relative(const SerdURI* uri,
*/
/**
- Create a new node from `str`.
+ Create a new "simple" node that is just a string.
+
+ This can be used to create blank, CURIE, or URI nodes from an already
+ measured string or slice of a buffer, which avoids a strlen compared to the
+ friendly constructors. This may not be used for literals since those must
+ be measured to set the SERD_HAS_NEWLINE and SERD_HAS_QUOTE flags.
+*/
+SERD_API
+SerdNode*
+serd_node_new_simple_node(SerdType type, const char* str, size_t len);
+
+/**
+ Create a new plain literal string node from `str`.
*/
SERD_API
SerdNode*
-serd_node_new_string(SerdType type, const char* str);
+serd_node_new_string(const char* str);
/**
- Create a new node from a prefix of `str`.
+ Create a new plain literal string node from a prefix of `str`.
*/
SERD_API
SerdNode*
-serd_node_new_substring(SerdType type, const char* str, size_t len);
+serd_node_new_substring(const char* str, size_t len);
/**
Create a new literal node from `str`.
@@ -490,81 +502,72 @@ serd_node_new_literal(const char* str,
/**
Create a new blank node.
-
- Note this function measures `str`, which is a common bottleneck.
- Use sord_node_from_serd_node() instead if `str` is already measured.
*/
SERD_API
SerdNode*
serd_node_new_blank(const char* str);
/**
- Simple wrapper for serd_node_new_uri() to resolve a URI node.
+ Create a new CURIE node.
*/
SERD_API
SerdNode*
-serd_node_new_uri_from_node(const SerdNode* uri_node,
- const SerdURI* base,
- SerdURI* out);
+serd_node_new_curie(const char* str);
/**
- Simple wrapper for serd_node_new_uri() to resolve a URI string.
+ Create a new URI from a string.
*/
SERD_API
SerdNode*
-serd_node_new_uri_from_string(const char* str,
- const SerdURI* base,
- SerdURI* out);
+serd_node_new_uri(const char* str);
/**
- Create a new file URI node from a file system path and optional hostname.
+ Create a new URI from a string, resolved against a base URI.
+*/
+SERD_API
+SerdNode*
+serd_node_new_resolved_uri(const char* str, const SerdNode* base);
- Backslashes in Windows paths will be converted and '%' will always be
- percent encoded. If `escape` is true, all other invalid characters will be
- percent encoded as well.
+/**
+ Resolve `node` against `base`.
- If `path` is relative, `hostname` is ignored.
- If `out` is not NULL, it will be set to the parsed URI.
+ If `node` is not a relative URI, an equivalent new node is returned.
*/
SERD_API
SerdNode*
-serd_node_new_file_uri(const char* path,
- const char* hostname,
- SerdURI* out,
- bool escape);
+serd_node_resolve(const SerdNode* node, const SerdNode* base);
/**
- Create a new node by serialising `uri` into a new string.
-
- @param uri The URI to serialise.
+ Create a new file URI node from a file system path and optional hostname.
- @param base Base URI to resolve `uri` against (or NULL for no resolution).
+ Backslashes in Windows paths will be converted and '%' will always be
+ percent encoded. If `escape` is true, all other invalid characters will be
+ percent encoded as well.
- @param out Set to the parsing of the new URI (i.e. points only to
- memory owned by the new returned node).
+ If `path` is relative, `hostname` is ignored.
*/
SERD_API
SerdNode*
-serd_node_new_uri(const SerdURI* uri, const SerdURI* base, SerdURI* out);
+serd_node_new_file_uri(const char* path, const char* hostname, bool escape);
/**
- Create a new node by serialising `uri` into a new relative URI.
+ Create a new URI from a string, relative to a base URI.
- @param uri The URI to serialise.
+ @param str URI string.
- @param base Base URI to make `uri` relative to, if possible.
+ @param base Base URI to make `str` relative to, if possible.
- @param root Root URI for resolution (see serd_uri_serialise_relative()).
+ @param root Optional root URI for resolution.
- @param out Set to the parsing of the new URI (i.e. points only to
- memory owned by the new returned node).
+ The URI is made relative iff if it a child of `base` and `root`. The
+ optional `root` parameter must be a prefix of `base` and can be used keep
+ up-references ("../") within a certain namespace.
*/
SERD_API
SerdNode*
-serd_node_new_relative_uri(const SerdURI* uri,
- const SerdURI* base,
- const SerdURI* root,
- SerdURI* out);
+serd_node_new_relative_uri(const char* str,
+ const SerdNode* base,
+ const SerdNode* root);
/**
Create a new node by serialising `d` into an xsd:decimal string.
@@ -793,7 +796,7 @@ serd_env_free(SerdEnv* env);
*/
SERD_API
const SerdNode*
-serd_env_base_uri(const SerdEnv* env, SerdURI* out);
+serd_env_base_uri(const SerdEnv* env);
/**
Set the current base URI.
@@ -990,13 +993,12 @@ serd_reader_free(SerdReader* reader);
*/
SERD_API
SerdWriter*
-serd_writer_new(SerdWorld* world,
- SerdSyntax syntax,
- SerdStyle style,
- SerdEnv* env,
- const SerdURI* base_uri,
- SerdWriteFunc ssink,
- void* stream);
+serd_writer_new(SerdWorld* world,
+ SerdSyntax syntax,
+ SerdStyle style,
+ SerdEnv* env,
+ SerdWriteFunc ssink,
+ void* stream);
/**
Free `writer`.
diff --git a/src/env.c b/src/env.c
index c99d2bc4..ea098c1b 100644
--- a/src/env.c
+++ b/src/env.c
@@ -14,6 +14,8 @@
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "env.h"
+
#include "node.h"
#include "serd/serd.h"
@@ -61,12 +63,15 @@ serd_env_free(SerdEnv* env)
free(env);
}
+const SerdURI*
+serd_env_get_parsed_base_uri(const SerdEnv* env)
+{
+ return &env->base_uri;
+}
+
const SerdNode*
-serd_env_base_uri(const SerdEnv* env, SerdURI* out)
+serd_env_base_uri(const SerdEnv* env)
{
- if (out) {
- *out = env->base_uri;
- }
return env->base_uri_node;
}
@@ -74,14 +79,16 @@ SerdStatus
serd_env_set_base_uri(SerdEnv* env,
const SerdNode* uri)
{
- if (!env || !uri) {
+ if (!env || !uri || uri->type != SERD_URI) {
return SERD_ERR_BAD_ARG;
}
// Resolve base URI and create a new node and URI for it
+ SerdNode* base_uri_node = serd_node_new_resolved_uri_i(
+ serd_node_string(uri), &env->base_uri);
+
SerdURI base_uri;
- SerdNode* base_uri_node = serd_node_new_uri_from_node(
- uri, &env->base_uri, &base_uri);
+ serd_uri_parse(serd_node_string(base_uri_node), &base_uri);
if (base_uri_node) {
// Replace the current base URI
@@ -142,13 +149,12 @@ serd_env_set_prefix(SerdEnv* env,
serd_env_add(env, name, uri);
} else {
// Resolve relative URI and create a new node and URI for it
- SerdURI abs_uri;
- SerdNode* abs_uri_node = serd_node_new_uri_from_node(
- uri, &env->base_uri, &abs_uri);
+ SerdNode* abs_uri = serd_node_new_resolved_uri_i(
+ serd_node_string(uri), &env->base_uri);
// Set prefix to resolved (absolute) URI
- serd_env_add(env, name, abs_uri_node);
- serd_node_free(abs_uri_node);
+ serd_env_add(env, name, abs_uri);
+ serd_node_free(abs_uri);
}
return SERD_SUCCESS;
}
@@ -158,8 +164,8 @@ serd_env_set_prefix_from_strings(SerdEnv* env,
const char* name,
const char* uri)
{
- SerdNode* name_node = serd_node_new_string(SERD_LITERAL, name);
- SerdNode* uri_node = serd_node_new_string(SERD_URI, uri);
+ SerdNode* name_node = serd_node_new_string(name);
+ SerdNode* uri_node = serd_node_new_uri(uri);
const SerdStatus st = serd_env_set_prefix(env, name_node, uri_node);
@@ -222,10 +228,9 @@ serd_env_expand_node(const SerdEnv* env,
switch (node->type) {
case SERD_LITERAL:
break;
- case SERD_URI: {
- SerdURI ignored;
- return serd_node_new_uri_from_node(node, &env->base_uri, &ignored);
- }
+ case SERD_URI:
+ return serd_node_new_resolved_uri_i(
+ serd_node_string(node), &env->base_uri);
case SERD_CURIE: {
SerdStringView prefix;
SerdStringView suffix;
diff --git a/src/env.h b/src/env.h
new file mode 100644
index 00000000..d1894613
--- /dev/null
+++ b/src/env.h
@@ -0,0 +1,24 @@
+/*
+ Copyright 2011-2020 David Robillard <http://drobilla.net>
+
+ Permission to use, copy, modify, and/or distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+#ifndef SERD_ENV_H
+#define SERD_ENV_H
+
+#include "serd/serd.h"
+
+const SerdURI* serd_env_get_parsed_base_uri(const SerdEnv* env);
+
+#endif // SERD_ENV_H
diff --git a/src/node.c b/src/node.c
index 95a34fac..2bb1d493 100644
--- a/src/node.c
+++ b/src/node.c
@@ -42,6 +42,9 @@
static const size_t serd_node_align = sizeof(SerdNode);
+static SerdNode*
+serd_node_new_from_uri(const SerdURI* uri, const SerdURI* base);
+
static size_t
serd_node_pad_size(const size_t n_bytes)
{
@@ -93,7 +96,22 @@ serd_node_set(SerdNode** dst, const SerdNode* src)
}
SerdNode*
-serd_node_new_string(SerdType type, const char* str)
+serd_node_new_simple_node(SerdType type, const char* str, const size_t len)
+{
+ if (!str) {
+ return NULL;
+ } else if (type != SERD_BLANK && type != SERD_CURIE && type != SERD_URI) {
+ return NULL;
+ }
+
+ SerdNode* node = serd_node_malloc(len, 0, type);
+ memcpy(serd_node_buffer(node), str, len);
+ node->n_bytes = len;
+ return node;
+}
+
+SerdNode*
+serd_node_new_string(const char* str)
{
if (!str) {
return NULL;
@@ -101,14 +119,14 @@ serd_node_new_string(SerdType type, const char* str)
SerdNodeFlags flags = 0;
const size_t n_bytes = serd_strlen(str, &flags);
- SerdNode* node = serd_node_malloc(n_bytes, flags, type);
+ SerdNode* node = serd_node_malloc(n_bytes, flags, SERD_LITERAL);
memcpy(serd_node_buffer(node), str, n_bytes);
node->n_bytes = n_bytes;
return node;
}
SerdNode*
-serd_node_new_substring(SerdType type, const char* str, const size_t len)
+serd_node_new_substring(const char* str, const size_t len)
{
if (!str) {
return NULL;
@@ -116,7 +134,7 @@ serd_node_new_substring(SerdType type, const char* str, const size_t len)
SerdNodeFlags flags = 0;
const size_t n_bytes = serd_substrlen(str, len, &flags);
- SerdNode* node = serd_node_malloc(n_bytes, flags, type);
+ SerdNode* node = serd_node_malloc(n_bytes, flags, SERD_LITERAL);
memcpy(serd_node_buffer(node), str, n_bytes);
node->n_bytes = n_bytes;
return node;
@@ -172,15 +190,19 @@ serd_node_new_literal(const char* str,
SerdNode*
serd_node_new_blank(const char* str)
{
- if (!str) {
- return NULL;
- }
+ return str ? serd_node_new_simple_node(SERD_BLANK, str, strlen(str)) : NULL;
+}
- const size_t n_bytes = strlen(str);
- SerdNode* node = serd_node_malloc(n_bytes, 0, SERD_BLANK);
- memcpy(serd_node_buffer(node), str, n_bytes);
- node->n_bytes = n_bytes;
- return node;
+SerdNode*
+serd_node_new_curie(const char* str)
+{
+ return str ? serd_node_new_simple_node(SERD_CURIE, str, strlen(str)) : NULL;
+}
+
+SerdNode*
+serd_node_new_uri(const char* str)
+{
+ return str ? serd_node_new_simple_node(SERD_URI, str, strlen(str)) : NULL;
}
SerdNode*
@@ -236,29 +258,43 @@ string_sink(const void* buf, size_t size, size_t nmemb, void* stream)
}
SerdNode*
-serd_node_new_uri_from_node(const SerdNode* uri_node,
- const SerdURI* base,
- SerdURI* out)
+serd_node_new_resolved_uri(const char* str, const SerdNode* base)
{
- const char* uri_str = serd_node_string(uri_node);
- return (uri_node && uri_node->type == SERD_URI && uri_str)
- ? serd_node_new_uri_from_string(uri_str, base, out)
- : NULL;
+ if (!base || base->type != SERD_URI) {
+ return NULL;
+ }
+
+ SerdURI base_uri;
+ serd_uri_parse(serd_node_string(base), &base_uri);
+ return serd_node_new_resolved_uri_i(str, &base_uri);
+}
+
+SerdNode*
+serd_node_resolve(const SerdNode* node, const SerdNode* base)
+{
+ if (!node || !base || node->type != SERD_URI || base->type != SERD_URI) {
+ return NULL;
+ }
+
+ SerdURI uri;
+ SerdURI base_uri;
+ serd_uri_parse(serd_node_string(node), &uri);
+ serd_uri_parse(serd_node_string(base), &base_uri);
+
+ return serd_node_new_from_uri(&uri, &base_uri);
}
SerdNode*
-serd_node_new_uri_from_string(const char* str,
- const SerdURI* base,
- SerdURI* out)
+serd_node_new_resolved_uri_i(const char* str, const SerdURI* base)
{
if (!str || str[0] == '\0') {
// Empty URI => Base URI, or nothing if no base is given
- return base ? serd_node_new_uri(base, NULL, out) : NULL;
+ return base ? serd_node_new_from_uri(base, NULL) : NULL;
}
SerdURI uri;
serd_uri_parse(str, &uri);
- return serd_node_new_uri(&uri, base, out); // Resolve/Serialise
+ return serd_node_new_from_uri(&uri, base);
}
static inline bool
@@ -281,10 +317,7 @@ is_uri_path_char(const char c)
}
SerdNode*
-serd_node_new_file_uri(const char* path,
- const char* hostname,
- SerdURI* out,
- bool escape)
+serd_node_new_file_uri(const char* path, const char* hostname, bool escape)
{
const size_t path_len = strlen(path);
const size_t hostname_len = hostname ? strlen(hostname) : 0;
@@ -318,18 +351,13 @@ serd_node_new_file_uri(const char* path,
}
serd_buffer_sink_finish(&buffer);
- SerdNode* node = serd_node_new_substring(
- SERD_URI, (const char*)buffer.buf, buffer.len);
- if (out) {
- serd_uri_parse(serd_node_buffer(node), out);
- }
-
+ SerdNode* node = serd_node_new_uri((const char*)buffer.buf);
free(buffer.buf);
return node;
}
-SerdNode*
-serd_node_new_uri(const SerdURI* uri, const SerdURI* base, SerdURI* out)
+static SerdNode*
+serd_node_new_from_uri(const SerdURI* uri, const SerdURI* base)
{
SerdURI abs_uri = *uri;
if (base) {
@@ -344,33 +372,36 @@ serd_node_new_uri(const SerdURI* uri, const SerdURI* base, SerdURI* out)
serd_node_buffer(node)[actual_len] = '\0';
node->n_bytes = actual_len;
- if (out) {
- serd_uri_parse(serd_node_buffer(node), out); // TODO: avoid double parse
- }
-
return node;
}
SerdNode*
-serd_node_new_relative_uri(const SerdURI* uri,
- const SerdURI* base,
- const SerdURI* root,
- SerdURI* out)
+serd_node_new_relative_uri(const char* str,
+ const SerdNode* base,
+ const SerdNode* root)
{
- const size_t uri_len = serd_uri_string_length(uri);
- const size_t base_len = serd_uri_string_length(base);
+ SerdURI uri = SERD_URI_NULL;
+ SerdURI base_uri = SERD_URI_NULL;
+ SerdURI root_uri = SERD_URI_NULL;
+
+ serd_uri_parse(str, &uri);
+ if (base) {
+ serd_uri_parse(serd_node_string(base), &base_uri);
+ }
+ if (root) {
+ serd_uri_parse(serd_node_string(root), &root_uri);
+ }
+
+ const size_t uri_len = serd_uri_string_length(&uri);
+ const size_t base_len = serd_uri_string_length(&base_uri);
SerdNode* node = serd_node_malloc(uri_len + base_len, 0, SERD_URI);
char* ptr = serd_node_buffer(node);
const size_t actual_len = serd_uri_serialise_relative(
- uri, base, root, string_sink, &ptr);
+ &uri, &base_uri, root ? &root_uri : NULL, string_sink, &ptr);
serd_node_buffer(node)[actual_len] = '\0';
node->n_bytes = actual_len;
- if (out) {
- serd_uri_parse(serd_node_buffer(node), out); // TODO: avoid double parse
- }
-
return node;
}
@@ -499,6 +530,15 @@ serd_node_length(const SerdNode* node)
return node ? node->n_bytes : 0;
}
+static const SerdNode*
+serd_node_meta_node(const SerdNode* node)
+{
+ const size_t len = serd_node_pad_size(node->n_bytes);
+ assert((intptr_t)node % serd_node_align == 0);
+ assert(len % serd_node_align == 0);
+ return node + 1 + (len / serd_node_align);
+}
+
const SerdNode*
serd_node_datatype(const SerdNode* node)
{
@@ -506,11 +546,7 @@ serd_node_datatype(const SerdNode* node)
return NULL;
}
- const size_t len = serd_node_pad_size(node->n_bytes);
- assert((intptr_t)node % serd_node_align == 0);
- assert(len % serd_node_align == 0);
-
- const SerdNode* const datatype = node + 1 + (len / serd_node_align);
+ const SerdNode* const datatype = serd_node_meta_node(node);
assert(datatype->type == SERD_URI || datatype->type == SERD_CURIE);
return datatype;
}
@@ -522,11 +558,7 @@ serd_node_language(const SerdNode* node)
return NULL;
}
- const size_t len = serd_node_pad_size(node->n_bytes);
- assert((intptr_t)node % serd_node_align == 0);
- assert(len % serd_node_align == 0);
-
- const SerdNode* const lang = node + 1 + (len / serd_node_align);
+ const SerdNode* const lang = serd_node_meta_node(node);
assert(lang->type == SERD_LITERAL);
return lang;
}
diff --git a/src/node.h b/src/node.h
index f99da1a6..8bc6083e 100644
--- a/src/node.h
+++ b/src/node.h
@@ -41,5 +41,6 @@ serd_node_buffer_c(const SerdNode* node)
SerdNode* serd_node_malloc(size_t n_bytes, SerdNodeFlags flags, SerdType type);
void serd_node_set(SerdNode** dst, const SerdNode* src);
+SerdNode* serd_node_new_resolved_uri_i(const char* str, const SerdURI* base);
#endif // SERD_NODE_H
diff --git a/src/serdi.c b/src/serdi.c
index e9a0299c..ef620c3c 100644
--- a/src/serdi.c
+++ b/src/serdi.c
@@ -224,13 +224,11 @@ main(int argc, char** argv)
: SERD_NQUADS);
}
- SerdURI base_uri = SERD_URI_NULL;
- SerdNode* base = NULL;
+ SerdNode* base = NULL;
if (a < argc) { // Base URI given on command line
- base = serd_node_new_uri_from_string(
- (const char*)argv[a], NULL, &base_uri);
+ base = serd_node_new_uri((const char*)argv[a]);
} else if (!from_string && !from_stdin) { // Use input file URI
- base = serd_node_new_file_uri(input, NULL, &base_uri, true);
+ base = serd_node_new_file_uri(input, NULL, true);
}
FILE* out_fd = stdout;
@@ -261,7 +259,6 @@ main(int argc, char** argv)
output_syntax,
(SerdStyle)output_style,
env,
- &base_uri,
(SerdWriteFunc)fwrite,
out_fd);
@@ -273,7 +270,7 @@ main(int argc, char** argv)
serd_world_set_error_sink(world, quiet_error_sink, NULL);
}
- SerdNode* root = serd_node_new_string(SERD_URI, root_uri);
+ SerdNode* root = serd_node_new_uri(root_uri);
serd_writer_set_root_uri(writer, root);
serd_writer_chop_blank_prefix(writer, chop_prefix);
serd_reader_add_blank_prefix(reader, add_prefix);
diff --git a/src/writer.c b/src/writer.c
index bbe2a247..9d7a6790 100644
--- a/src/writer.c
+++ b/src/writer.c
@@ -15,6 +15,7 @@
*/
#include "byte_sink.h"
+#include "env.h"
#include "node.h"
#include "serd_internal.h"
#include "stack.h"
@@ -100,7 +101,6 @@ struct SerdWriterImpl {
SerdEnv* env;
SerdNode* root_node;
SerdURI root_uri;
- SerdURI base_uri;
SerdStack anon_stack;
SerdByteSink byte_sink;
SerdErrorSink error_sink;
@@ -528,21 +528,19 @@ write_uri_node(SerdWriter* const writer,
write_sep(writer, SEP_URI_BEGIN);
if (writer->style & SERD_STYLE_RESOLVED) {
- SerdURI in_base_uri;
+ const SerdURI* base_uri = serd_env_get_parsed_base_uri(writer->env);
SerdURI uri;
SerdURI abs_uri;
- serd_env_base_uri(writer->env, &in_base_uri);
serd_uri_parse(node_str, &uri);
- serd_uri_resolve(&uri, &in_base_uri, &abs_uri);
- bool rooted = uri_is_under(&writer->base_uri, &writer->root_uri);
- SerdURI* root = rooted ? &writer->root_uri : & writer->base_uri;
+ serd_uri_resolve(&uri, base_uri, &abs_uri);
+ bool rooted = uri_is_under(base_uri, &writer->root_uri);
+ const SerdURI* root = rooted ? &writer->root_uri : base_uri;
if (!uri_is_under(&abs_uri, root) ||
writer->syntax == SERD_NTRIPLES ||
writer->syntax == SERD_NQUADS) {
serd_uri_serialise(&abs_uri, uri_sink, writer);
} else {
- serd_uri_serialise_relative(
- &uri, &writer->base_uri, root, uri_sink, writer);
+ serd_uri_serialise_relative(&uri, base_uri, root, uri_sink, writer);
}
} else {
write_uri_from_node(writer, node);
@@ -867,7 +865,6 @@ serd_writer_new(SerdWorld* world,
SerdSyntax syntax,
SerdStyle style,
SerdEnv* env,
- const SerdURI* base_uri,
SerdWriteFunc ssink,
void* stream)
{
@@ -879,7 +876,6 @@ serd_writer_new(SerdWorld* world,
writer->env = env;
writer->root_node = NULL;
writer->root_uri = SERD_URI_NULL;
- writer->base_uri = base_uri ? *base_uri : SERD_URI_NULL;
writer->anon_stack = serd_stack_new(4 * sizeof(WriteContext));
writer->context = context;
writer->list_subj = NULL;
@@ -915,8 +911,6 @@ serd_writer_set_base_uri(SerdWriter* writer,
const SerdNode* uri)
{
if (!serd_env_set_base_uri(writer->env, uri)) {
- serd_env_base_uri(writer->env, &writer->base_uri);
-
if (writer->syntax == SERD_TURTLE || writer->syntax == SERD_TRIG) {
if (ctx(writer, FIELD_GRAPH) || ctx(writer, FIELD_SUBJECT)) {
sink(" .\n\n", 4, writer);
diff --git a/tests/env_test.c b/tests/env_test.c
index 8e0c9205..607b8763 100644
--- a/tests/env_test.c
+++ b/tests/env_test.c
@@ -36,13 +36,21 @@ test_env(void)
{
SerdWorld* world = serd_world_new();
- SerdNode* u = serd_node_new_string(SERD_URI, "http://example.org/foo");
- SerdNode* b = serd_node_new_string(SERD_CURIE, "invalid");
- SerdNode* c = serd_node_new_string(SERD_CURIE, "eg.2:b");
- SerdNode* s = serd_node_new_string(SERD_LITERAL, "hello");
- SerdEnv* env = serd_env_new(NULL);
+ SerdNode* hello = serd_node_new_string("hello\"");
+ SerdNode* u = serd_node_new_uri("http://example.org/foo");
+ SerdNode* b = serd_node_new_curie("invalid");
+ SerdNode* c = serd_node_new_curie("eg.2:b");
+ SerdNode* s = serd_node_new_string("hello");
+ SerdEnv* env = serd_env_new(NULL);
serd_env_set_prefix_from_strings(env, "eg.2", "http://example.org/");
+ assert(!serd_env_base_uri(env));
+ assert(serd_env_set_base_uri(env, NULL));
+ assert(!serd_env_base_uri(env));
+ assert(serd_env_set_base_uri(env, hello));
+ assert(!serd_env_base_uri(env));
+ serd_node_free(hello);
+
SerdStringView prefix;
SerdStringView suffix;
assert(serd_env_expand(env, b, &prefix, &suffix));
@@ -57,7 +65,7 @@ test_env(void)
assert(!strcmp(serd_node_string(xu), "http://example.org/foo"));
serd_node_free(xu);
- SerdNode* badpre = serd_node_new_string(SERD_CURIE, "hm:what");
+ SerdNode* badpre = serd_node_new_curie("hm:what");
SerdNode* xbadpre = serd_env_expand_node(env, badpre);
assert(!xbadpre);
@@ -67,10 +75,10 @@ test_env(void)
assert(serd_env_set_prefix(env, NULL, NULL));
- SerdNode* lit = serd_node_new_string(SERD_LITERAL, "hello");
+ SerdNode* lit = serd_node_new_string("hello");
assert(serd_env_set_prefix(env, b, lit));
- SerdNode* blank = serd_node_new_string(SERD_BLANK, "b1");
+ SerdNode* blank = serd_node_new_blank("b1");
assert(!serd_env_expand_node(env, blank));
serd_node_free(blank);
@@ -79,10 +87,9 @@ test_env(void)
serd_env_foreach(env, count_prefixes, &n_prefixes);
assert(n_prefixes == 1);
- SerdNode* shorter_uri = serd_node_new_string(SERD_URI, "urn:foo");
+ SerdNode* shorter_uri = serd_node_new_uri("urn:foo");
const SerdNode* prefix_name = NULL;
assert(!serd_env_qualify(env, shorter_uri, &prefix_name, &suffix));
-
serd_node_free(shorter_uri);
serd_node_free(lit);
serd_node_free(badpre);
diff --git a/tests/serd_test.c b/tests/serd_test.c
index 067f5e2e..0a65fbe9 100644
--- a/tests/serd_test.c
+++ b/tests/serd_test.c
@@ -110,8 +110,8 @@ test_file_uri(const char* hostname,
expected_path = path;
}
- SerdNode* node = serd_node_new_file_uri(path, hostname, 0, escape);
- const char* node_str = serd_node_string(node);
+ SerdNode* node = serd_node_new_file_uri(path, hostname, escape);
+ const char* node_str = serd_node_string(node);
char* out_hostname = NULL;
char* out_path = serd_file_uri_parse(node_str, &out_hostname);
assert(!strcmp(node_str, expected_uri));
@@ -367,17 +367,16 @@ static void
test_node_equals(void)
{
const uint8_t replacement_char_str[] = { 0xEF, 0xBF, 0xBD, 0 };
- SerdNode* lhs = serd_node_new_string(SERD_LITERAL, (const char*)replacement_char_str);
- SerdNode* rhs = serd_node_new_string(SERD_LITERAL, "123");
+ SerdNode* lhs = serd_node_new_string((const char*)replacement_char_str);
+ SerdNode* rhs = serd_node_new_string("123");
assert(!serd_node_equals(lhs, rhs));
- SerdNode* qnode = serd_node_new_string(SERD_CURIE, "foo:bar");
+ SerdNode* qnode = serd_node_new_curie("foo:bar");
assert(!serd_node_equals(lhs, qnode));
- assert(serd_node_equals(lhs, lhs));
+ serd_node_free(qnode);
assert(!serd_node_copy(NULL));
- serd_node_free(qnode);
serd_node_free(lhs);
serd_node_free(rhs);
}
@@ -385,34 +384,44 @@ test_node_equals(void)
static void
test_node_from_string(void)
{
- SerdNode* hello = serd_node_new_string(SERD_LITERAL, "hello\"");
- assert(serd_node_length(hello) == 6 &&
- serd_node_flags(hello) == SERD_HAS_QUOTE &&
- !strcmp(serd_node_string(hello), "hello\""));
+ assert(!serd_node_new_string(NULL));
- assert(!serd_node_new_string(SERD_URI, NULL));
+ SerdNode* hello = serd_node_new_string("hello\"");
+ assert(serd_node_length(hello) == 6);
+ assert(serd_node_flags(hello) == SERD_HAS_QUOTE);
+ assert(!strncmp(serd_node_string(hello), "hello\"", 6));
serd_node_free(hello);
}
static void
test_node_from_substring(void)
{
- assert(!serd_node_new_substring(SERD_LITERAL, NULL, 32));
+ assert(!serd_node_new_substring(NULL, 32));
- SerdNode* a_b = serd_node_new_substring(SERD_LITERAL, "a\"bc", 3);
- assert(serd_node_length(a_b) == 3 &&
- serd_node_flags(a_b) == SERD_HAS_QUOTE &&
- !strncmp(serd_node_string(a_b), "a\"b", 3));
+ SerdNode* a_b = serd_node_new_substring("a\"bc", 3);
+ assert(serd_node_length(a_b) == 3);
+ assert(serd_node_flags(a_b) == SERD_HAS_QUOTE);
+ assert(strlen(serd_node_string(a_b)) == 3);
+ assert(!strncmp(serd_node_string(a_b), "a\"b", 3));
serd_node_free(a_b);
- a_b = serd_node_new_substring(SERD_LITERAL, "a\"bc", 10);
- assert(serd_node_length(a_b) == 4 &&
- serd_node_flags(a_b) == SERD_HAS_QUOTE &&
- !strncmp(serd_node_string(a_b), "a\"bc", 4));
+ a_b = serd_node_new_substring("a\"bc", 10);
+ assert(serd_node_length(a_b) == 4);
+ assert(serd_node_flags(a_b) == SERD_HAS_QUOTE);
+ assert(strlen(serd_node_string(a_b)) == 4);
+ assert(!strncmp(serd_node_string(a_b), "a\"bc", 4));
serd_node_free(a_b);
}
-static void test_literal(void)
+static void
+test_simple_node(void)
+{
+ assert(!serd_node_new_simple_node(SERD_LITERAL, "Literal", 7));
+ assert(!serd_node_new_simple_node(SERD_URI, NULL, 0));
+}
+
+static void
+test_literal(void)
{
assert(!serd_node_new_literal(NULL, NULL, NULL));
@@ -431,9 +440,7 @@ static void test_literal(void)
"en"));
serd_node_free(hello_l);
- SerdNode* eg_Thing = serd_node_new_uri_from_string(
- "http://example.org/Thing", NULL, NULL);
-
+ SerdNode* eg_Thing = serd_node_new_uri("http://example.org/Thing");
SerdNode* hello_dt = serd_node_new_literal("hello_dt\"", eg_Thing, NULL);
assert(serd_node_length(hello_dt) == 9);
assert(!strcmp(serd_node_string(hello_dt), "hello_dt\""));
@@ -447,58 +454,79 @@ static void test_literal(void)
static void
test_uri_from_string(void)
{
- assert(!serd_node_new_uri_from_string(NULL, NULL, NULL));
-
- SerdURI base_uri;
- SerdNode* base = serd_node_new_uri_from_string("http://example.org/",
- NULL, &base_uri);
- SerdNode* nil = serd_node_new_uri_from_string(NULL, &base_uri, NULL);
- SerdNode* nil2 = serd_node_new_uri_from_string("", &base_uri, NULL);
+ assert(!serd_node_new_uri(NULL));
+
+ SerdNode* base = serd_node_new_uri("http://example.org/a/b/c/");
+ SerdNode* not_a_uri = serd_node_new_string("hello");
+ SerdNode* nil = serd_node_new_resolved_uri(NULL, base);
+ SerdNode* nil2 = serd_node_new_resolved_uri("", base);
+ assert(!serd_node_new_resolved_uri("", NULL));
+ assert(!serd_node_new_resolved_uri("", not_a_uri));
assert(serd_node_type(nil) == SERD_URI);
assert(!strcmp(serd_node_string(nil), serd_node_string(base)));
assert(serd_node_type(nil2) == SERD_URI);
assert(!strcmp(serd_node_string(nil2), serd_node_string(base)));
- serd_node_free(nil);
serd_node_free(nil2);
+ serd_node_free(nil);
+ serd_node_free(not_a_uri);
serd_node_free(base);
}
static void
-test_relative_uri(void)
+check_rel_uri(const char* uri,
+ const SerdNode* base,
+ const SerdNode* root,
+ const char* expected)
{
- SerdURI base_uri;
- SerdNode* base = serd_node_new_uri_from_string("http://example.org/",
- NULL, &base_uri);
-
- SerdNode* abs = serd_node_new_string(SERD_URI, "http://example.org/foo/bar");
- SerdURI abs_uri;
- serd_uri_parse(serd_node_string(abs), &abs_uri);
-
- SerdURI rel_uri;
- SerdNode* rel = serd_node_new_relative_uri(&abs_uri, &base_uri, NULL, &rel_uri);
- assert(!strcmp(serd_node_string(rel), "/foo/bar"));
+ SerdNode* rel = serd_node_new_relative_uri(uri, base, root);
+ const int ret = strcmp(serd_node_string(rel), expected);
+ serd_node_free(rel);
+ assert(!ret);
+}
- SerdNode* up = serd_node_new_relative_uri(&base_uri, &abs_uri, NULL, NULL);
- assert(!strcmp(serd_node_string(up), "../"));
+static void
+test_relative_uri(void)
+{
+ SerdNode* root = serd_node_new_uri("http://example.org/a/b/");
+ SerdNode* base = serd_node_new_uri("http://example.org/a/b/c/");
- SerdNode* noup = serd_node_new_relative_uri(&base_uri, &abs_uri, &abs_uri, NULL);
- assert(!strcmp(serd_node_string(noup), "http://example.org/"));
+ check_rel_uri("http://example.org/a/b/c/foo", base, NULL, "foo");
+ check_rel_uri("http://example.org/a/", base, NULL, "../../");
+ check_rel_uri("http://example.org/a/", base, root, "http://example.org/a/");
+ check_rel_uri("http://example.org/", base, NULL, "../../../");
+ check_rel_uri("http://drobilla.net/a", base, NULL, "http://drobilla.net/a");
- SerdNode* x = serd_node_new_string(SERD_URI, "http://example.org/foo/x");
- SerdURI x_uri;
- serd_uri_parse(serd_node_string(x), &x_uri);
+ serd_node_free(base);
+ serd_node_free(root);
+}
- SerdNode* x_rel =
- serd_node_new_relative_uri(&x_uri, &abs_uri, &abs_uri, NULL);
- assert(!strcmp(serd_node_string(x_rel), "x"));
+static void
+test_uri_resolution(void)
+{
+ SerdNode* base = serd_node_new_uri("http://example.org/a/b/c/");
+ SerdNode* nil = serd_node_new_resolved_uri(NULL, base);
+ SerdNode* nil2 = serd_node_new_resolved_uri("", base);
+ SerdNode* not_a_uri = serd_node_new_string("hello");
+ SerdNode* root = serd_node_new_uri("http://example.org/a/b/");
+
+ assert(!serd_node_resolve(NULL, base));
+ assert(!serd_node_resolve(nil, NULL));
+ assert(!serd_node_resolve(not_a_uri, base));
+ assert(!serd_node_resolve(nil, not_a_uri));
+
+ SerdNode* rel = serd_node_new_relative_uri(
+ "http://example.org/a/b/c/foo", base, NULL);
+ SerdNode* resolved = serd_node_resolve(rel, base);
+ assert(!strcmp(serd_node_string(resolved),
+ "http://example.org/a/b/c/foo"));
- serd_node_free(x_rel);
- serd_node_free(x);
- serd_node_free(noup);
- serd_node_free(up);
- serd_node_free(abs);
+ serd_node_free(nil);
+ serd_node_free(nil2);
+ serd_node_free(not_a_uri);
+ serd_node_free(resolved);
serd_node_free(rel);
serd_node_free(base);
+ serd_node_free(root);
}
static void
@@ -526,7 +554,6 @@ test_writer(const char* const path)
SERD_TURTLE,
(SerdStyle)0,
env,
- NULL,
(SerdWriteFunc)fwrite,
fd);
assert(writer);
@@ -534,7 +561,7 @@ test_writer(const char* const path)
serd_writer_chop_blank_prefix(writer, "tmp");
serd_writer_chop_blank_prefix(writer, NULL);
- SerdNode* lit = serd_node_new_string(SERD_LITERAL, "hello");
+ SerdNode* lit = serd_node_new_string("hello");
const SerdSink* iface = serd_writer_get_sink(writer);
assert(iface->base(iface->handle, lit));
@@ -543,9 +570,9 @@ test_writer(const char* const path)
assert(serd_writer_env(writer) == env);
uint8_t buf[] = { 0xEF, 0xBF, 0xBD, 0 };
- SerdNode* s = serd_node_new_string(SERD_URI, "");
- SerdNode* p = serd_node_new_string(SERD_URI, "http://example.org/pred");
- SerdNode* o = serd_node_new_string(SERD_LITERAL, (char*)buf);
+ SerdNode* s = serd_node_new_uri("");
+ SerdNode* p = serd_node_new_uri("http://example.org/pred");
+ SerdNode* o = serd_node_new_string((char*)buf);
// Write 3 invalid statements (should write nothing)
const SerdNode* junk[][5] = { { s, p, NULL },
@@ -564,7 +591,7 @@ test_writer(const char* const path)
junk[i][0], junk[i][1], junk[i][2]));
}
- SerdNode* urn_Type = serd_node_new_uri_from_string("urn:Type", NULL, NULL);
+ SerdNode* urn_Type = serd_node_new_uri("urn:Type");
SerdNode* t = serd_node_new_literal((char*)buf, urn_Type, NULL);
SerdNode* l = serd_node_new_literal((char*)buf, NULL, "en");
@@ -585,16 +612,17 @@ test_writer(const char* const path)
// Write statements with bad UTF-8 (should be replaced)
const char bad_str[] = { (char)0xFF, (char)0x90, 'h', 'i', 0 };
- SerdNode* bad_lit = serd_node_new_string(SERD_LITERAL, bad_str);
- SerdNode* bad_uri = serd_node_new_string(SERD_URI, bad_str);
+ SerdNode* bad_lit = serd_node_new_string(bad_str);
+ SerdNode* bad_uri = serd_node_new_uri(bad_str);
assert(!iface->statement(iface->handle, 0, NULL, s, p, bad_lit));
assert(!iface->statement(iface->handle, 0, NULL, s, p, bad_uri));
- serd_node_free(bad_lit);
+
serd_node_free(bad_uri);
+ serd_node_free(bad_lit);
// Write 1 valid statement
serd_node_free(o);
- o = serd_node_new_string(SERD_LITERAL, "hello");
+ o = serd_node_new_string("hello");
assert(!iface->statement(iface->handle, 0, NULL, s, p, o));
serd_writer_free(writer);
@@ -607,9 +635,9 @@ test_writer(const char* const path)
// Test buffer sink
SerdBuffer buffer = { NULL, 0 };
writer = serd_writer_new(
- world, SERD_TURTLE, (SerdStyle)0, env, NULL, serd_buffer_sink, &buffer);
+ world, SERD_TURTLE, (SerdStyle)0, env, serd_buffer_sink, &buffer);
- o = serd_node_new_string(SERD_URI, "http://example.org/base");
+ o = serd_node_new_uri("http://example.org/base");
assert(!serd_writer_set_base_uri(writer, o));
serd_node_free(o);
@@ -633,7 +661,7 @@ test_reader(const char* path)
SerdReader* reader = serd_reader_new(world, SERD_TURTLE, &sink);
assert(reader);
- SerdNode* g = serd_node_new_string(SERD_URI, "http://example.org/");
+ SerdNode* g = serd_node_new_uri("http://example.org/");
serd_reader_set_default_graph(reader, g);
serd_reader_add_blank_prefix(reader, "tmp");
serd_reader_add_blank_prefix(reader, NULL);
@@ -706,9 +734,11 @@ main(void)
test_node_equals();
test_node_from_string();
test_node_from_substring();
+ test_simple_node();
test_literal();
test_uri_from_string();
test_relative_uri();
+ test_uri_resolution();
test_blank();
test_read_chunks();
test_read_string();