aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2019-10-14 19:18:17 +0200
committerDavid Robillard <d@drobilla.net>2019-12-20 10:26:55 -0500
commit97ee4b0c78e33d86bfaaaee6e485052e09910e5f (patch)
treed13f9d89703fc4de2d790828d224dfc35cdf54b3
parentaae660655a1786e89612312333f534fe6489eb27 (diff)
downloadserd-97ee4b0c78e33d86bfaaaee6e485052e09910e5f.tar.gz
serd-97ee4b0c78e33d86bfaaaee6e485052e09910e5f.tar.bz2
serd-97ee4b0c78e33d86bfaaaee6e485052e09910e5f.zip
Add function to SerdSink for freeing opaque handle
This can be used to associate dynamically allocated data with a sink and have it managed along with the sink's lifetime.
-rw-r--r--serd/serd.h6
-rw-r--r--serd/serd.hpp2
-rw-r--r--src/sink.c15
-rw-r--r--src/sink.h1
-rw-r--r--tests/overflow_test.c2
-rw-r--r--tests/read_chunk_test.c2
-rw-r--r--tests/serd_test.c6
-rw-r--r--tests/sink_test.c11
8 files changed, 33 insertions, 12 deletions
diff --git a/serd/serd.h b/serd/serd.h
index 7cf55f53..0ace8671 100644
--- a/serd/serd.h
+++ b/serd/serd.h
@@ -1102,6 +1102,9 @@ serd_env_write_prefixes(const SerdEnv* env, const SerdSink* sink);
@{
*/
+/// Function to free an opaque handle
+typedef void (*SerdFreeFunc)(void* ptr);
+
/**
Create a new sink
@@ -1109,11 +1112,12 @@ serd_env_write_prefixes(const SerdEnv* env, const SerdSink* sink);
serd_sink_set_*_func functions to set handlers for various events.
@param handle Opaque handle that will be passed to sink functions.
+ @param free_handle Free function to call on handle in serd_sink_free().
@param env Environment for sink, updated as base uri or prefixes change.
*/
SERD_API
SerdSink*
-serd_sink_new(void* handle, SerdEnv* env);
+serd_sink_new(void* handle, SerdFreeFunc free_handle, SerdEnv* env);
/// Free `sink`
SERD_API
diff --git a/serd/serd.hpp b/serd/serd.hpp
index f0b55fe5..190f5eb1 100644
--- a/serd/serd.hpp
+++ b/serd/serd.hpp
@@ -1050,7 +1050,7 @@ public:
class Sink : public SinkWrapper<SerdSink>
{
public:
- Sink() : SinkWrapper(serd_sink_new(this, nullptr)) {}
+ Sink() : SinkWrapper(serd_sink_new(this, nullptr, nullptr)) {}
// EnvView env() const { return serd_sink_get_env(cobj()); }
diff --git a/src/sink.c b/src/sink.c
index e62136d9..1477412b 100644
--- a/src/sink.c
+++ b/src/sink.c
@@ -23,12 +23,13 @@
#include <stdlib.h>
SerdSink*
-serd_sink_new(void* handle, SerdEnv* env)
+serd_sink_new(void* handle, SerdFreeFunc free_handle, SerdEnv* env)
{
SerdSink* sink = (SerdSink*)calloc(1, sizeof(SerdSink));
- sink->handle = handle;
- sink->env = env;
+ sink->handle = handle;
+ sink->free_handle = free_handle;
+ sink->env = env;
return sink;
}
@@ -36,7 +37,13 @@ serd_sink_new(void* handle, SerdEnv* env)
void
serd_sink_free(SerdSink* sink)
{
- free(sink);
+ if (sink) {
+ if (sink->free_handle) {
+ sink->free_handle(sink->handle);
+ }
+
+ free(sink);
+ }
}
const SerdEnv*
diff --git a/src/sink.h b/src/sink.h
index 1aeafc0a..a4349bbf 100644
--- a/src/sink.h
+++ b/src/sink.h
@@ -24,6 +24,7 @@
*/
struct SerdSinkImpl {
void* handle;
+ SerdFreeFunc free_handle;
SerdEnv* env;
SerdBaseFunc base;
SerdPrefixFunc prefix;
diff --git a/tests/overflow_test.c b/tests/overflow_test.c
index e3031b7e..98582597 100644
--- a/tests/overflow_test.c
+++ b/tests/overflow_test.c
@@ -58,7 +58,7 @@ main(void)
{NULL, 0}};
SerdWorld* world = serd_world_new();
- SerdSink* sink = serd_sink_new(NULL, NULL);
+ SerdSink* sink = serd_sink_new(NULL, NULL, NULL);
for (const Test* t = tests; t->str; ++t) {
const SerdStatus st = test(world, sink, t->str, t->stack_size);
diff --git a/tests/read_chunk_test.c b/tests/read_chunk_test.c
index f38f4cb8..c05b3591 100644
--- a/tests/read_chunk_test.c
+++ b/tests/read_chunk_test.c
@@ -74,7 +74,7 @@ int
main(void)
{
SerdWorld* world = serd_world_new();
- SerdSink* sink = serd_sink_new(NULL, NULL);
+ SerdSink* sink = serd_sink_new(NULL, NULL, NULL);
serd_sink_set_base_func(sink, on_base);
serd_sink_set_prefix_func(sink, on_prefix);
serd_sink_set_statement_func(sink, on_statement);
diff --git a/tests/serd_test.c b/tests/serd_test.c
index fe24f64a..1d05a789 100644
--- a/tests/serd_test.c
+++ b/tests/serd_test.c
@@ -106,7 +106,7 @@ test_read_chunks(void)
size_t n_statements = 0;
FILE* const f = tmpfile();
static const char null = 0;
- SerdSink* sink = serd_sink_new(&n_statements, NULL);
+ SerdSink* sink = serd_sink_new(&n_statements, NULL, NULL);
assert(sink);
serd_sink_set_statement_func(sink, count_statements);
@@ -585,7 +585,7 @@ test_env(void)
assert(serd_env_set_prefix(env, b, lit));
size_t n_prefixes = 0;
- SerdSink* count_prefixes_sink = serd_sink_new(&n_prefixes, NULL);
+ SerdSink* count_prefixes_sink = serd_sink_new(&n_prefixes, NULL, NULL);
serd_sink_set_prefix_func(count_prefixes_sink, count_prefixes);
serd_env_set_prefix(env, pre, eg);
serd_env_write_prefixes(env, count_prefixes_sink);
@@ -754,7 +754,7 @@ test_reader(const char* path)
SerdWorld* world = serd_world_new();
size_t n_statements = 0;
- SerdSink* sink = serd_sink_new(&n_statements, NULL);
+ SerdSink* sink = serd_sink_new(&n_statements, NULL, NULL);
serd_sink_set_statement_func(sink, count_statements);
SerdReader* reader = serd_reader_new(world, SERD_TURTLE, 0, sink, 4096);
diff --git a/tests/sink_test.c b/tests/sink_test.c
index fd38fc99..46bbd27c 100644
--- a/tests/sink_test.c
+++ b/tests/sink_test.c
@@ -20,6 +20,7 @@
#include <assert.h>
#include <stddef.h>
+#include <string.h>
#define NS_EG "http://example.org/"
@@ -33,6 +34,12 @@ typedef struct
SerdStatus return_status;
} State;
+static void
+clear_state(void* ptr)
+{
+ memset(ptr, 0, sizeof(State));
+}
+
static SerdStatus
on_base(void* handle, const SerdNode* uri)
{
@@ -89,7 +96,7 @@ main(void)
serd_statement_new(base, uri, blank, NULL, NULL);
State state = {0, 0, 0, 0, 0, SERD_SUCCESS};
- SerdSink* sink = serd_sink_new(&state, env);
+ SerdSink* sink = serd_sink_new(&state, clear_state, env);
assert(serd_sink_get_env(sink) == env);
@@ -121,6 +128,8 @@ main(void)
assert(serd_node_equals(state.last_end, blank));
serd_sink_free(sink);
+ assert(!state.last_base);
+
serd_statement_free(statement);
serd_env_free(env);
serd_nodes_free(nodes);