diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/node.h | 8 | ||||
-rw-r--r-- | src/reader.c | 8 | ||||
-rw-r--r-- | src/sink.c | 17 | ||||
-rw-r--r-- | src/statement.c | 142 | ||||
-rw-r--r-- | src/statement.h | 24 | ||||
-rw-r--r-- | src/writer.c | 15 |
6 files changed, 201 insertions, 13 deletions
@@ -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; @@ -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; |