summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDaniel Silverstone <dsilvers@digital-scurf.org>2017-06-11 10:08:37 +0100
committerDaniel Silverstone <dsilvers@digital-scurf.org>2017-06-11 10:08:37 +0100
commit8b4ce0ba86d0396bde2546dd248c863876da4106 (patch)
tree72ac2147cda97ddac20144a60e7b0644a0cc303f /src
parent8052642eadfb95b244f978b10889dff51f9133f5 (diff)
downloadlibnslog-8b4ce0ba86d0396bde2546dd248c863876da4106.tar.gz
libnslog-8b4ce0ba86d0396bde2546dd248c863876da4106.tar.bz2
Another step toward filters working
Diffstat (limited to 'src')
-rw-r--r--src/Makefile2
-rw-r--r--src/core.c28
-rw-r--r--src/filter.c310
-rw-r--r--src/nslog_internal.h29
4 files changed, 352 insertions, 17 deletions
diff --git a/src/Makefile b/src/Makefile
index 45ecb90..7fbad1c 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -1,3 +1,3 @@
-DIR_SOURCES := core.c
+DIR_SOURCES := core.c filter.c
include $(NSBUILD)/Makefile.subdir
diff --git a/src/core.c b/src/core.c
index ee5f2bc..978f169 100644
--- a/src/core.c
+++ b/src/core.c
@@ -4,7 +4,7 @@
* This file is part of libnslog.
*
* Licensed under the MIT License,
- * http://www.opensource.org/licenses/mit-license.php
+ * http://www.opensource.org/licenses/mit-license.php
*/
/**
@@ -12,21 +12,14 @@
* NetSurf Logging Core
*/
-#include "nslog/nslog.h"
-
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
-
+#include "nslog_internal.h"
static bool nslog__corked = true;
static struct nslog_cork_chain {
struct nslog_cork_chain *next;
nslog_entry_context_t context;
- char message[0]; /* NUL terminated */
+ char message[0]; /* NUL terminated */
} *nslog__cork_chain = NULL, *nslog__cork_chain_last = NULL;
static nslog_callback nslog__cb = NULL;
@@ -52,7 +45,7 @@ const char *nslog_level_name(nslog_level level)
case NSLOG_LEVEL_CRITICAL:
return "CRITICAL";
};
-
+
return "**UNKNOWN**";
}
@@ -61,6 +54,7 @@ static void nslog__normalise_category(nslog_category_t *cat)
{
if (cat->parent == NULL) {
cat->name = strdup(cat->cat_name);
+ cat->namelen = strlen(cat->name);
} else {
nslog__normalise_category(cat->parent);
cat->name = malloc(strlen(cat->parent->name) + strlen(cat->cat_name) + 2);
@@ -68,6 +62,7 @@ static void nslog__normalise_category(nslog_category_t *cat)
strcat(cat->name, "/");
strcat(cat->name, cat->cat_name);
cat->next = nslog__all_categories;
+ cat->namelen = strlen(cat->name);
nslog__all_categories = cat;
}
}
@@ -102,7 +97,8 @@ static void nslog__log_uncorked(nslog_entry_context_t *ctx,
if (ctx->category->name == NULL) {
nslog__normalise_category(ctx->category);
}
- (*nslog__cb)(nslog__cb_ctx, ctx, fmt, args);
+ if (nslog__filter_matches(ctx))
+ (*nslog__cb)(nslog__cb_ctx, ctx, fmt, args);
}
}
@@ -129,7 +125,7 @@ nslog_error nslog_set_render_callback(nslog_callback cb, void *context)
{
nslog__cb = cb;
nslog__cb_ctx = context;
-
+
return NSLOG_NO_ERROR;
}
@@ -155,12 +151,12 @@ nslog_error nslog_uncork()
if (ent->context.category->name == NULL) {
nslog__normalise_category(ent->context.category);
}
- __nslog__deliver_corked_entry(&ent->context,
- "%s", ent->message);
+ if (nslog__filter_matches(&ent->context))
+ __nslog__deliver_corked_entry(&ent->context,
+ "%s", ent->message);
free(ent);
}
nslog__corked = false;
}
return NSLOG_NO_ERROR;
}
-
diff --git a/src/filter.c b/src/filter.c
new file mode 100644
index 0000000..1dc4e81
--- /dev/null
+++ b/src/filter.c
@@ -0,0 +1,310 @@
+/*
+ * 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 Filters
+ */
+
+#include "nslog_internal.h"
+
+typedef enum {
+ /* Fundamentals */
+ NSLFK_CATEGORY = 0,
+ NSLFK_LEVEL,
+ NSLFK_FILENAME,
+ NSLFK_DIRNAME,
+ NSLFK_FUNCNAME,
+ /* logical operations */
+ NSLFK_AND,
+ NSLFK_OR,
+ NSLFK_XOR,
+ NSLFK_NOT,
+} nslog_filter_kind;
+
+struct nslog_filter_s {
+ nslog_filter_kind kind;
+ int refcount;
+ union {
+ struct {
+ char *ptr;
+ int len;
+ } str;
+ nslog_level level;
+ nslog_filter_t *unary_input;
+ struct {
+ nslog_filter_t *input1;
+ nslog_filter_t *input2;
+ } binary;
+ } params;
+};
+
+static nslog_filter_t *nslog__active_filter = NULL;
+
+nslog_error nslog_filter_category_new(const char *catname,
+ nslog_filter_t **filter)
+{
+ nslog_filter_t *ret = calloc(sizeof(*ret), 1);
+ if (ret == NULL)
+ return NSLOG_NO_MEMORY;
+ ret->kind = NSLFK_CATEGORY;
+ ret->refcount = 1;
+ ret->params.str.ptr = strdup(catname);
+ ret->params.str.len = strlen(catname);
+ if (ret->params.str.ptr == NULL) {
+ free(ret);
+ return NSLOG_NO_MEMORY;
+ }
+ *filter = ret;
+ return NSLOG_NO_ERROR;
+}
+
+nslog_error nslog_filter_level_new(nslog_level level,
+ nslog_filter_t **filter)
+{
+ nslog_filter_t *ret = calloc(sizeof(*ret), 1);
+ if (ret == NULL)
+ return NSLOG_NO_MEMORY;
+ ret->kind = NSLFK_LEVEL;
+ ret->refcount = 1;
+ ret->params.level = level;
+ *filter = ret;
+ return NSLOG_NO_ERROR;
+}
+
+nslog_error nslog_filter_filename_new(const char *filename,
+ nslog_filter_t **filter)
+{
+ nslog_filter_t *ret = calloc(sizeof(*ret), 1);
+ if (ret == NULL)
+ return NSLOG_NO_MEMORY;
+ ret->kind = NSLFK_FILENAME;
+ ret->refcount = 1;
+ ret->params.str.ptr = strdup(filename);
+ ret->params.str.len = strlen(filename);
+ if (ret->params.str.ptr == NULL) {
+ free(ret);
+ return NSLOG_NO_MEMORY;
+ }
+ *filter = ret;
+ return NSLOG_NO_ERROR;
+}
+
+nslog_error nslog_filter_dirname_new(const char *dirname,
+ nslog_filter_t **filter)
+{
+ nslog_filter_t *ret = calloc(sizeof(*ret), 1);
+ if (ret == NULL)
+ return NSLOG_NO_MEMORY;
+ ret->kind = NSLFK_DIRNAME;
+ ret->refcount = 1;
+ ret->params.str.ptr = strdup(dirname);
+ ret->params.str.len = strlen(dirname);
+ if (ret->params.str.ptr == NULL) {
+ free(ret);
+ return NSLOG_NO_MEMORY;
+ }
+ *filter = ret;
+ return NSLOG_NO_ERROR;
+}
+
+nslog_error nslog_filter_funcname_new(const char *funcname,
+ nslog_filter_t **filter)
+{
+ nslog_filter_t *ret = calloc(sizeof(*ret), 1);
+ if (ret == NULL)
+ return NSLOG_NO_MEMORY;
+ ret->kind = NSLFK_FUNCNAME;
+ ret->refcount = 1;
+ ret->params.str.ptr = strdup(funcname);
+ ret->params.str.len = strlen(funcname);
+ if (ret->params.str.ptr == NULL) {
+ free(ret);
+ return NSLOG_NO_MEMORY;
+ }
+ *filter = ret;
+ return NSLOG_NO_ERROR;
+}
+
+
+nslog_error nslog_filter_and_new(nslog_filter_t *left,
+ nslog_filter_t *right,
+ nslog_filter_t **filter)
+{
+ nslog_filter_t *ret = calloc(sizeof(*ret), 1);
+ if (ret == NULL)
+ return NSLOG_NO_MEMORY;
+ ret->kind = NSLFK_AND;
+ ret->refcount = 1;
+ ret->params.binary.input1 = nslog_filter_ref(left);
+ ret->params.binary.input2 = nslog_filter_ref(right);
+ *filter = ret;
+ return NSLOG_NO_ERROR;
+}
+
+nslog_error nslog_filter_or_new(nslog_filter_t *left,
+ nslog_filter_t *right,
+ nslog_filter_t **filter)
+{
+ nslog_filter_t *ret = calloc(sizeof(*ret), 1);
+ if (ret == NULL)
+ return NSLOG_NO_MEMORY;
+ ret->kind = NSLFK_OR;
+ ret->refcount = 1;
+ ret->params.binary.input1 = nslog_filter_ref(left);
+ ret->params.binary.input2 = nslog_filter_ref(right);
+ *filter = ret;
+ return NSLOG_NO_ERROR;
+}
+
+nslog_error nslog_filter_xor_new(nslog_filter_t *left,
+ nslog_filter_t *right,
+ nslog_filter_t **filter)
+{
+ nslog_filter_t *ret = calloc(sizeof(*ret), 1);
+ if (ret == NULL)
+ return NSLOG_NO_MEMORY;
+ ret->kind = NSLFK_XOR;
+ ret->refcount = 1;
+ ret->params.binary.input1 = nslog_filter_ref(left);
+ ret->params.binary.input2 = nslog_filter_ref(right);
+ *filter = ret;
+ return NSLOG_NO_ERROR;
+}
+
+nslog_error nslog_filter_not_new(nslog_filter_t *input,
+ nslog_filter_t **filter)
+{
+ nslog_filter_t *ret = calloc(sizeof(*ret), 1);
+ if (ret == NULL)
+ return NSLOG_NO_MEMORY;
+ ret->kind = NSLFK_NOT;
+ ret->refcount = 1;
+ ret->params.unary_input = nslog_filter_ref(input);
+ *filter = ret;
+ return NSLOG_NO_ERROR;
+}
+
+
+nslog_filter_t *nslog_filter_ref(nslog_filter_t *filter)
+{
+ if (filter != NULL)
+ filter->refcount++;
+
+ return filter;
+}
+
+nslog_filter_t *nslog_filter_unref(nslog_filter_t *filter)
+{
+ if (filter != NULL && filter->refcount-- == 1) {
+ switch(filter->kind) {
+ case NSLFK_CATEGORY:
+ case NSLFK_FILENAME:
+ case NSLFK_DIRNAME:
+ case NSLFK_FUNCNAME:
+ free(filter->params.str.ptr);
+ break;
+ case NSLFK_AND:
+ case NSLFK_OR:
+ case NSLFK_XOR:
+ nslog_filter_unref(filter->params.binary.input1);
+ nslog_filter_unref(filter->params.binary.input2);
+ break;
+ case NSLFK_NOT:
+ nslog_filter_unref(filter->params.unary_input);
+ break;
+ default:
+ /* Nothing to do for the other kind(s) */
+ break;
+ }
+ free(filter);
+ }
+
+ return NULL;
+}
+
+nslog_error nslog_filter_set_active(nslog_filter_t *filter,
+ nslog_filter_t **prev)
+{
+ if (prev != NULL)
+ *prev = nslog__active_filter;
+ else
+ nslog_filter_unref(nslog__active_filter);
+
+ nslog__active_filter = nslog_filter_ref(filter);
+
+ return NSLOG_NO_ERROR;
+}
+
+static bool _nslog__filter_matches(nslog_entry_context_t *ctx,
+ nslog_filter_t *filter)
+{
+ switch (filter->kind) {
+ case NSLFK_CATEGORY:
+ if (filter->params.str.len > ctx->category->namelen)
+ return false;
+ if (ctx->category->name[filter->params.str.len] != '\0' &&
+ ctx->category->name[filter->params.str.len] != '/')
+ return false;
+ return (strncmp(filter->params.str.ptr,
+ ctx->category->name,
+ filter->params.str.len) == 0);
+
+ case NSLFK_LEVEL:
+ return (ctx->level >= filter->params.level);
+ case NSLFK_FILENAME:
+ if (filter->params.str.len > ctx->filenamelen)
+ return false;
+ if ((filter->params.str.len == ctx->filenamelen) &&
+ (strcmp(filter->params.str.ptr, ctx->filename) == 0))
+ return true;
+ if ((ctx->filename[ctx->filenamelen - filter->params.str.len - 1] == '/')
+ && (strcmp(filter->params.str.ptr,
+ ctx->filename + ctx->filenamelen - filter->params.str.len) == 0))
+ return true;
+ return false;
+ case NSLFK_DIRNAME:
+ if (filter->params.str.len >= ctx->filenamelen)
+ return false;
+ if ((ctx->filename[filter->params.str.len] == '/')
+ && (strncmp(filter->params.str.ptr,
+ ctx->filename,
+ filter->params.str.len) == 0))
+ return true;
+ return false;
+ case NSLFK_FUNCNAME:
+ return (filter->params.str.len == ctx->funcnamelen &&
+ strcmp(ctx->funcname, filter->params.str.ptr) == 0);
+ case NSLFK_AND:
+ return (_nslog__filter_matches(ctx, filter->params.binary.input1)
+ &&
+ _nslog__filter_matches(ctx, filter->params.binary.input2));
+ case NSLFK_OR:
+ return (_nslog__filter_matches(ctx, filter->params.binary.input1)
+ ||
+ _nslog__filter_matches(ctx, filter->params.binary.input2));
+ case NSLFK_XOR:
+ return (_nslog__filter_matches(ctx, filter->params.binary.input1)
+ ^
+ _nslog__filter_matches(ctx, filter->params.binary.input2));
+ case NSLFK_NOT:
+ return !_nslog__filter_matches(ctx, filter->params.unary_input);
+ default:
+ /* unknown */
+ assert("Unknown filter kind" == NULL);
+ return false;
+ }
+}
+
+bool nslog__filter_matches(nslog_entry_context_t *ctx)
+{
+ if (nslog__active_filter == NULL)
+ return true;
+ return _nslog__filter_matches(ctx, nslog__active_filter);
+}
diff --git a/src/nslog_internal.h b/src/nslog_internal.h
new file mode 100644
index 0000000..d5519e7
--- /dev/null
+++ b/src/nslog_internal.h
@@ -0,0 +1,29 @@
+/*
+ * 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
+ */
+
+#ifndef NSLOG_INTERNAL_H_
+#define NSLOG_INTERNAL_H_
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+#include <stdarg.h>
+#include <assert.h>
+
+#include "nslog/nslog.h"
+
+bool nslog__filter_matches(nslog_entry_context_t *ctx);
+
+#endif /* NSLOG_INTERNAL_H_ */