diff options
-rw-r--r-- | serd/serd.h | 102 | ||||
-rw-r--r-- | src/env.c | 41 | ||||
-rw-r--r-- | src/env.h | 24 | ||||
-rw-r--r-- | src/node.c | 154 | ||||
-rw-r--r-- | src/node.h | 1 | ||||
-rw-r--r-- | src/serdi.c | 11 | ||||
-rw-r--r-- | src/writer.c | 18 | ||||
-rw-r--r-- | tests/env_test.c | 27 | ||||
-rw-r--r-- | tests/serd_test.c | 176 |
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`. @@ -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 @@ -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; } @@ -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(); |