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:
Jef Driesen 2012-05-27 23:46:30 +02:00
parent 0f6d23757f
commit 43cd111198
3 changed files with 39 additions and 1 deletions

View File

@ -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 */

View File

@ -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;
}

View File

@ -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