aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2018-02-04 15:33:36 +0100
committerDavid Robillard <d@drobilla.net>2022-01-13 15:33:54 -0500
commitcda46ec67d41fb120809d5d1d16c05eb1b3882da (patch)
treea968e71f84289c3ce96b654e9bc285812c17f7d4
parenta650d2ad2d4785c40405854740e70f487ae1016a (diff)
downloadserd-cda46ec67d41fb120809d5d1d16c05eb1b3882da.tar.gz
serd-cda46ec67d41fb120809d5d1d16c05eb1b3882da.tar.bz2
serd-cda46ec67d41fb120809d5d1d16c05eb1b3882da.zip
Make nodes opaque
-rw-r--r--.clang-format5
-rw-r--r--NEWS1
-rw-r--r--include/serd/serd.h104
-rw-r--r--src/base64.h3
-rw-r--r--src/byte_source.h3
-rw-r--r--src/env.c124
-rw-r--r--src/n3.c35
-rw-r--r--src/node.c180
-rw-r--r--src/node.h8
-rw-r--r--src/reader.c41
-rw-r--r--src/reader.h12
-rw-r--r--src/serdi.c14
-rw-r--r--src/uri_utils.h9
-rw-r--r--src/writer.c229
-rw-r--r--test/test_env.c78
-rw-r--r--test/test_node.c92
-rw-r--r--test/test_reader_writer.c101
-rw-r--r--test/test_uri.c77
-rw-r--r--test/test_writer.c11
19 files changed, 582 insertions, 545 deletions
diff --git a/.clang-format b/.clang-format
index bc0a1c2f..1aeedb25 100644
--- a/.clang-format
+++ b/.clang-format
@@ -19,7 +19,12 @@ IndentPPDirectives: AfterHash
KeepEmptyLinesAtTheStartOfBlocks: false
SpacesInContainerLiterals: false
StatementMacros:
+ - SERD_ALLOCATED
- SERD_API
+ - SERD_CONST_API
+ - SERD_CONST_FUNC
- SERD_DEPRECATED_BY
+ - SERD_PURE_API
+ - SERD_PURE_FUNC
- _Pragma
...
diff --git a/NEWS b/NEWS
index ace783f8..f66ebd6c 100644
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,7 @@
serd (1.0.1) unstable;
* Add SerdBuffer for mutable buffers to keep SerdChunk const-correct
+ * Make nodes opaque
* Remove serd_uri_to_path()
* Remove support for Turtle named inline nodes extension
* Remove useless character counting from API
diff --git a/include/serd/serd.h b/include/serd/serd.h
index b14cf24d..a55caffc 100644
--- a/include/serd/serd.h
+++ b/include/serd/serd.h
@@ -381,6 +381,9 @@ serd_uri_serialise_relative(const SerdURIView* SERD_NONNULL uri,
@{
*/
+/// A syntactic RDF node
+typedef struct SerdNodeImpl SerdNode;
+
/**
Type of a node.
@@ -394,13 +397,6 @@ serd_uri_serialise_relative(const SerdURIView* SERD_NONNULL uri,
*/
typedef enum {
/**
- The type of a nonexistent node.
-
- This type is useful as a sentinel, but is never emitted by the reader.
- */
- SERD_NOTHING = 0,
-
- /**
Literal value.
A literal optionally has either a language, or a datatype (not both).
@@ -435,47 +431,32 @@ typedef enum {
SERD_BLANK = 4
} SerdNodeType;
-/// 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.
+ Create a new node from `str`.
*/
SERD_API
-SerdNode
-serd_node_from_string(SerdNodeType type, const char* SERD_NULLABLE str);
+SerdNode* SERD_ALLOCATED
+serd_new_string(SerdNodeType type, const char* SERD_NULLABLE str);
/**
- Make a (shallow) node from a prefix of `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);
+SerdNode* SERD_ALLOCATED
+serd_new_substring(SerdNodeType type,
+ const char* SERD_NULLABLE str,
+ size_t len);
/// Simple wrapper for serd_new_uri() to resolve a URI node
SERD_API
-SerdNode
+SerdNode* SERD_ALLOCATED
serd_new_uri_from_node(const SerdNode* SERD_NONNULL uri_node,
const SerdURIView* SERD_NULLABLE base,
SerdURIView* SERD_NULLABLE out);
/// Simple wrapper for serd_new_uri() to resolve a URI string
SERD_API
-SerdNode
+SerdNode* SERD_ALLOCATED
serd_new_uri_from_string(const char* SERD_NULLABLE str,
const SerdURIView* SERD_NULLABLE base,
SerdURIView* SERD_NULLABLE out);
@@ -490,7 +471,7 @@ serd_new_uri_from_string(const char* SERD_NULLABLE str,
If `out` is not NULL, it will be set to the parsed URI.
*/
SERD_API
-SerdNode
+SerdNode* SERD_ALLOCATED
serd_new_file_uri(const char* SERD_NONNULL path,
const char* SERD_NULLABLE hostname,
SerdURIView* SERD_NULLABLE out);
@@ -506,7 +487,7 @@ serd_new_file_uri(const char* SERD_NONNULL path,
memory owned by the new returned node).
*/
SERD_API
-SerdNode
+SerdNode* SERD_ALLOCATED
serd_new_uri(const SerdURIView* SERD_NONNULL uri,
const SerdURIView* SERD_NULLABLE base,
SerdURIView* SERD_NULLABLE out);
@@ -524,7 +505,7 @@ serd_new_uri(const SerdURIView* SERD_NONNULL uri,
memory owned by the new returned node).
*/
SERD_API
-SerdNode
+SerdNode* SERD_ALLOCATED
serd_new_relative_uri(const SerdURIView* SERD_NONNULL uri,
const SerdURIView* SERD_NULLABLE base,
const SerdURIView* SERD_NULLABLE root,
@@ -546,12 +527,12 @@ serd_new_relative_uri(const SerdURIView* SERD_NONNULL uri,
@param frac_digits The maximum number of digits after the decimal place.
*/
SERD_API
-SerdNode
+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
+SerdNode* SERD_ALLOCATED
serd_new_integer(int64_t i);
/**
@@ -565,32 +546,33 @@ serd_new_integer(int64_t i);
@param wrap_lines Wrap lines at 76 characters to conform to RFC 2045.
*/
SERD_API
-SerdNode
+SerdNode* SERD_ALLOCATED
serd_new_blob(const void* SERD_NONNULL buf, size_t size, bool wrap_lines);
-/**
- Make a deep copy of `node`.
-
- @return a node that the caller must free with serd_node_free().
-*/
+/// Return a deep copy of `node`
SERD_API
-SerdNode
+SerdNode* SERD_ALLOCATED
serd_node_copy(const SerdNode* SERD_NULLABLE node);
+/// Free any data owned by `node`
+SERD_API
+void
+serd_node_free(SerdNode* SERD_NULLABLE node);
+
/// Return the type of a node (SERD_URI, SERD_BLANK, or SERD_LITERAL)
SERD_PURE_API
SerdNodeType
serd_node_type(const SerdNode* SERD_NONNULL node);
/// Return the node's string
-SERD_PURE_API
+SERD_CONST_API
const char* SERD_NONNULL
serd_node_string(const SerdNode* SERD_NONNULL node);
/// Return the length of the node's string in bytes (excluding terminator)
SERD_PURE_API
size_t
-serd_node_length(const SerdNode* SERD_NONNULL node);
+serd_node_length(const SerdNode* SERD_NULLABLE node);
/// Return the flags (string properties) of a node
SERD_PURE_API
@@ -600,18 +582,8 @@ serd_node_flags(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);
-
-/**
- Free any data owned by `node`.
-
- Note that if `node` is itself dynamically allocated (which is not the case
- for nodes created internally by serd), it will not be freed.
-*/
-SERD_API
-void
-serd_node_free(SerdNode* SERD_NULLABLE node);
+serd_node_equals(const SerdNode* SERD_NULLABLE a,
+ const SerdNode* SERD_NULLABLE b);
/**
@}
@@ -716,7 +688,7 @@ serd_env_free(SerdEnv* SERD_NULLABLE env);
/// Get the current base URI
SERD_API
-const SerdNode* SERD_NONNULL
+const SerdNode* SERD_NULLABLE
serd_env_base_uri(const SerdEnv* SERD_NONNULL env,
SerdURIView* SERD_NULLABLE out);
@@ -751,8 +723,8 @@ SERD_API
bool
serd_env_qualify(const SerdEnv* SERD_NULLABLE env,
const SerdNode* SERD_NONNULL uri,
- SerdNode* SERD_NONNULL prefix,
- SerdStringView* SERD_NONNULL suffix);
+ const SerdNode* SERD_NULLABLE* SERD_NONNULL prefix,
+ SerdStringView* SERD_NONNULL suffix);
/**
Expand `curie`.
@@ -762,10 +734,10 @@ serd_env_qualify(const SerdEnv* SERD_NULLABLE 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.
@@ -773,7 +745,7 @@ serd_env_expand(const SerdEnv* SERD_NULLABLE env,
Returns null if `node` can not be expanded.
*/
SERD_API
-SerdNode
+SerdNode* SERD_ALLOCATED
serd_env_expand_node(const SerdEnv* SERD_NULLABLE env,
const SerdNode* SERD_NONNULL node);
diff --git a/src/base64.h b/src/base64.h
index 8ff6acc4..6fbe6c5c 100644
--- a/src/base64.h
+++ b/src/base64.h
@@ -30,7 +30,8 @@
@param wrap_lines Wrap lines at 76 characters to conform to RFC 2045.
@return The length of the base64 encoding, excluding null terminator.
*/
-SERD_CONST_FUNC size_t
+SERD_CONST_FUNC
+size_t
serd_base64_get_length(size_t size, bool wrap_lines);
/**
diff --git a/src/byte_source.h b/src/byte_source.h
index 7a42feaa..63cc1b51 100644
--- a/src/byte_source.h
+++ b/src/byte_source.h
@@ -70,7 +70,8 @@ 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 4ca5bfe4..84fd43d4 100644
--- a/src/env.c
+++ b/src/env.c
@@ -14,6 +14,8 @@
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "node.h"
+
#include "serd/serd.h"
#include <stdbool.h>
@@ -22,14 +24,14 @@
#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;
};
@@ -52,12 +54,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);
}
@@ -68,7 +69,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
@@ -78,40 +79,40 @@ serd_env_set_base_uri(SerdEnv* const env, const SerdNode* const uri)
return SERD_ERR_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;
return SERD_SUCCESS;
}
-SERD_PURE_FUNC static SerdPrefix*
+SERD_PURE_FUNC
+static SerdPrefix*
serd_env_find(const SerdEnv* const env,
const char* const name,
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;
}
@@ -120,12 +121,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 {
env->prefixes = (SerdPrefix*)realloc(
@@ -140,22 +142,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_ERR_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;
@@ -166,29 +168,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->buf = uri->buf + prefix_uri->n_bytes;
- suffix->len = uri->n_bytes - prefix_uri->n_bytes;
+ suffix->buf = uri_str + prefix_uri->length;
+ suffix->len = uri->length - prefix_uri->length;
return true;
}
}
@@ -202,37 +211,36 @@ serd_env_expand(const SerdEnv* const env,
SerdStringView* const uri_prefix,
SerdStringView* const uri_suffix)
{
- if (!env) {
+ if (!env || !curie) {
return SERD_ERR_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_ERR_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->buf = prefix->uri.buf;
- uri_prefix->len = prefix->uri.n_bytes;
+ uri_prefix->buf = serd_node_string(prefix->uri);
+ uri_prefix->len = prefix->uri ? prefix->uri->length : 0;
uri_suffix->buf = colon + 1;
- uri_suffix->len = curie->n_bytes - name_len - 1;
+ uri_suffix->len = curie->length - name_len - 1;
return SERD_SUCCESS;
}
return SERD_ERR_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: {
@@ -243,18 +251,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.len + suffix.len;
- char* buf = (char*)malloc(len + 1);
- SerdNode ret = {buf, len, 0, SERD_URI};
- snprintf(buf, ret.n_bytes + 1, "%s%s", prefix.buf, suffix.buf);
+ SerdNode* ret = serd_node_malloc(len, 0, SERD_URI);
+ char* buf = serd_node_buffer(ret);
+
+ snprintf(buf, len + 1, "%s%s", prefix.buf, suffix.buf);
+ ret->length = len;
return ret;
}
case SERD_BLANK:
break;
}
- return SERD_NODE_NULL;
+ return NULL;
}
void
@@ -263,6 +273,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 80a3bb8a..a4745733 100644
--- a/src/n3.c
+++ b/src/n3.c
@@ -15,6 +15,7 @@
*/
#include "byte_source.h"
+#include "node.h"
#include "reader.h"
#include "serd_internal.h"
#include "stack.h"
@@ -633,7 +634,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;
}
@@ -655,7 +656,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_ERR_BAD_SYNTAX, "prefix ends with `.'\n");
}
@@ -986,8 +988,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;
@@ -1031,20 +1033,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_ERR_ID_CLASH,
@@ -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);
ret = SERD_SUCCESS;
@@ -1573,11 +1576,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 869d9bfc..ff3f3f71 100644
--- a/src/node.c
+++ b/src/node.c
@@ -66,45 +66,68 @@ 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;
+ if (src) {
+ if (!(*dst) || (*dst)->length < src->length) {
+ (*dst) = (SerdNode*)realloc(*dst, sizeof(SerdNode) + src->length + 1);
+ }
+
+ memcpy(*dst, src, sizeof(SerdNode) + src->length + 1);
+ } else if (*dst) {
+ memset(*dst, 0, sizeof(SerdNode));
}
+}
+
+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;
+}
- SerdNodeFlags flags = 0;
- const size_t n_bytes = serd_substrlen(str, len, &flags);
- const SerdNode ret = {str, n_bytes, flags, type};
- return ret;
+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;
}
@@ -112,28 +135,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_uri_path_char(const char c)
}
}
-SerdNode
+SerdNode*
serd_new_file_uri(const char* const path,
const char* const hostname,
SerdURIView* const out)
@@ -219,15 +243,17 @@ serd_new_file_uri(const char* const path,
}
serd_buffer_sink_finish(&buffer);
+ SerdNode* node =
+ serd_new_substring(SERD_URI, (const char*)buffer.buf, buffer.len);
if (out) {
- serd_uri_parse((const char*)buffer.buf, out);
+ serd_uri_parse(serd_node_buffer(node), out);
}
- return serd_node_from_substring(
- SERD_URI, (const char*)buffer.buf, buffer.len);
+ free(buffer.buf);
+ return node;
}
-SerdNode
+SerdNode*
serd_new_uri(const SerdURIView* const uri,
const SerdURIView* const base,
SerdURIView* const out)
@@ -238,22 +264,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,
@@ -261,17 +286,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;
@@ -284,18 +308,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;
@@ -317,7 +342,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;
@@ -327,7 +352,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) {
@@ -339,13 +364,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 = (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;
@@ -354,7 +379,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 {
@@ -364,16 +389,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)
{
+ if (!buf || !size) {
+ return NULL;
+ }
+
const size_t len = serd_base64_get_length(size, wrap_lines);
- uint8_t* str = (uint8_t*)calloc(len + 2, 1);
- SerdNode node = {(const char*)str, len, 0, SERD_LITERAL};
+ SerdNode* node = serd_node_malloc(len + 1, 0, SERD_LITERAL);
+ uint8_t* str = (uint8_t*)serd_node_buffer(node);
if (serd_base64_encode(str, buf, size, wrap_lines)) {
- node.flags |= SERD_HAS_NEWLINE;
+ node->flags |= SERD_HAS_NEWLINE;
}
+
+ node->length = len;
return node;
}
@@ -386,13 +417,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
@@ -404,8 +435,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 1c37c68d..124b6a0d 100644
--- a/src/node.h
+++ b/src/node.h
@@ -22,9 +22,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*
@@ -40,7 +40,7 @@ serd_node_buffer_c(const SerdNode* node)
}
SerdNode*
-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** dst, const SerdNode* src);
diff --git a/src/reader.c b/src/reader.c
index cc30c86e..86df3134 100644
--- a/src/reader.c
+++ b/src/reader.c
@@ -17,6 +17,7 @@
#include "reader.h"
#include "byte_source.h"
+#include "node.h"
#include "stack.h"
#include "system.h"
@@ -45,9 +46,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
@@ -88,19 +91,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,
@@ -114,20 +117,16 @@ 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);
}
+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
@@ -154,8 +153,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
@@ -202,7 +201,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;
@@ -240,7 +239,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);
@@ -278,7 +277,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 ae248410..bb8f0b30 100644
--- a/src/reader.h
+++ b/src/reader.h
@@ -18,6 +18,7 @@
#define SERD_READER_H
#include "byte_source.h"
+#include "node.h"
#include "stack.h"
#include "serd/serd.h"
@@ -67,7 +68,7 @@ struct SerdReaderImpl {
Ref rdf_first;
Ref rdf_rest;
Ref rdf_nil;
- SerdNode default_graph;
+ SerdNode* default_graph;
SerdByteSource source;
SerdStack stack;
SerdSyntax syntax;
@@ -92,15 +93,16 @@ 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
+SERD_PURE_FUNC
+size_t
genid_size(const SerdReader* reader);
Ref
@@ -181,7 +183,7 @@ push_byte(SerdReader* reader, Ref ref, const int c)
*(uint8_t*)(s - 1) = (uint8_t)c;
*s = '\0';
- ++node->n_bytes;
+ ++node->length;
return SERD_SUCCESS;
}
diff --git a/src/serdi.c b/src/serdi.c
index c447e2b2..babe4575 100644
--- a/src/serdi.c
+++ b/src/serdi.c
@@ -65,7 +65,8 @@ get_syntax(const char* const name)
return (SerdSyntax)0;
}
-static SERD_PURE_FUNC SerdSyntax
+static SERD_PURE_FUNC
+SerdSyntax
guess_syntax(const char* const filename)
{
const char* ext = strrchr(filename, '.');
@@ -316,7 +317,7 @@ main(int argc, char** argv)
choose_style(input_syntax, output_syntax, ascii, bulk_write, full_uris);
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
@@ -324,7 +325,7 @@ 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);
@@ -344,10 +345,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) {
@@ -366,7 +368,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/uri_utils.h b/src/uri_utils.h
index 03d397d2..6b07ec48 100644
--- a/src/uri_utils.h
+++ b/src/uri_utils.h
@@ -50,7 +50,8 @@ uri_path_at(const SerdURIView* uri, size_t i)
Return the index of the first differing character after the last root slash,
or zero if `uri` is not under `root`.
*/
-static inline SERD_PURE_FUNC size_t
+static inline SERD_PURE_FUNC
+size_t
uri_rooted_index(const SerdURIView* uri, const SerdURIView* root)
{
if (!root || !root->scheme.len ||
@@ -80,14 +81,16 @@ uri_rooted_index(const SerdURIView* uri, const SerdURIView* root)
}
/** Return true iff `uri` shares path components with `root` */
-static inline SERD_PURE_FUNC bool
+static inline SERD_PURE_FUNC
+bool
uri_is_related(const SerdURIView* uri, const SerdURIView* root)
{
return uri_rooted_index(uri, root) > 0;
}
/** Return true iff `uri` is within the base of `root` */
-static inline SERD_PURE_FUNC bool
+static inline SERD_PURE_FUNC
+bool
uri_is_under(const SerdURIView* uri, const SerdURIView* root)
{
const size_t index = uri_rooted_index(uri, root);
diff --git a/src/writer.c b/src/writer.c
index 579c7f3e..abfe327b 100644
--- a/src/writer.c
+++ b/src/writer.c
@@ -15,6 +15,7 @@
*/
#include "byte_sink.h"
+#include "node.h"
#include "serd_internal.h"
#include "stack.h"
#include "string_utils.h"
@@ -39,14 +40,12 @@ typedef enum {
} Field;
typedef struct {
- SerdNode graph;
- SerdNode subject;
- SerdNode predicate;
+ SerdNode* graph;
+ SerdNode* subject;
+ SerdNode* predicate;
} WriteContext;
-static const WriteContext WRITE_CONTEXT_NULL = {{0, 0, 0, SERD_NOTHING},
- {0, 0, 0, SERD_NOTHING},
- {0, 0, 0, SERD_NOTHING}};
+static const WriteContext WRITE_CONTEXT_NULL = {NULL, NULL, NULL};
typedef enum {
SEP_NONE,
@@ -95,7 +94,7 @@ struct SerdWriterImpl {
SerdSyntax syntax;
SerdWriterFlags flags;
SerdEnv* env;
- SerdNode root_node;
+ SerdNode* root_node;
SerdURIView root_uri;
SerdURIView base_uri;
SerdStack anon_stack;
@@ -103,7 +102,7 @@ struct SerdWriterImpl {
SerdErrorFunc error_func;
void* error_handle;
WriteContext context;
- SerdNode list_subj;
+ SerdNode* list_subj;
unsigned list_depth;
unsigned indent;
char* bprefix;
@@ -150,7 +149,8 @@ w_err(SerdWriter* writer, SerdStatus st, const char* fmt, ...)
va_end(args);
}
-SERD_PURE_FUNC static WriteContext*
+SERD_PURE_FUNC
+static WriteContext*
anon_stack_top(SerdWriter* writer)
{
assert(!serd_stack_is_empty(&writer->anon_stack));
@@ -158,18 +158,19 @@ anon_stack_top(SerdWriter* writer)
sizeof(WriteContext));
}
-static void
-copy_node(SerdNode* dst, const SerdNode* src)
+static inline SerdNode*
+ctx(SerdWriter* writer, const Field field)
{
- if (src) {
- dst->buf = (char*)realloc((char*)dst->buf, src->n_bytes + 1);
- dst->n_bytes = src->n_bytes;
- dst->flags = src->flags;
- dst->type = src->type;
- memcpy((char*)dst->buf, src->buf, src->n_bytes + 1);
- } else {
- dst->type = SERD_NOTHING;
+ SerdNode* node = NULL;
+ if (field == FIELD_SUBJECT) {
+ node = writer->context.subject;
+ } else if (field == FIELD_PREDICATE) {
+ node = writer->context.predicate;
+ } else if (field == FIELD_GRAPH) {
+ node = writer->context.graph;
}
+
+ return node && node->type ? node : NULL;
}
static size_t
@@ -264,6 +265,12 @@ write_uri(SerdWriter* writer, const char* utf8, size_t n_bytes)
return len;
}
+static size_t
+write_uri_from_node(SerdWriter* writer, const SerdNode* node)
+{
+ return write_uri(writer, serd_node_string(node), node->length);
+}
+
static bool
lname_must_escape(const char c)
{
@@ -473,23 +480,26 @@ write_sep(SerdWriter* writer, const Sep sep)
static SerdStatus
reset_context(SerdWriter* writer, bool graph)
{
- if (graph) {
- writer->context.graph.type = SERD_NOTHING;
+ if (graph && writer->context.graph) {
+ memset(writer->context.graph, 0, sizeof(SerdNode));
}
-
- writer->context.subject.type = SERD_NOTHING;
- writer->context.predicate.type = SERD_NOTHING;
- writer->empty = false;
+ if (writer->context.subject) {
+ memset(writer->context.subject, 0, sizeof(SerdNode));
+ }
+ if (writer->context.predicate) {
+ memset(writer->context.predicate, 0, sizeof(SerdNode));
+ }
+ writer->empty = false;
return SERD_SUCCESS;
}
static SerdStatus
free_context(SerdWriter* writer)
{
- serd_node_free(&writer->context.graph);
- serd_node_free(&writer->context.subject);
- serd_node_free(&writer->context.predicate);
- return reset_context(writer, true);
+ serd_node_free(writer->context.graph);
+ serd_node_free(writer->context.subject);
+ serd_node_free(writer->context.predicate);
+ return SERD_SUCCESS;
}
static bool
@@ -507,23 +517,24 @@ write_literal(SerdWriter* writer,
const SerdNode* lang,
SerdStatementFlags flags)
{
- if (supports_abbrev(writer) && datatype && datatype->buf) {
- const char* type_uri = datatype->buf;
+ const char* node_str = serd_node_string(node);
+ const char* type_uri = datatype ? serd_node_string(datatype) : NULL;
+ 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"))) {
- sink(node->buf, node->n_bytes, writer);
+ sink(node_str, node->length, writer);
return true;
}
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.
*/
- sink(node->buf, node->n_bytes, writer);
+ sink(node_str, node->length, writer);
return true;
}
}
@@ -531,17 +542,17 @@ write_literal(SerdWriter* writer,
if (supports_abbrev(writer) &&
(node->flags & (SERD_HAS_NEWLINE | SERD_HAS_QUOTE))) {
sink("\"\"\"", 3, writer);
- write_text(writer, WRITE_LONG_STRING, node->buf, node->n_bytes);
+ write_text(writer, WRITE_LONG_STRING, node_str, node->length);
sink("\"\"\"", 3, writer);
} else {
sink("\"", 1, writer);
- write_text(writer, WRITE_STRING, node->buf, node->n_bytes);
+ write_text(writer, WRITE_STRING, node_str, node->length);
sink("\"", 1, writer);
}
- if (lang && lang->buf) {
+ if (lang && serd_node_string(lang)) {
sink("@", 1, writer);
- sink(lang->buf, lang->n_bytes, writer);
- } else if (datatype && datatype->buf) {
+ sink(serd_node_string(lang), lang->length, writer);
+ } else if (type_uri) {
sink("^^", 2, writer);
return write_node(writer, datatype, NULL, NULL, FIELD_NONE, flags);
}
@@ -567,24 +578,25 @@ write_uri_node(SerdWriter* const writer,
const SerdNode* node,
const Field field)
{
- SerdNode prefix;
- SerdStringView suffix;
+ const SerdNode* prefix = NULL;
+ SerdStringView suffix = {NULL, 0};
- const bool has_scheme = serd_uri_string_has_scheme(node->buf);
+ const char* node_str = serd_node_string(node);
+ const bool has_scheme = serd_uri_string_has_scheme(node_str);
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 sink("a", 1, writer) == 1;
}
- if (!strcmp(node->buf, NS_RDF "nil")) {
+ if (!strcmp(node_str, NS_RDF "nil")) {
return sink("()", 2, writer) == 2;
}
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.buf, suffix.len)) {
- write_uri(writer, prefix.buf, prefix.n_bytes);
+ write_uri_from_node(writer, prefix);
sink(":", 1, writer);
write_uri(writer, suffix.buf, suffix.len);
return true;
@@ -592,11 +604,11 @@ write_uri_node(SerdWriter* const writer,
}
if (!has_scheme && !supports_uriref(writer) &&
- !serd_env_base_uri(writer->env, NULL)->buf) {
+ !serd_env_base_uri(writer->env, NULL)) {
w_err(writer,
SERD_ERR_BAD_ARG,
"syntax does not support URI reference <%s>\n",
- node->buf);
+ node_str);
return false;
}
@@ -606,7 +618,7 @@ 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;
@@ -618,7 +630,7 @@ write_uri_node(SerdWriter* const writer,
&uri, &writer->base_uri, root, uri_sink, writer);
}
} else {
- write_uri(writer, node->buf, node->n_bytes);
+ write_uri_from_node(writer, node);
}
write_sep(writer, SEP_URI_END);
return true;
@@ -627,6 +639,8 @@ write_uri_node(SerdWriter* const writer,
static bool
write_curie(SerdWriter* const writer, const SerdNode* const node)
{
+ const char* node_str = serd_node_string(node);
+
SerdStringView prefix = {NULL, 0};
SerdStringView suffix = {NULL, 0};
SerdStatus st = SERD_SUCCESS;
@@ -634,7 +648,7 @@ write_curie(SerdWriter* const writer, const SerdNode* const node)
case SERD_NTRIPLES:
case SERD_NQUADS:
if ((st = serd_env_expand(writer->env, node, &prefix, &suffix))) {
- w_err(writer, st, "undefined namespace prefix `%s'\n", node->buf);
+ w_err(writer, st, "undefined namespace prefix `%s'\n", node_str);
return false;
}
write_sep(writer, SEP_URI_BEGIN);
@@ -644,7 +658,8 @@ write_curie(SerdWriter* const writer, const SerdNode* const node)
break;
case SERD_TURTLE:
case SERD_TRIG:
- write_lname(writer, node->buf, node->n_bytes);
+ write_lname(writer, node_str, node->length);
+ break;
}
return true;
@@ -656,6 +671,7 @@ write_blank(SerdWriter* const writer,
const Field field,
const SerdStatementFlags flags)
{
+ const char* node_str = serd_node_string(node);
if (supports_abbrev(writer)) {
if (is_inline_start(writer, field, flags)) {
++writer->indent;
@@ -664,7 +680,7 @@ write_blank(SerdWriter* const writer,
if (field == FIELD_SUBJECT && (flags & SERD_LIST_S_BEGIN)) {
assert(writer->list_depth == 0);
- copy_node(&writer->list_subj, node);
+ serd_node_set(&writer->list_subj, node);
++writer->list_depth;
++writer->indent;
return write_sep(writer, SEP_LIST_BEGIN);
@@ -684,12 +700,12 @@ write_blank(SerdWriter* const writer,
sink("_:", 2, writer);
if (writer->bprefix &&
- !strncmp(node->buf, writer->bprefix, writer->bprefix_len)) {
- sink(node->buf + writer->bprefix_len,
- node->n_bytes - writer->bprefix_len,
+ !strncmp(node_str, writer->bprefix, writer->bprefix_len)) {
+ sink(node_str + writer->bprefix_len,
+ node->length - writer->bprefix_len,
writer);
} else {
- sink(node->buf, node->n_bytes, writer);
+ sink(node_str, node->length, writer);
}
return true;
@@ -705,8 +721,6 @@ write_node(SerdWriter* writer,
{
bool ret = false;
switch (node->type) {
- case SERD_NOTHING:
- break;
case SERD_LITERAL:
ret = write_literal(writer, node, datatype, lang, flags);
break;
@@ -720,7 +734,6 @@ write_node(SerdWriter* writer,
ret = write_blank(writer, node, field, flags);
break;
}
-
writer->last_sep = SEP_NONE;
return ret;
}
@@ -728,7 +741,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;
}
static void
@@ -736,7 +749,7 @@ write_pred(SerdWriter* writer, SerdStatementFlags flags, const SerdNode* pred)
{
write_node(writer, pred, NULL, NULL, FIELD_PREDICATE, flags);
write_sep(writer, SEP_P_O);
- copy_node(&writer->context.predicate, pred);
+ serd_node_set(&writer->context.predicate, pred);
}
static bool
@@ -747,13 +760,13 @@ write_list_obj(SerdWriter* writer,
const SerdNode* datatype,
const SerdNode* lang)
{
- if (!strcmp(object->buf, NS_RDF "nil")) {
+ if (!strcmp(serd_node_string(object), NS_RDF "nil")) {
--writer->indent;
write_sep(writer, SEP_LIST_END);
return true;
}
- if (!strcmp(predicate->buf, NS_RDF "first")) {
+ if (!strcmp(serd_node_string(predicate), NS_RDF "first")) {
write_sep(writer, SEP_LIST_SEP);
write_node(writer, object, datatype, lang, FIELD_OBJECT, flags);
}
@@ -771,8 +784,7 @@ serd_writer_write_statement(SerdWriter* writer,
const SerdNode* datatype,
const SerdNode* lang)
{
- if (!is_resource(subject) || !is_resource(predicate) || !object ||
- !object->buf) {
+ if (!is_resource(subject) || !is_resource(predicate) || !object) {
return SERD_ERR_BAD_ARG;
}
@@ -797,15 +809,13 @@ serd_writer_write_statement(SerdWriter* writer,
return SERD_SUCCESS;
}
- 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))) {
writer->indent = 0;
-
- if (writer->context.subject.type) {
+ if (ctx(writer, FIELD_SUBJECT)) {
write_sep(writer, SEP_END_S);
}
-
- if (writer->context.graph.type) {
+ if (ctx(writer, FIELD_GRAPH)) {
write_sep(writer, SEP_GRAPH_END);
}
@@ -814,23 +824,23 @@ serd_writer_write_statement(SerdWriter* writer,
TRY(write_node(writer, graph, datatype, lang, FIELD_GRAPH, flags));
++writer->indent;
write_sep(writer, SEP_GRAPH_BEGIN);
- copy_node(&writer->context.graph, graph);
+ serd_node_set(&writer->context.graph, graph);
}
}
if ((flags & SERD_LIST_CONT)) {
if (write_list_obj(writer, flags, predicate, object, datatype, lang)) {
// Reached end of list
- if (--writer->list_depth == 0 && writer->list_subj.type) {
+ if (--writer->list_depth == 0 && writer->list_subj) {
reset_context(writer, false);
- serd_node_free(&writer->context.subject);
+ serd_node_free(writer->context.subject);
writer->context.subject = writer->list_subj;
- writer->list_subj = SERD_NODE_NULL;
+ writer->list_subj = NULL;
}
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)) {
// Abbreviate S P
if (!(flags & SERD_ANON_O_BEGIN)) {
++writer->indent;
@@ -842,14 +852,14 @@ serd_writer_write_statement(SerdWriter* writer,
}
} else {
// Abbreviate S
- Sep sep = writer->context.predicate.type ? SEP_END_P : SEP_S_P;
+ Sep sep = ctx(writer, FIELD_PREDICATE) ? SEP_END_P : SEP_S_P;
write_sep(writer, sep);
write_pred(writer, flags, predicate);
write_node(writer, object, datatype, lang, FIELD_OBJECT, flags);
}
} else {
// No abbreviation
- if (writer->context.subject.type) {
+ if (ctx(writer, FIELD_SUBJECT)) {
assert(writer->indent > 0);
--writer->indent;
if (serd_stack_is_empty(&writer->anon_stack)) {
@@ -868,7 +878,7 @@ serd_writer_write_statement(SerdWriter* writer,
}
reset_context(writer, false);
- copy_node(&writer->context.subject, subject);
+ serd_node_set(&writer->context.subject, subject);
if (!(flags & SERD_LIST_S_BEGIN)) {
write_pred(writer, flags, predicate);
@@ -882,15 +892,15 @@ serd_writer_write_statement(SerdWriter* writer,
(WriteContext*)serd_stack_push(&writer->anon_stack, sizeof(WriteContext));
*ctx = writer->context;
WriteContext new_context = {
- serd_node_copy(graph), serd_node_copy(subject), SERD_NODE_NULL};
+ serd_node_copy(graph), serd_node_copy(subject), NULL};
if ((flags & SERD_ANON_S_BEGIN)) {
new_context.predicate = serd_node_copy(predicate);
}
writer->context = new_context;
} else {
- copy_node(&writer->context.graph, graph);
- copy_node(&writer->context.subject, subject);
- copy_node(&writer->context.predicate, predicate);
+ serd_node_set(&writer->context.graph, graph);
+ serd_node_set(&writer->context.subject, subject);
+ serd_node_set(&writer->context.predicate, predicate);
}
return SERD_SUCCESS;
@@ -902,40 +912,37 @@ serd_writer_end_anon(SerdWriter* writer, const SerdNode* node)
if (writer->syntax == SERD_NTRIPLES || writer->syntax == SERD_NQUADS) {
return SERD_SUCCESS;
}
-
if (serd_stack_is_empty(&writer->anon_stack) || writer->indent == 0) {
w_err(writer, SERD_ERR_UNKNOWN, "unexpected end of anonymous node\n");
return SERD_ERR_UNKNOWN;
}
-
--writer->indent;
write_sep(writer, SEP_ANON_END);
free_context(writer);
writer->context = *anon_stack_top(writer);
serd_stack_pop(&writer->anon_stack, sizeof(WriteContext));
- const bool is_subject = serd_node_equals(node, &writer->context.subject);
+ const bool is_subject = serd_node_equals(node, writer->context.subject);
if (is_subject) {
- copy_node(&writer->context.subject, node);
- writer->context.predicate.type = SERD_NOTHING;
+ serd_node_set(&writer->context.subject, node);
+ memset(writer->context.predicate, 0, sizeof(SerdNode));
}
-
return SERD_SUCCESS;
}
SerdStatus
serd_writer_finish(SerdWriter* writer)
{
- if (writer->context.subject.type) {
+ if (ctx(writer, FIELD_SUBJECT)) {
write_sep(writer, SEP_END_S);
}
-
- if (writer->context.graph.type) {
+ if (ctx(writer, FIELD_GRAPH)) {
write_sep(writer, SEP_GRAPH_END);
}
-
serd_byte_sink_flush(&writer->byte_sink);
- writer->indent = 0;
- return free_context(writer);
+ free_context(writer);
+ writer->indent = 0;
+ writer->context = WRITE_CONTEXT_NULL;
+ return SERD_SUCCESS;
}
SerdWriter*
@@ -952,12 +959,12 @@ 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(4 * sizeof(WriteContext));
writer->context = context;
- writer->list_subj = SERD_NODE_NULL;
+ writer->list_subj = NULL;
writer->empty = true;
writer->byte_sink = serd_byte_sink_new(
ssink, stream, (flags & SERD_WRITE_BULK) ? SERD_PAGE_SIZE : 1);
@@ -996,12 +1003,12 @@ serd_writer_set_base_uri(SerdWriter* writer, const SerdNode* uri)
serd_env_base_uri(writer->env, &writer->base_uri);
if (writer->syntax == SERD_TURTLE || writer->syntax == SERD_TRIG) {
- if (writer->context.graph.type || writer->context.subject.type) {
+ if (ctx(writer, FIELD_GRAPH) || ctx(writer, FIELD_SUBJECT)) {
sink(" .\n\n", 4, writer);
reset_context(writer, true);
}
sink("@base <", 7, writer);
- sink(uri->buf, uri->n_bytes, writer);
+ sink(serd_node_string(uri), uri->length, writer);
sink("> .\n", 4, writer);
}
writer->indent = 0;
@@ -1013,14 +1020,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;
@@ -1033,20 +1039,19 @@ serd_writer_set_prefix(SerdWriter* writer,
{
if (!serd_env_set_prefix(writer->env, name, uri)) {
if (writer->syntax == SERD_TURTLE || writer->syntax == SERD_TRIG) {
- if (writer->context.graph.type || writer->context.subject.type) {
+ if (ctx(writer, FIELD_GRAPH) || ctx(writer, FIELD_SUBJECT)) {
sink(" .\n\n", 4, writer);
reset_context(writer, true);
}
sink("@prefix ", 8, writer);
- sink(name->buf, name->n_bytes, writer);
+ sink(serd_node_string(name), name->length, writer);
sink(": <", 3, writer);
- write_uri(writer, uri->buf, uri->n_bytes);
+ write_uri_from_node(writer, uri);
sink("> .\n", 4, writer);
}
writer->indent = 0;
return reset_context(writer, true);
}
-
return SERD_ERR_UNKNOWN;
}
@@ -1061,7 +1066,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/test_env.c b/test/test_env.c
index f0dd4d47..b86783db 100644
--- a/test/test_env.c
+++ b/test/test_env.c
@@ -34,62 +34,66 @@ 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));
+ const SerdNode* prefix_node = NULL;
+ SerdStringView prefix = SERD_EMPTY_STRING();
+ SerdStringView suffix = SERD_EMPTY_STRING();
- 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));
+ assert(!serd_env_qualify(NULL, u, &prefix_node, &suffix));
- SerdNode nxnode = serd_env_expand_node(NULL, &c);
- assert(serd_node_equals(&nxnode, &SERD_NODE_NULL));
+ assert(serd_env_expand(env, NULL, &prefix, &suffix) == SERD_ERR_BAD_CURIE);
- SerdNode xnode = serd_env_expand_node(env, &SERD_NODE_NULL);
- assert(serd_node_equals(&xnode, &SERD_NODE_NULL));
+ assert(!serd_env_expand_node(NULL, u));
+ assert(!serd_env_expand_node(env, b));
+ assert(!serd_env_expand_node(env, s));
- SerdNode xu = serd_env_expand_node(env, &u);
- assert(!strcmp(xu.buf, "http://example.org/foo"));
- serd_node_free(&xu);
+ assert(!serd_env_set_base_uri(env, NULL));
- 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));
+ SerdNode* xu = serd_env_expand_node(env, u);
+ assert(!strcmp(serd_node_string(xu), "http://example.org/foo"));
+ serd_node_free(xu);
- SerdNode xc = serd_env_expand_node(env, &c);
- assert(!strcmp(xc.buf, "http://example.org/b"));
- serd_node_free(&xc);
+ SerdNode* badpre = serd_new_string(SERD_CURIE, "hm:what");
+ SerdNode* xbadpre = serd_env_expand_node(env, badpre);
+ assert(!xbadpre);
- assert(serd_env_set_prefix(env, &SERD_NODE_NULL, &SERD_NODE_NULL));
+ SerdNode* xc = serd_env_expand_node(env, c);
+ assert(!strcmp(serd_node_string(xc), "http://example.org/b"));
+ serd_node_free(xc);
- const SerdNode lit = serd_node_from_string(SERD_LITERAL, "hello");
- assert(serd_env_set_prefix(env, &b, &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 52a98740..be3576ff 100644
--- a/test/test_node.c
+++ b/test/test_node.c
@@ -91,14 +91,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);
}
}
@@ -111,36 +111,39 @@ test_integer_to_node(void)
"0", "0", "-23", "23", "-12340", "1000", "-1000"};
for (size_t i = 0; i < sizeof(int_test_nums) / sizeof(double); ++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);
}
}
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);
}
@@ -150,46 +153,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 3a1a103d..e81fb348 100644
--- a/test/test_reader_writer.c
+++ b/test/test_reader_writer.c
@@ -191,25 +191,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,
@@ -221,18 +217,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,
@@ -245,47 +241,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, "");
- FILE* const empty = tmpfile();
-
- writer = serd_writer_new(SERD_TURTLE, 0, env, NULL, serd_file_sink, empty);
-
- // FIXME: error handling
- serd_writer_write_statement(writer, 0, NULL, &s, &p, &nothing, NULL, NULL);
-
- assert((size_t)ftell(empty) == strlen("<>\n\t<http://example.org/pred> "));
-
- serd_writer_free(writer);
- fclose(empty);
+ serd_node_free(p);
+ serd_node_free(s);
serd_env_free(env);
fclose(fd);
@@ -300,8 +293,8 @@ test_reader(const char* path)
assert(reader);
assert(serd_reader_handle(reader) == rt);
- 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__)
@@ -313,6 +306,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://"));
@@ -320,8 +315,8 @@ test_reader(const char* path)
const SerdStatus st = serd_reader_read_file(reader, path);
assert(!st);
assert(rt->n_statements == 13);
- 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 8f3b559b..60e03ad8 100644
--- a/test/test_uri.c
+++ b/test/test_uri.c
@@ -32,16 +32,17 @@ test_file_uri(const char* 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(!strcmp(out_path, expected_path));
serd_free(out_path);
serd_free(out_hostname);
- serd_node_free(&node);
+ serd_node_free(node);
}
static void
@@ -66,57 +67,57 @@ 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 void
test_relative_uri(void)
{
SerdURIView base_uri;
- SerdNode base =
+ SerdNode* base =
serd_new_uri_from_string("http://example.org/", NULL, &base_uri);
- SerdNode abs = serd_node_from_string(SERD_URI, "http://example.org/foo/bar");
+ SerdNode* abs = serd_new_string(SERD_URI, "http://example.org/foo/bar");
SerdURIView abs_uri;
- serd_uri_parse(abs.buf, &abs_uri);
+ serd_uri_parse(serd_node_string(abs), &abs_uri);
SerdURIView rel_uri;
- SerdNode rel = serd_new_relative_uri(&abs_uri, &base_uri, NULL, &rel_uri);
- assert(!strcmp(rel.buf, "/foo/bar"));
+ SerdNode* rel = serd_new_relative_uri(&abs_uri, &base_uri, NULL, &rel_uri);
+ assert(!strcmp(serd_node_string(rel), "/foo/bar"));
- SerdNode up = serd_new_relative_uri(&base_uri, &abs_uri, NULL, NULL);
- assert(!strcmp(up.buf, "../"));
+ SerdNode* up = serd_new_relative_uri(&base_uri, &abs_uri, NULL, NULL);
+ assert(!strcmp(serd_node_string(up), "../"));
- SerdNode noup = serd_new_relative_uri(&base_uri, &abs_uri, &abs_uri, NULL);
- assert(!strcmp(noup.buf, "http://example.org/"));
+ SerdNode* noup = serd_new_relative_uri(&base_uri, &abs_uri, &abs_uri, NULL);
+ assert(!strcmp(serd_node_string(noup), "http://example.org/"));
- SerdNode x = serd_node_from_string(SERD_URI, "http://example.org/foo/x");
+ SerdNode* x = serd_new_string(SERD_URI, "http://example.org/foo/x");
SerdURIView x_uri;
- serd_uri_parse(x.buf, &x_uri);
-
- SerdNode x_rel = serd_new_relative_uri(&x_uri, &abs_uri, &abs_uri, NULL);
- assert(!strcmp(x_rel.buf, "x"));
-
- serd_node_free(&x_rel);
- serd_node_free(&noup);
- serd_node_free(&up);
- serd_node_free(&rel);
- serd_node_free(&base);
+ serd_uri_parse(serd_node_string(x), &x_uri);
+
+ SerdNode* x_rel = serd_new_relative_uri(&x_uri, &abs_uri, &abs_uri, NULL);
+ assert(!strcmp(serd_node_string(x_rel), "x"));
+
+ serd_node_free(x_rel);
+ serd_node_free(x);
+ serd_node_free(noup);
+ serd_node_free(up);
+ serd_node_free(abs);
+ serd_node_free(rel);
+ serd_node_free(base);
}
int
diff --git a/test/test_writer.c b/test/test_writer.c
index e7cfe231..7568984d 100644
--- a/test/test_writer.c
+++ b/test/test_writer.c
@@ -31,12 +31,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);