aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/node.h8
-rw-r--r--src/reader.c8
-rw-r--r--src/sink.c17
-rw-r--r--src/statement.c142
-rw-r--r--src/statement.h24
-rw-r--r--src/writer.c15
6 files changed, 201 insertions, 13 deletions
diff --git a/src/node.h b/src/node.h
index fc03bf72..ee903d3c 100644
--- a/src/node.h
+++ b/src/node.h
@@ -10,6 +10,7 @@
#include "serd/string_view.h"
#include "serd/uri.h"
+#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
@@ -39,6 +40,13 @@ serd_node_string_i(const SerdNode* const SERD_NONNULL node)
return (const char*)(node + 1);
}
+static inline bool
+serd_node_pattern_match(const SerdNode* SERD_NULLABLE a,
+ const SerdNode* SERD_NULLABLE b)
+{
+ return !a || !b || serd_node_equals(a, b);
+}
+
SerdNode* SERD_ALLOCATED
serd_node_malloc(size_t length, SerdNodeFlags flags, SerdNodeType type);
diff --git a/src/reader.c b/src/reader.c
index a9c483c0..3c80c491 100644
--- a/src/reader.c
+++ b/src/reader.c
@@ -7,6 +7,7 @@
#include "node.h"
#include "serd_internal.h"
#include "stack.h"
+#include "statement.h"
#include "system.h"
#include "world.h"
@@ -118,8 +119,11 @@ emit_statement(SerdReader* const reader,
(subject and predicate) were already zeroed by subsequent pushes. */
serd_node_zero_pad(o);
- const SerdStatus st = serd_sink_write(
- reader->sink, *ctx.flags, ctx.subject, ctx.predicate, o, ctx.graph);
+ const SerdStatement statement = {{ctx.subject, ctx.predicate, o, ctx.graph},
+ &reader->source.caret};
+
+ const SerdStatus st =
+ serd_sink_write_statement(reader->sink, *ctx.flags, &statement);
*ctx.flags &= SERD_ANON_CONT | SERD_LIST_CONT; // Preserve only cont flags
return st;
diff --git a/src/sink.c b/src/sink.c
index 5e04ced6..51b23ea5 100644
--- a/src/sink.c
+++ b/src/sink.c
@@ -3,6 +3,8 @@
#include "sink.h"
+#include "statement.h"
+
#include "serd/node.h"
#include "serd/sink.h"
#include "serd/statement.h"
@@ -77,6 +79,15 @@ serd_sink_write_prefix(const SerdSink* sink,
}
SerdStatus
+serd_sink_write_statement(const SerdSink* sink,
+ const SerdStatementFlags flags,
+ const SerdStatement* statement)
+{
+ return sink->statement ? sink->statement(sink->handle, flags, statement)
+ : SERD_SUCCESS;
+}
+
+SerdStatus
serd_sink_write(const SerdSink* sink,
const SerdStatementFlags flags,
const SerdNode* subject,
@@ -89,10 +100,8 @@ serd_sink_write(const SerdSink* sink,
assert(predicate);
assert(object);
- return sink->statement
- ? sink->statement(
- sink->handle, flags, graph, subject, predicate, object)
- : SERD_SUCCESS;
+ const SerdStatement statement = {{subject, predicate, object, graph}, NULL};
+ return serd_sink_write_statement(sink, flags, &statement);
}
SerdStatus
diff --git a/src/statement.c b/src/statement.c
new file mode 100644
index 00000000..430194b7
--- /dev/null
+++ b/src/statement.c
@@ -0,0 +1,142 @@
+// Copyright 2011-2020 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
+
+#include "statement.h"
+
+#include "caret.h"
+#include "node.h"
+
+#include "serd/statement.h"
+
+#include <assert.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+
+static bool
+is_resource(const SerdNode* const node)
+{
+ const SerdNodeType type = node ? serd_node_type(node) : (SerdNodeType)0;
+ return type == SERD_URI || type == SERD_CURIE || type == SERD_BLANK;
+}
+
+bool
+serd_statement_is_valid(const SerdNode* const subject,
+ const SerdNode* const predicate,
+ const SerdNode* const object,
+ const SerdNode* const graph)
+{
+ return is_resource(subject) && is_resource(predicate) && object &&
+ serd_node_type(predicate) != SERD_BLANK &&
+ (!graph || is_resource(graph));
+}
+
+SerdStatement*
+serd_statement_new(const SerdNode* const s,
+ const SerdNode* const p,
+ const SerdNode* const o,
+ const SerdNode* const g,
+ const SerdCaret* const caret)
+{
+ assert(s);
+ assert(p);
+ assert(o);
+
+ if (!serd_statement_is_valid(s, p, o, g)) {
+ return NULL;
+ }
+
+ SerdStatement* statement = (SerdStatement*)malloc(sizeof(SerdStatement));
+ if (statement) {
+ statement->nodes[0] = s;
+ statement->nodes[1] = p;
+ statement->nodes[2] = o;
+ statement->nodes[3] = g;
+ statement->caret = serd_caret_copy(caret);
+ }
+ return statement;
+}
+
+SerdStatement*
+serd_statement_copy(const SerdStatement* const statement)
+{
+ if (!statement) {
+ return NULL;
+ }
+
+ SerdStatement* copy = (SerdStatement*)malloc(sizeof(SerdStatement));
+ memcpy(copy, statement, sizeof(SerdStatement));
+ if (statement->caret) {
+ copy->caret = (SerdCaret*)malloc(sizeof(SerdCaret));
+ memcpy(copy->caret, statement->caret, sizeof(SerdCaret));
+ }
+ return copy;
+}
+
+void
+serd_statement_free(SerdStatement* const statement)
+{
+ if (statement) {
+ free(statement->caret);
+ free(statement);
+ }
+}
+
+const SerdNode*
+serd_statement_node(const SerdStatement* const statement, const SerdField field)
+{
+ return statement->nodes[field];
+}
+
+const SerdNode*
+serd_statement_subject(const SerdStatement* const statement)
+{
+ return statement->nodes[SERD_SUBJECT];
+}
+
+const SerdNode*
+serd_statement_predicate(const SerdStatement* const statement)
+{
+ return statement->nodes[SERD_PREDICATE];
+}
+
+const SerdNode*
+serd_statement_object(const SerdStatement* const statement)
+{
+ return statement->nodes[SERD_OBJECT];
+}
+
+const SerdNode*
+serd_statement_graph(const SerdStatement* const statement)
+{
+ return statement->nodes[SERD_GRAPH];
+}
+
+const SerdCaret*
+serd_statement_caret(const SerdStatement* const statement)
+{
+ return statement->caret;
+}
+
+bool
+serd_statement_equals(const SerdStatement* const a,
+ const SerdStatement* const b)
+{
+ return (a == b || (a && b && serd_node_equals(a->nodes[0], b->nodes[0]) &&
+ serd_node_equals(a->nodes[1], b->nodes[1]) &&
+ serd_node_equals(a->nodes[2], b->nodes[2]) &&
+ serd_node_equals(a->nodes[3], b->nodes[3])));
+}
+
+bool
+serd_statement_matches(const SerdStatement* const statement,
+ const SerdNode* const subject,
+ const SerdNode* const predicate,
+ const SerdNode* const object,
+ const SerdNode* const graph)
+{
+ return (serd_node_pattern_match(statement->nodes[0], subject) &&
+ serd_node_pattern_match(statement->nodes[1], predicate) &&
+ serd_node_pattern_match(statement->nodes[2], object) &&
+ serd_node_pattern_match(statement->nodes[3], graph));
+}
diff --git a/src/statement.h b/src/statement.h
new file mode 100644
index 00000000..d4a64da5
--- /dev/null
+++ b/src/statement.h
@@ -0,0 +1,24 @@
+// Copyright 2011-2020 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
+
+#ifndef SERD_SRC_STATEMENT_H
+#define SERD_SRC_STATEMENT_H
+
+#include "serd/attributes.h"
+#include "serd/caret.h"
+#include "serd/node.h"
+
+#include <stdbool.h>
+
+struct SerdStatementImpl {
+ const SerdNode* SERD_NULLABLE nodes[4];
+ SerdCaret* SERD_NULLABLE caret;
+};
+
+SERD_PURE_FUNC bool
+serd_statement_is_valid(const SerdNode* SERD_NULLABLE subject,
+ const SerdNode* SERD_NULLABLE predicate,
+ const SerdNode* SERD_NULLABLE object,
+ const SerdNode* SERD_NULLABLE graph);
+
+#endif // SERD_SRC_STATEMENT_H
diff --git a/src/writer.c b/src/writer.c
index 5419e565..376becf1 100644
--- a/src/writer.c
+++ b/src/writer.c
@@ -961,14 +961,15 @@ terminate_context(SerdWriter* writer)
}
static SerdStatus
-serd_writer_write_statement(SerdWriter* const writer,
- const SerdStatementFlags flags,
- const SerdNode* const graph,
- const SerdNode* const subject,
- const SerdNode* const predicate,
- const SerdNode* const object)
+serd_writer_write_statement(SerdWriter* const writer,
+ const SerdStatementFlags flags,
+ const SerdStatement* const statement)
{
- SerdStatus st = SERD_SUCCESS;
+ SerdStatus st = SERD_SUCCESS;
+ const SerdNode* const subject = serd_statement_subject(statement);
+ const SerdNode* const predicate = serd_statement_predicate(statement);
+ const SerdNode* const object = serd_statement_object(statement);
+ const SerdNode* const graph = serd_statement_graph(statement);
if (!is_resource(subject) || !is_resource(predicate) || !object) {
return SERD_BAD_ARG;