diff options
author | Daniel Silverstone <dsilvers@digital-scurf.org> | 2017-06-11 10:08:37 +0100 |
---|---|---|
committer | Daniel Silverstone <dsilvers@digital-scurf.org> | 2017-06-11 10:08:37 +0100 |
commit | 8b4ce0ba86d0396bde2546dd248c863876da4106 (patch) | |
tree | 72ac2147cda97ddac20144a60e7b0644a0cc303f /src | |
parent | 8052642eadfb95b244f978b10889dff51f9133f5 (diff) | |
download | libnslog-8b4ce0ba86d0396bde2546dd248c863876da4106.tar.gz libnslog-8b4ce0ba86d0396bde2546dd248c863876da4106.tar.bz2 |
Another step toward filters working
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile | 2 | ||||
-rw-r--r-- | src/core.c | 28 | ||||
-rw-r--r-- | src/filter.c | 310 | ||||
-rw-r--r-- | src/nslog_internal.h | 29 |
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 @@ -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_ */ |