diff options
author | David Robillard <d@drobilla.net> | 2021-02-20 19:18:28 -0500 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2023-12-02 18:49:07 -0500 |
commit | d62c7dc45af3256c6cd70d12a11e91b5b872c7db (patch) | |
tree | 63f9f1cc8f8900ad59b5bd8f07b70e6008522d21 /include | |
parent | ab1aa43256fac3e017212abe6f9d845bf74c024c (diff) | |
download | serd-d62c7dc45af3256c6cd70d12a11e91b5b872c7db.tar.gz serd-d62c7dc45af3256c6cd70d12a11e91b5b872c7db.tar.bz2 serd-d62c7dc45af3256c6cd70d12a11e91b5b872c7db.zip |
Replace multiple stream callbacks with SerdEvent
This makes plumbing easier since everything goes through the same "stream" and
only one callback is required to handling everything. It's also more easily
extensible in case more event types need to be added in the future.
Diffstat (limited to 'include')
-rw-r--r-- | include/serd/env.h | 9 | ||||
-rw-r--r-- | include/serd/event.h | 99 | ||||
-rw-r--r-- | include/serd/serd.h | 1 | ||||
-rw-r--r-- | include/serd/sink.h | 31 | ||||
-rw-r--r-- | include/serd/status.h | 1 | ||||
-rw-r--r-- | include/serd/writer.h | 9 |
6 files changed, 113 insertions, 37 deletions
diff --git a/include/serd/env.h b/include/serd/env.h index db2c1150..ca02523b 100644 --- a/include/serd/env.h +++ b/include/serd/env.h @@ -79,11 +79,10 @@ SERD_API SerdNode* SERD_ALLOCATED serd_env_expand_node(const SerdEnv* SERD_NULLABLE env, const SerdNode* SERD_NONNULL node); -/// Call `func` for each prefix defined in `env` -SERD_API void -serd_env_foreach(const SerdEnv* SERD_NONNULL env, - SerdPrefixFunc SERD_NONNULL func, - void* SERD_NULLABLE handle); +/// Write all prefixes in `env` to `sink` +SERD_API SerdStatus +serd_env_write_prefixes(const SerdEnv* SERD_NONNULL env, + const SerdSink* SERD_NONNULL sink); /** @} diff --git a/include/serd/event.h b/include/serd/event.h new file mode 100644 index 00000000..0c6437f6 --- /dev/null +++ b/include/serd/event.h @@ -0,0 +1,99 @@ +// Copyright 2011-2022 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC + +#ifndef SERD_EVENT_H +#define SERD_EVENT_H + +#include "serd/attributes.h" +#include "serd/node.h" +#include "serd/statement.h" +#include "serd/status.h" + +SERD_BEGIN_DECLS + +/** + @defgroup serd_event Events + @ingroup serd_streaming + @{ +*/ + +/// Type of a SerdEvent +typedef enum { + SERD_BASE = 1, ///< Base URI changed + SERD_PREFIX = 2, ///< New URI prefix + SERD_STATEMENT = 3, ///< Statement + SERD_END = 4, ///< End of anonymous node +} SerdEventType; + +/** + Event for base URI changes. + + Emitted whenever the base URI changes. +*/ +typedef struct { + SerdEventType type; ///< #SERD_BASE + const SerdNode* SERD_NONNULL uri; ///< Base URI +} SerdBaseEvent; + +/** + Event for namespace definitions. + + Emitted whenever a prefix is defined. +*/ +typedef struct { + SerdEventType type; ///< #SERD_PREFIX + const SerdNode* SERD_NONNULL name; ///< Prefix name + const SerdNode* SERD_NONNULL uri; ///< Namespace URI +} SerdPrefixEvent; + +/** + Event for statements. + + Emitted for every statement. +*/ +typedef struct { + SerdEventType type; ///< #SERD_STATEMENT + SerdStatementFlags flags; ///< Flags for pretty-printing + const SerdStatement* SERD_NONNULL statement; ///< Statement +} SerdStatementEvent; + +/** + Event for the end of anonymous node descriptions. + + This is emitted to indicate that the given anonymous node will no longer be + described. This is used by the writer which may, for example, need to + write a delimiter. +*/ +typedef struct { + SerdEventType type; ///< #SERD_END + const SerdNode* SERD_NONNULL node; ///< Anonymous node that is finished +} SerdEndEvent; + +/** + An event in a data stream. + + Streams of data are represented as a series of events. Events represent + everything that can occur in an RDF document, and are used to plumb together + different components. For example, when parsing a document, a reader emits + a stream of events which can be sent to a writer to rewrite a document, or + to an inserter to build a model in memory. +*/ +typedef union { + SerdEventType type; ///< Event type (always set) + SerdBaseEvent base; ///< Base URI changed + SerdPrefixEvent prefix; ///< New namespace prefix + SerdStatementEvent statement; ///< Statement + SerdEndEvent end; ///< End of anonymous node +} SerdEvent; + +/// Function for handling events +typedef SerdStatus (*SerdEventFunc)(void* SERD_NULLABLE handle, + const SerdEvent* SERD_NONNULL event); + +/** + @} +*/ + +SERD_END_DECLS + +#endif // SERD_EVENT_H diff --git a/include/serd/serd.h b/include/serd/serd.h index 8de151c6..5b13f676 100644 --- a/include/serd/serd.h +++ b/include/serd/serd.h @@ -69,6 +69,7 @@ */ #include "serd/env.h" +#include "serd/event.h" #include "serd/sink.h" /** diff --git a/include/serd/sink.h b/include/serd/sink.h index 95979b50..09fa7858 100644 --- a/include/serd/sink.h +++ b/include/serd/sink.h @@ -5,6 +5,7 @@ #define SERD_SINK_H #include "serd/attributes.h" +#include "serd/event.h" #include "serd/node.h" #include "serd/statement.h" #include "serd/status.h" @@ -63,39 +64,23 @@ typedef void (*SerdFreeFunc)(void* SERD_NULLABLE ptr); /** 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. + @param event_func Function that will be called for every event. @param free_handle Free function to call on handle in serd_sink_free(). */ SERD_API SerdSink* SERD_ALLOCATED -serd_sink_new(void* SERD_NULLABLE handle, - SerdFreeFunc SERD_NULLABLE free_handle); +serd_sink_new(void* SERD_NULLABLE handle, + SerdEventFunc SERD_NULLABLE event_func, + SerdFreeFunc SERD_NULLABLE free_handle); /// Free `sink` SERD_API void serd_sink_free(SerdSink* SERD_NULLABLE sink); -/// Set a function to be called when the base URI changes -SERD_API SerdStatus -serd_sink_set_base_func(SerdSink* SERD_NONNULL sink, - SerdBaseFunc SERD_NULLABLE base_func); - -/// Set a function to be called when a namespace prefix is defined -SERD_API SerdStatus -serd_sink_set_prefix_func(SerdSink* SERD_NONNULL sink, - SerdPrefixFunc SERD_NULLABLE prefix_func); - -/// Set a function to be called when a statement is emitted -SERD_API SerdStatus -serd_sink_set_statement_func(SerdSink* SERD_NONNULL sink, - SerdStatementFunc SERD_NULLABLE statement_func); - -/// Set a function to be called when an anonymous node ends +/// Send an event to the sink SERD_API SerdStatus -serd_sink_set_end_func(SerdSink* SERD_NONNULL sink, - SerdEndFunc SERD_NULLABLE end_func); +serd_sink_write_event(const SerdSink* SERD_NONNULL sink, + const SerdEvent* SERD_NONNULL event); /// Set the base URI SERD_API SerdStatus diff --git a/include/serd/status.h b/include/serd/status.h index 3ebdaf8f..e21297cd 100644 --- a/include/serd/status.h +++ b/include/serd/status.h @@ -34,6 +34,7 @@ typedef enum { SERD_BAD_STACK, ///< Stack overflow SERD_BAD_TEXT, ///< Invalid text encoding SERD_BAD_CALL, ///< Invalid call + SERD_BAD_EVENT, ///< Invalid event in stream SERD_BAD_URI, ///< Invalid or unresolved URI SERD_BAD_DATA, ///< Invalid data SERD_BAD_LITERAL, ///< Invalid literal diff --git a/include/serd/writer.h b/include/serd/writer.h index 96059932..db402fea 100644 --- a/include/serd/writer.h +++ b/include/serd/writer.h @@ -72,15 +72,6 @@ serd_writer_chop_blank_prefix(SerdWriter* SERD_NONNULL writer, const char* SERD_NULLABLE prefix); /** - Set the current output base URI, and emit a directive if applicable. - - Note this function can be safely casted to #SerdBaseFunc. -*/ -SERD_API SerdStatus -serd_writer_set_base_uri(SerdWriter* SERD_NONNULL writer, - const SerdNode* SERD_NULLABLE uri); - -/** Set the current root URI. The root URI should be a prefix of the base URI. The path of the root URI |