aboutsummaryrefslogtreecommitdiffstats
path: root/src
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 /src
parenta650d2ad2d4785c40405854740e70f487ae1016a (diff)
downloadserd-cda46ec67d41fb120809d5d1d16c05eb1b3882da.tar.gz
serd-cda46ec67d41fb120809d5d1d16c05eb1b3882da.tar.bz2
serd-cda46ec67d41fb120809d5d1d16c05eb1b3882da.zip
Make nodes opaque
Diffstat (limited to 'src')
-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
11 files changed, 356 insertions, 302 deletions
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);
}