Add support for an application defined logging function.
An application can now register an application defined callback function, which will perform the actual logging. This provides additional flexibility compared to logging to stderr with a hardcoded format. Applications can now easily display the messages in their user interface, customize the format, etc. Although the internal logging function is a printf like function, the arguments are converted into a plain string before being passed to the callback function. This greatly improves interoperability with programming languages which don't support C style variadic functions (e.g. Python, C#, etc).
This commit is contained in:
parent
0f6d23757f
commit
43cd111198
@ -39,6 +39,8 @@ typedef enum dc_loglevel_t {
|
||||
DC_LOGLEVEL_ALL
|
||||
} dc_loglevel_t;
|
||||
|
||||
typedef void (*dc_logfunc_t) (dc_context_t *context, dc_loglevel_t loglevel, const char *file, unsigned int line, const char *function, const char *message, void *userdata);
|
||||
|
||||
dc_status_t
|
||||
dc_context_new (dc_context_t **context);
|
||||
|
||||
@ -48,6 +50,9 @@ dc_context_free (dc_context_t *context);
|
||||
dc_status_t
|
||||
dc_context_set_loglevel (dc_context_t *context, dc_loglevel_t loglevel);
|
||||
|
||||
dc_status_t
|
||||
dc_context_set_logfunc (dc_context_t *context, dc_logfunc_t logfunc, void *userdata);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
@ -28,8 +28,19 @@
|
||||
|
||||
struct dc_context_t {
|
||||
dc_loglevel_t loglevel;
|
||||
dc_logfunc_t logfunc;
|
||||
void *userdata;
|
||||
char msg[4096];
|
||||
};
|
||||
|
||||
static void
|
||||
logfunc (dc_context_t *context, dc_loglevel_t loglevel, const char *file, unsigned int line, const char *function, const char *msg, void *userdata)
|
||||
{
|
||||
const char *loglevels[] = {"NONE", "ERROR", "WARNING", "INFO", "DEBUG", "ALL"};
|
||||
|
||||
fprintf (stderr, "%s: %s [in %s:%d (%s)]\n", loglevels[loglevel], msg, file, line, function);
|
||||
}
|
||||
|
||||
dc_status_t
|
||||
dc_context_new (dc_context_t **out)
|
||||
{
|
||||
@ -43,6 +54,10 @@ dc_context_new (dc_context_t **out)
|
||||
return DC_STATUS_NOMEMORY;
|
||||
|
||||
context->loglevel = DC_LOGLEVEL_WARNING;
|
||||
context->logfunc = logfunc;
|
||||
context->userdata = NULL;
|
||||
|
||||
memset (context->msg, 0, sizeof (context->msg));
|
||||
|
||||
*out = context;
|
||||
|
||||
@ -68,6 +83,18 @@ dc_context_set_loglevel (dc_context_t *context, dc_loglevel_t loglevel)
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
dc_status_t
|
||||
dc_context_set_logfunc (dc_context_t *context, dc_logfunc_t logfunc, void *userdata)
|
||||
{
|
||||
if (context == NULL)
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
context->logfunc = logfunc;
|
||||
context->userdata = userdata;
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
dc_status_t
|
||||
dc_context_log (dc_context_t *context, dc_loglevel_t loglevel, const char *file, unsigned int line, const char *function, const char *format, ...)
|
||||
{
|
||||
@ -79,9 +106,14 @@ dc_context_log (dc_context_t *context, dc_loglevel_t loglevel, const char *file,
|
||||
if (loglevel > context->loglevel)
|
||||
return DC_STATUS_SUCCESS;
|
||||
|
||||
if (context->logfunc == NULL)
|
||||
return DC_STATUS_SUCCESS;
|
||||
|
||||
va_start (ap, format);
|
||||
vfprintf (stderr, format, ap);
|
||||
vsnprintf (context->msg, sizeof (context->msg), format, ap);
|
||||
va_end (ap);
|
||||
|
||||
context->logfunc (context, loglevel, file, line, function, context->msg, context->userdata);
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
@ -20,6 +20,7 @@ dc_datetime_mktime
|
||||
dc_context_new
|
||||
dc_context_free
|
||||
dc_context_set_loglevel
|
||||
dc_context_set_logfunc
|
||||
|
||||
dc_iterator_next
|
||||
dc_iterator_free
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user