summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDaniel Silverstone <dsilvers@digital-scurf.org>2017-06-10 18:11:25 +0100
committerDaniel Silverstone <dsilvers@digital-scurf.org>2017-06-10 18:11:25 +0100
commit551cf378a93588d42732983ec30716e14afef945 (patch)
tree0e8e261afb40a4a7f137408546bdaeb63d2e3eb1 /src
downloadlibnslog-551cf378a93588d42732983ec30716e14afef945.tar.gz
libnslog-551cf378a93588d42732983ec30716e14afef945.tar.bz2
Initial version
Diffstat (limited to 'src')
-rw-r--r--src/Makefile3
-rw-r--r--src/core.c150
2 files changed, 153 insertions, 0 deletions
diff --git a/src/Makefile b/src/Makefile
new file mode 100644
index 0000000..45ecb90
--- /dev/null
+++ b/src/Makefile
@@ -0,0 +1,3 @@
+DIR_SOURCES := core.c
+
+include $(NSBUILD)/Makefile.subdir
diff --git a/src/core.c b/src/core.c
new file mode 100644
index 0000000..0665195
--- /dev/null
+++ b/src/core.c
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2017 Daniel Silverstone <dsilvers@netsurf-browser.org>
+ *
+ * This file is part of libnslog.
+ *
+ * Licensed under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ */
+
+/**
+ * \file
+ * NetSurf Logging Core
+ */
+
+#include "nslog/nslog.h"
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdarg.h>
+#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;
+
+static nslog_callback nslog__cb = NULL;
+static void *nslog__cb_ctx = NULL;
+
+static nslog_category_t *nslog__all_categories = NULL;
+
+const char *nslog_level_name(nslog_level level)
+{
+ switch (level) {
+ case NSLOG_LEVEL_DEEPDEBUG:
+ return "DEEPDEBUG";
+ case NSLOG_LEVEL_DEBUG:
+ return "DEBUG";
+ case NSLOG_LEVEL_VERBOSE:
+ return "VERBOSE";
+ case NSLOG_LEVEL_INFO:
+ return "INFO";
+ case NSLOG_LEVEL_WARNING:
+ return "WARNING";
+ case NSLOG_LEVEL_ERROR:
+ return "ERROR";
+ case NSLOG_LEVEL_CRITICAL:
+ return "CRITICAL";
+ };
+
+ return "**UNKNOWN**";
+}
+
+
+static void nslog__normalise_category(nslog_category_t *cat)
+{
+ if (cat->parent == NULL) {
+ cat->name = strdup(cat->cat_name);
+ } else {
+ nslog__normalise_category(cat->parent);
+ cat->name = malloc(strlen(cat->parent->name) + strlen(cat->cat_name) + 2);
+ strcpy(cat->name, cat->parent->name);
+ strcat(cat->name, "/");
+ strcat(cat->name, cat->cat_name);
+ cat->next = nslog__all_categories;
+ nslog__all_categories = cat;
+ }
+}
+
+static void nslog__deliver(nslog_entry_t *entry)
+{
+ /* TODO: Add filtering here */
+ if (nslog__cb != NULL) {
+ if (entry->category->name == NULL) {
+ nslog__normalise_category(entry->category);
+ }
+ (*nslog__cb)(nslog__cb_ctx, entry);
+ }
+}
+
+void nslog__log(nslog_category_t *category,
+ nslog_level level,
+ const char *filename,
+ int lineno,
+ const char *funcname,
+ 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;
+ } else {
+ /* Not corked */
+ nslog__deliver(entry);
+ free(entry);
+ }
+}
+
+nslog_error nslog_set_render_callback(nslog_callback cb, void *context)
+{
+ nslog__cb = cb;
+ nslog__cb_ctx = context;
+
+ return NSLOG_NO_ERROR;
+}
+
+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);
+ free(ent);
+ }
+ nslog__corked = false;
+ }
+ return NSLOG_NO_ERROR;
+}
+