diff options
author | David Robillard <d@drobilla.net> | 2018-02-04 15:33:36 +0100 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2023-12-02 16:27:02 -0500 |
commit | c644f404054e6d68f3bb645cf93b8ad1501b8938 (patch) | |
tree | 6291623c37dd9ef6be062113bf6ac5afa8115171 | |
parent | b0d4ae792c88cc55f9cc9a579530a1a13a158fda (diff) | |
download | serd-c644f404054e6d68f3bb645cf93b8ad1501b8938.tar.gz serd-c644f404054e6d68f3bb645cf93b8ad1501b8938.tar.bz2 serd-c644f404054e6d68f3bb645cf93b8ad1501b8938.zip |
Make nodes opaque
-rw-r--r-- | .clang-format | 5 | ||||
-rw-r--r-- | NEWS | 1 | ||||
-rw-r--r-- | doc/conf.py.in | 1 | ||||
-rw-r--r-- | include/serd/env.h | 20 | ||||
-rw-r--r-- | include/serd/node.h | 133 | ||||
-rw-r--r-- | include/serd/reader.h | 3 | ||||
-rw-r--r-- | include/serd/status.h | 3 | ||||
-rw-r--r-- | include/serd/uri.h | 3 | ||||
-rw-r--r-- | include/serd/writer.h | 16 | ||||
-rw-r--r-- | src/byte_source.h | 2 | ||||
-rw-r--r-- | src/env.c | 125 | ||||
-rw-r--r-- | src/n3.c | 35 | ||||
-rw-r--r-- | src/node.c | 184 | ||||
-rw-r--r-- | src/node.h | 12 | ||||
-rw-r--r-- | src/reader.c | 42 | ||||
-rw-r--r-- | src/reader.h | 9 | ||||
-rw-r--r-- | src/serdi.c | 13 | ||||
-rw-r--r-- | src/writer.c | 256 | ||||
-rw-r--r-- | test/headers/test_headers.c | 3 | ||||
-rw-r--r-- | test/test_env.c | 80 | ||||
-rw-r--r-- | test/test_node.c | 93 | ||||
-rw-r--r-- | test/test_reader_writer.c | 107 | ||||
-rw-r--r-- | test/test_uri.c | 53 | ||||
-rw-r--r-- | test/test_writer.c | 48 |
24 files changed, 651 insertions, 596 deletions
diff --git a/.clang-format b/.clang-format index 0a3ac765..fabbc837 100644 --- a/.clang-format +++ b/.clang-format @@ -25,12 +25,15 @@ AttributeMacros: - SERD_ALLOCATED - SERD_ALWAYS_INLINE_FUNC - SERD_API - - SERD_CONST_FINC + - SERD_CONST_API + - SERD_CONST_FUNC - SERD_FALLTHROUGH - SERD_MALLOC_FUNC - SERD_NODISCARD - SERD_NONNULL - SERD_NULLABLE + - SERD_PURE_API + - SERD_PURE_FUNC - SERD_PURE_FUNC StatementMacros: - SERD_LOG_FUNC @@ -1,6 +1,7 @@ serd (1.1.1) unstable; urgency=medium * Add SerdBuffer for mutable buffers to keep SerdChunk const-correct + * Make nodes opaque * Remove SERD_DISABLE_DEPRECATED and SERD_DEPRECATED_BY * Remove serd_uri_to_path() * Remove support for reading Turtle named inline nodes extension diff --git a/doc/conf.py.in b/doc/conf.py.in index 5037d217..8f99424c 100644 --- a/doc/conf.py.in +++ b/doc/conf.py.in @@ -28,6 +28,7 @@ except ModuleNotFoundError: _opaque = [ "FILE", "SerdEnvImpl", + "SerdNodeImpl", "SerdReaderImpl", "SerdWriterImpl", "int64_t", diff --git a/include/serd/env.h b/include/serd/env.h index 3d4cafd0..7a03e80d 100644 --- a/include/serd/env.h +++ b/include/serd/env.h @@ -33,7 +33,7 @@ SERD_API void serd_env_free(SerdEnv* SERD_NULLABLE env); /// Get the current base URI -SERD_API const SerdNode* SERD_NONNULL +SERD_API const SerdNode* SERD_NULLABLE serd_env_base_uri(const SerdEnv* SERD_NONNULL env, SerdURIView* SERD_NULLABLE out); @@ -62,10 +62,10 @@ serd_env_set_prefix_from_strings(SerdEnv* SERD_NONNULL env, /// Qualify `uri` into a CURIE if possible SERD_API bool -serd_env_qualify(const SerdEnv* SERD_NULLABLE env, - const SerdNode* SERD_NONNULL uri, - SerdNode* SERD_NONNULL prefix, - SerdStringView* SERD_NONNULL suffix); +serd_env_qualify(const SerdEnv* SERD_NULLABLE env, + const SerdNode* SERD_NONNULL uri, + const SerdNode* SERD_NULLABLE* SERD_NONNULL prefix, + SerdStringView* SERD_NONNULL suffix); /** Expand `curie`. @@ -74,17 +74,17 @@ serd_env_qualify(const SerdEnv* SERD_NULLABLE env, not defined in `env`. */ SERD_API SerdStatus -serd_env_expand(const SerdEnv* SERD_NULLABLE env, - const SerdNode* SERD_NONNULL curie, - SerdStringView* SERD_NONNULL uri_prefix, - SerdStringView* SERD_NONNULL uri_suffix); +serd_env_expand(const SerdEnv* SERD_NULLABLE env, + const SerdNode* SERD_NULLABLE curie, + SerdStringView* SERD_NONNULL uri_prefix, + SerdStringView* SERD_NONNULL uri_suffix); /** Expand `node`, which must be a CURIE or URI, to a full URI. Returns null if `node` can not be expanded. */ -SERD_API SerdNode +SERD_API SerdNode* SERD_ALLOCATED serd_env_expand_node(const SerdEnv* SERD_NULLABLE env, const SerdNode* SERD_NONNULL node); diff --git a/include/serd/node.h b/include/serd/node.h index 73be120e..eb4f8c9e 100644 --- a/include/serd/node.h +++ b/include/serd/node.h @@ -20,24 +20,26 @@ SERD_BEGIN_DECLS */ /** - Type of a node. + @defgroup serd_node_types Types + @{ +*/ - An RDF node, in the abstract sense, can be either a resource, literal, or a - blank. This type is more precise, because syntactically there are two ways - to refer to a resource (by URI or CURIE). +/** + An RDF node. - There are also two ways to refer to a blank node in syntax (by ID or - anonymously), but this is handled by statement flags rather than distinct - node types. + A node in memory is a single contiguous chunk of data, but the + representation is opaque and may only be accessed through the API. */ -typedef enum { - /** - The type of a nonexistent node. +typedef struct SerdNodeImpl SerdNode; - This type is useful as a sentinel, but is never emitted by the reader. - */ - SERD_NOTHING = 0, +/** + Type of a node. + An abstract RDF node can be either a resource or a literal. This type is + more precise to preserve syntactic differences and support additional + features. +*/ +typedef enum { /** Literal value. @@ -88,39 +90,30 @@ typedef enum { /// Bitwise OR of #SerdNodeFlag values typedef uint32_t SerdNodeFlags; -/// A syntactic RDF node -typedef struct { - const char* SERD_NULLABLE buf; ///< Value string - size_t n_bytes; ///< Size in bytes (excluding null) - SerdNodeFlags flags; ///< Node flags (string properties) - SerdNodeType type; ///< Node type -} SerdNode; - -static const SerdNode SERD_NODE_NULL = {NULL, 0, 0, SERD_NOTHING}; - /** - Make a (shallow) node from `str`. - - This measures, but does not copy, `str`. No memory is allocated. + @} + @defgroup serd_node_dynamic_allocation Dynamic Allocation + @{ */ -SERD_API SerdNode -serd_node_from_string(SerdNodeType type, const char* SERD_NULLABLE str); /** - Make a (shallow) node from a prefix of `str`. + Create a new node from `str`. +*/ +SERD_API SerdNode* SERD_ALLOCATED +serd_new_string(SerdNodeType type, const char* SERD_NULLABLE str); - This measures, but does not copy, `str`. No memory is allocated. - Note that the returned node may not be null terminated. +/** + Create a new node from a prefix of `str`. */ -SERD_API SerdNode -serd_node_from_substring(SerdNodeType type, - const char* SERD_NULLABLE str, - size_t len); +SERD_API SerdNode* SERD_ALLOCATED +serd_new_substring(SerdNodeType type, + const char* SERD_NULLABLE str, + size_t len); /** Create a new URI node from a node. */ -SERD_API SerdNode +SERD_API SerdNode* SERD_ALLOCATED serd_new_uri_from_node(const SerdNode* SERD_NONNULL uri_node, const SerdURIView* SERD_NULLABLE base, SerdURIView* SERD_NULLABLE out); @@ -128,7 +121,7 @@ serd_new_uri_from_node(const SerdNode* SERD_NONNULL uri_node, /** Create a new URI node from a string. */ -SERD_API SerdNode +SERD_API SerdNode* SERD_ALLOCATED serd_new_uri_from_string(const char* SERD_NULLABLE str, const SerdURIView* SERD_NULLABLE base, SerdURIView* SERD_NULLABLE out); @@ -142,7 +135,7 @@ serd_new_uri_from_string(const char* SERD_NULLABLE str, If `path` is relative, `hostname` is ignored. If `out` is not NULL, it will be set to the parsed URI. */ -SERD_API SerdNode +SERD_API SerdNode* SERD_ALLOCATED serd_new_file_uri(const char* SERD_NONNULL path, const char* SERD_NULLABLE hostname, SerdURIView* SERD_NULLABLE out); @@ -157,7 +150,7 @@ serd_new_file_uri(const char* SERD_NONNULL path, @param out Set to the parsing of the new URI (i.e. points only to memory owned by the new returned node). */ -SERD_API SerdNode +SERD_API SerdNode* SERD_ALLOCATED serd_new_uri(const SerdURIView* SERD_NONNULL uri, const SerdURIView* SERD_NULLABLE base, SerdURIView* SERD_NULLABLE out); @@ -174,7 +167,7 @@ serd_new_uri(const SerdURIView* SERD_NONNULL uri, @param out Set to the parsing of the new URI (i.e. points only to memory owned by the new returned node). */ -SERD_API SerdNode +SERD_API SerdNode* SERD_ALLOCATED serd_new_relative_uri(const SerdURIView* SERD_NONNULL uri, const SerdURIView* SERD_NULLABLE base, const SerdURIView* SERD_NULLABLE root, @@ -195,11 +188,11 @@ serd_new_relative_uri(const SerdURIView* SERD_NONNULL uri, @param d The value for the new node. @param frac_digits The maximum number of digits after the decimal place. */ -SERD_API SerdNode +SERD_API SerdNode* SERD_ALLOCATED serd_new_decimal(double d, unsigned frac_digits); /// Create a new node by serialising `i` into an xsd:integer string -SERD_API SerdNode +SERD_API SerdNode* SERD_ALLOCATED serd_new_integer(int64_t i); /** @@ -212,54 +205,62 @@ serd_new_integer(int64_t i); @param size Size of `buf`. @param wrap_lines Wrap lines at 76 characters to conform to RFC 2045. */ -SERD_API SerdNode +SERD_API SerdNode* SERD_ALLOCATED serd_new_blob(const void* SERD_NONNULL buf, size_t size, bool wrap_lines); +/// Return a deep copy of `node` +SERD_API SerdNode* SERD_ALLOCATED +serd_node_copy(const SerdNode* SERD_NULLABLE node); + /** - Make a deep copy of `node`. + Free any data owned by `node`. +*/ +SERD_API void +serd_node_free(SerdNode* SERD_NULLABLE node); - @return a node that the caller must free with serd_node_free(). +/** + @} + @defgroup serd_node_accessors Accessors + @{ */ -SERD_API SerdNode -serd_node_copy(const SerdNode* SERD_NULLABLE node); /// Return the type of a node -SERD_PURE_API -SerdNodeType +SERD_PURE_API SerdNodeType serd_node_type(const SerdNode* SERD_NONNULL node); /// Return the length of a node's string in bytes, excluding the terminator -SERD_PURE_API -size_t -serd_node_length(const SerdNode* SERD_NONNULL node); +SERD_PURE_API size_t +serd_node_length(const SerdNode* SERD_NULLABLE node); /// Return the additional flags of a node -SERD_PURE_API -SerdNodeFlags +SERD_PURE_API SerdNodeFlags serd_node_flags(const SerdNode* SERD_NONNULL node); /// Return the string contents of a node -SERD_PURE_API -const char* SERD_NONNULL +SERD_CONST_API const char* SERD_NONNULL serd_node_string(const SerdNode* SERD_NONNULL node); -/// Return true iff `a` is equal to `b` -SERD_PURE_API -bool -serd_node_equals(const SerdNode* SERD_NONNULL a, - const SerdNode* SERD_NONNULL b); +/** + @} + @defgroup serd_node_operators Operators + @{ +*/ /** - Free any data owned by `node`. + Return true iff `a` is equal to `b`. - Note that if `node` is itself dynamically allocated (which is not the case - for nodes created internally by serd), it will not be freed. + For convenience, either argument may be null, which isn't considered equal + to any node. + + @return True if `a` and `b` point to equal nodes, or are both null. */ -SERD_API void -serd_node_free(SerdNode* SERD_NULLABLE node); +SERD_PURE_API bool +serd_node_equals(const SerdNode* SERD_NULLABLE a, + const SerdNode* SERD_NULLABLE b); /** @} + @} */ SERD_END_DECLS diff --git a/include/serd/reader.h b/include/serd/reader.h index 1d9e9a6b..e4bd9b2f 100644 --- a/include/serd/reader.h +++ b/include/serd/reader.h @@ -59,8 +59,7 @@ serd_reader_set_error_sink(SerdReader* SERD_NONNULL reader, void* SERD_NULLABLE error_handle); /// Return the `handle` passed to serd_reader_new() -SERD_PURE_API -void* SERD_NULLABLE +SERD_PURE_API void* SERD_NULLABLE serd_reader_handle(const SerdReader* SERD_NONNULL reader); /** diff --git a/include/serd/status.h b/include/serd/status.h index 5de96d1d..3ebdaf8f 100644 --- a/include/serd/status.h +++ b/include/serd/status.h @@ -40,8 +40,7 @@ typedef enum { } SerdStatus; /// Return a string describing a status code -SERD_CONST_API -const char* SERD_NONNULL +SERD_CONST_API const char* SERD_NONNULL serd_strerror(SerdStatus status); /** diff --git a/include/serd/uri.h b/include/serd/uri.h index fc41c0c2..06cb97fb 100644 --- a/include/serd/uri.h +++ b/include/serd/uri.h @@ -53,8 +53,7 @@ serd_file_uri_parse(const char* SERD_NONNULL uri, char* SERD_NONNULL* SERD_NULLABLE hostname); /// Return true iff `utf8` starts with a valid URI scheme -SERD_PURE_API -bool +SERD_PURE_API bool serd_uri_string_has_scheme(const char* SERD_NULLABLE utf8); /// Parse `utf8`, writing result to `out` diff --git a/include/serd/writer.h b/include/serd/writer.h index 35f44940..66c3d338 100644 --- a/include/serd/writer.h +++ b/include/serd/writer.h @@ -12,7 +12,6 @@ #include "serd/status.h" #include "serd/stream.h" #include "serd/syntax.h" -#include "serd/uri.h" #include <stddef.h> #include <stdint.h> @@ -49,20 +48,19 @@ typedef uint32_t SerdWriterFlags; /// Create a new RDF writer SERD_API SerdWriter* SERD_ALLOCATED -serd_writer_new(SerdSyntax syntax, - SerdWriterFlags flags, - SerdEnv* SERD_NONNULL env, - const SerdURIView* SERD_NULLABLE base_uri, - SerdSink SERD_NONNULL ssink, - void* SERD_NULLABLE stream); +serd_writer_new(SerdSyntax syntax, + SerdWriterFlags flags, + SerdEnv* SERD_NONNULL env, + const SerdNode* SERD_NULLABLE base_uri, + SerdSink SERD_NONNULL ssink, + void* SERD_NULLABLE stream); /// Free `writer` SERD_API void serd_writer_free(SerdWriter* SERD_NULLABLE writer); /// Return the env used by `writer` -SERD_PURE_API -SerdEnv* SERD_NONNULL +SERD_PURE_API SerdEnv* SERD_NONNULL serd_writer_env(SerdWriter* SERD_NONNULL writer); /** diff --git a/src/byte_source.h b/src/byte_source.h index 46e1f874..e8ddb98a 100644 --- a/src/byte_source.h +++ b/src/byte_source.h @@ -59,7 +59,7 @@ serd_byte_source_prepare(SerdByteSource* source); SerdStatus serd_byte_source_page(SerdByteSource* source); -static inline SERD_PURE_FUNC uint8_t +SERD_PURE_FUNC static inline uint8_t serd_byte_source_peek(SerdByteSource* source) { assert(source->prepared); @@ -3,20 +3,24 @@ #include "serd/env.h" +#include "node.h" + +#include "serd/node.h" + #include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct { - SerdNode name; - SerdNode uri; + SerdNode* name; + SerdNode* uri; } SerdPrefix; struct SerdEnvImpl { SerdPrefix* prefixes; size_t n_prefixes; - SerdNode base_uri_node; + SerdNode* base_uri_node; SerdURIView base_uri; }; @@ -24,7 +28,7 @@ SerdEnv* serd_env_new(const SerdNode* const base_uri) { SerdEnv* env = (SerdEnv*)calloc(1, sizeof(struct SerdEnvImpl)); - if (env && base_uri && base_uri->type != SERD_NOTHING) { + if (env && base_uri) { if (serd_env_set_base_uri(env, base_uri)) { free(env); return NULL; @@ -42,12 +46,11 @@ serd_env_free(SerdEnv* const env) } for (size_t i = 0; i < env->n_prefixes; ++i) { - serd_node_free(&env->prefixes[i].name); - serd_node_free(&env->prefixes[i].uri); + serd_node_free(env->prefixes[i].name); + serd_node_free(env->prefixes[i].uri); } - free(env->prefixes); - serd_node_free(&env->base_uri_node); + serd_node_free(env->base_uri_node); free(env); } @@ -58,7 +61,7 @@ serd_env_base_uri(const SerdEnv* const env, SerdURIView* const out) *out = env->base_uri; } - return &env->base_uri_node; + return env->base_uri_node; } SerdStatus @@ -68,20 +71,20 @@ serd_env_set_base_uri(SerdEnv* const env, const SerdNode* const uri) return SERD_BAD_ARG; } - if (!uri || !uri->buf) { - serd_node_free(&env->base_uri_node); - env->base_uri_node = SERD_NODE_NULL; + if (!uri) { + serd_node_free(env->base_uri_node); + env->base_uri_node = NULL; env->base_uri = SERD_URI_NULL; return SERD_SUCCESS; } // Resolve base URI and create a new node and URI for it SerdURIView base_uri; - SerdNode base_uri_node = + SerdNode* base_uri_node = serd_new_uri_from_node(uri, &env->base_uri, &base_uri); // Replace the current base URI - serd_node_free(&env->base_uri_node); + serd_node_free(env->base_uri_node); env->base_uri_node = base_uri_node; env->base_uri = base_uri; @@ -94,14 +97,13 @@ serd_env_find(const SerdEnv* const env, const size_t name_len) { for (size_t i = 0; i < env->n_prefixes; ++i) { - const SerdNode* const prefix_name = &env->prefixes[i].name; - if (prefix_name->n_bytes == name_len) { - if (!memcmp(prefix_name->buf, name, name_len)) { + const SerdNode* const prefix_name = env->prefixes[i].name; + if (prefix_name->length == name_len) { + if (!memcmp(serd_node_string(prefix_name), name, name_len)) { return &env->prefixes[i]; } } } - return NULL; } @@ -110,12 +112,13 @@ serd_env_add(SerdEnv* const env, const SerdNode* const name, const SerdNode* const uri) { - SerdPrefix* const prefix = serd_env_find(env, name->buf, name->n_bytes); + const char* name_str = serd_node_string(name); + SerdPrefix* const prefix = serd_env_find(env, name_str, 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 (!serd_node_equals(prefix->uri, uri)) { + SerdNode* old_prefix_uri = prefix->uri; + prefix->uri = serd_node_copy(uri); + serd_node_free(old_prefix_uri); } } else { SerdPrefix* const new_prefixes = (SerdPrefix*)realloc( @@ -133,22 +136,22 @@ serd_env_set_prefix(SerdEnv* const env, const SerdNode* const name, const SerdNode* const uri) { - if (!name->buf || uri->type != SERD_URI) { + if (!name || uri->type != SERD_URI) { return SERD_BAD_ARG; } - if (serd_uri_string_has_scheme(uri->buf)) { + if (serd_uri_string_has_scheme(serd_node_string(uri))) { // Set prefix to absolute URI serd_env_add(env, name, uri); } else { // Resolve relative URI and create a new node and URI for it SerdURIView abs_uri; - SerdNode abs_uri_node = + SerdNode* abs_uri_node = serd_new_uri_from_node(uri, &env->base_uri, &abs_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_node); + serd_node_free(abs_uri_node); } return SERD_SUCCESS; @@ -159,29 +162,36 @@ serd_env_set_prefix_from_strings(SerdEnv* const env, const char* const name, const char* const uri) { - const SerdNode name_node = serd_node_from_string(SERD_LITERAL, name); - const SerdNode uri_node = serd_node_from_string(SERD_URI, 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); - return 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, - SerdNode* const prefix, - SerdStringView* const suffix) +serd_env_qualify(const SerdEnv* const env, + const SerdNode* const uri, + const SerdNode** const prefix, + SerdStringView* const suffix) { if (!env) { return false; } for (size_t i = 0; i < env->n_prefixes; ++i) { - const SerdNode* const prefix_uri = &env->prefixes[i].uri; - if (uri->n_bytes >= prefix_uri->n_bytes) { - if (!strncmp(uri->buf, prefix_uri->buf, prefix_uri->n_bytes)) { + const SerdNode* const prefix_uri = env->prefixes[i].uri; + if (uri->length >= prefix_uri->length) { + const char* prefix_str = serd_node_string(prefix_uri); + const char* uri_str = serd_node_string(uri); + + if (!strncmp(uri_str, prefix_str, prefix_uri->length)) { *prefix = env->prefixes[i].name; - suffix->data = uri->buf + prefix_uri->n_bytes; - suffix->length = uri->n_bytes - prefix_uri->n_bytes; + suffix->data = uri_str + prefix_uri->length; + suffix->length = uri->length - prefix_uri->length; return true; } } @@ -195,37 +205,36 @@ serd_env_expand(const SerdEnv* const env, SerdStringView* const uri_prefix, SerdStringView* const uri_suffix) { - if (!env) { + if (!env || !curie) { return SERD_BAD_CURIE; } - const char* const colon = - (const char*)memchr(curie->buf, ':', curie->n_bytes + 1); + const char* const str = serd_node_string(curie); + const char* const colon = (const char*)memchr(str, ':', curie->length + 1); if (curie->type != SERD_CURIE || !colon) { return SERD_BAD_ARG; } - const size_t name_len = (size_t)(colon - curie->buf); - const SerdPrefix* const prefix = serd_env_find(env, curie->buf, name_len); + const size_t name_len = (size_t)(colon - str); + const SerdPrefix* const prefix = serd_env_find(env, str, name_len); if (prefix) { - uri_prefix->data = prefix->uri.buf; - uri_prefix->length = prefix->uri.n_bytes; + uri_prefix->data = serd_node_string(prefix->uri); + uri_prefix->length = prefix->uri ? prefix->uri->length : 0; uri_suffix->data = colon + 1; - uri_suffix->length = curie->n_bytes - name_len - 1; + uri_suffix->length = curie->length - name_len - 1; return SERD_SUCCESS; } return SERD_BAD_CURIE; } -SerdNode +SerdNode* serd_env_expand_node(const SerdEnv* const env, const SerdNode* const node) { if (!env) { - return SERD_NODE_NULL; + return NULL; } switch (node->type) { - case SERD_NOTHING: case SERD_LITERAL: break; case SERD_URI: { @@ -236,18 +245,20 @@ serd_env_expand_node(const SerdEnv* const env, const SerdNode* const node) SerdStringView prefix; SerdStringView suffix; if (serd_env_expand(env, node, &prefix, &suffix)) { - return SERD_NODE_NULL; + return NULL; } const size_t len = prefix.length + suffix.length; - char* buf = (char*)malloc(len + 1); - SerdNode ret = {buf, len, 0, SERD_URI}; - snprintf(buf, ret.n_bytes + 1, "%s%s", prefix.data, suffix.data); + SerdNode* ret = serd_node_malloc(len, 0, SERD_URI); + char* buf = serd_node_buffer(ret); + + snprintf(buf, len + 1, "%s%s", prefix.data, suffix.data); + ret->length = len; return ret; } case SERD_BLANK: break; } - return SERD_NODE_NULL; + return NULL; } void @@ -256,6 +267,6 @@ serd_env_foreach(const SerdEnv* const env, void* const handle) { for (size_t i = 0; i < env->n_prefixes; ++i) { - func(handle, &env->prefixes[i].name, &env->prefixes[i].uri); + func(handle, env->prefixes[i].name, env->prefixes[i].uri); } } @@ -1,6 +1,7 @@ // Copyright 2011-2023 David Robillard <d@drobilla.net> // SPDX-License-Identifier: ISC +#include "node.h" #include "reader.h" #include "serd_internal.h" #include "stack.h" @@ -626,7 +627,7 @@ read_PN_LOCAL(SerdReader* const reader, const Ref dest, bool* const ate_dot) SerdNode* const n = deref(reader, dest); if (trailing_unescaped_dot) { // Ate trailing dot, pop it from stack/node and inform caller - --n->n_bytes; + --n->length; serd_stack_pop(&reader->stack, 1); *ate_dot = true; } @@ -648,7 +649,8 @@ read_PN_PREFIX_tail(SerdReader* const reader, const Ref dest) } const SerdNode* const n = deref(reader, dest); - if (n->buf[n->n_bytes - 1] == '.' && read_PN_CHARS(reader, dest)) { + if (serd_node_string(n)[serd_node_length(n) - 1] == '.' && + read_PN_CHARS(reader, dest)) { return r_err(reader, SERD_BAD_SYNTAX, "prefix ends with '.'\n"); } @@ -977,8 +979,8 @@ read_verb(SerdReader* const reader, Ref* const dest) bool ate_dot = false; SerdNode* node = deref(reader, *dest); const int next = peek_byte(reader); - if (!st && node->n_bytes == 1 && node->buf[0] == 'a' && next != ':' && - !is_PN_CHARS_BASE((uint32_t)next)) { + if (!st && node->length == 1 && serd_node_string(node)[0] == 'a' && + next != ':' && !is_PN_CHARS_BASE((uint32_t)next)) { pop_node(reader, *dest); *dest = push_node(reader, SERD_URI, NS_RDF "type", 47); return SERD_SUCCESS; @@ -1025,20 +1027,21 @@ read_BLANK_NODE_LABEL(SerdReader* const reader, } } - SerdNode* n = deref(reader, ref); - if (n->buf[n->n_bytes - 1] == '.' && read_PN_CHARS(reader, ref)) { + SerdNode* n = deref(reader, ref); + char* buf = serd_node_buffer(n); + if (buf[n->length - 1] == '.' && read_PN_CHARS(reader, ref)) { // Ate trailing dot, pop it from stack/node and inform caller - --n->n_bytes; + --n->length; serd_stack_pop(&reader->stack, 1); *ate_dot = true; } if (fancy_syntax(reader)) { - if (is_digit(n->buf[reader->bprefix_len + 1])) { - if ((n->buf[reader->bprefix_len]) == 'b') { - ((char*)n->buf)[reader->bprefix_len] = 'B'; // Prevent clash - reader->seen_genid = true; - } else if (reader->seen_genid && n->buf[reader->bprefix_len] == 'B') { + if (is_digit(buf[reader->bprefix_len + 1])) { + if ((buf[reader->bprefix_len]) == 'b') { + buf[reader->bprefix_len] = 'B'; // Prevent clash + reader->seen_genid = true; + } else if (reader->seen_genid && buf[reader->bprefix_len] == 'B') { *dest = pop_node(reader, *dest); return r_err(reader, SERD_BAD_LABEL, @@ -1186,8 +1189,8 @@ read_object(SerdReader* const reader, while (!read_PN_CHARS_BASE(reader, o)) { } node = deref(reader, o); - if ((node->n_bytes == 4 && !memcmp(node->buf, "true", 4)) || - (node->n_bytes == 5 && !memcmp(node->buf, "false", 5))) { + if ((node->length == 4 && !memcmp(serd_node_string(node), "true", 4)) || + (node->length == 5 && !memcmp(serd_node_string(node), "false", 5))) { node->type = SERD_LITERAL; datatype = push_node(reader, SERD_URI, XSD_BOOLEAN, XSD_BOOLEAN_LEN); st = SERD_SUCCESS; @@ -1570,11 +1573,11 @@ tokcmp(SerdReader* const reader, const size_t n) { SerdNode* node = deref(reader, ref); - if (!node || node->n_bytes != n) { + if (!node || node->length != n) { return -1; } - return serd_strncasecmp(node->buf, tok, n); + return serd_strncasecmp(serd_node_string(node), tok, n); } SerdStatus @@ -11,6 +11,7 @@ #include "serd/string.h" #include "serd/uri.h" +#include <assert.h> #include <float.h> #include <math.h> #include <stdbool.h> @@ -56,45 +57,67 @@ string_sink(const void* const buf, const size_t len, void* const stream) return len; } -SerdNode -serd_node_from_string(const SerdNodeType type, const char* const str) +SerdNode* +serd_node_malloc(const size_t length, + const SerdNodeFlags flags, + const SerdNodeType type) { - if (!str) { - return SERD_NODE_NULL; - } + SerdNode* node = (SerdNode*)calloc(1, sizeof(SerdNode) + length + 1); + + node->length = 0; + node->flags = flags; + node->type = type; - SerdNodeFlags flags = 0; - const size_t n_bytes = serd_strlen(str, &flags); - const SerdNode ret = {str, n_bytes, flags, type}; - return ret; + return node; } -SerdNode -serd_node_from_substring(const SerdNodeType type, - const char* const str, - const size_t len) +void +serd_node_set(SerdNode** const dst, const SerdNode* const src) { - if (!str) { - return SERD_NODE_NULL; + assert(dst); + assert(src); + + if (!*dst || (*dst)->length < src->length) { + (*dst) = (SerdNode*)realloc(*dst, sizeof(SerdNode) + src->length + 1); } - SerdNodeFlags flags = 0; - const size_t n_bytes = serd_substrlen(str, len, &flags); - const SerdNode ret = {str, n_bytes, flags, type}; - return ret; + memcpy(*dst, src, sizeof(SerdNode) + src->length + 1); +} + +SerdNode* +serd_new_string(SerdNodeType type, const char* str) +{ + SerdNodeFlags flags = 0; + const size_t length = serd_strlen(str, &flags); + SerdNode* node = serd_node_malloc(length, flags, type); + memcpy(serd_node_buffer(node), str, length); + node->length = length; + return node; +} + +SerdNode* +serd_new_substring(const SerdNodeType type, + const char* const str, + const size_t len) +{ + 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); + node->length = length; + return node; } -SerdNode -serd_node_copy(const SerdNode* const node) +SerdNode* +serd_node_copy(const SerdNode* node) { - if (!node || !node->buf) { - return SERD_NODE_NULL; + if (!node) { + return NULL; } - SerdNode copy = *node; - char* buf = (char*)malloc(copy.n_bytes + 1); - memcpy(buf, node->buf, copy.n_bytes + 1); - copy.buf = buf; + const size_t size = sizeof(SerdNode) + node->length + 1; + SerdNode* copy = (SerdNode*)malloc(size); + memcpy(copy, node, size); return copy; } @@ -102,28 +125,29 @@ bool serd_node_equals(const SerdNode* const a, const SerdNode* const b) { return (a == b) || - (a->type == b->type && a->n_bytes == b->n_bytes && - ((a->buf == b->buf) || !memcmp(a->buf, b->buf, a->n_bytes + 1))); + (a && b && a->type == b->type && a->length == b->length && + !memcmp(serd_node_string(a), serd_node_string(b), a->length)); } -SerdNode +SerdNode* serd_new_uri_from_node(const SerdNode* const uri_node, const SerdURIView* const base, SerdURIView* const out) { - return (uri_node->type == SERD_URI && uri_node->buf) - ? serd_new_uri_from_string(uri_node->buf, base, out) - : SERD_NODE_NULL; + const char* uri_str = serd_node_string(uri_node); + return (uri_node && uri_node->type == SERD_URI && uri_str) + ? serd_new_uri_from_string(uri_str, base, out) + : NULL; } -SerdNode +SerdNode* serd_new_uri_from_string(const char* const str, const SerdURIView* const base, SerdURIView* const out) { if (!str || str[0] == '\0') { // Empty URI => Base URI, or nothing if no base is given - return base ? serd_new_uri(base, NULL, out) : SERD_NODE_NULL; + return base ? serd_new_uri(base, NULL, out) : NULL; } SerdURIView uri; @@ -177,7 +201,7 @@ is_dir_sep(const char c) #endif } -SerdNode +SerdNode* serd_new_file_uri(const char* const path, const char* const hostname, SerdURIView* const out) @@ -220,15 +244,18 @@ serd_new_file_uri(const char* const path, } } + const size_t length = buffer.len; const char* const string = serd_buffer_sink_finish(&buffer); - if (string && out) { - serd_uri_parse(string, out); + SerdNode* const node = serd_new_substring(SERD_URI, string, length); + if (out) { + serd_uri_parse(serd_node_buffer(node), out); } - return serd_node_from_substring(SERD_URI, string, buffer.len); + free(buffer.buf); + return node; } -SerdNode +SerdNode* serd_new_uri(const SerdURIView* const uri, const SerdURIView* const base, SerdURIView* const out) @@ -239,22 +266,21 @@ serd_new_uri(const SerdURIView* const uri, } const size_t len = serd_uri_string_length(&abs_uri); - char* buf = (char*)malloc(len + 1); - SerdNode node = {buf, len, 0, SERD_URI}; - char* ptr = buf; + SerdNode* node = serd_node_malloc(len, 0, SERD_URI); + char* ptr = serd_node_buffer(node); const size_t actual_len = serd_uri_serialise(&abs_uri, string_sink, &ptr); - buf[actual_len] = '\0'; - node.n_bytes = actual_len; + serd_node_buffer(node)[actual_len] = '\0'; + node->length = actual_len; if (out) { - serd_uri_parse(buf, out); // TODO: cleverly avoid double parse + serd_uri_parse(serd_node_buffer(node), out); // TODO: avoid double parse } return node; } -SerdNode +SerdNode* serd_new_relative_uri(const SerdURIView* const uri, const SerdURIView* const base, const SerdURIView* const root, @@ -262,17 +288,16 @@ serd_new_relative_uri(const SerdURIView* const uri, { const size_t uri_len = serd_uri_string_length(uri); const size_t base_len = serd_uri_string_length(base); - char* buf = (char*)malloc(uri_len + base_len + 1); - SerdNode node = {buf, 0, 0, SERD_URI}; - char* ptr = buf; + 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); - buf[actual_len] = '\0'; - node.n_bytes = actual_len; + serd_node_buffer(node)[actual_len] = '\0'; + node->length = actual_len; if (out) { - serd_uri_parse(buf, out); // TODO: cleverly avoid double parse + serd_uri_parse(serd_node_buffer(node), out); // TODO: avoid double parse } return node; @@ -285,18 +310,19 @@ serd_digits(const double abs) return lg < 1.0 ? 1U : (unsigned)lg; } -SerdNode +SerdNode* serd_new_decimal(const double d, const unsigned frac_digits) { if (isnan(d) || isinf(d)) { - return SERD_NODE_NULL; + return NULL; } - const double abs_d = fabs(d); - const unsigned int_digits = serd_digits(abs_d); - char* buf = (char*)calloc(int_digits + frac_digits + 3, 1); - SerdNode node = {buf, 0, 0, SERD_LITERAL}; - const double int_part = floor(abs_d); + const double abs_d = fabs(d); + const unsigned int_digits = serd_digits(abs_d); + const size_t len = int_digits + frac_digits + 3; + SerdNode* const node = serd_node_malloc(len, 0, SERD_LITERAL); + char* const buf = serd_node_buffer(node); + const double int_part = floor(abs_d); // Point s to decimal point location char* s = buf + int_digits; @@ -318,7 +344,7 @@ serd_new_decimal(const double d, const unsigned frac_digits) double frac_part = fabs(d - int_part); if (frac_part < DBL_EPSILON) { *s++ = '0'; - node.n_bytes = (size_t)(s - buf); + node->length = (size_t)(s - buf); } else { uint64_t frac = (uint64_t)llround(frac_part * pow(10.0, (int)frac_digits)); s += frac_digits - 1; @@ -328,7 +354,7 @@ serd_new_decimal(const double d, const unsigned frac_digits) for (; i < frac_digits - 1 && !(frac % 10); ++i, --s, frac /= 10) { } - node.n_bytes = (size_t)(s - buf) + 1U; + node->length = (size_t)(s - buf) + 1U; // Write digits from last trailing zero to decimal point for (; i < frac_digits; ++i) { @@ -340,13 +366,13 @@ serd_new_decimal(const double d, const unsigned frac_digits) return node; } -SerdNode +SerdNode* serd_new_integer(const int64_t i) { uint64_t abs_i = (uint64_t)((i < 0) ? -i : i); const unsigned digits = serd_digits((double)abs_i); - char* buf = (char*)calloc(digits + 2, 1); - SerdNode node = {(const char*)buf, 0, 0, SERD_LITERAL}; + SerdNode* node = serd_node_malloc(digits + 2, 0, SERD_LITERAL); + char* buf = serd_node_buffer(node); // Point s to the end char* s = buf + digits - 1; @@ -355,7 +381,7 @@ serd_new_integer(const int64_t i) ++s; } - node.n_bytes = (size_t)(s - buf) + 1U; + node->length = (size_t)(s - buf) + 1U; // Write integer part (right to left) do { @@ -365,17 +391,22 @@ serd_new_integer(const int64_t i) return node; } -SerdNode +SerdNode* serd_new_blob(const void* const buf, const size_t size, const bool wrap_lines) { - const size_t len = serd_base64_get_length(size, wrap_lines); - char* const str = (char*)calloc(len + 2, 1); - SerdNode node = {str, len, 0, SERD_LITERAL}; + if (!buf || !size) { + return NULL; + } - if (serd_base64_encode((uint8_t*)str, buf, size, wrap_lines)) { - node.flags |= SERD_HAS_NEWLINE; + const size_t len = serd_base64_get_length(size, wrap_lines); + SerdNode* const node = serd_node_malloc(len + 1, 0, SERD_LITERAL); + uint8_t* const str = (uint8_t*)serd_node_buffer(node); + + if (serd_base64_encode(str, buf, size, wrap_lines)) { + node->flags |= SERD_HAS_NEWLINE; } + node->length = len; return node; } @@ -388,13 +419,13 @@ serd_node_type(const SerdNode* const node) const char* serd_node_string(const SerdNode* const node) { - return node->buf; + return (const char*)(node + 1); } size_t serd_node_length(const SerdNode* const node) { - return node->n_bytes; + return node->length; } SerdNodeFlags @@ -406,8 +437,5 @@ serd_node_flags(const SerdNode* const node) void serd_node_free(SerdNode* const node) { - if (node && node->buf) { - free((char*)node->buf); - node->buf = NULL; - } + free(node); } @@ -10,9 +10,9 @@ #include <stddef.h> struct SerdNodeImpl { - size_t n_bytes; /**< Size in bytes (not including null) */ - SerdNodeFlags flags; /**< Node flags (e.g. string properties) */ - SerdNodeType type; /**< Node type */ + size_t length; ///< Length in bytes (not including null) + SerdNodeFlags flags; ///< Node flags + SerdNodeType type; ///< Node type }; static inline char* SERD_NONNULL @@ -28,10 +28,10 @@ serd_node_buffer_c(const SerdNode* SERD_NONNULL node) } SerdNode* SERD_ALLOCATED -serd_node_malloc(size_t n_bytes, SerdNodeFlags flags, SerdNodeType type); +serd_node_malloc(size_t length, SerdNodeFlags flags, SerdNodeType type); void -serd_node_set(SerdNode* SERD_NULLABLE* SERD_NONNULL dst, - const SerdNode* SERD_NULLABLE src); +serd_node_set(SerdNode* SERD_NONNULL* SERD_NONNULL dst, + const SerdNode* SERD_NONNULL src); #endif // SERD_SRC_NODE_H diff --git a/src/reader.c b/src/reader.c index 6e520208..9a9fe744 100644 --- a/src/reader.c +++ b/src/reader.c @@ -4,6 +4,7 @@ #include "reader.h" #include "byte_source.h" +#include "node.h" #include "stack.h" #include "system.h" @@ -36,9 +37,11 @@ void set_blank_id(SerdReader* const reader, const Ref ref, const size_t buf_size) { SerdNode* node = deref(reader, ref); + char* buf = (char*)(node + 1); const char* prefix = reader->bprefix ? (const char*)reader->bprefix : ""; - node->n_bytes = (size_t)snprintf( - (char*)node->buf, buf_size, "%sb%u", prefix, reader->next_id++); + + node->length = + (size_t)snprintf(buf, buf_size, "%sb%u", prefix, reader->next_id++); } size_t @@ -79,19 +82,19 @@ push_node_padded(SerdReader* const reader, const size_t maxlen, const SerdNodeType type, const char* const str, - const size_t n_bytes) + const size_t length) { void* mem = serd_stack_push_aligned( &reader->stack, sizeof(SerdNode) + maxlen + 1, sizeof(SerdNode)); SerdNode* const node = (SerdNode*)mem; - node->n_bytes = n_bytes; - node->flags = 0; - node->type = type; - node->buf = NULL; + + node->length = length; + node->flags = 0; + node->type = type; char* buf = (char*)(node + 1); - memcpy(buf, str, n_bytes + 1); + memcpy(buf, str, length + 1); #ifdef SERD_STACK_CHECK reader->allocs = (Ref*)realloc(reader->allocs, @@ -105,20 +108,15 @@ Ref push_node(SerdReader* const reader, const SerdNodeType type, const char* const str, - const size_t n_bytes) + const size_t length) { - return push_node_padded(reader, n_bytes, type, str, n_bytes); + return push_node_padded(reader, length, type, str, length); } -SerdNode* +SERD_PURE_FUNC SerdNode* deref(SerdReader* const reader, const Ref ref) { - if (ref) { - SerdNode* node = (SerdNode*)(reader->stack.buf + ref); - node->buf = (char*)node + sizeof(SerdNode); - return node; - } - return NULL; + return ref ? (SerdNode*)(reader->stack.buf + ref) : NULL; } Ref @@ -145,8 +143,8 @@ emit_statement(SerdReader* const reader, const Ref l) { SerdNode* graph = deref(reader, ctx.graph); - if (!graph && reader->default_graph.buf) { - graph = &reader->default_graph; + if (!graph && reader->default_graph) { + graph = reader->default_graph; } const SerdStatus st = !reader->statement_func @@ -187,7 +185,7 @@ serd_reader_new(const SerdSyntax syntax, me->prefix_func = prefix_func; me->statement_func = statement_func; me->end_func = end_func; - me->default_graph = SERD_NODE_NULL; + me->default_graph = NULL; me->stack = serd_stack_new(SERD_PAGE_SIZE); me->syntax = syntax; me->next_id = 1; @@ -225,7 +223,7 @@ serd_reader_free(SerdReader* const reader) pop_node(reader, reader->rdf_nil); pop_node(reader, reader->rdf_rest); pop_node(reader, reader->rdf_first); - serd_node_free(&reader->default_graph); + serd_node_free(reader->default_graph); #ifdef SERD_STACK_CHECK free(reader->allocs); @@ -263,7 +261,7 @@ void serd_reader_set_default_graph(SerdReader* const reader, const SerdNode* const graph) { - serd_node_free(&reader->default_graph); + serd_node_free(reader->default_graph); reader->default_graph = serd_node_copy(graph); } diff --git a/src/reader.h b/src/reader.h index 1dcf926f..a528fcc8 100644 --- a/src/reader.h +++ b/src/reader.h @@ -5,6 +5,7 @@ #define SERD_SRC_READER_H #include "byte_source.h" +#include "node.h" #include "stack.h" #include "serd/attributes.h" @@ -55,7 +56,7 @@ struct SerdReaderImpl { Ref rdf_first; Ref rdf_rest; Ref rdf_nil; - SerdNode default_graph; + SerdNode* default_graph; SerdByteSource source; SerdStack stack; SerdSyntax syntax; @@ -80,13 +81,13 @@ push_node_padded(SerdReader* reader, size_t maxlen, SerdNodeType type, const char* str, - size_t n_bytes); + size_t length); Ref push_node(SerdReader* reader, SerdNodeType type, const char* str, - size_t n_bytes); + size_t length); SERD_PURE_FUNC size_t genid_size(const SerdReader* reader); @@ -181,7 +182,7 @@ push_byte(SerdReader* reader, Ref ref, const int c) *(s - 1) = (char)c; *s = '\0'; - ++node->n_bytes; + ++node->length; return SERD_SUCCESS; } diff --git a/src/serdi.c b/src/serdi.c index 81ca35c5..afae904c 100644 --- a/src/serdi.c +++ b/src/serdi.c @@ -332,7 +332,7 @@ main(int argc, char** argv) input_syntax, output_syntax, ascii, bulk_write, full_uris, lax); SerdURIView base_uri = SERD_URI_NULL; - SerdNode base = SERD_NODE_NULL; + SerdNode* base = NULL; if (a < argc) { // Base URI given on command line base = serd_new_uri_from_string((const char*)argv[a], NULL, &base_uri); } else if (from_file && in_fd != stdin) { // Use input file URI @@ -340,10 +340,10 @@ main(int argc, char** argv) } FILE* const out_fd = stdout; - SerdEnv* const env = serd_env_new(&base); + SerdEnv* const env = serd_env_new(base); SerdWriter* const writer = serd_writer_new( - output_syntax, writer_flags, env, &base_uri, serd_file_sink, out_fd); + output_syntax, writer_flags, env, base, serd_file_sink, out_fd); SerdReader* const reader = serd_reader_new(input_syntax, @@ -360,10 +360,11 @@ main(int argc, char** argv) serd_writer_set_error_sink(writer, quiet_error_sink, NULL); } - SerdNode root = serd_node_from_string(SERD_URI, root_uri); - serd_writer_set_root_uri(writer, &root); + SerdNode* root = root_uri ? serd_new_string(SERD_URI, root_uri) : NULL; + serd_writer_set_root_uri(writer, 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) { @@ -382,7 +383,7 @@ main(int argc, char** argv) serd_writer_finish(writer); serd_writer_free(writer); serd_env_free(env); - serd_node_free(&base); + serd_node_free(base); free(input_path); if (from_file) { diff --git a/src/writer.c b/src/writer.c index a177f4f3..2372f712 100644 --- a/src/writer.c +++ b/src/writer.c @@ -2,6 +2,7 @@ // SPDX-License-Identifier: ISC #include "byte_sink.h" +#include "node.h" #include "serd_internal.h" #include "stack.h" #include "string_utils.h" @@ -45,19 +46,15 @@ typedef enum { typedef struct { ContextType type; - SerdNode graph; - SerdNode subject; - SerdNode predicate; + SerdNode* graph; + SerdNode* subject; + SerdNode* predicate; bool predicates; bool comma_indented; } WriteContext; -static const WriteContext WRITE_CONTEXT_NULL = {CTX_NAMED, - {0, 0, 0, SERD_NOTHING}, - {0, 0, 0, SERD_NOTHING}, - {0, 0, 0, SERD_NOTHING}, - 0U, - 0U}; +static const WriteContext WRITE_CONTEXT_NULL = + {CTX_NAMED, NULL, NULL, NULL, 0U, 0U}; typedef enum { SEP_NONE, ///< Sentinel before the start of a document @@ -127,9 +124,8 @@ struct SerdWriterImpl { SerdSyntax syntax; SerdWriterFlags flags; SerdEnv* env; - SerdNode root_node; + SerdNode* root_node; SerdURIView root_uri; - SerdURIView base_uri; SerdStack anon_stack; SerdByteSink byte_sink; SerdErrorFunc error_func; @@ -167,12 +163,12 @@ supports_uriref(const SerdWriter* writer) static SerdStatus free_context(WriteContext* const ctx) { - serd_node_free(&ctx->graph); - serd_node_free(&ctx->subject); - serd_node_free(&ctx->predicate); - ctx->graph.type = SERD_NOTHING; - ctx->subject.type = SERD_NOTHING; - ctx->predicate.type = SERD_NOTHING; + serd_node_free(ctx->graph); + serd_node_free(ctx->subject); + serd_node_free(ctx->predicate); + ctx->graph = NULL; + ctx->subject = NULL; + ctx->predicate = NULL; return SERD_SUCCESS; } @@ -194,34 +190,38 @@ w_err(SerdWriter* writer, SerdStatus st, const char* fmt, ...) return st; } -static void -copy_node(SerdNode* dst, const SerdNode* src) +static inline SerdNode* +ctx(SerdWriter* writer, const Field field) { - const size_t new_size = src->n_bytes + 1U; - char* const new_buf = (char*)realloc((char*)dst->buf, new_size); - if (new_buf) { - dst->buf = new_buf; - dst->n_bytes = src->n_bytes; - dst->flags = src->flags; - dst->type = src->type; - memcpy(new_buf, src->buf, new_size); - } + SerdNode* node = (field == FIELD_SUBJECT) ? writer->context.subject + : (field == FIELD_PREDICATE) ? writer->context.predicate + : (field == FIELD_GRAPH) ? writer->context.graph + : NULL; + + return node && node->type ? node : NULL; } static void -push_context(SerdWriter* const writer, - const ContextType type, - const SerdNode graph, - const SerdNode subject, - const SerdNode predicate) +push_context(SerdWriter* const writer, + const ContextType type, + const SerdNode* const graph, + const SerdNode* const subject, + const SerdNode* const predicate) { // Push the current context to the stack void* const top = serd_stack_push(&writer->anon_stack, sizeof(WriteContext)); *(WriteContext*)top = writer->context; // Update the current context - const WriteContext current = {type, graph, subject, predicate, 0U, 0U}; - writer->context = current; + + const WriteContext current = {type, + serd_node_copy(graph), + serd_node_copy(subject), + serd_node_copy(predicate), + 0U, + 0U}; + + writer->context = current; } static void @@ -373,7 +373,7 @@ ewrite_uri(SerdWriter* writer, const char* utf8, size_t n_bytes) SERD_NODISCARD static SerdStatus write_uri_from_node(SerdWriter* writer, const SerdNode* node) { - return ewrite_uri(writer, node->buf, node->n_bytes); + return ewrite_uri(writer, serd_node_string(node), serd_node_length(node)); } static bool @@ -619,7 +619,7 @@ write_sep(SerdWriter* writer, const Sep sep) // Reset context and write a blank line after ends of subjects if (sep == SEP_END_S) { - writer->indent = writer->context.graph.type ? 1 : 0; + writer->indent = ctx(writer, FIELD_GRAPH) ? 1 : 0; writer->context.predicates = false; writer->context.comma_indented = false; TRY(st, esink("\n", 1, writer)); @@ -642,8 +642,18 @@ reset_context(SerdWriter* writer, const unsigned flags) { free_anon_stack(writer); + if (writer->context.predicate) { + memset(writer->context.predicate, 0, sizeof(SerdNode)); + } + + if (writer->context.subject) { + memset(writer->context.subject, 0, sizeof(SerdNode)); + } + if (flags & RESET_GRAPH) { - writer->context.graph.type = SERD_NOTHING; + if (writer->context.graph) { + memset(writer->context.graph, 0, sizeof(SerdNode)); + } } if (flags & RESET_INDENT) { @@ -651,8 +661,6 @@ reset_context(SerdWriter* writer, const unsigned flags) } writer->context.type = CTX_NAMED; - writer->context.subject.type = SERD_NOTHING; - writer->context.predicate.type = SERD_NOTHING; writer->context.predicates = false; writer->context.comma_indented = false; return SERD_SUCCESS; @@ -665,41 +673,42 @@ write_literal(SerdWriter* writer, const SerdNode* lang, SerdStatementFlags flags) { - SerdStatus st = SERD_SUCCESS; + SerdStatus st = SERD_SUCCESS; + const char* const node_str = serd_node_string(node); + const char* const type_uri = datatype ? serd_node_string(datatype) : NULL; - if (supports_abbrev(writer) && datatype && datatype->buf) { - const char* type_uri = datatype->buf; + if (supports_abbrev(writer) && type_uri) { if (!strncmp(type_uri, NS_XSD, sizeof(NS_XSD) - 1) && (!strcmp(type_uri + sizeof(NS_XSD) - 1, "boolean") || !strcmp(type_uri + sizeof(NS_XSD) - 1, "integer"))) { - return esink(node->buf, node->n_bytes, writer); + return esink(node_str, node->length, writer); } if (!strncmp(type_uri, NS_XSD, sizeof(NS_XSD) - 1) && !strcmp(type_uri + sizeof(NS_XSD) - 1, "decimal") && - strchr(node->buf, '.') && node->buf[node->n_bytes - 1] != '.') { + strchr(node_str, '.') && node_str[node->length - 1] != '.') { /* xsd:decimal literals without trailing digits, e.g. "5.", can not be written bare in Turtle. We could add a 0 which is prettier, but changes the text and breaks round tripping. */ - return esink(node->buf, node->n_bytes, writer); + return esink(node_str, node->length, writer); } } if (supports_abbrev(writer) && (node->flags & (SERD_HAS_NEWLINE | SERD_HAS_QUOTE))) { TRY(st, esink("\"\"\"", 3, writer)); - TRY(st, write_text(writer, WRITE_LONG_STRING, node->buf, node->n_bytes)); + TRY(st, write_text(writer, WRITE_LONG_STRING, node_str, node->length)); TRY(st, esink("\"\"\"", 3, writer)); } else { TRY(st, esink("\"", 1, writer)); - TRY(st, write_text(writer, WRITE_STRING, node->buf, node->n_bytes)); + TRY(st, write_text(writer, WRITE_STRING, node_str, node->length)); TRY(st, esink("\"", 1, writer)); } - if (lang && lang->buf) { + if (lang && serd_node_string(lang)) { TRY(st, esink("@", 1, writer)); - TRY(st, esink(lang->buf, lang->n_bytes, writer)); - } else if (datatype && datatype->buf) { + TRY(st, esink(serd_node_string(lang), lang->length, writer)); + } else if (type_uri) { TRY(st, esink("^^", 2, writer)); return write_node(writer, datatype, NULL, NULL, FIELD_NONE, flags); } @@ -726,36 +735,37 @@ write_uri_node(SerdWriter* const writer, const SerdNode* node, const Field field) { - SerdStatus st = SERD_SUCCESS; - SerdNode prefix; - SerdStringView suffix; + SerdStatus st = SERD_SUCCESS; + const SerdNode* prefix = NULL; + SerdStringView suffix = {NULL, 0}; + const char* const node_str = serd_node_string(node); + const bool has_scheme = serd_uri_string_has_scheme(node_str); - const bool has_scheme = serd_uri_string_has_scheme(node->buf); if (supports_abbrev(writer)) { - if (field == FIELD_PREDICATE && !strcmp(node->buf, NS_RDF "type")) { + if (field == FIELD_PREDICATE && !strcmp(node_str, NS_RDF "type")) { return esink("a", 1, writer); } - if (!strcmp(node->buf, NS_RDF "nil")) { + if (!strcmp(node_str, NS_RDF "nil")) { return esink("()", 2, writer); } if (has_scheme && (writer->flags & SERD_WRITE_CURIED) && serd_env_qualify(writer->env, node, &prefix, &suffix) && - is_name(prefix.buf, prefix.n_bytes) && + is_name(serd_node_string(prefix), serd_node_length(prefix)) && is_name(suffix.data, suffix.length)) { - TRY(st, write_uri_from_node(writer, &prefix)); + TRY(st, write_uri_from_node(writer, prefix)); TRY(st, esink(":", 1, writer)); return ewrite_uri(writer, suffix.data, suffix.length); } } if (!has_scheme && !supports_uriref(writer) && - !serd_env_base_uri(writer->env, NULL)->buf) { + !serd_env_base_uri(writer->env, NULL)) { return w_err(writer, SERD_BAD_ARG, "syntax does not support URI reference <%s>\n", - node->buf); + node_str); } TRY(st, esink("<", 1, writer)); @@ -765,17 +775,16 @@ write_uri_node(SerdWriter* const writer, SerdURIView uri; SerdURIView abs_uri; serd_env_base_uri(writer->env, &in_base_uri); - serd_uri_parse(node->buf, &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); - SerdURIView* root = rooted ? &writer->root_uri : &writer->base_uri; + bool rooted = uri_is_under(&in_base_uri, &writer->root_uri); + SerdURIView* root = rooted ? &writer->root_uri : &in_base_uri; UriSinkContext ctx = {writer, SERD_SUCCESS}; if (!uri_is_under(&abs_uri, root) || writer->syntax == SERD_NTRIPLES || writer->syntax == SERD_NQUADS) { serd_uri_serialise(&abs_uri, uri_sink, &ctx); } else { - serd_uri_serialise_relative( - &uri, &writer->base_uri, root, uri_sink, &ctx); + serd_uri_serialise_relative(&uri, &in_base_uri, root, uri_sink, &ctx); } } else { TRY(st, write_uri_from_node(writer, node)); @@ -787,9 +796,10 @@ write_uri_node(SerdWriter* const writer, SERD_NODISCARD static SerdStatus write_curie(SerdWriter* const writer, const SerdNode* const node) { - SerdStringView prefix = {NULL, 0}; - SerdStringView suffix = {NULL, 0}; - SerdStatus st = SERD_SUCCESS; + const char* const node_str = serd_node_string(node); + SerdStringView prefix = {NULL, 0}; + SerdStringView suffix = {NULL, 0}; + SerdStatus st = SERD_SUCCESS; // In fast-and-loose Turtle/TriG mode CURIEs are simply passed through const bool fast = @@ -797,7 +807,7 @@ write_curie(SerdWriter* const writer, const SerdNode* const node) if (!supports_abbrev(writer) || !fast) { if ((st = serd_env_expand(writer->env, node, &prefix, &suffix))) { - return w_err(writer, st, "undefined namespace prefix '%s'\n", node->buf); + return w_err(writer, st, "undefined namespace prefix '%s'\n", node_str); } } @@ -807,7 +817,7 @@ write_curie(SerdWriter* const writer, const SerdNode* const node) TRY(st, ewrite_uri(writer, suffix.data, suffix.length)); TRY(st, esink(">", 1, writer)); } else { - TRY(st, write_lname(writer, node->buf, node->n_bytes)); + TRY(st, write_lname(writer, node_str, node->length)); } return st; @@ -819,7 +829,8 @@ write_blank(SerdWriter* const writer, const Field field, const SerdStatementFlags flags) { - SerdStatus st = SERD_SUCCESS; + SerdStatus st = SERD_SUCCESS; + const char* const node_str = serd_node_string(node); if (supports_abbrev(writer)) { if ((field == FIELD_SUBJECT && (flags & SERD_ANON_S_BEGIN)) || @@ -840,13 +851,13 @@ write_blank(SerdWriter* const writer, TRY(st, esink("_:", 2, writer)); if (writer->bprefix && - !strncmp(node->buf, writer->bprefix, writer->bprefix_len)) { + !strncmp(node_str, writer->bprefix, writer->bprefix_len)) { TRY(st, - esink(node->buf + writer->bprefix_len, - node->n_bytes - writer->bprefix_len, + esink(node_str + writer->bprefix_len, + node->length - writer->bprefix_len, writer)); } else { - TRY(st, esink(node->buf, node->n_bytes, writer)); + TRY(st, esink(node_str, node->length, writer)); } return st; @@ -863,8 +874,6 @@ write_node(SerdWriter* writer, SerdStatus st = SERD_SUCCESS; switch (node->type) { - case SERD_NOTHING: - break; case SERD_LITERAL: st = write_literal(writer, node, datatype, lang, flags); break; @@ -889,7 +898,7 @@ write_node(SerdWriter* writer, static bool is_resource(const SerdNode* node) { - return node && node->buf && node->type > SERD_LITERAL; + return node && node->type > SERD_LITERAL; } SERD_NODISCARD static SerdStatus @@ -900,7 +909,7 @@ write_pred(SerdWriter* writer, SerdStatementFlags flags, const SerdNode* pred) TRY(st, write_node(writer, pred, NULL, NULL, FIELD_PREDICATE, flags)); TRY(st, write_sep(writer, SEP_P_O)); - copy_node(&writer->context.predicate, pred); + serd_node_set(&writer->context.predicate, pred); writer->context.predicates = true; writer->context.comma_indented = false; return st; @@ -916,12 +925,12 @@ write_list_next(SerdWriter* writer, { SerdStatus st = SERD_SUCCESS; - if (!strcmp(object->buf, NS_RDF "nil")) { + if (!strcmp(serd_node_string(object), NS_RDF "nil")) { TRY(st, write_sep(writer, SEP_LIST_END)); return SERD_FAILURE; } - if (!strcmp(predicate->buf, NS_RDF "first")) { + if (!strcmp(serd_node_string(predicate), NS_RDF "first")) { TRY(st, write_node(writer, object, datatype, lang, FIELD_OBJECT, flags)); } else { TRY(st, write_sep(writer, SEP_LIST_SEP)); @@ -930,16 +939,16 @@ write_list_next(SerdWriter* writer, return st; } -SERD_NODISCARD static SerdStatus +static SerdStatus terminate_context(SerdWriter* writer) { SerdStatus st = SERD_SUCCESS; - if (writer->context.subject.type) { + if (writer->context.subject && writer->context.subject->type) { TRY(st, write_sep(writer, SEP_END_S)); } - if (writer->context.graph.type) { + if (writer->context.graph && writer->context.graph->type) { TRY(st, write_sep(writer, SEP_GRAPH_END)); } @@ -958,8 +967,7 @@ serd_writer_write_statement(SerdWriter* writer, { SerdStatus st = SERD_SUCCESS; - if (!is_resource(subject) || !is_resource(predicate) || !object || - !object->buf) { + if (!is_resource(subject) || !is_resource(predicate) || !object) { return SERD_BAD_ARG; } @@ -979,22 +987,22 @@ serd_writer_write_statement(SerdWriter* writer, } // Separate graphs if necessary - if ((graph && !serd_node_equals(graph, &writer->context.graph)) || - (!graph && writer->context.graph.type)) { + if ((graph && !serd_node_equals(graph, writer->context.graph)) || + (!graph && ctx(writer, FIELD_GRAPH))) { TRY(st, terminate_context(writer)); reset_context(writer, RESET_GRAPH | RESET_INDENT); if (graph) { TRY(st, write_newline(writer)); TRY(st, write_node(writer, graph, datatype, lang, FIELD_GRAPH, flags)); TRY(st, write_sep(writer, SEP_GRAPH_BEGIN)); - copy_node(&writer->context.graph, graph); + serd_node_set(&writer->context.graph, graph); } } if ((flags & SERD_LIST_CONT)) { // Continue a list - if (!strcmp((const char*)predicate->buf, NS_RDF "first") && - !strcmp((const char*)object->buf, NS_RDF "nil")) { + if (!strcmp(serd_node_string(predicate), NS_RDF "first") && + !strcmp(serd_node_string(object), NS_RDF "nil")) { return esink("()", 2, writer); } @@ -1006,8 +1014,8 @@ serd_writer_write_statement(SerdWriter* writer, return SERD_SUCCESS; } - } else if (serd_node_equals(subject, &writer->context.subject)) { - if (serd_node_equals(predicate, &writer->context.predicate)) { + } else if (serd_node_equals(subject, writer->context.subject)) { + if (serd_node_equals(predicate, writer->context.predicate)) { // Elide S P (write O) const Sep last = writer->last_sep; @@ -1029,7 +1037,7 @@ serd_writer_write_statement(SerdWriter* writer, writer->context.comma_indented = false; } - const bool first = !writer->context.predicate.type; + const bool first = !ctx(writer, FIELD_PREDICATE); TRY(st, write_sep(writer, first ? SEP_S_P : SEP_END_P)); TRY(st, write_pred(writer, flags, predicate)); } @@ -1039,7 +1047,7 @@ serd_writer_write_statement(SerdWriter* writer, } else { // No abbreviation if (serd_stack_is_empty(&writer->anon_stack)) { - if (writer->context.subject.type) { + if (ctx(writer, FIELD_SUBJECT)) { TRY(st, write_sep(writer, SEP_END_S)); } @@ -1059,7 +1067,7 @@ serd_writer_write_statement(SerdWriter* writer, } reset_context(writer, 0U); - copy_node(&writer->context.subject, subject); + serd_node_set(&writer->context.subject, subject); if (!(flags & SERD_LIST_S_BEGIN)) { TRY(st, write_pred(writer, flags, predicate)); @@ -1073,18 +1081,18 @@ serd_writer_write_statement(SerdWriter* writer, const bool is_list = (flags & SERD_LIST_S_BEGIN); push_context(writer, is_list ? CTX_LIST : CTX_BLANK, - serd_node_copy(graph), - serd_node_copy(subject), - is_list ? SERD_NODE_NULL : serd_node_copy(predicate)); + graph, + subject, + is_list ? NULL : predicate); } if (flags & (SERD_ANON_O_BEGIN | SERD_LIST_O_BEGIN)) { // Push context for anonymous or list object if necessary push_context(writer, (flags & SERD_LIST_O_BEGIN) ? CTX_LIST : CTX_BLANK, - serd_node_copy(graph), - serd_node_copy(object), - SERD_NODE_NULL); + graph, + object, + NULL); } return st; @@ -1107,9 +1115,10 @@ serd_writer_end_anon(SerdWriter* writer, const SerdNode* node) TRY(st, write_sep(writer, SEP_ANON_END)); pop_context(writer); - if (serd_node_equals(node, &writer->context.subject)) { + if (writer->context.predicate && + serd_node_equals(node, writer->context.subject)) { // Now-finished anonymous node is the new subject with no other context - writer->context.predicate.type = SERD_NOTHING; + memset(writer->context.predicate, 0, sizeof(SerdNode)); } return st; @@ -1126,12 +1135,12 @@ serd_writer_finish(SerdWriter* writer) } SerdWriter* -serd_writer_new(SerdSyntax syntax, - SerdWriterFlags flags, - SerdEnv* env, - const SerdURIView* base_uri, - SerdSink ssink, - void* stream) +serd_writer_new(SerdSyntax syntax, + SerdWriterFlags flags, + SerdEnv* env, + const SerdNode* base_uri, + SerdSink ssink, + void* stream) { const WriteContext context = WRITE_CONTEXT_NULL; SerdWriter* writer = (SerdWriter*)calloc(1, sizeof(SerdWriter)); @@ -1139,14 +1148,14 @@ serd_writer_new(SerdSyntax syntax, writer->syntax = syntax; writer->flags = flags; writer->env = env; - writer->root_node = SERD_NODE_NULL; + 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(SERD_PAGE_SIZE); writer->context = context; 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; } @@ -1181,12 +1190,10 @@ serd_writer_set_base_uri(SerdWriter* writer, const SerdNode* uri) TRY(st, serd_env_set_base_uri(writer->env, uri)); - serd_env_base_uri(writer->env, &writer->base_uri); - if (uri && (writer->syntax == SERD_TURTLE || writer->syntax == SERD_TRIG)) { TRY(st, terminate_context(writer)); TRY(st, esink("@base <", 7, writer)); - TRY(st, esink(uri->buf, uri->n_bytes, writer)); + TRY(st, esink(serd_node_string(uri), serd_node_length(uri), writer)); TRY(st, esink(">", 1, writer)); writer->last_sep = SEP_NODE; TRY(st, write_sep(writer, SEP_END_DIRECT)); @@ -1198,14 +1205,13 @@ serd_writer_set_base_uri(SerdWriter* writer, const SerdNode* uri) SerdStatus serd_writer_set_root_uri(SerdWriter* writer, const SerdNode* uri) { - serd_node_free(&writer->root_node); + serd_node_free(writer->root_node); + writer->root_node = NULL; + writer->root_uri = SERD_URI_NULL; - if (uri && uri->buf) { + if (uri) { writer->root_node = serd_node_copy(uri); - serd_uri_parse(uri->buf, &writer->root_uri); - } else { - writer->root_node = SERD_NODE_NULL; - writer->root_uri = SERD_URI_NULL; + serd_uri_parse(serd_node_string(writer->root_node), &writer->root_uri); } return SERD_SUCCESS; @@ -1223,9 +1229,9 @@ serd_writer_set_prefix(SerdWriter* writer, if (writer->syntax == SERD_TURTLE || writer->syntax == SERD_TRIG) { TRY(st, terminate_context(writer)); TRY(st, esink("@prefix ", 8, writer)); - TRY(st, esink(name->buf, name->n_bytes, writer)); + TRY(st, esink(serd_node_string(name), name->length, writer)); TRY(st, esink(": <", 3, writer)); - TRY(st, ewrite_uri(writer, uri->buf, uri->n_bytes)); + TRY(st, ewrite_uri(writer, serd_node_string(uri), uri->length)); TRY(st, esink(">", 1, writer)); writer->last_sep = SEP_NODE; TRY(st, write_sep(writer, SEP_END_DIRECT)); @@ -1247,7 +1253,7 @@ serd_writer_free(SerdWriter* writer) serd_stack_free(&writer->anon_stack); free(writer->bprefix); serd_byte_sink_free(&writer->byte_sink); - serd_node_free(&writer->root_node); + serd_node_free(writer->root_node); free(writer); } diff --git a/test/headers/test_headers.c b/test/headers/test_headers.c index c855c103..62be0976 100644 --- a/test/headers/test_headers.c +++ b/test/headers/test_headers.c @@ -3,8 +3,7 @@ #include "serd/serd.h" // IWYU pragma: keep -SERD_CONST_FUNC -int +SERD_CONST_FUNC int main(void) { return 0; diff --git a/test/test_env.c b/test/test_env.c index 8ef95f1a..198c7e9b 100644 --- a/test/test_env.c +++ b/test/test_env.c @@ -24,64 +24,68 @@ count_prefixes(void* handle, const SerdNode* name, const SerdNode* uri) static void test_env(void) { - SerdNode u = serd_node_from_string(SERD_URI, "http://example.org/foo"); - SerdNode b = serd_node_from_string(SERD_CURIE, "invalid"); - SerdNode c = serd_node_from_string(SERD_CURIE, "eg.2:b"); - SerdEnv* env = serd_env_new(NULL); + SerdNode* u = serd_new_string(SERD_URI, "http://example.org/foo"); + SerdNode* b = serd_new_string(SERD_CURIE, "invalid"); + SerdNode* c = serd_new_string(SERD_CURIE, "eg.2:b"); + SerdNode* s = serd_new_string(SERD_LITERAL, "hello"); + SerdEnv* env = serd_env_new(NULL); serd_env_set_prefix_from_strings(env, "eg.2", "http://example.org/"); - assert(!serd_env_set_base_uri(env, NULL)); - assert(serd_env_set_base_uri(env, &SERD_NODE_NULL)); - assert(serd_node_equals(serd_env_base_uri(env, NULL), &SERD_NODE_NULL)); + assert(!serd_env_new(s)); - SerdStringView prefix; - SerdStringView suffix; - assert(!serd_env_qualify(NULL, &u, &u, &suffix)); - assert(serd_env_expand(NULL, &c, &prefix, &suffix)); - assert(serd_env_expand(env, &b, &prefix, &suffix)); + const SerdNode* prefix_node = NULL; + SerdStringView prefix = serd_empty_string(); + SerdStringView suffix = serd_empty_string(); - SerdNode nxnode = serd_env_expand_node(NULL, &c); - assert(serd_node_equals(&nxnode, &SERD_NODE_NULL)); + assert(!serd_env_qualify(NULL, u, &prefix_node, &suffix)); - SerdNode xnode = serd_env_expand_node(env, &SERD_NODE_NULL); - assert(serd_node_equals(&xnode, &SERD_NODE_NULL)); + assert(serd_env_expand(env, NULL, &prefix, &suffix) == SERD_BAD_CURIE); - SerdNode xu = serd_env_expand_node(env, &u); - assert(!strcmp(xu.buf, "http://example.org/foo")); - serd_node_free(&xu); + assert(!serd_env_expand_node(NULL, u)); + assert(!serd_env_expand_node(env, b)); + assert(!serd_env_expand_node(env, s)); - SerdNode badpre = serd_node_from_string(SERD_CURIE, "hm:what"); - SerdNode xbadpre = serd_env_expand_node(env, &badpre); - assert(serd_node_equals(&xbadpre, &SERD_NODE_NULL)); + assert(!serd_env_set_base_uri(env, NULL)); - SerdNode xc = serd_env_expand_node(env, &c); - assert(!strcmp(xc.buf, "http://example.org/b")); - serd_node_free(&xc); + SerdNode* xu = serd_env_expand_node(env, u); + assert(!strcmp(serd_node_string(xu), "http://example.org/foo")); + serd_node_free(xu); - assert(serd_env_set_prefix(env, &SERD_NODE_NULL, &SERD_NODE_NULL)); + SerdNode* badpre = serd_new_string(SERD_CURIE, "hm:what"); + SerdNode* xbadpre = serd_env_expand_node(env, badpre); + assert(!xbadpre); - const SerdNode lit = serd_node_from_string(SERD_LITERAL, "hello"); - assert(serd_env_set_prefix(env, &b, &lit)); + SerdNode* xc = serd_env_expand_node(env, c); + assert(!strcmp(serd_node_string(xc), "http://example.org/b")); + serd_node_free(xc); - assert(!serd_env_new(&lit)); + SerdNode* lit = serd_new_string(SERD_LITERAL, "hello"); + assert(serd_env_set_prefix(env, b, lit)); - const SerdNode blank = serd_node_from_string(SERD_BLANK, "b1"); - const SerdNode xblank = serd_env_expand_node(env, &blank); - assert(serd_node_equals(&xblank, &SERD_NODE_NULL)); + SerdNode* blank = serd_new_string(SERD_BLANK, "b1"); + assert(!serd_env_expand_node(env, blank)); + serd_node_free(blank); int n_prefixes = 0; serd_env_set_prefix_from_strings(env, "eg.2", "http://example.org/"); serd_env_foreach(env, count_prefixes, &n_prefixes); assert(n_prefixes == 1); - SerdNode shorter_uri = serd_node_from_string(SERD_URI, "urn:foo"); - SerdNode prefix_name; - assert(!serd_env_qualify(env, &shorter_uri, &prefix_name, &suffix)); + SerdNode* shorter_uri = serd_new_string(SERD_URI, "urn:foo"); + assert(!serd_env_qualify(env, shorter_uri, &prefix_node, &suffix)); - assert(!serd_env_set_base_uri(env, &u)); - assert(serd_node_equals(serd_env_base_uri(env, NULL), &u)); + assert(!serd_env_set_base_uri(env, u)); + assert(serd_node_equals(serd_env_base_uri(env, NULL), u)); assert(!serd_env_set_base_uri(env, NULL)); - assert(!serd_env_base_uri(env, NULL)->buf); + assert(!serd_env_base_uri(env, NULL)); + + serd_node_free(shorter_uri); + serd_node_free(lit); + serd_node_free(badpre); + serd_node_free(s); + serd_node_free(c); + serd_node_free(b); + serd_node_free(u); serd_env_free(env); } diff --git a/test/test_node.c b/test/test_node.c index 21ef6feb..937d8a5f 100644 --- a/test/test_node.c +++ b/test/test_node.c @@ -6,6 +6,7 @@ #include "serd/memory.h" #include "serd/node.h" #include "serd/string.h" +#include "serd/uri.h" #include <assert.h> #include <float.h> @@ -80,14 +81,14 @@ test_double_to_node(void) NULL}; for (size_t i = 0; i < sizeof(dbl_test_nums) / sizeof(double); ++i) { - SerdNode node = serd_new_decimal(dbl_test_nums[i], 8); - const bool pass = (node.buf && dbl_test_strs[i]) - ? !strcmp(node.buf, dbl_test_strs[i]) - : (node.buf == dbl_test_strs[i]); + SerdNode* node = serd_new_decimal(dbl_test_nums[i], 8); + const char* node_str = node ? serd_node_string(node) : NULL; + const bool pass = (node_str && dbl_test_strs[i]) + ? !strcmp(node_str, dbl_test_strs[i]) + : (node_str == dbl_test_strs[i]); assert(pass); - const size_t len = node.buf ? strlen(node.buf) : 0; - assert(node.n_bytes == len); - serd_node_free(&node); + assert(!node || serd_node_length(node) == strlen(node_str)); + serd_node_free(node); } } @@ -102,10 +103,11 @@ test_integer_to_node(void) "0", "0", "-23", "23", "-12340", "1000", "-1000"}; for (size_t i = 0; i < N_TEST_NUMS; ++i) { - SerdNode node = serd_new_integer(int_test_nums[i]); - assert(!strcmp(node.buf, int_test_strs[i])); - assert(node.n_bytes == strlen(node.buf)); - serd_node_free(&node); + SerdNode* node = serd_new_integer(int_test_nums[i]); + const char* node_str = serd_node_string(node); + assert(!strcmp(node_str, int_test_strs[i])); + assert(serd_node_length(node) == strlen(node_str)); + serd_node_free(node); } #undef N_TEST_NUMS @@ -114,26 +116,28 @@ test_integer_to_node(void) static void test_blob_to_node(void) { + assert(!serd_new_blob(&SERD_URI_NULL, 0, false)); + for (size_t size = 1; size < 256; ++size) { uint8_t* const data = (uint8_t*)malloc(size); for (size_t i = 0; i < size; ++i) { data[i] = (uint8_t)((size + i) % 256); } - SerdNode blob = serd_new_blob(data, size, size % 5); - - assert(blob.n_bytes == strlen(blob.buf)); + size_t out_size = 0; + SerdNode* blob = serd_new_blob(data, size, size % 5); + const char* blob_str = serd_node_string(blob); + uint8_t* out = + (uint8_t*)serd_base64_decode(blob_str, serd_node_length(blob), &out_size); - size_t out_size = 0; - uint8_t* out = - (uint8_t*)serd_base64_decode(blob.buf, blob.n_bytes, &out_size); + assert(serd_node_length(blob) == strlen(blob_str)); assert(out_size == size); for (size_t i = 0; i < size; ++i) { assert(out[i] == data[i]); } - serd_node_free(&blob); + serd_node_free(blob); serd_free(out); free(data); } @@ -143,46 +147,45 @@ static void test_node_equals(void) { const uint8_t replacement_char_str[] = {0xEF, 0xBF, 0xBD, 0}; - SerdNode lhs = - serd_node_from_string(SERD_LITERAL, (const char*)replacement_char_str); - SerdNode rhs = serd_node_from_string(SERD_LITERAL, "123"); - assert(!serd_node_equals(&lhs, &rhs)); + SerdNode* lhs = + serd_new_string(SERD_LITERAL, (const char*)replacement_char_str); + SerdNode* rhs = serd_new_string(SERD_LITERAL, "123"); + assert(!serd_node_equals(lhs, rhs)); + + SerdNode* qnode = serd_new_string(SERD_CURIE, "foo:bar"); + assert(!serd_node_equals(lhs, qnode)); + assert(serd_node_equals(lhs, lhs)); - SerdNode qnode = serd_node_from_string(SERD_CURIE, "foo:bar"); - assert(!serd_node_equals(&lhs, &qnode)); - assert(serd_node_equals(&lhs, &lhs)); + assert(!serd_node_copy(NULL)); - SerdNode null_copy = serd_node_copy(&SERD_NODE_NULL); - assert(serd_node_equals(&SERD_NODE_NULL, &null_copy)); + serd_node_free(qnode); + serd_node_free(lhs); + serd_node_free(rhs); } static void test_node_from_string(void) { - SerdNode node = serd_node_from_string(SERD_LITERAL, "hello\""); - assert(node.n_bytes == 6 && node.flags == SERD_HAS_QUOTE && - !strcmp(node.buf, "hello\"")); + SerdNode* hello = serd_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(node.n_bytes == 6 && node.flags == SERD_HAS_QUOTE && - !strcmp((const char*)node.buf, "hello\"")); - - node = serd_node_from_string(SERD_URI, NULL); - assert(serd_node_equals(&node, &SERD_NODE_NULL)); + serd_node_free(hello); } static void test_node_from_substring(void) { - SerdNode empty = serd_node_from_substring(SERD_LITERAL, NULL, 32); - assert(!empty.buf && !empty.n_bytes && !empty.flags && !empty.type); - - SerdNode a_b = serd_node_from_substring(SERD_LITERAL, "a\"bc", 3); - assert(a_b.n_bytes == 3 && a_b.flags == SERD_HAS_QUOTE && - !strncmp(a_b.buf, "a\"b", 3)); - - a_b = serd_node_from_substring(SERD_LITERAL, "a\"bc", 10); - assert(a_b.n_bytes == 4 && a_b.flags == SERD_HAS_QUOTE && - !strncmp(a_b.buf, "a\"bc", 4)); + SerdNode* a_b = serd_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)); + + serd_node_free(a_b); + a_b = serd_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)); + serd_node_free(a_b); } int diff --git a/test/test_reader_writer.c b/test/test_reader_writer.c index f6dfe512..5aa2b850 100644 --- a/test/test_reader_writer.c +++ b/test/test_reader_writer.c @@ -458,25 +458,21 @@ test_writer(const char* const path) serd_writer_chop_blank_prefix(writer, "tmp"); serd_writer_chop_blank_prefix(writer, NULL); - const SerdNode lit = serd_node_from_string(SERD_LITERAL, "hello"); + SerdNode* lit = serd_new_string(SERD_LITERAL, "hello"); - assert(serd_writer_set_base_uri(writer, &lit)); - assert(serd_writer_set_prefix(writer, &lit, &lit)); + assert(serd_writer_set_base_uri(writer, lit)); + assert(serd_writer_set_prefix(writer, lit, lit)); assert(serd_writer_end_anon(writer, NULL)); assert(serd_writer_env(writer) == env); - uint8_t buf[] = {0xEF, 0xBF, 0xBD, 0}; - SerdNode s = serd_node_from_string(SERD_URI, ""); - SerdNode p = serd_node_from_string(SERD_URI, "http://example.org/pred"); - SerdNode o = serd_node_from_string(SERD_LITERAL, (char*)buf); + uint8_t buf[] = {0xEF, 0xBF, 0xBD, 0}; + SerdNode* s = serd_new_string(SERD_URI, ""); + SerdNode* p = serd_new_string(SERD_URI, "http://example.org/pred"); + SerdNode* o = serd_new_string(SERD_LITERAL, (char*)buf); // Write 3 invalid statements (should write nothing) - const SerdNode* junk[][5] = {{&s, &p, &SERD_NODE_NULL, NULL, NULL}, - {&s, &SERD_NODE_NULL, &o, NULL, NULL}, - {&SERD_NODE_NULL, &p, &o, NULL, NULL}, - {&s, &o, &o, NULL, NULL}, - {&o, &p, &o, NULL, NULL}, - {&s, &p, &SERD_NODE_NULL, NULL, NULL}}; + const SerdNode* junk[][5] = { + {s, o, o, NULL, NULL}, {o, p, o, NULL, NULL}, {s, o, p, NULL, NULL}}; for (size_t i = 0; i < sizeof(junk) / (sizeof(SerdNode*) * 5); ++i) { assert(serd_writer_write_statement(writer, 0, @@ -488,18 +484,18 @@ test_writer(const char* const path) junk[i][4])); } - const SerdNode t = serd_node_from_string(SERD_URI, "urn:Type"); - const SerdNode l = serd_node_from_string(SERD_LITERAL, "en"); - const SerdNode* good[][5] = {{&s, &p, &o, NULL, NULL}, - {&s, &p, &o, &SERD_NODE_NULL, &SERD_NODE_NULL}, - {&s, &p, &o, &t, NULL}, - {&s, &p, &o, NULL, &l}, - {&s, &p, &o, &t, &l}, - {&s, &p, &o, &t, &SERD_NODE_NULL}, - {&s, &p, &o, &SERD_NODE_NULL, &l}, - {&s, &p, &o, NULL, &SERD_NODE_NULL}, - {&s, &p, &o, &SERD_NODE_NULL, NULL}, - {&s, &p, &o, &SERD_NODE_NULL, NULL}}; + SerdNode* t = serd_new_string(SERD_URI, "urn:Type"); + SerdNode* l = serd_new_string(SERD_LITERAL, "en"); + const SerdNode* good[][5] = {{s, p, o, NULL, NULL}, + {s, p, o, NULL, NULL}, + {s, p, o, t, NULL}, + {s, p, o, NULL, l}, + {s, p, o, t, l}, + {s, p, o, t, NULL}, + {s, p, o, NULL, l}, + {s, p, o, NULL, NULL}, + {s, p, o, NULL, NULL}, + {s, p, o, NULL, NULL}}; for (size_t i = 0; i < sizeof(good) / (sizeof(SerdNode*) * 5); ++i) { assert(!serd_writer_write_statement(writer, 0, @@ -512,53 +508,44 @@ test_writer(const char* const path) } // Write statements with bad UTF-8 (should be replaced) - const uint8_t bad_str[] = {0xFF, 0x90, 'h', 'i', 0}; - SerdNode bad_lit = serd_node_from_string(SERD_LITERAL, (const char*)bad_str); - SerdNode bad_uri = serd_node_from_string(SERD_URI, (const char*)bad_str); - assert(!serd_writer_write_statement( - writer, 0, NULL, &s, &p, &bad_lit, NULL, NULL)); - assert(!serd_writer_write_statement( - writer, 0, NULL, &s, &p, &bad_uri, NULL, NULL)); + const char bad_str[] = {(char)0xFF, (char)0x90, 'h', 'i', 0}; + SerdNode* bad_lit = serd_new_string(SERD_LITERAL, bad_str); + SerdNode* bad_uri = serd_new_string(SERD_URI, bad_str); + assert( + !serd_writer_write_statement(writer, 0, NULL, s, p, bad_lit, NULL, NULL)); + assert( + !serd_writer_write_statement(writer, 0, NULL, s, p, bad_uri, NULL, NULL)); + serd_node_free(bad_lit); + serd_node_free(bad_uri); // Write 1 valid statement - o = serd_node_from_string(SERD_LITERAL, "hello"); - assert(!serd_writer_write_statement(writer, 0, NULL, &s, &p, &o, NULL, NULL)); + serd_node_free(o); + o = serd_new_string(SERD_LITERAL, "hello"); + assert(!serd_writer_write_statement(writer, 0, NULL, s, p, o, NULL, NULL)); serd_writer_free(writer); + serd_node_free(lit); + serd_node_free(o); + serd_node_free(t); + serd_node_free(l); // Test buffer sink SerdBuffer buffer = {NULL, 0}; writer = serd_writer_new(SERD_TURTLE, 0, env, NULL, serd_buffer_sink, &buffer); - o = serd_node_from_string(SERD_URI, "http://example.org/base"); - assert(!serd_writer_set_base_uri(writer, &o)); + o = serd_new_string(SERD_URI, "http://example.org/base"); + assert(!serd_writer_set_base_uri(writer, o)); + serd_node_free(o); serd_writer_free(writer); char* out = serd_buffer_sink_finish(&buffer); assert(!strcmp(out, "@base <http://example.org/base> .\n")); serd_free(out); - // Test writing empty node - SerdNode nothing = serd_node_from_string(SERD_NOTHING, ""); - - buffer.buf = NULL; - buffer.len = 0; - writer = - serd_writer_new(SERD_TURTLE, 0U, env, NULL, serd_buffer_sink, &buffer); - - assert(!serd_writer_write_statement( - writer, 0, NULL, &s, &p, ¬hing, NULL, NULL)); - - assert( - !strncmp((const char*)buffer.buf, "<>\n\t<http://example.org/pred> ", 30)); - - serd_writer_free(writer); - out = serd_buffer_sink_finish(&buffer); - - assert(!strcmp((const char*)out, "<>\n\t<http://example.org/pred> .\n")); - serd_free(out); + serd_node_free(p); + serd_node_free(s); serd_env_free(env); fclose(fd); @@ -581,8 +568,8 @@ test_reader(const char* path) assert(serd_reader_read_chunk(reader) == SERD_FAILURE); - SerdNode g = serd_node_from_string(SERD_URI, "http://example.org/"); - serd_reader_set_default_graph(reader, &g); + SerdNode* g = serd_new_string(SERD_URI, "http://example.org/"); + serd_reader_set_default_graph(reader, g); serd_reader_add_blank_prefix(reader, "tmp"); #if defined(__GNUC__) @@ -594,6 +581,8 @@ test_reader(const char* path) # pragma GCC diagnostic pop #endif + serd_node_free(g); + assert(serd_reader_read_file(reader, "http://notafile")); assert(serd_reader_read_file(reader, "file:///better/not/exist")); assert(serd_reader_read_file(reader, "file://")); @@ -604,8 +593,8 @@ test_reader(const char* path) assert(rt->n_prefix == 0); assert(rt->n_statement == 13); assert(rt->n_end == 0); - assert(rt->graph && rt->graph->buf && - !strcmp(rt->graph->buf, "http://example.org/")); + assert(rt->graph && serd_node_string(rt->graph) && + !strcmp(serd_node_string(rt->graph), "http://example.org/")); assert(serd_reader_read_string(reader, "This isn't Turtle at all.")); diff --git a/test/test_uri.c b/test/test_uri.c index d3ba5514..0942439f 100644 --- a/test/test_uri.c +++ b/test/test_uri.c @@ -44,17 +44,18 @@ test_file_uri(const char* const hostname, expected_path = path; } - SerdNode node = serd_new_file_uri(path, hostname, 0); - char* out_hostname = NULL; - char* out_path = serd_file_uri_parse(node.buf, &out_hostname); - assert(!strcmp(node.buf, expected_uri)); + SerdNode* node = serd_new_file_uri(path, hostname, 0); + 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)); assert((hostname && out_hostname) || (!hostname && !out_hostname)); assert(!hostname || !strcmp(hostname, out_hostname)); assert(!strcmp(out_path, expected_path)); serd_free(out_path); serd_free(out_hostname); - serd_node_free(&node); + serd_node_free(node); } static void @@ -114,22 +115,20 @@ test_uri_parsing(void) static void test_uri_from_string(void) { - SerdNode nonsense = serd_new_uri_from_string(NULL, NULL, NULL); - assert(nonsense.type == SERD_NOTHING); + assert(!serd_new_uri_from_string(NULL, NULL, NULL)); SerdURIView base_uri; - SerdNode base = + SerdNode* base = serd_new_uri_from_string("http://example.org/", NULL, &base_uri); - SerdNode nil = serd_new_uri_from_string(NULL, &base_uri, NULL); - SerdNode nil2 = serd_new_uri_from_string("", &base_uri, NULL); - assert(nil.type == SERD_URI); - assert(!strcmp(nil.buf, base.buf)); - assert(nil2.type == SERD_URI); - assert(!strcmp(nil2.buf, base.buf)); - serd_node_free(&nil); - serd_node_free(&nil2); - - serd_node_free(&base); + SerdNode* nil = serd_new_uri_from_string(NULL, &base_uri, NULL); + SerdNode* nil2 = serd_new_uri_from_string("", &base_uri, NULL); + 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(base); } static inline bool @@ -154,21 +153,21 @@ check_relative_uri(const char* const uri_string, SerdURIView base = SERD_URI_NULL; SerdURIView result = SERD_URI_NULL; - SerdNode uri_node = serd_new_uri_from_string(uri_string, NULL, &uri); - SerdNode base_node = serd_new_uri_from_string(base_string, NULL, &base); + SerdNode* uri_node = serd_new_uri_from_string(uri_string, NULL, &uri); + SerdNode* base_node = serd_new_uri_from_string(base_string, NULL, &base); - SerdNode result_node = SERD_NODE_NULL; + SerdNode* result_node = NULL; if (root_string) { SerdURIView root = SERD_URI_NULL; - SerdNode root_node = serd_new_uri_from_string(root_string, NULL, &root); + SerdNode* root_node = serd_new_uri_from_string(root_string, NULL, &root); result_node = serd_new_relative_uri(&uri, &base, &root, &result); - serd_node_free(&root_node); + serd_node_free(root_node); } else { result_node = serd_new_relative_uri(&uri, &base, NULL, &result); } - assert(!strcmp((const char*)result_node.buf, expected_string)); + assert(!strcmp(serd_node_string(result_node), expected_string)); SerdURIView expected = SERD_URI_NULL; assert(!serd_uri_parse(expected_string, &expected)); @@ -179,9 +178,9 @@ check_relative_uri(const char* const uri_string, assert(chunk_equals(&result.query, &expected.query)); assert(chunk_equals(&result.fragment, &expected.fragment)); - serd_node_free(&result_node); - serd_node_free(&base_node); - serd_node_free(&uri_node); + serd_node_free(result_node); + serd_node_free(base_node); + serd_node_free(uri_node); } static void diff --git a/test/test_writer.c b/test/test_writer.c index 6a7a35b5..9d004076 100644 --- a/test/test_writer.c +++ b/test/test_writer.c @@ -27,12 +27,15 @@ test_write_long_literal(void) assert(writer); - SerdNode s = serd_node_from_string(SERD_URI, "http://example.org/s"); - SerdNode p = serd_node_from_string(SERD_URI, "http://example.org/p"); - SerdNode o = serd_node_from_string(SERD_LITERAL, "hello \"\"\"world\"\"\"!"); + SerdNode* s = serd_new_string(SERD_URI, "http://example.org/s"); + SerdNode* p = serd_new_string(SERD_URI, "http://example.org/p"); + SerdNode* o = serd_new_string(SERD_LITERAL, "hello \"\"\"world\"\"\"!"); - assert(!serd_writer_write_statement(writer, 0, NULL, &s, &p, &o, NULL, NULL)); + assert(!serd_writer_write_statement(writer, 0, NULL, s, p, o, NULL, NULL)); + serd_node_free(o); + serd_node_free(p); + serd_node_free(s); serd_writer_free(writer); serd_env_free(env); @@ -63,12 +66,12 @@ test_writer_cleanup(void) SerdWriter* writer = serd_writer_new(SERD_TURTLE, 0U, env, NULL, null_sink, NULL); - SerdNode s = serd_node_from_string(SERD_URI, "http://example.org/s"); - SerdNode p = serd_node_from_string(SERD_URI, "http://example.org/p"); - SerdNode o = serd_node_from_string(SERD_BLANK, "http://example.org/o"); + SerdNode* s = serd_new_string(SERD_URI, "http://example.org/s"); + SerdNode* p = serd_new_string(SERD_URI, "http://example.org/p"); + SerdNode* o = serd_new_string(SERD_BLANK, "http://example.org/o"); st = serd_writer_write_statement( - writer, SERD_ANON_O_BEGIN, NULL, &s, &p, &o, NULL, NULL); + writer, SERD_ANON_O_BEGIN, NULL, s, p, o, NULL, NULL); assert(!st); @@ -77,11 +80,12 @@ test_writer_cleanup(void) char buf[12] = {0}; snprintf(buf, sizeof(buf), "b%u", i); - SerdNode next_o = serd_node_from_string(SERD_BLANK, buf); + SerdNode* next_o = serd_new_string(SERD_BLANK, buf); st = serd_writer_write_statement( - writer, SERD_ANON_O_BEGIN, NULL, &o, &p, &next_o, NULL, NULL); + writer, SERD_ANON_O_BEGIN, NULL, o, p, next_o, NULL, NULL); + serd_node_free(o); o = next_o; } @@ -92,6 +96,9 @@ test_writer_cleanup(void) assert(!(st = serd_writer_set_base_uri(writer, NULL))); // Free (which could leak if the writer doesn't clean up the stack properly) + serd_node_free(o); + serd_node_free(p); + serd_node_free(s); serd_writer_free(writer); serd_env_free(env); } @@ -111,18 +118,22 @@ test_strict_write(void) const uint8_t bad_str[] = {0xFF, 0x90, 'h', 'i', 0}; - SerdNode s = serd_node_from_string(SERD_URI, "http://example.org/s"); - SerdNode p = serd_node_from_string(SERD_URI, "http://example.org/p"); + SerdNode* s = serd_new_string(SERD_URI, "http://example.org/s"); + SerdNode* p = serd_new_string(SERD_URI, "http://example.org/p"); - SerdNode bad_lit = serd_node_from_string(SERD_LITERAL, (const char*)bad_str); - SerdNode bad_uri = serd_node_from_string(SERD_URI, (const char*)bad_str); + SerdNode* bad_lit = serd_new_string(SERD_LITERAL, (const char*)bad_str); + SerdNode* bad_uri = serd_new_string(SERD_URI, (const char*)bad_str); assert(serd_writer_write_statement( - writer, 0, NULL, &s, &p, &bad_lit, NULL, NULL) == SERD_BAD_TEXT); + writer, 0, NULL, s, p, bad_lit, NULL, NULL) == SERD_BAD_TEXT); assert(serd_writer_write_statement( - writer, 0, NULL, &s, &p, &bad_uri, NULL, NULL) == SERD_BAD_TEXT); + writer, 0, NULL, s, p, bad_uri, NULL, NULL) == SERD_BAD_TEXT); + serd_node_free(bad_uri); + serd_node_free(bad_lit); + serd_node_free(p); + serd_node_free(s); serd_writer_free(writer); serd_env_free(env); fclose(fd); @@ -146,15 +157,16 @@ test_write_error(void) SerdWriter* writer = NULL; SerdStatus st = SERD_SUCCESS; - SerdNode u = serd_node_from_string(SERD_URI, "http://example.com/u"); + SerdNode* u = serd_new_string(SERD_URI, "http://example.com/u"); writer = serd_writer_new( SERD_TURTLE, (SerdWriterFlags)0, env, NULL, error_sink, NULL); assert(writer); - st = serd_writer_write_statement(writer, 0U, NULL, &u, &u, &u, NULL, NULL); + st = serd_writer_write_statement(writer, 0U, NULL, u, u, u, NULL, NULL); assert(st == SERD_BAD_WRITE); serd_writer_free(writer); + serd_node_free(u); serd_env_free(env); } |