aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2018-02-04 15:33:36 +0100
committerDavid Robillard <d@drobilla.net>2023-12-02 16:27:02 -0500
commitc644f404054e6d68f3bb645cf93b8ad1501b8938 (patch)
tree6291623c37dd9ef6be062113bf6ac5afa8115171
parentb0d4ae792c88cc55f9cc9a579530a1a13a158fda (diff)
downloadserd-c644f404054e6d68f3bb645cf93b8ad1501b8938.tar.gz
serd-c644f404054e6d68f3bb645cf93b8ad1501b8938.tar.bz2
serd-c644f404054e6d68f3bb645cf93b8ad1501b8938.zip
Make nodes opaque
-rw-r--r--.clang-format5
-rw-r--r--NEWS1
-rw-r--r--doc/conf.py.in1
-rw-r--r--include/serd/env.h20
-rw-r--r--include/serd/node.h133
-rw-r--r--include/serd/reader.h3
-rw-r--r--include/serd/status.h3
-rw-r--r--include/serd/uri.h3
-rw-r--r--include/serd/writer.h16
-rw-r--r--src/byte_source.h2
-rw-r--r--src/env.c125
-rw-r--r--src/n3.c35
-rw-r--r--src/node.c184
-rw-r--r--src/node.h12
-rw-r--r--src/reader.c42
-rw-r--r--src/reader.h9
-rw-r--r--src/serdi.c13
-rw-r--r--src/writer.c256
-rw-r--r--test/headers/test_headers.c3
-rw-r--r--test/test_env.c80
-rw-r--r--test/test_node.c93
-rw-r--r--test/test_reader_writer.c107
-rw-r--r--test/test_uri.c53
-rw-r--r--test/test_writer.c48
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
diff --git a/NEWS b/NEWS
index 4ddba2fd..f4b060cc 100644
--- a/NEWS
+++ b/NEWS
@@ -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);
diff --git a/src/env.c b/src/env.c
index d11a5bab..516eaf32 100644
--- a/src/env.c
+++ b/src/env.c
@@ -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);
}
}
diff --git a/src/n3.c b/src/n3.c
index b7b89342..c0c00985 100644
--- a/src/n3.c
+++ b/src/n3.c
@@ -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
diff --git a/src/node.c b/src/node.c
index 63e4b486..21bbb4d0 100644
--- a/src/node.c
+++ b/src/node.c
@@ -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);
}
diff --git a/src/node.h b/src/node.h
index 58673284..60e0d2ff 100644
--- a/src/node.h
+++ b/src/node.h
@@ -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, &nothing, 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);
}