aboutsummaryrefslogtreecommitdiffstats
path: root/include/serd/serd.h
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2021-01-13 20:00:25 +0100
committerDavid Robillard <d@drobilla.net>2021-03-08 23:23:06 -0500
commit468f7dc4294905d19f55c58c47ba91cd23bf357b (patch)
tree3531d4dbc53e3454534ea607dfa4f44d0f085f5d /include/serd/serd.h
parent229443778ffc6b26a13322983b81f4f1912427af (diff)
downloadserd-468f7dc4294905d19f55c58c47ba91cd23bf357b.tar.gz
serd-468f7dc4294905d19f55c58c47ba91cd23bf357b.tar.bz2
serd-468f7dc4294905d19f55c58c47ba91cd23bf357b.zip
WIP: Add extensible logging API
Diffstat (limited to 'include/serd/serd.h')
-rw-r--r--include/serd/serd.h132
1 files changed, 109 insertions, 23 deletions
diff --git a/include/serd/serd.h b/include/serd/serd.h
index 4cf00f02..04d8708b 100644
--- a/include/serd/serd.h
+++ b/include/serd/serd.h
@@ -67,6 +67,12 @@
SERD_API \
SERD_MALLOC_FUNC
+#if defined(__GNUC__)
+# define SERD_LOG_FUNC(fmt, arg1) __attribute__((format(printf, fmt, arg1)))
+#else
+# define SERD_LOG_FUNC(fmt, arg1)
+#endif
+
#ifdef __cplusplus
extern "C" {
# if defined(__GNUC__)
@@ -268,14 +274,6 @@ typedef struct {
size_t len; ///< Size of buffer in bytes
} SerdBuffer;
-/// An error description
-typedef struct {
- SerdStatus status; ///< Error code
- const SerdCursor* SERD_NULLABLE cursor; ///< Origin of error
- const char* SERD_NONNULL fmt; ///< Printf-style format string
- va_list* SERD_NONNULL args; ///< Arguments for fmt
-} SerdError;
-
/**
A parsed URI.
@@ -1050,15 +1048,6 @@ serd_node_compare(const SerdNode* SERD_NULLABLE a,
@{
*/
-/**
- Callback function for errors.
-
- @param handle Handle for user data.
- @param error Error description.
-*/
-typedef SerdStatus (*SerdErrorFunc)(void* SERD_NULLABLE handle,
- const SerdError* SERD_NONNULL error);
-
/// Type of a SerdEvent
typedef enum {
SERD_BASE = 1, ///< Base URI changed
@@ -1175,16 +1164,113 @@ const SerdNode* SERD_NONNULL
serd_world_get_blank(SerdWorld* SERD_NONNULL world);
/**
- Set a function to be called when errors occur.
+ @}
+ @defgroup serd_logging Logging
+ @{
+*/
+
+/// Log message level, compatible with syslog
+typedef enum {
+ SERD_LOG_LEVEL_EMERG, ///< Emergency, system is unusable
+ SERD_LOG_LEVEL_ALERT, ///< Action must be taken immediately
+ SERD_LOG_LEVEL_CRIT, ///< Critical condition
+ SERD_LOG_LEVEL_ERR, ///< Error
+ SERD_LOG_LEVEL_WARNING, ///< Warning
+ SERD_LOG_LEVEL_NOTICE, ///< Normal but significant condition
+ SERD_LOG_LEVEL_INFO, ///< Informational message
+ SERD_LOG_LEVEL_DEBUG ///< Debug message
+} SerdLogLevel;
+
+/**
+ A structured log field.
+
+ This can be used to pass additional information along with log messages.
+ Syslog-compatible keys should be used where possible, otherwise, keys should
+ be namespaced to prevent clashes.
+
+ Serd itself uses the following keys:
+ - ERRNO
+ - SERD_COL
+ - SERD_FILE
+ - SERD_LINE
+ - SERD_STATUS
+*/
+typedef struct {
+ const char* SERD_NONNULL key; ///< Field name
+ const char* SERD_NONNULL value; ///< Field value
+} SerdLogField;
+
+/**
+ A log entry (message).
+
+ This is the description of a log entry which is passed to log functions.
+ It is only valid in the stack frame it appears in, and may not be copied.
+*/
+typedef struct {
+ const char* SERD_NONNULL domain; ///< Library/program/module name
+ const SerdLogField* SERD_NULLABLE fields; ///< Extra log fields
+ const char* SERD_NONNULL fmt; ///< Printf-style format string
+ va_list* SERD_NONNULL args; ///< Arguments for `fmt`
+ SerdLogLevel level; ///< Log level
+ size_t n_fields; ///< Number of `fields`
+} SerdLogEntry;
+
+/**
+ Sink function for log messages.
+
+ @param handle Handle for user data.
+ @param entry Pointer to log entry description.
+*/
+typedef SerdStatus (*SerdLogFunc)(void* SERD_NULLABLE handle,
+ const SerdLogEntry* SERD_NONNULL entry);
+
+/// A SerdLogFunc that does nothing, for suppressing log output
+SERD_API
+SerdStatus
+serd_quiet_error_func(void* SERD_NULLABLE handle,
+ const SerdLogEntry* SERD_NONNULL entry);
+
+/// Return the value of the log field named `key`, or NULL if none exists
+SERD_PURE_API
+const char* SERD_NULLABLE
+serd_log_entry_get_field(const SerdLogEntry* SERD_NONNULL entry,
+ const char* SERD_NONNULL key);
+
+/**
+ Set a function to be called with log messages (typically errors).
- The `error_func` will be called with `handle` as its first argument. If
- no error function is set, errors are printed to stderr.
+ The `log_func` will be called with `handle` as its first argument. If
+ no function is set, messages are printed to stderr.
*/
SERD_API
void
-serd_world_set_error_func(SerdWorld* SERD_NONNULL world,
- SerdErrorFunc SERD_NULLABLE error_func,
- void* SERD_NULLABLE handle);
+serd_world_set_log_func(SerdWorld* SERD_NONNULL world,
+ SerdLogFunc SERD_NULLABLE log_func,
+ void* SERD_NULLABLE handle);
+
+/// Write a message to the log
+SERD_API
+SERD_LOG_FUNC(6, 0)
+SerdStatus
+serd_world_vlogf(const SerdWorld* SERD_NONNULL world,
+ const char* SERD_NONNULL domain,
+ SerdLogLevel level,
+ size_t n_fields,
+ const SerdLogField* SERD_NULLABLE fields,
+ const char* SERD_NONNULL fmt,
+ va_list args);
+
+/// Write a message to the log
+SERD_API
+SERD_LOG_FUNC(6, 7)
+SerdStatus
+serd_world_logf(const SerdWorld* SERD_NONNULL world,
+ const char* SERD_NONNULL domain,
+ SerdLogLevel level,
+ size_t n_fields,
+ const SerdLogField* SERD_NULLABLE fields,
+ const char* SERD_NONNULL fmt,
+ ...);
/**
@}