diff options
author | David Robillard <d@drobilla.net> | 2018-04-29 18:29:03 +0200 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2023-12-02 16:27:02 -0500 |
commit | 5c02da92038072f28408854e862fc2d4edf765d4 (patch) | |
tree | 34577415801279981b626b18c1dc69dc79afea7f /src | |
parent | 672e90382da08efa8f593fdc9081e31d0e548fa0 (diff) | |
download | serd-5c02da92038072f28408854e862fc2d4edf765d4.tar.gz serd-5c02da92038072f28408854e862fc2d4edf765d4.tar.bz2 serd-5c02da92038072f28408854e862fc2d4edf765d4.zip |
Simplify node construction API
Diffstat (limited to 'src')
-rw-r--r-- | src/env.c | 97 | ||||
-rw-r--r-- | src/env.h | 14 | ||||
-rw-r--r-- | src/node.c | 151 | ||||
-rw-r--r-- | src/serdi.c | 25 | ||||
-rw-r--r-- | src/writer.c | 42 |
5 files changed, 171 insertions, 158 deletions
@@ -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 @@ -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)); |