diff options
author | Daniel Silverstone <dsilvers@digital-scurf.org> | 2017-06-10 20:48:38 +0100 |
---|---|---|
committer | Daniel Silverstone <dsilvers@digital-scurf.org> | 2017-06-10 20:48:38 +0100 |
commit | 8052642eadfb95b244f978b10889dff51f9133f5 (patch) | |
tree | c8287316266cf98b5886cbef2fa5a44551d40982 /src | |
parent | 551cf378a93588d42732983ec30716e14afef945 (diff) | |
download | libnslog-8052642eadfb95b244f978b10889dff51f9133f5.tar.gz libnslog-8052642eadfb95b244f978b10889dff51f9133f5.tar.bz2 |
Rework to only allocate one thing in the corked state and nothing in the uncorked state
Diffstat (limited to 'src')
-rw-r--r-- | src/core.c | 100 |
1 files changed, 58 insertions, 42 deletions
@@ -20,12 +20,14 @@ #include <stdlib.h> #include <string.h> + static bool nslog__corked = true; static struct nslog_cork_chain { struct nslog_cork_chain *next; - nslog_entry_t *entry; -} *nslog__cork_chain = NULL; + nslog_entry_context_t context; + char message[0]; /* NUL terminated */ +} *nslog__cork_chain = NULL, *nslog__cork_chain_last = NULL; static nslog_callback nslog__cb = NULL; static void *nslog__cb_ctx = NULL; @@ -70,58 +72,56 @@ static void nslog__normalise_category(nslog_category_t *cat) } } -static void nslog__deliver(nslog_entry_t *entry) +static void nslog__log_corked(nslog_entry_context_t *ctx, + int measured_len, + const char *fmt, + va_list args) +{ + /* If corked, we need to store a copy */ + struct nslog_cork_chain *newcork = malloc(sizeof(*newcork) + measured_len + 1); + if (newcork == NULL) { + /* Wow, something went wrong */ + return; + } + newcork->context = *ctx; + vsprintf(newcork->message, fmt, args); + if (nslog__cork_chain == NULL) { + nslog__cork_chain = nslog__cork_chain_last = newcork; + } else { + nslog__cork_chain_last->next = newcork; + nslog__cork_chain_last = newcork; + } +} + +static void nslog__log_uncorked(nslog_entry_context_t *ctx, + const char *fmt, + va_list args) { /* TODO: Add filtering here */ if (nslog__cb != NULL) { - if (entry->category->name == NULL) { - nslog__normalise_category(entry->category); + if (ctx->category->name == NULL) { + nslog__normalise_category(ctx->category); } - (*nslog__cb)(nslog__cb_ctx, entry); + (*nslog__cb)(nslog__cb_ctx, ctx, fmt, args); } } -void nslog__log(nslog_category_t *category, - nslog_level level, - const char *filename, - int lineno, - const char *funcname, +void nslog__log(nslog_entry_context_t *ctx, const char *pattern, ...) { va_list ap; va_start(ap, pattern); - va_list ap2; - va_copy(ap2, ap); - int slen = vsnprintf(NULL, 0, pattern, ap); - va_end(ap); - nslog_entry_t *entry = malloc(sizeof(nslog_entry_t) + slen + 1); - if (entry == NULL) { - /* We're at ENOMEM! log entry is lost */ - va_end(ap2); - return; - } - entry->category = category; - entry->level = level; - entry->filename = filename; - entry->funcname = funcname; - entry->lineno = lineno; - vsprintf(entry->message, pattern, ap2); - va_end(ap2); if (nslog__corked) { - struct nslog_cork_chain *chained = malloc(sizeof(struct nslog_cork_chain)); - if (chained == NULL) { - /* ENOMEM during corked operation! wow */ - free(entry); - return; - } - chained->next = nslog__cork_chain; - chained->entry = entry; - nslog__cork_chain = chained; + va_list ap2; + va_copy(ap2, ap); + int slen = vsnprintf(NULL, 0, pattern, ap); + va_end(ap); + nslog__log_corked(ctx, slen, pattern, ap2); + va_end(ap2); } else { - /* Not corked */ - nslog__deliver(entry); - free(entry); + nslog__log_uncorked(ctx, pattern, ap); + va_end(ap); } } @@ -133,14 +133,30 @@ nslog_error nslog_set_render_callback(nslog_callback cb, void *context) return NSLOG_NO_ERROR; } + +static void __nslog__deliver_corked_entry(nslog_entry_context_t *ctx, + const char *fmt, + ...) +{ + va_list args; + va_start(args, fmt); + if (nslog__cb != NULL) { + (*nslog__cb)(nslog__cb_ctx, ctx, fmt, args); + } + va_end(args); +} + nslog_error nslog_uncork() { if (nslog__corked) { while (nslog__cork_chain != NULL) { struct nslog_cork_chain *ent = nslog__cork_chain; nslog__cork_chain = ent->next; - nslog__deliver(ent->entry); - free(ent->entry); + if (ent->context.category->name == NULL) { + nslog__normalise_category(ent->context.category); + } + __nslog__deliver_corked_entry(&ent->context, + "%s", ent->message); free(ent); } nslog__corked = false; |