diff options
author | David Robillard <d@drobilla.net> | 2019-10-14 19:18:17 +0200 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2019-12-20 10:26:55 -0500 |
commit | 97ee4b0c78e33d86bfaaaee6e485052e09910e5f (patch) | |
tree | d13f9d89703fc4de2d790828d224dfc35cdf54b3 | |
parent | aae660655a1786e89612312333f534fe6489eb27 (diff) | |
download | serd-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.h | 6 | ||||
-rw-r--r-- | serd/serd.hpp | 2 | ||||
-rw-r--r-- | src/sink.c | 15 | ||||
-rw-r--r-- | src/sink.h | 1 | ||||
-rw-r--r-- | tests/overflow_test.c | 2 | ||||
-rw-r--r-- | tests/read_chunk_test.c | 2 | ||||
-rw-r--r-- | tests/serd_test.c | 6 | ||||
-rw-r--r-- | tests/sink_test.c | 11 |
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()); } @@ -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* @@ -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); |