aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-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
9 files changed, 363 insertions, 315 deletions
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);
}