From 96894224c76b371a7198dc18b9f6be78e7eb1b97 Mon Sep 17 00:00:00 2001
From: David Robillard <d@drobilla.net>
Date: Wed, 17 Dec 2014 05:50:07 +0000
Subject: Add support for Turtle named inline nodes extension.

git-svn-id: http://svn.drobilla.net/serd/trunk@482 490d8e77-9747-427b-9fa3-0b8f29cee8a0
---
 src/reader.c | 25 ++++++++++++++++++++++++-
 src/writer.c | 52 +++++++++++++++++++++++++++++++++++++---------------
 2 files changed, 61 insertions(+), 16 deletions(-)

(limited to 'src')

diff --git a/src/reader.c b/src/reader.c
index d5c29c04..012dcb43 100644
--- a/src/reader.c
+++ b/src/reader.c
@@ -1072,6 +1072,21 @@ blank_id(SerdReader* reader)
 	return ref;
 }
 
+static Ref
+read_blankName(SerdReader* reader)
+{
+	eat_byte_safe(reader, '=');
+	if (eat_byte_check(reader, '=') != '=') {
+		return r_err(reader, SERD_ERR_BAD_SYNTAX, "expected `='\n");
+	}
+
+	Ref  subject = 0;
+	bool ate_dot = false;
+	read_ws_star(reader);
+	read_iri(reader, &subject, &ate_dot);
+	return subject;
+}
+
 static bool
 read_blank(SerdReader* reader, ReadContext ctx, bool subject, Ref* dest, bool* ate_dot)
 {
@@ -1086,9 +1101,17 @@ read_blank(SerdReader* reader, ReadContext ctx, bool subject, Ref* dest, bool* a
 			*ctx.flags |= (subject) ? SERD_EMPTY_S : SERD_EMPTY_O;
 		} else {
 			*ctx.flags |= (subject) ? SERD_ANON_S_BEGIN : SERD_ANON_O_BEGIN;
+			if (peek_delim(reader, '=')) {
+				if (!(*dest = read_blankName(reader)) ||
+				    !eat_delim(reader, ';')) {
+					return false;
+				}
+			}
 		}
 
-		*dest = blank_id(reader);
+		if (!*dest) {
+			*dest = blank_id(reader);
+		}
 		if (ctx.subject) {
 			TRY_RET(emit_statement(reader, ctx, *dest, 0, 0));
 		}
diff --git a/src/writer.c b/src/writer.c
index 1c59a3e7..4eb39493 100644
--- a/src/writer.c
+++ b/src/writer.c
@@ -434,6 +434,14 @@ typedef enum {
 	FIELD_OBJECT
 } Field;
 
+static bool
+is_inline_start(const SerdWriter* writer, Field field, SerdStatementFlags flags)
+{
+	return (writer->syntax != SERD_NTRIPLES &&
+	        ((field == FIELD_SUBJECT && (flags & SERD_ANON_S_BEGIN)) ||
+	         (field == FIELD_OBJECT &&  (flags & SERD_ANON_O_BEGIN))));
+}
+
 static bool
 write_node(SerdWriter*        writer,
            const SerdNode*    node,
@@ -443,13 +451,12 @@ write_node(SerdWriter*        writer,
            SerdStatementFlags flags)
 {
 	SerdChunk uri_prefix;
-	SerdChunk uri_suffix;
+	SerdNode  prefix;
+	SerdChunk suffix;
 	bool      has_scheme;
 	switch (node->type) {
 	case SERD_BLANK:
-		if (writer->syntax != SERD_NTRIPLES
-		    && ((field == FIELD_SUBJECT && (flags & SERD_ANON_S_BEGIN))
-		        || (field == FIELD_OBJECT && (flags & SERD_ANON_O_BEGIN)))) {
+		if (is_inline_start(writer, field, flags)) {
 			++writer->indent;
 			write_sep(writer, SEP_ANON_BEGIN);
 		} else if (writer->syntax != SERD_NTRIPLES
@@ -484,18 +491,27 @@ write_node(SerdWriter*        writer,
 	case SERD_CURIE:
 		switch (writer->syntax) {
 		case SERD_NTRIPLES:
-			if (serd_env_expand(writer->env, node, &uri_prefix, &uri_suffix)) {
+			if (serd_env_expand(writer->env, node, &uri_prefix, &suffix)) {
 				w_err(writer, SERD_ERR_BAD_CURIE,
 				      "undefined namespace prefix `%s'\n", node->buf);
 				return false;
 			}
 			sink("<", 1, writer);
 			write_uri(writer, uri_prefix.buf, uri_prefix.len);
-			write_uri(writer, uri_suffix.buf, uri_suffix.len);
+			write_uri(writer, suffix.buf, suffix.len);
 			sink(">", 1, writer);
 			break;
 		case SERD_TURTLE:
+			if (is_inline_start(writer, field, flags)) {
+				++writer->indent;
+				write_sep(writer, SEP_ANON_BEGIN);
+				sink("== ", 3, writer);
+			}
 			write_lname(writer, node->buf, node->n_bytes);
+			if (is_inline_start(writer, field, flags)) {
+				sink(" ;", 2, writer);
+				write_newline(writer);
+			}
 		}
 		break;
 	case SERD_LITERAL:
@@ -536,6 +552,11 @@ write_node(SerdWriter*        writer,
 		}
 		break;
 	case SERD_URI:
+		if (is_inline_start(writer, field, flags)) {
+			++writer->indent;
+			write_sep(writer, SEP_ANON_BEGIN);
+			sink("== ", 3, writer);
+		}
 		has_scheme = serd_uri_string_has_scheme(node->buf);
 		if (field == FIELD_PREDICATE && (writer->syntax == SERD_TURTLE)
 		    && !strcmp((const char*)node->buf, NS_RDF "type")) {
@@ -545,15 +566,12 @@ write_node(SerdWriter*        writer,
 		           && !strcmp((const char*)node->buf, NS_RDF "nil")) {
 			sink("()", 2, writer);
 			break;
-		} else if (has_scheme && (writer->style & SERD_STYLE_CURIED)) {
-			SerdNode  prefix;
-			SerdChunk suffix;
-			if (serd_env_qualify(writer->env, node, &prefix, &suffix)) {
-				write_uri(writer, prefix.buf, prefix.n_bytes);
-				sink(":", 1, writer);
-				write_uri(writer, suffix.buf, suffix.len);
-				break;
-			}
+		} else if (has_scheme && (writer->style & SERD_STYLE_CURIED) &&
+		           serd_env_qualify(writer->env, node, &prefix, &suffix)) {
+			write_uri(writer, prefix.buf, prefix.n_bytes);
+			sink(":", 1, writer);
+			write_uri(writer, suffix.buf, suffix.len);
+			break;
 		}
 		sink("<", 1, writer);
 		if (writer->style & SERD_STYLE_RESOLVED) {
@@ -574,6 +592,10 @@ write_node(SerdWriter*        writer,
 			write_uri(writer, node->buf, node->n_bytes);
 		}
 		sink(">", 1, writer);
+		if (is_inline_start(writer, field, flags)) {
+			sink(" ;", 2, writer);
+			write_newline(writer);
+		}
 	default:
 		break;
 	}
-- 
cgit v1.2.1