diff options
author | David Robillard <d@drobilla.net> | 2018-06-03 19:24:59 +0200 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2021-03-08 23:23:05 -0500 |
commit | 846553f8894264d64cdd1dfb08df56fe08189dac (patch) | |
tree | 6ca8d42da04999851491edcf6811d05d4962bcac | |
parent | 7c6c3159d1804f4855d9a4e0cd52486f61fcbab6 (diff) | |
download | serd-846553f8894264d64cdd1dfb08df56fe08189dac.tar.gz serd-846553f8894264d64cdd1dfb08df56fe08189dac.tar.bz2 serd-846553f8894264d64cdd1dfb08df56fe08189dac.zip |
Add SerdStatement
-rw-r--r-- | include/serd/serd.h | 57 | ||||
-rw-r--r-- | meson.build | 1 | ||||
-rw-r--r-- | src/reader.c | 9 | ||||
-rw-r--r-- | src/sink.c | 17 | ||||
-rw-r--r-- | src/statement.c | 53 | ||||
-rw-r--r-- | src/statement.h | 34 | ||||
-rw-r--r-- | src/writer.c | 14 | ||||
-rw-r--r-- | test/test_read_chunk.c | 14 | ||||
-rw-r--r-- | test/test_reader_writer.c | 16 |
9 files changed, 177 insertions, 38 deletions
diff --git a/include/serd/serd.h b/include/serd/serd.h index b5c7c4f0..e32e66cc 100644 --- a/include/serd/serd.h +++ b/include/serd/serd.h @@ -84,6 +84,9 @@ extern "C" { /// Global library state typedef struct SerdWorldImpl SerdWorld; +/// A subject, predicate, and object, with optional graph context +typedef struct SerdStatementImpl SerdStatement; + /// The origin of a statement in a document typedef struct SerdCursorImpl SerdCursor; @@ -841,12 +844,10 @@ typedef SerdStatus (*SerdPrefixFunc)(void* SERD_NULLABLE handle, Called for every RDF statement in the serialisation. */ -typedef SerdStatus (*SerdStatementFunc)(void* SERD_NULLABLE handle, - SerdStatementFlags flags, - const SerdNode* SERD_NULLABLE graph, - const SerdNode* SERD_NONNULL subject, - const SerdNode* SERD_NONNULL predicate, - const SerdNode* SERD_NONNULL object); +typedef SerdStatus (*SerdStatementFunc)(void* SERD_NULLABLE handle, + SerdStatementFlags flags, + const SerdStatement* SERD_NONNULL + statement); /** Sink function for anonymous node end markers @@ -1037,6 +1038,13 @@ serd_sink_write_prefix(const SerdSink* SERD_NONNULL sink, const SerdNode* SERD_NONNULL name, const SerdNode* SERD_NONNULL uri); +/// Write a statement +SERD_API +SerdStatus +serd_sink_write_statement(const SerdSink* SERD_NONNULL sink, + SerdStatementFlags flags, + const SerdStatement* SERD_NONNULL statement); + /// Write a statement from individual nodes SERD_API SerdStatus @@ -1266,6 +1274,43 @@ serd_writer_finish(SerdWriter* SERD_NONNULL writer); /** @} + @defgroup serd_statement Statement + @{ +*/ + +/// Return the given node in `statement` +SERD_PURE_API +const SerdNode* SERD_NULLABLE +serd_statement_node(const SerdStatement* SERD_NONNULL statement, + SerdField field); + +/// Return the subject in `statement` +SERD_PURE_API +const SerdNode* SERD_NONNULL +serd_statement_subject(const SerdStatement* SERD_NONNULL statement); + +/// Return the predicate in `statement` +SERD_PURE_API +const SerdNode* SERD_NONNULL +serd_statement_predicate(const SerdStatement* SERD_NONNULL statement); + +/// Return the object in `statement` +SERD_PURE_API +const SerdNode* SERD_NONNULL +serd_statement_object(const SerdStatement* SERD_NONNULL statement); + +/// Return the graph in `statement` +SERD_PURE_API +const SerdNode* SERD_NULLABLE +serd_statement_graph(const SerdStatement* SERD_NONNULL statement); + +/// Return the source location where `statement` originated, or NULL +SERD_PURE_API +const SerdCursor* SERD_NULLABLE +serd_statement_cursor(const SerdStatement* SERD_NONNULL statement); + +/** + @} @defgroup serd_cursor Cursor @{ */ diff --git a/meson.build b/meson.build index 5bfafbd5..05120981 100644 --- a/meson.build +++ b/meson.build @@ -99,6 +99,7 @@ sources = [ 'src/node.c', 'src/reader.c', 'src/sink.c', + 'src/statement.c', 'src/string.c', 'src/syntax.c', 'src/system.c', diff --git a/src/reader.c b/src/reader.c index f6c5e056..351428fc 100644 --- a/src/reader.c +++ b/src/reader.c @@ -18,6 +18,8 @@ #include "byte_source.h" #include "serd_internal.h" +#include "stack.h" +#include "statement.h" #include "system.h" #include "world.h" @@ -121,8 +123,11 @@ emit_statement(SerdReader* reader, ReadContext ctx, SerdNode* o) (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.cur}; + + 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; @@ -16,6 +16,8 @@ #include "sink.h" +#include "statement.h" + #include "serd/serd.h" #include <stdlib.h> @@ -86,6 +88,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, @@ -93,10 +104,8 @@ serd_sink_write(const SerdSink* sink, const SerdNode* object, const SerdNode* graph) { - 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..c9bac440 --- /dev/null +++ b/src/statement.c @@ -0,0 +1,53 @@ +/* + Copyright 2011-2020 David Robillard <d@drobilla.net> + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#include "statement.h" + +const SerdNode* +serd_statement_node(const SerdStatement* statement, SerdField field) +{ + return statement->nodes[field]; +} + +const SerdNode* +serd_statement_subject(const SerdStatement* statement) +{ + return statement->nodes[SERD_SUBJECT]; +} + +const SerdNode* +serd_statement_predicate(const SerdStatement* statement) +{ + return statement->nodes[SERD_PREDICATE]; +} + +const SerdNode* +serd_statement_object(const SerdStatement* statement) +{ + return statement->nodes[SERD_OBJECT]; +} + +const SerdNode* +serd_statement_graph(const SerdStatement* statement) +{ + return statement->nodes[SERD_GRAPH]; +} + +const SerdCursor* +serd_statement_cursor(const SerdStatement* statement) +{ + return statement->cursor; +} diff --git a/src/statement.h b/src/statement.h new file mode 100644 index 00000000..a5baaa6a --- /dev/null +++ b/src/statement.h @@ -0,0 +1,34 @@ +/* + Copyright 2011-2020 David Robillard <d@drobilla.net> + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#ifndef SERD_STATEMENT_H +#define SERD_STATEMENT_H + +#include "serd/serd.h" + +/** + Quad of nodes (a statement), or a quad pattern. + + Nodes are ordered (S P O G). The ID of the default graph is 0. +*/ +typedef const SerdNode* SerdQuad[4]; + +struct SerdStatementImpl { + SerdQuad nodes; + SerdCursor* cursor; +}; + +#endif // SERD_STATEMENT_H diff --git a/src/writer.c b/src/writer.c index 8800282d..4160c09d 100644 --- a/src/writer.c +++ b/src/writer.c @@ -773,13 +773,15 @@ write_list_obj(SerdWriter* writer, } static SerdStatus -serd_writer_write_statement(SerdWriter* writer, - SerdStatementFlags flags, - const SerdNode* graph, - const SerdNode* subject, - const SerdNode* predicate, - const SerdNode* object) +serd_writer_write_statement(SerdWriter* writer, + SerdStatementFlags flags, + const SerdStatement* statement) { + 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_ERR_BAD_ARG; } diff --git a/test/test_read_chunk.c b/test/test_read_chunk.c index 8be4ad63..d77c3398 100644 --- a/test/test_read_chunk.c +++ b/test/test_read_chunk.c @@ -48,19 +48,13 @@ on_prefix(void* handle, const SerdNode* name, const SerdNode* uri) } static SerdStatus -on_statement(void* handle, - SerdStatementFlags flags, - const SerdNode* graph, - const SerdNode* subject, - const SerdNode* predicate, - const SerdNode* object) +on_statement(void* handle, + SerdStatementFlags flags, + const SerdStatement* statement) { (void)handle; (void)flags; - (void)graph; - (void)subject; - (void)predicate; - (void)object; + (void)statement; ++n_statement; return SERD_SUCCESS; diff --git a/test/test_reader_writer.c b/test/test_reader_writer.c index 788b2d63..9ccfa967 100644 --- a/test/test_reader_writer.c +++ b/test/test_reader_writer.c @@ -26,18 +26,12 @@ #include <string.h> static SerdStatus -test_sink(void* handle, - SerdStatementFlags flags, - const SerdNode* graph, - const SerdNode* subject, - const SerdNode* predicate, - const SerdNode* object) +test_sink(void* handle, + SerdStatementFlags flags, + const SerdStatement* statement) { (void)flags; - (void)subject; - (void)predicate; - (void)object; - (void)graph; + (void)statement; ++*(size_t*)handle; @@ -164,6 +158,8 @@ test_read_string(void) serd_sink_set_statement_func(sink, test_sink); + serd_sink_set_statement_func(sink, test_sink); + // Test reading a string that ends exactly at the end of input (no newline) assert( !serd_reader_start_string(reader, |