aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/env.c97
-rw-r--r--src/env.h14
-rw-r--r--src/node.c151
-rw-r--r--src/serdi.c25
-rw-r--r--src/writer.c42
5 files changed, 171 insertions, 158 deletions
diff --git a/src/env.c b/src/env.c
index 78680a0f..8b3970b3 100644
--- a/src/env.c
+++ b/src/env.c
@@ -3,10 +3,10 @@
#include "serd/env.h"
+#include "env.h"
#include "node.h"
#include "serd/node.h"
-#include "serd/uri.h"
#include <stdbool.h>
#include <stdio.h>
@@ -26,14 +26,11 @@ struct SerdEnvImpl {
};
SerdEnv*
-serd_env_new(const SerdNode* const base_uri)
+serd_env_new(const SerdStringView base_uri)
{
SerdEnv* env = (SerdEnv*)calloc(1, sizeof(struct SerdEnvImpl));
- if (env && base_uri) {
- if (serd_env_set_base_uri(env, base_uri)) {
- free(env);
- return NULL;
- }
+ if (env && base_uri.length) {
+ serd_env_set_base_uri(env, base_uri);
}
return env;
@@ -55,41 +52,39 @@ serd_env_free(SerdEnv* const env)
free(env);
}
-const SerdNode*
-serd_env_base_uri(const SerdEnv* const env, SerdURIView* const out)
+SerdURIView
+serd_env_base_uri_view(const SerdEnv* const env)
{
- if (out) {
- *out = env->base_uri;
- }
+ return env->base_uri;
+}
- return env->base_uri_node;
+const SerdNode*
+serd_env_base_uri(const SerdEnv* const env)
+{
+ return env ? env->base_uri_node : NULL;
}
SerdStatus
-serd_env_set_base_uri(SerdEnv* const env, const SerdNode* const uri)
+serd_env_set_base_uri(SerdEnv* const env, const SerdStringView uri)
{
- if (uri && uri->type != SERD_URI) {
- return SERD_BAD_ARG;
- }
-
- if (!uri) {
+ if (!uri.length) {
serd_node_free(env->base_uri_node);
env->base_uri_node = NULL;
env->base_uri = SERD_URI_NULL;
return SERD_SUCCESS;
}
+ SerdNode* const old_base_uri = env->base_uri_node;
+
// Resolve the new base against the current base in case it is relative
const SerdURIView new_base_uri =
- serd_resolve_uri(serd_parse_uri(serd_node_string(uri)), env->base_uri);
-
- SerdNode* const new_base_node = serd_new_parsed_uri(new_base_uri);
+ serd_resolve_uri(serd_parse_uri(uri.data), env->base_uri);
// Replace the current base URI
- serd_node_free(env->base_uri_node);
- env->base_uri_node = new_base_node;
+ env->base_uri_node = serd_new_parsed_uri(new_base_uri);
env->base_uri = serd_node_uri_view(env->base_uri_node);
+ serd_node_free(old_base_uri);
return SERD_SUCCESS;
}
@@ -110,39 +105,33 @@ serd_env_find(const SerdEnv* const env,
}
static void
-serd_env_add(SerdEnv* const env,
- const SerdNode* const name,
- const SerdNode* const uri)
+serd_env_add(SerdEnv* const env,
+ const SerdStringView name,
+ const SerdStringView uri)
{
- const char* name_str = serd_node_string(name);
- SerdPrefix* const prefix = serd_env_find(env, name_str, name->length);
+ SerdPrefix* const prefix = serd_env_find(env, name.data, name.length);
if (prefix) {
- if (!serd_node_equals(prefix->uri, uri)) {
- SerdNode* old_prefix_uri = prefix->uri;
- prefix->uri = serd_node_copy(uri);
- serd_node_free(old_prefix_uri);
+ if (!!strcmp(serd_node_string(prefix->uri), uri.data)) {
+ serd_node_free(prefix->uri);
+ prefix->uri = serd_new_uri(uri);
}
} else {
SerdPrefix* const new_prefixes = (SerdPrefix*)realloc(
env->prefixes, (++env->n_prefixes) * sizeof(SerdPrefix));
if (new_prefixes) {
env->prefixes = new_prefixes;
- env->prefixes[env->n_prefixes - 1].name = serd_node_copy(name);
- env->prefixes[env->n_prefixes - 1].uri = serd_node_copy(uri);
+ env->prefixes[env->n_prefixes - 1].name = serd_new_string(name);
+ env->prefixes[env->n_prefixes - 1].uri = serd_new_uri(uri);
}
}
}
SerdStatus
-serd_env_set_prefix(SerdEnv* const env,
- const SerdNode* const name,
- const SerdNode* const uri)
+serd_env_set_prefix(SerdEnv* const env,
+ const SerdStringView name,
+ const SerdStringView uri)
{
- if (!name || uri->type != SERD_URI) {
- return SERD_BAD_ARG;
- }
-
- if (serd_uri_string_has_scheme(serd_node_string(uri))) {
+ if (serd_uri_string_has_scheme(uri.data)) {
// Set prefix to absolute URI
serd_env_add(env, name, uri);
return SERD_SUCCESS;
@@ -153,32 +142,14 @@ serd_env_set_prefix(SerdEnv* const env,
}
// Resolve relative URI and create a new node and URI for it
- SerdNode* const abs_uri =
- serd_new_resolved_uri(serd_node_string_view(uri), env->base_uri);
+ SerdNode* const abs_uri = serd_new_resolved_uri(uri, env->base_uri);
// Set prefix to resolved (absolute) URI
- serd_env_add(env, name, abs_uri);
-
+ serd_env_add(env, name, serd_node_string_view(abs_uri));
serd_node_free(abs_uri);
-
return SERD_SUCCESS;
}
-SerdStatus
-serd_env_set_prefix_from_strings(SerdEnv* const env,
- const char* const name,
- const char* const uri)
-{
- SerdNode* name_node = serd_new_string(SERD_LITERAL, name);
- SerdNode* uri_node = serd_new_string(SERD_URI, uri);
-
- const SerdStatus st = serd_env_set_prefix(env, name_node, uri_node);
-
- serd_node_free(name_node);
- serd_node_free(uri_node);
- return st;
-}
-
bool
serd_env_qualify(const SerdEnv* const env,
const SerdNode* const uri,
diff --git a/src/env.h b/src/env.h
new file mode 100644
index 00000000..ed3fbfd9
--- /dev/null
+++ b/src/env.h
@@ -0,0 +1,14 @@
+// Copyright 2011-2020 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
+
+#ifndef SERD_SRC_ENV_H
+#define SERD_SRC_ENV_H
+
+#include "serd/attributes.h"
+#include "serd/env.h"
+#include "serd/uri.h"
+
+SERD_PURE_FUNC SerdURIView
+serd_env_base_uri_view(const SerdEnv* env);
+
+#endif // SERD_SRC_ENV_H
diff --git a/src/node.c b/src/node.c
index 8edf7fc1..43a4b502 100644
--- a/src/node.c
+++ b/src/node.c
@@ -10,7 +10,6 @@
#include "serd/attributes.h"
#include "serd/buffer.h"
#include "serd/node.h"
-#include "serd/string.h"
#include "serd/string_view.h"
#include "serd/uri.h"
@@ -36,6 +35,9 @@ static const size_t serd_node_align = 2 * sizeof(uint64_t);
static const SerdNodeFlags meta_mask = (SERD_HAS_DATATYPE | SERD_HAS_LANGUAGE);
+static SerdNode*
+serd_new_from_uri(SerdURIView uri, SerdURIView base);
+
static size_t
serd_uri_string_length(const SerdURIView* const uri)
{
@@ -124,68 +126,74 @@ serd_node_set(SerdNode** const dst, const SerdNode* const src)
}
SerdNode*
-serd_new_string(SerdNodeType type, const char* str)
+serd_new_token(const SerdNodeType type, const SerdStringView str)
{
- SerdNodeFlags flags = 0;
- const size_t length = serd_strlen(str, &flags);
+ SerdNodeFlags flags = 0U;
+ const size_t length = str.data ? str.length : 0U;
SerdNode* node = serd_node_malloc(length, flags, type);
- memcpy(serd_node_buffer(node), str, length);
- node->length = length;
+ if (node) {
+ if (str.data) {
+ memcpy(serd_node_buffer(node), str.data, length);
+ }
+
+ node->length = length;
+ }
return node;
}
SerdNode*
-serd_new_substring(const SerdNodeType type,
- const char* const str,
- const size_t len)
+serd_new_string(const SerdStringView str)
{
SerdNodeFlags flags = 0;
- const size_t length = serd_substrlen(str, len, &flags);
- SerdNode* node = serd_node_malloc(length, flags, type);
- memcpy(serd_node_buffer(node), str, length);
+ const size_t length = serd_substrlen(str.data, str.length, &flags);
+ SerdNode* node = serd_node_malloc(length, flags, SERD_LITERAL);
+
+ memcpy(serd_node_buffer(node), str.data, str.length);
node->length = length;
+
return node;
}
SerdNode*
-serd_new_literal(const char* const str,
- const char* const datatype,
- const char* const lang)
+serd_new_literal(const SerdStringView str,
+ const SerdStringView datatype_uri,
+ const SerdStringView lang)
{
SerdNodeFlags flags = 0;
- const size_t length = serd_strlen(str, &flags);
+ const size_t length = serd_substrlen(str.data, str.length, &flags);
const size_t len = serd_node_pad_size(length);
SerdNode* node = NULL;
- if (lang) {
- flags |= SERD_HAS_LANGUAGE;
- const size_t lang_len = strlen(lang);
- const size_t total_len = len + sizeof(SerdNode) + lang_len;
- node = serd_node_malloc(total_len, flags, SERD_LITERAL);
- memcpy(serd_node_buffer(node), str, length);
+ if (lang.length) {
+ const size_t total_len = len + sizeof(SerdNode) + lang.length;
+
+ node = serd_node_malloc(total_len, flags | SERD_HAS_LANGUAGE, SERD_LITERAL);
node->length = length;
+ memcpy(serd_node_buffer(node), str.data, length);
SerdNode* lang_node = node + 1 + (len / sizeof(SerdNode));
lang_node->type = SERD_LITERAL;
- lang_node->length = lang_len;
- memcpy(serd_node_buffer(lang_node), lang, lang_len);
- } else if (datatype) {
- flags |= SERD_HAS_DATATYPE;
- const size_t datatype_len = strlen(datatype);
- const size_t total_len = len + sizeof(SerdNode) + datatype_len;
- node = serd_node_malloc(total_len, flags, SERD_LITERAL);
- memcpy(serd_node_buffer(node), str, length);
+ lang_node->length = lang.length;
+ memcpy(serd_node_buffer(lang_node), lang.data, lang.length);
+
+ } else if (datatype_uri.length) {
+ const size_t total_len = len + sizeof(SerdNode) + datatype_uri.length;
+
+ node = serd_node_malloc(total_len, flags | SERD_HAS_DATATYPE, SERD_LITERAL);
node->length = length;
+ memcpy(serd_node_buffer(node), str.data, length);
SerdNode* datatype_node = node + 1 + (len / sizeof(SerdNode));
datatype_node->type = SERD_URI;
- datatype_node->length = datatype_len;
- memcpy(serd_node_buffer(datatype_node), datatype, datatype_len);
+ datatype_node->length = datatype_uri.length;
+ memcpy(
+ serd_node_buffer(datatype_node), datatype_uri.data, datatype_uri.length);
+
} else {
node = serd_node_malloc(length, flags, SERD_LITERAL);
- memcpy(serd_node_buffer(node), str, length);
+ memcpy(serd_node_buffer(node), str.data, length);
node->length = length;
}
@@ -193,6 +201,18 @@ serd_new_literal(const char* const str,
}
SerdNode*
+serd_new_blank(const SerdStringView str)
+{
+ return serd_new_token(SERD_BLANK, str);
+}
+
+SerdNode*
+serd_new_curie(const SerdStringView str)
+{
+ return serd_new_token(SERD_CURIE, str);
+}
+
+SerdNode*
serd_node_copy(const SerdNode* node)
{
if (!node) {
@@ -235,13 +255,9 @@ serd_node_equals(const SerdNode* const a, const SerdNode* const b)
}
SerdNode*
-serd_new_uri(const char* const str)
+serd_new_uri(const SerdStringView string)
{
- const size_t length = strlen(str);
- SerdNode* node = serd_node_malloc(length, 0, SERD_URI);
- memcpy(serd_node_buffer(node), str, length);
- node->length = length;
- return node;
+ return serd_new_token(SERD_URI, string);
}
SerdNode*
@@ -334,54 +350,48 @@ is_dir_sep(const char c)
}
SerdNode*
-serd_new_file_uri(const char* const path,
- const char* const hostname,
- SerdURIView* const out)
-{
- const size_t path_len = strlen(path);
- const size_t hostname_len = hostname ? strlen(hostname) : 0;
- const bool is_windows = is_windows_path(path);
- size_t uri_len = 0;
- char* uri = NULL;
-
- if (is_dir_sep(path[0]) || is_windows) {
- uri_len = strlen("file://") + hostname_len + is_windows;
+serd_new_file_uri(const SerdStringView path, const SerdStringView hostname)
+{
+ const bool is_windows = is_windows_path(path.data);
+ size_t uri_len = 0;
+ char* uri = NULL;
+
+ if (is_dir_sep(path.data[0]) || is_windows) {
+ uri_len = strlen("file://") + hostname.length + is_windows;
uri = (char*)calloc(uri_len + 1, 1);
memcpy(uri, "file://", 7);
- if (hostname) {
- memcpy(uri + 7, hostname, hostname_len + 1);
+ if (hostname.length) {
+ memcpy(uri + 7, hostname.data, hostname.length + 1);
}
if (is_windows) {
- uri[7 + hostname_len] = '/';
+ uri[7 + hostname.length] = '/';
}
}
SerdBuffer buffer = {uri, uri_len};
- for (size_t i = 0; i < path_len; ++i) {
- if (path[i] == '%') {
+ for (size_t i = 0; i < path.length; ++i) {
+ if (path.data[i] == '%') {
serd_buffer_sink("%%", 2, &buffer);
- } else if (is_uri_path_char(path[i])) {
- serd_buffer_sink(path + i, 1, &buffer);
+ } else if (is_uri_path_char(path.data[i])) {
+ serd_buffer_sink(path.data + i, 1, &buffer);
#ifdef _WIN32
- } else if (path[i] == '\\') {
+ } else if (path.data[i] == '\\') {
serd_buffer_sink("/", 1, &buffer);
#endif
} else {
char escape_str[10] = {'%', 0, 0, 0, 0, 0, 0, 0, 0, 0};
- snprintf(escape_str + 1, sizeof(escape_str) - 1, "%X", (unsigned)path[i]);
+ snprintf(
+ escape_str + 1, sizeof(escape_str) - 1, "%X", (unsigned)path.data[i]);
serd_buffer_sink(escape_str, 3, &buffer);
}
}
const size_t length = buffer.len;
const char* const string = serd_buffer_sink_finish(&buffer);
- SerdNode* const node = serd_new_substring(SERD_URI, string, length);
- if (out) {
- *out = serd_parse_uri(serd_node_buffer(node));
- }
+ SerdNode* const node = serd_new_string(serd_substring(string, length));
free(buffer.buf);
return node;
@@ -527,6 +537,13 @@ serd_node_uri_view(const SerdNode* const node)
: SERD_URI_NULL;
}
+SERD_PURE_FUNC static const SerdNode*
+serd_node_meta_node(const SerdNode* node)
+{
+ const size_t len = serd_node_pad_size(node->length);
+ return node + 1 + (len / sizeof(SerdNode));
+}
+
const SerdNode*
serd_node_datatype(const SerdNode* const node)
{
@@ -534,8 +551,7 @@ serd_node_datatype(const SerdNode* const node)
return NULL;
}
- const size_t len = serd_node_pad_size(node->length);
- const SerdNode* const datatype = node + 1 + (len / sizeof(SerdNode));
+ const SerdNode* const datatype = serd_node_meta_node(node);
assert(datatype->type == SERD_URI || datatype->type == SERD_CURIE);
return datatype;
}
@@ -547,8 +563,7 @@ serd_node_language(const SerdNode* const node)
return NULL;
}
- const size_t len = serd_node_pad_size(node->length);
- const SerdNode* const lang = node + 1 + (len / sizeof(SerdNode));
+ const SerdNode* const lang = serd_node_meta_node(node);
assert(lang->type == SERD_LITERAL);
return lang;
}
diff --git a/src/serdi.c b/src/serdi.c
index 85462532..cdd3a7b1 100644
--- a/src/serdi.c
+++ b/src/serdi.c
@@ -11,6 +11,7 @@
#include "serd/reader.h"
#include "serd/sink.h"
#include "serd/status.h"
+#include "serd/string_view.h"
#include "serd/syntax.h"
#include "serd/uri.h"
#include "serd/version.h"
@@ -331,20 +332,19 @@ main(int argc, char** argv)
const SerdWriterFlags writer_flags = choose_style(
input_syntax, output_syntax, ascii, bulk_write, full_uris, lax);
- SerdURIView base_uri = SERD_URI_NULL;
- SerdNode* base = NULL;
+ SerdNode* base = NULL;
if (a < argc) { // Base URI given on command line
- base_uri = serd_parse_uri(argv[a]);
- base = serd_new_parsed_uri(base_uri);
+ base = serd_new_uri(serd_string((const char*)argv[a]));
} else if (from_file && in_fd != stdin) { // Use input file URI
- base = serd_new_file_uri(input, NULL, &base_uri);
+ base = serd_new_file_uri(serd_string(input), serd_empty_string());
}
FILE* const out_fd = stdout;
- SerdEnv* const env = serd_env_new(base);
+ SerdEnv* const env =
+ serd_env_new(base ? serd_node_string_view(base) : serd_empty_string());
- SerdWriter* const writer = serd_writer_new(
- output_syntax, writer_flags, env, base, serd_file_sink, out_fd);
+ SerdWriter* const writer =
+ serd_writer_new(output_syntax, writer_flags, env, serd_file_sink, out_fd);
SerdReader* const reader =
serd_reader_new(input_syntax,
@@ -361,11 +361,14 @@ main(int argc, char** argv)
serd_writer_set_error_sink(writer, quiet_error_sink, NULL);
}
- SerdNode* root = root_uri ? serd_new_string(SERD_URI, root_uri) : NULL;
- serd_writer_set_root_uri(writer, root);
+ if (root_uri) {
+ SerdNode* const root = serd_new_uri(serd_string(root_uri));
+ serd_writer_set_root_uri(writer, root);
+ serd_node_free(root);
+ }
+
serd_writer_chop_blank_prefix(writer, chop_prefix);
serd_reader_add_blank_prefix(reader, add_prefix);
- serd_node_free(root);
SerdStatus st = SERD_SUCCESS;
if (!from_file) {
diff --git a/src/writer.c b/src/writer.c
index 5aad6d29..cea75aec 100644
--- a/src/writer.c
+++ b/src/writer.c
@@ -2,6 +2,7 @@
// SPDX-License-Identifier: ISC
#include "byte_sink.h"
+#include "env.h"
#include "node.h"
#include "serd_internal.h"
#include "stack.h"
@@ -759,7 +760,7 @@ write_uri_node(SerdWriter* const writer,
}
if (!has_scheme && !supports_uriref(writer) &&
- !serd_env_base_uri(writer->env, NULL)) {
+ !serd_env_base_uri(writer->env)) {
return w_err(writer,
SERD_BAD_ARG,
"syntax does not support URI reference <%s>\n",
@@ -768,14 +769,13 @@ write_uri_node(SerdWriter* const writer,
TRY(st, esink("<", 1, writer));
- SerdURIView base_uri = SERD_URI_NULL;
- if ((writer->flags & SERD_WRITE_RESOLVED) &&
- serd_env_base_uri(writer->env, &base_uri)) {
- SerdURIView uri = serd_parse_uri(node_str);
- SerdURIView abs_uri = serd_resolve_uri(uri, base_uri);
- bool rooted = uri_is_under(&base_uri, &writer->root_uri);
- const SerdURIView* root = rooted ? &writer->root_uri : &base_uri;
- UriSinkContext ctx = {writer, SERD_SUCCESS};
+ if ((writer->flags & SERD_WRITE_RESOLVED) && serd_env_base_uri(writer->env)) {
+ const SerdURIView base_uri = serd_env_base_uri_view(writer->env);
+ SerdURIView uri = serd_parse_uri(node_str);
+ SerdURIView abs_uri = serd_resolve_uri(uri, base_uri);
+ bool rooted = uri_is_under(&base_uri, &writer->root_uri);
+ const SerdURIView* root = rooted ? &writer->root_uri : &base_uri;
+ UriSinkContext ctx = {writer, SERD_SUCCESS};
if (!supports_abbrev(writer) || !uri_is_under(&abs_uri, root)) {
serd_write_uri(abs_uri, uri_sink, &ctx);
@@ -1126,7 +1126,6 @@ SerdWriter*
serd_writer_new(SerdSyntax syntax,
SerdWriterFlags flags,
SerdEnv* env,
- const SerdNode* base_uri,
SerdSink ssink,
void* stream)
{
@@ -1143,7 +1142,6 @@ serd_writer_new(SerdSyntax syntax,
writer->byte_sink = serd_byte_sink_new(
ssink, stream, (flags & SERD_WRITE_BULK) ? SERD_PAGE_SIZE : 1);
- serd_env_set_base_uri(writer->env, base_uri);
return writer;
}
@@ -1174,14 +1172,24 @@ serd_writer_chop_blank_prefix(SerdWriter* writer, const char* prefix)
SerdStatus
serd_writer_set_base_uri(SerdWriter* writer, const SerdNode* uri)
{
- SerdStatus st = SERD_SUCCESS;
+ if (uri && serd_node_type(uri) != SERD_URI) {
+ return SERD_BAD_ARG;
+ }
+
+ if (serd_node_equals(serd_env_base_uri(writer->env), uri)) {
+ return SERD_SUCCESS;
+ }
- TRY(st, serd_env_set_base_uri(writer->env, uri));
+ const SerdStringView uri_string =
+ uri ? serd_node_string_view(uri) : serd_empty_string();
+
+ SerdStatus st = SERD_SUCCESS;
+ TRY(st, serd_env_set_base_uri(writer->env, uri_string));
if (uri && (writer->syntax == SERD_TURTLE || writer->syntax == SERD_TRIG)) {
TRY(st, terminate_context(writer));
TRY(st, esink("@base <", 7, writer));
- TRY(st, esink(serd_node_string(uri), serd_node_length(uri), writer));
+ TRY(st, esink(uri_string.data, uri_string.length, writer));
TRY(st, esink(">", 1, writer));
writer->last_sep = SEP_NODE;
TRY(st, write_sep(writer, SEP_END_DIRECT));
@@ -1199,7 +1207,7 @@ serd_writer_set_root_uri(SerdWriter* writer, const SerdNode* uri)
if (uri) {
writer->root_node = serd_node_copy(uri);
- writer->root_uri = serd_parse_uri(serd_node_string(writer->root_node));
+ writer->root_uri = serd_node_uri_view(writer->root_node);
}
return SERD_SUCCESS;
@@ -1212,7 +1220,9 @@ serd_writer_set_prefix(SerdWriter* writer,
{
SerdStatus st = SERD_SUCCESS;
- TRY(st, serd_env_set_prefix(writer->env, name, uri));
+ TRY(st,
+ serd_env_set_prefix(
+ writer->env, serd_node_string_view(name), serd_node_string_view(uri)));
if (writer->syntax == SERD_TURTLE || writer->syntax == SERD_TRIG) {
TRY(st, terminate_context(writer));