aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2024-01-20 16:41:13 -0500
committerDavid Robillard <d@drobilla.net>2024-01-20 16:41:13 -0500
commit91786a70ed2dbb003e12d6d33ca72593b70b6290 (patch)
tree85888e9896256af81fef040738c1a9a6ac2c24a1
parent117ae267046ed564684793270b82767c585c724b (diff)
downloadserd-91786a70ed2dbb003e12d6d33ca72593b70b6290.tar.gz
serd-91786a70ed2dbb003e12d6d33ca72593b70b6290.tar.bz2
serd-91786a70ed2dbb003e12d6d33ca72593b70b6290.zip
Fix writing empty list objects within blank nodes
-rw-r--r--NEWS3
-rw-r--r--src/writer.c8
-rw-r--r--test/test_writer.c74
3 files changed, 84 insertions, 1 deletions
diff --git a/NEWS b/NEWS
index 54f2db90..ad6ed098 100644
--- a/NEWS
+++ b/NEWS
@@ -1,8 +1,9 @@
serd (0.32.1) unstable; urgency=medium
* Enable clang nullability checks
+ * Fix writing empty list objects within blank nodes
- -- David Robillard <d@drobilla.net> Tue, 09 Jan 2024 22:38:27 +0000
+ -- David Robillard <d@drobilla.net> Sat, 20 Jan 2024 21:28:04 +0000
serd (0.32.0) stable; urgency=medium
diff --git a/src/writer.c b/src/writer.c
index bdcb8e8e..52badc46 100644
--- a/src/writer.c
+++ b/src/writer.c
@@ -964,6 +964,14 @@ serd_writer_write_statement(SerdWriter* writer,
return SERD_ERR_BAD_ARG;
}
+ if ((flags & SERD_LIST_O_BEGIN) &&
+ !strcmp((const char*)object->buf, NS_RDF "nil")) {
+ /* Tolerate LIST_O_BEGIN for "()" objects, even though it doesn't make
+ much sense, because older versions handled this gracefully. Consider
+ making this an error in a later major version. */
+ flags &= (SerdStatementFlags)~SERD_LIST_O_BEGIN;
+ }
+
// Simple case: write a line of NTriples or NQuads
if (writer->syntax == SERD_NTRIPLES || writer->syntax == SERD_NQUADS) {
TRY(st, write_node(writer, subject, NULL, NULL, FIELD_SUBJECT, flags));
diff --git a/test/test_writer.c b/test/test_writer.c
index 0622dc82..b02aba7e 100644
--- a/test/test_writer.c
+++ b/test/test_writer.c
@@ -42,6 +42,79 @@ test_write_long_literal(void)
serd_free(out);
}
+static void
+test_write_nested_anon(void)
+{
+ SerdEnv* env = serd_env_new(NULL);
+ SerdChunk chunk = {NULL, 0};
+ SerdWriter* writer = serd_writer_new(
+ SERD_TURTLE, (SerdStyle)0, env, NULL, serd_chunk_sink, &chunk);
+
+ assert(writer);
+
+ SerdNode s0 = serd_node_from_string(SERD_URI, USTR("http://example.org/s0"));
+ SerdNode p0 = serd_node_from_string(SERD_URI, USTR("http://example.org/p0"));
+ SerdNode b0 = serd_node_from_string(SERD_BLANK, USTR("b0"));
+ SerdNode p1 = serd_node_from_string(SERD_URI, USTR("http://example.org/p1"));
+ SerdNode b1 = serd_node_from_string(SERD_BLANK, USTR("b1"));
+ SerdNode p2 = serd_node_from_string(SERD_URI, USTR("http://example.org/p2"));
+ SerdNode o2 = serd_node_from_string(SERD_URI, USTR("http://example.org/o2"));
+ SerdNode p3 = serd_node_from_string(SERD_URI, USTR("http://example.org/p3"));
+ SerdNode p4 = serd_node_from_string(SERD_URI, USTR("http://example.org/p4"));
+ SerdNode o4 = serd_node_from_string(SERD_URI, USTR("http://example.org/o4"));
+ SerdNode nil = serd_node_from_string(
+ SERD_URI, USTR("http://www.w3.org/1999/02/22-rdf-syntax-ns#nil"));
+
+ assert(!serd_writer_write_statement(
+ writer, SERD_ANON_O_BEGIN, NULL, &s0, &p0, &b0, NULL, NULL));
+
+ assert(!serd_writer_write_statement(writer,
+ SERD_ANON_O_BEGIN | SERD_ANON_CONT,
+ NULL,
+ &b0,
+ &p1,
+ &b1,
+ NULL,
+ NULL));
+
+ assert(!serd_writer_write_statement(
+ writer, SERD_ANON_CONT, NULL, &b1, &p2, &o2, NULL, NULL));
+
+ assert(!serd_writer_write_statement(writer,
+ SERD_ANON_CONT | SERD_LIST_O_BEGIN,
+ NULL,
+ &b1,
+ &p3,
+ &nil,
+ NULL,
+ NULL));
+
+ assert(!serd_writer_end_anon(writer, &b1));
+ assert(!serd_writer_write_statement(
+ writer, SERD_ANON_CONT, NULL, &b0, &p4, &o4, NULL, NULL));
+
+ assert(!serd_writer_end_anon(writer, &b0));
+
+ serd_writer_free(writer);
+ serd_env_free(env);
+
+ uint8_t* const out = serd_chunk_sink_finish(&chunk);
+
+ static const char* const expected =
+ "<http://example.org/s0>\n"
+ "\t<http://example.org/p0> [\n"
+ "\t\t<http://example.org/p1> [\n"
+ "\t\t\t<http://example.org/p2> <http://example.org/o2> ;\n"
+ "\t\t\t<http://example.org/p3> ()\n"
+ "\t\t] ;\n"
+ "\t\t<http://example.org/p4> <http://example.org/o4>\n"
+ "\t] .\n";
+
+ fprintf(stderr, "%s\n", out);
+ assert(!strcmp((char*)out, expected));
+ serd_free(out);
+}
+
static size_t
null_sink(const void* const buf, const size_t len, void* const stream)
{
@@ -158,6 +231,7 @@ int
main(void)
{
test_write_long_literal();
+ test_write_nested_anon();
test_writer_cleanup();
test_strict_write();
test_write_error();