aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--serd/serd.h63
-rw-r--r--src/n3.c1
-rw-r--r--src/reader.c1
-rw-r--r--src/sink.c62
-rw-r--r--src/sink.h33
-rw-r--r--src/writer.c1
-rw-r--r--tests/serd_test.c24
7 files changed, 158 insertions, 27 deletions
diff --git a/serd/serd.h b/serd/serd.h
index 6279e09d..7ad4d36b 100644
--- a/serd/serd.h
+++ b/serd/serd.h
@@ -99,6 +99,11 @@ typedef struct SerdReaderImpl SerdReader;
typedef struct SerdWriterImpl SerdWriter;
/**
+ An interface that receives a stream of RDF data.
+*/
+typedef struct SerdSinkImpl SerdSink;
+
+/**
Return status code.
*/
typedef enum {
@@ -827,17 +832,6 @@ typedef SerdStatus (*SerdEndSink)(void* handle,
const SerdNode* node);
/**
- An interface that receives a stream of RDF data.
-*/
-typedef struct SerdSink {
- void* handle;
- SerdBaseSink base;
- SerdPrefixSink prefix;
- SerdStatementSink statement;
- SerdEndSink end;
-} SerdSink;
-
-/**
@}
@name World
@{
@@ -966,6 +960,53 @@ serd_env_foreach(const SerdEnv* env,
*/
/**
+ Create a new sink.
+
+ Initially, the sink has no set functions and will do nothing. Use the
+ serd_sink_set_*_func functions to set handlers for various events.
+
+ @param handle Opaque handle that will be passed to sink functions.
+*/
+SERD_API
+SerdSink*
+serd_sink_new(void* handle);
+
+/**
+ Free `sink`.
+*/
+SERD_API
+void
+serd_sink_free(SerdSink* sink);
+
+/**
+ Set a function to be called when the base URI changes.
+*/
+SERD_API
+SerdStatus
+serd_sink_set_base_func(SerdSink* sink, SerdBaseSink base_func);
+
+/**
+ Set a function to be called when a namespace prefix is defined.
+*/
+SERD_API
+SerdStatus
+serd_sink_set_prefix_func(SerdSink* sink, SerdPrefixSink prefix_func);
+
+/**
+ Set a function to be called when a statement is emitted.
+*/
+SERD_API
+SerdStatus
+serd_sink_set_statement_func(SerdSink* sink, SerdStatementSink statement_func);
+
+/**
+ Set a function to be called when an anonymous node ends.
+*/
+SERD_API
+SerdStatus
+serd_sink_set_end_func(SerdSink* sink, SerdEndSink end_func);
+
+/**
Set the base URI.
Simple wrapper for the `SerdBaseSink` of `sink`.
diff --git a/src/n3.c b/src/n3.c
index 45891f1e..88b8ff1b 100644
--- a/src/n3.c
+++ b/src/n3.c
@@ -18,6 +18,7 @@
#include "node.h"
#include "reader.h"
#include "serd_internal.h"
+#include "sink.h"
#include "stack.h"
#include "string_utils.h"
#include "uri_utils.h"
diff --git a/src/reader.c b/src/reader.c
index 82f92a44..1bbb17dc 100644
--- a/src/reader.c
+++ b/src/reader.c
@@ -20,6 +20,7 @@
#include "node.h"
#include "serd/serd.h"
#include "serd_internal.h"
+#include "sink.h"
#include "stack.h"
#include "statement.h"
#include "system.h"
diff --git a/src/sink.c b/src/sink.c
index 40071d72..c8a0dd62 100644
--- a/src/sink.c
+++ b/src/sink.c
@@ -1,5 +1,5 @@
/*
- Copyright 2011-2018 David Robillard <http://drobilla.net>
+ Copyright 2011-2020 David Robillard <http://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
@@ -14,16 +14,61 @@
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#include "serd/serd.h"
+#include "sink.h"
#include "statement.h"
-#include <stddef.h>
+#include "serd/serd.h"
+
+#include <stdlib.h>
+
+SerdSink*
+serd_sink_new(void* handle)
+{
+ SerdSink* sink = (SerdSink*)calloc(1, sizeof(SerdSink));
+
+ sink->handle = handle;
+ return sink;
+}
+
+void
+serd_sink_free(SerdSink* sink)
+{
+ free(sink);
+}
+
+SerdStatus
+serd_sink_set_base_func(SerdSink* sink, SerdBaseSink base_func)
+{
+ sink->base = base_func;
+ return SERD_SUCCESS;
+}
+
+SerdStatus
+serd_sink_set_prefix_func(SerdSink* sink, SerdPrefixSink prefix_func)
+{
+ sink->prefix = prefix_func;
+ return SERD_SUCCESS;
+}
+
+SerdStatus
+serd_sink_set_statement_func(SerdSink* sink, SerdStatementSink statement_func)
+{
+ sink->statement = statement_func;
+ return SERD_SUCCESS;
+}
+
+SerdStatus
+serd_sink_set_end_func(SerdSink* sink, SerdEndSink end_func)
+{
+ sink->end = end_func;
+ return SERD_SUCCESS;
+}
SerdStatus
serd_sink_write_base(const SerdSink* sink, const SerdNode* uri)
{
- return sink->base(sink->handle, uri);
+ return sink->base ? sink->base(sink->handle, uri) : SERD_SUCCESS;
}
SerdStatus
@@ -31,7 +76,7 @@ serd_sink_write_prefix(const SerdSink* sink,
const SerdNode* name,
const SerdNode* uri)
{
- return sink->prefix(sink->handle, name, uri);
+ return sink->prefix ? sink->prefix(sink->handle, name, uri) : SERD_SUCCESS;
}
SerdStatus
@@ -39,7 +84,8 @@ serd_sink_write_statement(const SerdSink* sink,
const SerdStatementFlags flags,
const SerdStatement* statement)
{
- return sink->statement(sink->handle, flags, statement);
+ return sink->statement ? sink->statement(sink->handle, flags, statement)
+ : SERD_SUCCESS;
}
SerdStatus
@@ -52,11 +98,11 @@ serd_sink_write(const SerdSink* sink,
{
const SerdStatement statement = { { subject, predicate, object, graph },
NULL };
- return sink->statement(sink->handle, flags, &statement);
+ return serd_sink_write_statement(sink, flags, &statement);
}
SerdStatus
serd_sink_write_end(const SerdSink* sink, const SerdNode* node)
{
- return sink->end(sink->handle, node);
+ return sink->end ? sink->end(sink->handle, node) : SERD_SUCCESS;
}
diff --git a/src/sink.h b/src/sink.h
new file mode 100644
index 00000000..25dfb079
--- /dev/null
+++ b/src/sink.h
@@ -0,0 +1,33 @@
+/*
+ Copyright 2011-2020 David Robillard <http://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_SINK_H
+#define SERD_SINK_H
+
+#include "serd/serd.h"
+
+/**
+ An interface that receives a stream of RDF data.
+*/
+struct SerdSinkImpl {
+ void* handle;
+ SerdBaseSink base;
+ SerdPrefixSink prefix;
+ SerdStatementSink statement;
+ SerdEndSink end;
+};
+
+#endif // SERD_SINK_H
diff --git a/src/writer.c b/src/writer.c
index ccfdf989..062cb4c5 100644
--- a/src/writer.c
+++ b/src/writer.c
@@ -18,6 +18,7 @@
#include "env.h"
#include "node.h"
#include "serd_internal.h"
+#include "sink.h"
#include "stack.h"
#include "string_utils.h"
#include "system.h"
diff --git a/tests/serd_test.c b/tests/serd_test.c
index 7b1301d3..ea555950 100644
--- a/tests/serd_test.c
+++ b/tests/serd_test.c
@@ -109,12 +109,14 @@ test_read_chunks(void)
ReaderTest* const rt = (ReaderTest*)calloc(1, sizeof(ReaderTest));
FILE* const f = tmpfile();
static const char null = 0;
- SerdSink sink = {rt, NULL, NULL, test_sink, NULL};
- SerdReader* reader = serd_reader_new(world, SERD_TURTLE, &sink, 4096);
+ SerdSink* sink = serd_sink_new(rt);
+ SerdReader* reader = serd_reader_new(world, SERD_TURTLE, sink, 4096);
assert(reader);
assert(f);
+ serd_sink_set_statement_func(sink, test_sink);
+
SerdStatus st = serd_reader_start_stream(reader,
(SerdReadFunc)fread,
(SerdStreamErrorFunc)ferror,
@@ -162,6 +164,7 @@ test_read_chunks(void)
assert(rt->n_statements == 2);
serd_reader_free(reader);
+ serd_sink_free(sink);
fclose(f);
free(rt);
serd_world_free(world);
@@ -632,9 +635,9 @@ test_writer(const char* const path)
SerdNode* lit = serd_new_string("hello");
const SerdSink* iface = serd_writer_get_sink(writer);
- assert(iface->base(iface->handle, lit));
- assert(iface->prefix(iface->handle, lit, lit));
- assert(iface->end(iface->handle, NULL));
+ assert(serd_sink_write_base(iface, lit));
+ assert(serd_sink_write_prefix(iface, lit, lit));
+ assert(serd_sink_write_end(iface, NULL));
assert(serd_writer_get_env(writer) == env);
uint8_t buf[] = { 0xEF, 0xBF, 0xBD, 0 };
@@ -723,9 +726,12 @@ static void
test_reader(const char* path)
{
SerdWorld* world = serd_world_new();
- ReaderTest rt = { 0, NULL };
- SerdSink sink = { &rt, NULL, NULL, test_sink, NULL };
- SerdReader* reader = serd_reader_new(world, SERD_TURTLE, &sink, 4096);
+
+ ReaderTest rt = { 0, NULL };
+ SerdSink* sink = serd_sink_new(&rt);
+ serd_sink_set_statement_func(sink, test_sink);
+
+ SerdReader* reader = serd_reader_new(world, SERD_TURTLE, sink, 4096);
assert(reader);
SerdNode* g = serd_new_uri("http://example.org/");
@@ -746,6 +752,8 @@ test_reader(const char* path)
serd_reader_finish(reader);
serd_reader_free(reader);
+ serd_sink_free(sink);
+
serd_world_free(world);
}