aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2020-08-14 16:05:10 +0200
committerDavid Robillard <d@drobilla.net>2020-10-27 13:13:58 +0100
commitc5fb8c6326dfe8c46fe2247e611ae1bf94275da0 (patch)
tree2e5b4424924f395922c70f32d4f83c5d2853241a
parent2f2f791edb3ae4ccb825db548050461568570e03 (diff)
downloadserd-c5fb8c6326dfe8c46fe2247e611ae1bf94275da0.tar.gz
serd-c5fb8c6326dfe8c46fe2247e611ae1bf94275da0.tar.bz2
serd-c5fb8c6326dfe8c46fe2247e611ae1bf94275da0.zip
Merge datatype and/or language into node
This moves closer to the sord API, and is more convenient in most cases.
-rw-r--r--serd/serd.h38
-rw-r--r--src/n3.c26
-rw-r--r--src/node.c130
-rw-r--r--src/reader.c6
-rw-r--r--src/reader.h2
-rw-r--r--src/writer.c48
-rw-r--r--tests/read_chunk_test.c6
-rw-r--r--tests/serd_test.c91
8 files changed, 252 insertions, 95 deletions
diff --git a/serd/serd.h b/serd/serd.h
index 1333b61a..a488dad7 100644
--- a/serd/serd.h
+++ b/serd/serd.h
@@ -197,8 +197,10 @@ typedef enum {
Flags indicating certain string properties relevant to serialisation.
*/
typedef enum {
- SERD_HAS_NEWLINE = 1, /**< Contains line breaks ('\\n' or '\\r') */
- SERD_HAS_QUOTE = 1 << 1 /**< Contains quotes ('"') */
+ SERD_HAS_NEWLINE = 1, /**< Contains line breaks ('\\n' or '\\r') */
+ SERD_HAS_QUOTE = 1 << 1, /**< Contains quotes ('"') */
+ SERD_HAS_DATATYPE = 1 << 2, /**< Literal node has datatype */
+ SERD_HAS_LANGUAGE = 1 << 3 /**< Literal node has language */
} SerdNodeFlag;
/**
@@ -456,6 +458,16 @@ SerdNode*
serd_node_new_substring(SerdType type, const char* str, size_t len);
/**
+ Create a new literal node from `str`.
+
+ Either `datatype` or `lang` can be given, but not both, unless `datatype` is
+ rdf:langString in which case it is ignored.
+*/
+SERD_API
+SerdNode*
+serd_node_new_literal(const char* str, const char* datatype, const char* lang);
+
+/**
Simple wrapper for serd_node_new_uri() to resolve a URI node.
*/
SERD_API
@@ -605,6 +617,20 @@ SerdNodeFlags
serd_node_flags(const SerdNode* node);
/**
+ Return the datatype of a literal node, or NULL.
+*/
+SERD_API
+const SerdNode*
+serd_node_datatype(const SerdNode* node);
+
+/**
+ Return the language tag of a literal node, or NULL.
+*/
+SERD_API
+const SerdNode*
+serd_node_language(const SerdNode* node);
+
+/**
Return true iff `a` is equal to `b`.
*/
SERD_API
@@ -653,9 +679,7 @@ typedef SerdStatus (*SerdStatementSink)(void* handle,
const SerdNode* graph,
const SerdNode* subject,
const SerdNode* predicate,
- const SerdNode* object,
- const SerdNode* object_datatype,
- const SerdNode* object_lang);
+ const SerdNode* object);
/**
Sink (callback) for anonymous node end markers.
@@ -1043,9 +1067,7 @@ serd_writer_write_statement(SerdWriter* writer,
const SerdNode* graph,
const SerdNode* subject,
const SerdNode* predicate,
- const SerdNode* object,
- const SerdNode* datatype,
- const SerdNode* lang);
+ const SerdNode* object);
/**
Mark the end of an anonymous node's description.
diff --git a/src/n3.c b/src/n3.c
index 38acdb46..6c904c1a 100644
--- a/src/n3.c
+++ b/src/n3.c
@@ -778,7 +778,11 @@ read_0_9(SerdReader* reader, Ref str, bool at_least_one)
}
static SerdStatus
-read_number(SerdReader* reader, Ref* dest, Ref* datatype, bool* ate_dot)
+read_number(SerdReader* reader,
+ Ref* dest,
+ Ref* datatype,
+ SerdNodeFlags* flags,
+ bool* ate_dot)
{
#define XSD_DECIMAL NS_XSD "decimal"
#define XSD_DOUBLE NS_XSD "double"
@@ -835,6 +839,10 @@ read_number(SerdReader* reader, Ref* dest, Ref* datatype, bool* ate_dot)
XSD_INTEGER, sizeof(XSD_INTEGER) - 1);
}
+ if (*datatype) {
+ *flags |= SERD_HAS_DATATYPE;
+ }
+
return SERD_SUCCESS;
}
@@ -865,6 +873,7 @@ read_literal(SerdReader* reader, Ref* dest,
switch (peek_byte(reader)) {
case '@':
eat_byte_safe(reader, '@');
+ *flags |= SERD_HAS_LANGUAGE;
if ((st = read_LANGTAG(reader, lang))) {
*datatype = pop_node(reader, *datatype);
*lang = pop_node(reader, *lang);
@@ -875,6 +884,7 @@ read_literal(SerdReader* reader, Ref* dest,
case '^':
eat_byte_safe(reader, '^');
eat_byte_check(reader, '^');
+ *flags |= SERD_HAS_DATATYPE;
if ((st = read_iri(reader, datatype, ate_dot))) {
*datatype = pop_node(reader, *datatype);
*lang = pop_node(reader, *lang);
@@ -1012,7 +1022,7 @@ read_anon(SerdReader* reader, ReadContext ctx, bool subject, Ref* dest)
SerdStatus st = SERD_SUCCESS;
if (ctx.subject) {
- TRY(st, emit_statement(reader, ctx, *dest, 0, 0));
+ TRY(st, emit_statement(reader, ctx, *dest));
}
ctx.subject = *dest;
@@ -1085,7 +1095,7 @@ read_object(SerdReader* reader, ReadContext* ctx, bool emit, bool* ate_dot)
break;
case '+': case '-': case '.': case '0': case '1': case '2': case '3':
case '4': case '5': case '6': case '7': case '8': case '9':
- ret = read_number(reader, &o, &datatype, ate_dot);
+ ret = read_number(reader, &o, &datatype, &flags, ate_dot);
break;
case '\"':
case '\'':
@@ -1102,6 +1112,7 @@ read_object(SerdReader* reader, ReadContext* ctx, bool emit, bool* ate_dot)
!memcmp(serd_node_string(node), "true", 4)) ||
(node->n_bytes == 5 &&
!memcmp(serd_node_string(node), "false", 5))) {
+ flags = flags | SERD_HAS_DATATYPE;
node->type = SERD_LITERAL;
datatype = push_node(
reader, SERD_URI, XSD_BOOLEAN, XSD_BOOLEAN_LEN);
@@ -1122,7 +1133,7 @@ read_object(SerdReader* reader, ReadContext* ctx, bool emit, bool* ate_dot)
}
if (!ret && emit && simple) {
- ret = emit_statement(reader, *ctx, o, datatype, lang);
+ ret = emit_statement(reader, *ctx, o);
} else if (!ret && !emit) {
ctx->object = o;
ctx->datatype = datatype;
@@ -1215,7 +1226,7 @@ read_collection(SerdReader* reader, ReadContext ctx, Ref* dest)
if (ctx.subject) {
// subject predicate _:head
*ctx.flags |= (end ? 0 : SERD_LIST_O_BEGIN);
- TRY(st, emit_statement(reader, ctx, *dest, 0, 0));
+ TRY(st, emit_statement(reader, ctx, *dest));
*ctx.flags |= SERD_LIST_CONT;
} else {
*ctx.flags |= (end ? 0 : SERD_LIST_S_BEGIN);
@@ -1254,8 +1265,7 @@ read_collection(SerdReader* reader, ReadContext ctx, Ref* dest)
// _:node rdf:rest _:rest
*ctx.flags |= SERD_LIST_CONT;
ctx.predicate = reader->rdf_rest;
- TRY(st, emit_statement(reader, ctx,
- (end ? reader->rdf_nil : rest), 0, 0));
+ TRY(st, emit_statement(reader, ctx, (end ? reader->rdf_nil : rest)));
ctx.subject = rest; // _:node = _:rest
rest = node; // _:rest = (old)_:node
@@ -1616,7 +1626,7 @@ read_nquadsDoc(SerdReader* reader)
}
}
- TRY(st, emit_statement(reader, ctx, ctx.object, ctx.datatype, ctx.lang));
+ TRY(st, emit_statement(reader, ctx, ctx.object));
pop_node(reader, ctx.graph);
pop_node(reader, ctx.lang);
diff --git a/src/node.c b/src/node.c
index ac21c295..d0e978f2 100644
--- a/src/node.c
+++ b/src/node.c
@@ -17,10 +17,12 @@
#include "node.h"
#include "base64.h"
+#include "serd_internal.h"
#include "string_utils.h"
#include "serd/serd.h"
+#include <assert.h>
#include <float.h>
#include <math.h>
#include <stdbool.h>
@@ -38,13 +40,40 @@
# endif
#endif
+static const size_t serd_node_align = sizeof(SerdNode);
+
+static size_t
+serd_node_pad_size(const size_t n_bytes)
+{
+ const size_t pad = serd_node_align - (n_bytes + 2) % serd_node_align;
+ return n_bytes + 2 + pad;
+}
+
+static const SerdNode*
+serd_node_maybe_get_meta_c(const SerdNode* node)
+{
+ return (node->flags & (SERD_HAS_LANGUAGE | SERD_HAS_DATATYPE))
+ ? (node + 1 + (serd_node_pad_size(node->n_bytes) / serd_node_align))
+ : NULL;
+}
+
+static size_t
+serd_node_total_size(const SerdNode* node)
+{
+ return node ? (sizeof(SerdNode) + serd_node_pad_size(node->n_bytes) +
+ serd_node_total_size(serd_node_maybe_get_meta_c(node)))
+ : 0;
+}
+
SerdNode*
serd_node_malloc(size_t n_bytes, SerdNodeFlags flags, SerdType type)
{
- SerdNode* node = (SerdNode*)calloc(1, sizeof(SerdNode) + n_bytes + 1);
+ const size_t size = sizeof(SerdNode) + serd_node_pad_size(n_bytes);
+ SerdNode* node = (SerdNode*)calloc(1, size);
node->n_bytes = 0;
node->flags = flags;
node->type = type;
+ assert((intptr_t)node % serd_node_align == 0);
return node;
}
@@ -52,11 +81,12 @@ void
serd_node_set(SerdNode** dst, const SerdNode* src)
{
if (src) {
- if (!(*dst) || (*dst)->n_bytes < src->n_bytes) {
- (*dst) = (SerdNode*)realloc(*dst, sizeof(SerdNode) + src->n_bytes + 1);
+ const size_t size = serd_node_total_size(src);
+ if (!(*dst) || serd_node_total_size(*dst) < size) {
+ (*dst) = (SerdNode*)realloc(*dst, size);
}
- memcpy(*dst, src, sizeof(SerdNode) + src->n_bytes + 1);
+ memcpy(*dst, src, size);
} else if (*dst) {
memset(*dst, 0, sizeof(SerdNode));
}
@@ -93,14 +123,59 @@ serd_node_new_substring(SerdType type, const char* str, const size_t len)
}
SerdNode*
+serd_node_new_literal(const char* str, const char* datatype, const char* lang)
+{
+ if (!str || (lang && datatype && strcmp(datatype, NS_RDF "#langString"))) {
+ return NULL;
+ }
+
+ SerdNodeFlags flags = 0;
+ const size_t n_bytes = serd_strlen(str, &flags);
+ const size_t len = serd_node_pad_size(n_bytes);
+
+ SerdNode* node = NULL;
+ if (lang) {
+ flags |= SERD_HAS_LANGUAGE;
+ const size_t lang_len = strlen(lang);
+ const size_t total_len = len + sizeof(SerdNode) + lang_len;
+ node = serd_node_malloc(total_len, flags, SERD_LITERAL);
+ memcpy(serd_node_buffer(node), str, n_bytes);
+ node->n_bytes = n_bytes;
+
+ SerdNode* lang_node = node + 1 + (len / serd_node_align);
+ lang_node->type = SERD_LITERAL;
+ lang_node->n_bytes = lang_len;
+ memcpy(serd_node_buffer(lang_node), lang, lang_len);
+ } else if (datatype) {
+ flags |= SERD_HAS_DATATYPE;
+ const size_t datatype_len = strlen(datatype);
+ const size_t total_len = len + sizeof(SerdNode) + datatype_len;
+ node = serd_node_malloc(total_len, flags, SERD_LITERAL);
+ memcpy(serd_node_buffer(node), str, n_bytes);
+ node->n_bytes = n_bytes;
+
+ SerdNode* datatype_node = node + 1 + (len / serd_node_align);
+ datatype_node->type = SERD_URI;
+ datatype_node->n_bytes = datatype_len;
+ memcpy(serd_node_buffer(datatype_node), datatype, datatype_len);
+ } else {
+ node = serd_node_malloc(n_bytes, flags, SERD_LITERAL);
+ memcpy(serd_node_buffer(node), str, n_bytes);
+ node->n_bytes = n_bytes;
+ }
+
+ return node;
+}
+
+SerdNode*
serd_node_copy(const SerdNode* node)
{
if (!node) {
return NULL;
}
- const size_t size = sizeof(SerdNode) + node->n_bytes + 1;
- SerdNode* copy = (SerdNode*)malloc(size);
+ const size_t size = serd_node_total_size(node);
+ SerdNode* copy = (SerdNode*)calloc(1, size + 3);
memcpy(copy, node, size);
return copy;
}
@@ -108,9 +183,14 @@ serd_node_copy(const SerdNode* node)
bool
serd_node_equals(const SerdNode* a, const SerdNode* b)
{
- return (a == b) ||
- (a && b && a->type == b->type && a->n_bytes == b->n_bytes &&
- !memcmp(serd_node_string(a), serd_node_string(b), a->n_bytes));
+ if (a == b) {
+ return true;
+ } else if (!a || !b) {
+ return false;
+ }
+
+ const size_t a_size = serd_node_total_size(a);
+ return serd_node_total_size(b) == a_size && !memcmp(a, b, a_size);
}
static size_t
@@ -403,6 +483,38 @@ serd_node_length(const SerdNode* node)
return node ? node->n_bytes : 0;
}
+const SerdNode*
+serd_node_datatype(const SerdNode* node)
+{
+ if (!node || !(node->flags & SERD_HAS_DATATYPE)) {
+ return NULL;
+ }
+
+ const size_t len = serd_node_pad_size(node->n_bytes);
+ assert((intptr_t)node % serd_node_align == 0);
+ assert(len % serd_node_align == 0);
+
+ const SerdNode* const datatype = node + 1 + (len / serd_node_align);
+ assert(datatype->type == SERD_URI || datatype->type == SERD_CURIE);
+ return datatype;
+}
+
+const SerdNode*
+serd_node_language(const SerdNode* node)
+{
+ if (!node || !(node->flags & SERD_HAS_LANGUAGE)) {
+ return NULL;
+ }
+
+ const size_t len = serd_node_pad_size(node->n_bytes);
+ assert((intptr_t)node % serd_node_align == 0);
+ assert(len % serd_node_align == 0);
+
+ const SerdNode* const lang = node + 1 + (len / serd_node_align);
+ assert(lang->type == SERD_LITERAL);
+ return lang;
+}
+
SerdNodeFlags
serd_node_flags(const SerdNode* node)
{
diff --git a/src/reader.c b/src/reader.c
index 3784f297..c90f6355 100644
--- a/src/reader.c
+++ b/src/reader.c
@@ -116,7 +116,7 @@ pop_node(SerdReader* reader, Ref ref)
}
SerdStatus
-emit_statement(SerdReader* reader, ReadContext ctx, Ref o, Ref d, Ref l)
+emit_statement(SerdReader* reader, ReadContext ctx, Ref o)
{
SerdNode* graph = deref(reader, ctx.graph);
if (!graph && reader->default_graph) {
@@ -131,9 +131,7 @@ emit_statement(SerdReader* reader, ReadContext ctx, Ref o, Ref d, Ref l)
graph,
deref(reader, ctx.subject),
deref(reader, ctx.predicate),
- deref(reader, o),
- deref(reader, d),
- deref(reader, l));
+ deref(reader, o));
*ctx.flags &= SERD_ANON_CONT|SERD_LIST_CONT; // Preserve only cont flags
return st;
diff --git a/src/reader.h b/src/reader.h
index dbe4350d..fc4d7a1c 100644
--- a/src/reader.h
+++ b/src/reader.h
@@ -108,7 +108,7 @@ SerdNode* deref(SerdReader* reader, Ref ref);
Ref pop_node(SerdReader* reader, Ref ref);
SerdStatus
-emit_statement(SerdReader* reader, ReadContext ctx, Ref o, Ref d, Ref l);
+emit_statement(SerdReader* reader, ReadContext ctx, Ref o);
SerdStatus read_n3_statement(SerdReader* reader);
SerdStatus read_nquadsDoc(SerdReader* reader);
diff --git a/src/writer.c b/src/writer.c
index aea714f3..b2c6ad72 100644
--- a/src/writer.c
+++ b/src/writer.c
@@ -121,8 +121,6 @@ typedef enum {
static bool
write_node(SerdWriter* writer,
const SerdNode* node,
- const SerdNode* datatype,
- const SerdNode* lang,
Field field,
SerdStatementFlags flags);
@@ -445,12 +443,12 @@ is_inline_start(const SerdWriter* writer, Field field, SerdStatementFlags flags)
static bool
write_literal(SerdWriter* writer,
const SerdNode* node,
- const SerdNode* datatype,
- const SerdNode* lang,
SerdStatementFlags flags)
{
- const char* node_str = serd_node_string(node);
- const char* type_uri = serd_node_string(datatype);
+ const SerdNode* datatype = serd_node_datatype(node);
+ const SerdNode* lang = serd_node_language(node);
+ const char* node_str = serd_node_string(node);
+ const char* type_uri = serd_node_string(datatype);
if (supports_abbrev(writer) && type_uri) {
if (!strncmp(type_uri, NS_XSD, sizeof(NS_XSD) - 1) && (
!strcmp(type_uri + sizeof(NS_XSD) - 1, "boolean") ||
@@ -485,7 +483,7 @@ write_literal(SerdWriter* writer,
sink(serd_node_string(lang), lang->n_bytes, writer);
} else if (type_uri) {
sink("^^", 2, writer);
- return write_node(writer, datatype, NULL, NULL, FIELD_NONE, flags);
+ return write_node(writer, datatype, FIELD_NONE, flags);
}
return true;
}
@@ -645,15 +643,13 @@ write_blank(SerdWriter* const writer,
static bool
write_node(SerdWriter* writer,
const SerdNode* node,
- const SerdNode* datatype,
- const SerdNode* lang,
Field field,
SerdStatementFlags flags)
{
bool ret = false;
switch (node->type) {
case SERD_LITERAL:
- ret = write_literal(writer, node, datatype, lang, flags);
+ ret = write_literal(writer, node, flags);
break;
case SERD_URI:
ret = write_uri_node(writer, node, field, flags);
@@ -678,7 +674,7 @@ is_resource(const SerdNode* node)
static void
write_pred(SerdWriter* writer, SerdStatementFlags flags, const SerdNode* pred)
{
- write_node(writer, pred, NULL, NULL, FIELD_PREDICATE, flags);
+ write_node(writer, pred, FIELD_PREDICATE, flags);
write_sep(writer, SEP_P_O);
serd_node_set(&writer->context.predicate, pred);
}
@@ -687,9 +683,7 @@ static bool
write_list_obj(SerdWriter* writer,
SerdStatementFlags flags,
const SerdNode* predicate,
- const SerdNode* object,
- const SerdNode* datatype,
- const SerdNode* lang)
+ const SerdNode* object)
{
if (!strcmp(serd_node_string(object), NS_RDF "nil")) {
--writer->indent;
@@ -697,7 +691,7 @@ write_list_obj(SerdWriter* writer,
return true;
} else if (!strcmp(serd_node_string(predicate), NS_RDF "first")) {
write_sep(writer, SEP_LIST_SEP);
- write_node(writer, object, datatype, lang, FIELD_OBJECT, flags);
+ write_node(writer, object, FIELD_OBJECT, flags);
}
return false;
}
@@ -708,9 +702,7 @@ serd_writer_write_statement(SerdWriter* writer,
const SerdNode* graph,
const SerdNode* subject,
const SerdNode* predicate,
- const SerdNode* object,
- const SerdNode* datatype,
- const SerdNode* lang)
+ const SerdNode* object)
{
if (!subject || !predicate || !object ||
!is_resource(subject) || !is_resource(predicate)) {
@@ -725,14 +717,14 @@ serd_writer_write_statement(SerdWriter* writer,
} while (0)
if (writer->syntax == SERD_NTRIPLES || writer->syntax == SERD_NQUADS) {
- TRY(write_node(writer, subject, NULL, NULL, FIELD_SUBJECT, flags));
+ TRY(write_node(writer, subject, FIELD_SUBJECT, flags));
sink(" ", 1, writer);
- TRY(write_node(writer, predicate, NULL, NULL, FIELD_PREDICATE, flags));
+ TRY(write_node(writer, predicate, FIELD_PREDICATE, flags));
sink(" ", 1, writer);
- TRY(write_node(writer, object, datatype, lang, FIELD_OBJECT, flags));
+ TRY(write_node(writer, object, FIELD_OBJECT, flags));
if (writer->syntax == SERD_NQUADS && graph) {
sink(" ", 1, writer);
- TRY(write_node(writer, graph, datatype, lang, FIELD_GRAPH, flags));
+ TRY(write_node(writer, graph, FIELD_GRAPH, flags));
}
sink(" .\n", 3, writer);
return SERD_SUCCESS;
@@ -750,7 +742,7 @@ serd_writer_write_statement(SerdWriter* writer,
reset_context(writer, true);
if (graph) {
- TRY(write_node(writer, graph, datatype, lang, FIELD_GRAPH, flags));
+ TRY(write_node(writer, graph, FIELD_GRAPH, flags));
++writer->indent;
write_sep(writer, SEP_GRAPH_BEGIN);
serd_node_set(&writer->context.graph, graph);
@@ -758,7 +750,7 @@ serd_writer_write_statement(SerdWriter* writer,
}
if ((flags & SERD_LIST_CONT)) {
- if (write_list_obj(writer, flags, predicate, object, datatype, lang)) {
+ if (write_list_obj(writer, flags, predicate, object)) {
// Reached end of list
if (--writer->list_depth == 0 && writer->list_subj) {
reset_context(writer, false);
@@ -775,7 +767,7 @@ serd_writer_write_statement(SerdWriter* writer,
++writer->indent;
}
write_sep(writer, SEP_END_O);
- write_node(writer, object, datatype, lang, FIELD_OBJECT, flags);
+ write_node(writer, object, FIELD_OBJECT, flags);
if (!(flags & SERD_ANON_O_BEGIN)) {
--writer->indent;
}
@@ -784,7 +776,7 @@ serd_writer_write_statement(SerdWriter* writer,
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);
+ write_node(writer, object, FIELD_OBJECT, flags);
}
} else {
// No abbreviation
@@ -799,7 +791,7 @@ serd_writer_write_statement(SerdWriter* writer,
}
if (!(flags & SERD_ANON_CONT)) {
- write_node(writer, subject, NULL, NULL, FIELD_SUBJECT, flags);
+ write_node(writer, subject, FIELD_SUBJECT, flags);
++writer->indent;
write_sep(writer, SEP_S_P);
} else {
@@ -813,7 +805,7 @@ serd_writer_write_statement(SerdWriter* writer,
write_pred(writer, flags, predicate);
}
- write_node(writer, object, datatype, lang, FIELD_OBJECT, flags);
+ write_node(writer, object, FIELD_OBJECT, flags);
}
if (flags & (SERD_ANON_S_BEGIN|SERD_ANON_O_BEGIN)) {
diff --git a/tests/read_chunk_test.c b/tests/read_chunk_test.c
index 93291e01..6515df32 100644
--- a/tests/read_chunk_test.c
+++ b/tests/read_chunk_test.c
@@ -53,9 +53,7 @@ on_statement(void* handle,
const SerdNode* graph,
const SerdNode* subject,
const SerdNode* predicate,
- const SerdNode* object,
- const SerdNode* object_datatype,
- const SerdNode* object_lang)
+ const SerdNode* object)
{
(void)handle;
(void)flags;
@@ -63,8 +61,6 @@ on_statement(void* handle,
(void)subject;
(void)predicate;
(void)object;
- (void)object_datatype;
- (void)object_lang;
++n_statement;
return SERD_SUCCESS;
diff --git a/tests/serd_test.c b/tests/serd_test.c
index ff1d2467..7062cee8 100644
--- a/tests/serd_test.c
+++ b/tests/serd_test.c
@@ -59,16 +59,12 @@ test_sink(void* handle,
const SerdNode* graph,
const SerdNode* subject,
const SerdNode* predicate,
- const SerdNode* object,
- const SerdNode* object_datatype,
- const SerdNode* object_lang)
+ const SerdNode* object)
{
(void)flags;
(void)subject;
(void)predicate;
(void)object;
- (void)object_datatype;
- (void)object_lang;
ReaderTest* rt = (ReaderTest*)handle;
++rt->n_statements;
@@ -413,6 +409,36 @@ test_node_from_substring(void)
serd_node_free(a_b);
}
+static void test_literal(void)
+{
+ assert(!serd_node_new_literal(NULL, NULL, NULL));
+
+ SerdNode* hello2 = serd_node_new_literal("hello\"", NULL, NULL);
+ assert(serd_node_length(hello2) == 6 &&
+ serd_node_flags(hello2) == SERD_HAS_QUOTE &&
+ !strcmp(serd_node_string(hello2), "hello\""));
+ serd_node_free(hello2);
+
+ SerdNode* hello_l = serd_node_new_literal("hello_l\"", NULL, "en");
+ assert(serd_node_length(hello_l) == 8);
+ assert(!strcmp(serd_node_string(hello_l), "hello_l\""));
+ assert(serd_node_flags(hello_l) ==
+ (SERD_HAS_QUOTE | SERD_HAS_LANGUAGE));
+ assert(!strcmp(serd_node_string(serd_node_language(hello_l)),
+ "en"));
+ serd_node_free(hello_l);
+
+ SerdNode* hello_dt = serd_node_new_literal(
+ "hello_dt\"", "http://example.org/Thing", NULL);
+ assert(serd_node_length(hello_dt) == 9);
+ assert(!strcmp(serd_node_string(hello_dt), "hello_dt\""));
+ assert(serd_node_flags(hello_dt) ==
+ (SERD_HAS_QUOTE | SERD_HAS_DATATYPE));
+ assert(!strcmp(serd_node_string(serd_node_datatype(hello_dt)),
+ "http://example.org/Thing"));
+ serd_node_free(hello_dt);
+}
+
static void
test_uri_from_string(void)
{
@@ -497,38 +523,38 @@ test_writer(const char* const path)
SerdNode* o = serd_node_new_string(SERD_LITERAL, (char*)buf);
// Write 3 invalid statements (should write nothing)
- const SerdNode* junk[][5] = { { s, p, NULL, NULL, NULL },
- { s, NULL, o, NULL, NULL },
- { NULL, p, o, NULL, NULL },
- { s, p, NULL, NULL, NULL },
- { s, NULL, o, NULL, NULL },
- { NULL, p, o, NULL, NULL },
- { s, o, o, NULL, NULL },
- { o, p, o, NULL, NULL },
- { s, p, NULL, NULL, NULL },
- { NULL, NULL, NULL, NULL, NULL } };
+ const SerdNode* junk[][5] = { { s, p, NULL },
+ { s, NULL, o },
+ { NULL, p, o },
+ { s, p, NULL },
+ { s, NULL, o },
+ { NULL, p, o },
+ { s, o, o },
+ { o, p, o },
+ { s, p, NULL },
+ { NULL, NULL, NULL } };
for (size_t i = 0; i < sizeof(junk) / (sizeof(SerdNode*) * 5); ++i) {
assert(serd_writer_write_statement(
writer, 0, NULL,
- junk[i][0], junk[i][1], junk[i][2], junk[i][3], junk[i][4]));
+ junk[i][0], junk[i][1], junk[i][2]));
}
- SerdNode* t = serd_node_new_string(SERD_URI, "urn:Type");
- SerdNode* l = serd_node_new_string(SERD_LITERAL, "en");
- const SerdNode* good[][5] = { { s, p, o, NULL, NULL },
- { s, p, o, NULL, NULL },
- { s, p, o, t, NULL },
- { s, p, o, NULL, l },
- { s, p, o, t, l },
- { s, p, o, t, NULL },
- { s, p, o, NULL, l },
- { s, p, o, NULL, NULL },
- { s, p, o, NULL, NULL },
- { s, p, o, NULL, NULL } };
+ SerdNode* t = serd_node_new_literal((char*)buf, "urn:Type", NULL);
+ SerdNode* l = serd_node_new_literal((char*)buf, NULL, "en");
+ const SerdNode* good[][5] = { { s, p, o },
+ { s, p, o },
+ { s, p, t },
+ { s, p, l },
+ { s, p, l },
+ { s, p, t },
+ { s, p, l },
+ { s, p, o },
+ { s, p, o },
+ { s, p, o } };
for (size_t i = 0; i < sizeof(good) / (sizeof(SerdNode*) * 5); ++i) {
assert(!serd_writer_write_statement(
writer, 0, NULL,
- good[i][0], good[i][1], good[i][2], good[i][3], good[i][4]));
+ good[i][0], good[i][1], good[i][2]));
}
// Write statements with bad UTF-8 (should be replaced)
@@ -536,9 +562,9 @@ test_writer(const char* const path)
SerdNode* bad_lit = serd_node_new_string(SERD_LITERAL, bad_str);
SerdNode* bad_uri = serd_node_new_string(SERD_URI, bad_str);
assert(!serd_writer_write_statement(
- writer, 0, NULL, s, p, bad_lit, NULL, NULL));
+ writer, 0, NULL, s, p, bad_lit));
assert(!serd_writer_write_statement(writer, 0, NULL,
- s, p, bad_uri, NULL, NULL));
+ s, p, bad_uri));
serd_node_free(bad_lit);
serd_node_free(bad_uri);
@@ -546,7 +572,7 @@ test_writer(const char* const path)
serd_node_free(o);
o = serd_node_new_string(SERD_LITERAL, "hello");
assert(!serd_writer_write_statement(writer, 0, NULL,
- s, p, o, NULL, NULL));
+ s, p, o));
serd_writer_free(writer);
serd_node_free(lit);
@@ -656,6 +682,7 @@ main(void)
test_node_equals();
test_node_from_string();
test_node_from_substring();
+ test_literal();
test_uri_from_string();
test_relative_uri();
test_read_chunks();