From 8e04e69b5a724af9ce16c1178022afc8fdf38d69 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Fri, 11 May 2018 18:11:44 +0200 Subject: Clean up node construction API --- src/env.c | 42 ++++++++-------- src/env.h | 24 ++++++++++ src/node.c | 154 ++++++++++++++++++++++++++++++++++++----------------------- src/node.h | 1 + src/serdi.c | 11 ++--- src/writer.c | 19 +++----- 6 files changed, 152 insertions(+), 99 deletions(-) create mode 100644 src/env.h (limited to 'src') diff --git a/src/env.c b/src/env.c index bd312b9d..64a09569 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" @@ -57,13 +59,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_get_base_uri(const SerdEnv* env, - SerdURI* out) +serd_env_get_base_uri(const SerdEnv* env) { - if (out) { - *out = env->base_uri; - } return env->base_uri_node; } @@ -71,14 +75,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_get_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_get_string(base_uri_node), &base_uri); if (base_uri_node) { // Replace the current base URI @@ -137,13 +143,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_get_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; } @@ -153,8 +158,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); @@ -228,10 +233,9 @@ serd_env_expand_node(const SerdEnv* env, ret->n_bytes = len; return ret; } - 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_get_string(node), &env->base_uri); default: return NULL; } diff --git a/src/env.h b/src/env.h new file mode 100644 index 00000000..ecb6cc15 --- /dev/null +++ b/src/env.h @@ -0,0 +1,24 @@ +/* + Copyright 2011-2018 David Robillard + + 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 87dde842..d9ce6dce 100644 --- a/src/node.c +++ b/src/node.c @@ -39,6 +39,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) { @@ -90,7 +93,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; @@ -98,14 +116,14 @@ serd_node_new_string(SerdType type, const char* str) uint32_t 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; @@ -113,7 +131,7 @@ serd_node_new_substring(SerdType type, const char* str, const size_t len) uint32_t 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; @@ -169,15 +187,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* @@ -233,29 +255,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_get_string(uri_node); - return (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_get_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_get_string(node), &uri); + serd_uri_parse(serd_node_get_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 @@ -278,10 +314,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; @@ -312,18 +345,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) { @@ -338,33 +366,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_get_string(base), &base_uri); + } + if (root) { + serd_uri_parse(serd_node_get_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; } @@ -521,6 +552,15 @@ serd_node_get_length(const SerdNode* node) return node ? node->n_bytes : 0; } +static const SerdNode* +serd_node_get_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_get_datatype(const SerdNode* node) { @@ -528,11 +568,7 @@ serd_node_get_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_get_meta_node(node); assert(datatype->type == SERD_URI || datatype->type == SERD_CURIE); return datatype; } @@ -544,11 +580,7 @@ serd_node_get_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_get_meta_node(node); assert(lang->type == SERD_LITERAL); return lang; } diff --git a/src/node.h b/src/node.h index e39702a5..1dbb10d0 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 6a1c6d29..2627f572 100644 --- a/src/serdi.c +++ b/src/serdi.c @@ -223,13 +223,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; @@ -260,7 +258,6 @@ main(int argc, char** argv) output_syntax, (SerdStyle)output_style, env, - &base_uri, (SerdWriteFunc)fwrite, out_fd); @@ -272,7 +269,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 2273b415..1b50a254 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" @@ -101,7 +102,6 @@ struct SerdWriterImpl { SerdEnv* env; SerdNode* root_node; SerdURI root_uri; - SerdURI base_uri; SerdStack anon_stack; SerdByteSink byte_sink; SerdErrorSink error_sink; @@ -526,19 +526,18 @@ write_uri_node(SerdWriter* const writer, write_sep(writer, SEP_URI_BEGIN); if (writer->style & SERD_STYLE_RESOLVED) { - SerdURI in_base_uri, uri, abs_uri; - serd_env_get_base_uri(writer->env, &in_base_uri); + const SerdURI* base_uri = serd_env_get_parsed_base_uri(writer->env); + SerdURI uri, abs_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); @@ -865,7 +864,6 @@ serd_writer_new(SerdWorld* world, SerdSyntax syntax, SerdStyle style, SerdEnv* env, - const SerdURI* base_uri, SerdWriteFunc ssink, void* stream) { @@ -877,7 +875,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; @@ -913,8 +910,6 @@ serd_writer_set_base_uri(SerdWriter* writer, const SerdNode* uri) { if (!serd_env_set_base_uri(writer->env, uri)) { - serd_env_get_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); -- cgit v1.2.1